mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-11 00:04:33 +08:00
Merge tag 'amd-drm-next-5.18-2022-02-11-1' of https://gitlab.freedesktop.org/agd5f/linux into drm-next
amd-drm-next-5.18-2022-02-11-1: amdgpu: - Clean up of power management code - Enable freesync video mode by default - Clean up of RAS code - Improve VRAM access for debug using SDMA - Coding style cleanups - SR-IOV fixes - More display FP reorg - TLB flush fixes for Arcuturus, Vega20 - Misc display fixes - Rework special register access methods for SR-IOV - DP2 fixes - DP tunneling fixes - DSC fixes - More IP discovery cleanups - Misc RAS fixes - Enable both SMU i2c buses where applicable - s2idle improvements - DPCS header cleanup - Add new CAP firmware support for SR-IOV amdkfd: - Misc cleanups - SVM fixes - CRIU support - Clean up MQD manager UAPI: - Add interface to amdgpu CTX ioctl to request a stable power state for profiling https://gitlab.freedesktop.org/mesa/drm/-/merge_requests/207 - Add amdkfd support for CRIU https://github.com/checkpoint-restore/criu/pull/1709 - Remove old unused amdkfd debugger interface Was only implemented for Kaveri and was only ever used by an old HSA tool that was never open sourced radeon: - Fix error handling in radeon_driver_open_kms - UVD suspend fix - Misc fixes From: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220211220706.5803-1-alexander.deucher@amd.com
This commit is contained in:
commit
123db17ddf
@ -260,7 +260,7 @@ static int aldebaran_mode2_restore_ip(struct amdgpu_device *adev)
|
||||
adev->gfx.rlc.funcs->resume(adev);
|
||||
|
||||
/* Wait for FW reset event complete */
|
||||
r = smu_wait_for_event(adev, SMU_EVENT_RESET_COMPLETE, 0);
|
||||
r = amdgpu_dpm_wait_for_event(adev, SMU_EVENT_RESET_COMPLETE, 0);
|
||||
if (r) {
|
||||
dev_err(adev->dev,
|
||||
"Failed to get response from firmware after reset\n");
|
||||
|
@ -99,7 +99,6 @@
|
||||
#include "amdgpu_gem.h"
|
||||
#include "amdgpu_doorbell.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_smu.h"
|
||||
#include "amdgpu_discovery.h"
|
||||
#include "amdgpu_mes.h"
|
||||
#include "amdgpu_umc.h"
|
||||
@ -109,6 +108,7 @@
|
||||
#include "amdgpu_smuio.h"
|
||||
#include "amdgpu_fdinfo.h"
|
||||
#include "amdgpu_mca.h"
|
||||
#include "amdgpu_ras.h"
|
||||
|
||||
#define MAX_GPU_INSTANCE 16
|
||||
|
||||
@ -197,7 +197,6 @@ extern int amdgpu_emu_mode;
|
||||
extern uint amdgpu_smu_memory_pool_size;
|
||||
extern int amdgpu_smu_pptable_id;
|
||||
extern uint amdgpu_dc_feature_mask;
|
||||
extern uint amdgpu_freesync_vid_mode;
|
||||
extern uint amdgpu_dc_debug_mask;
|
||||
extern uint amdgpu_dm_abm_level;
|
||||
extern int amdgpu_backlight;
|
||||
@ -373,7 +372,8 @@ int amdgpu_device_ip_block_add(struct amdgpu_device *adev,
|
||||
*/
|
||||
bool amdgpu_get_bios(struct amdgpu_device *adev);
|
||||
bool amdgpu_read_bios(struct amdgpu_device *adev);
|
||||
|
||||
bool amdgpu_soc15_read_bios_from_rom(struct amdgpu_device *adev,
|
||||
u8 *bios, u32 length_bytes);
|
||||
/*
|
||||
* Clocks
|
||||
*/
|
||||
@ -950,12 +950,6 @@ struct amdgpu_device {
|
||||
|
||||
/* powerplay */
|
||||
struct amd_powerplay powerplay;
|
||||
bool pp_force_state_enabled;
|
||||
|
||||
/* smu */
|
||||
struct smu_context smu;
|
||||
|
||||
/* dpm */
|
||||
struct amdgpu_pm pm;
|
||||
u32 cg_flags;
|
||||
u32 pg_flags;
|
||||
@ -1100,6 +1094,8 @@ struct amdgpu_device {
|
||||
uint32_t ip_versions[MAX_HWIP][HWIP_MAX_INSTANCE];
|
||||
|
||||
bool ram_is_direct_mapped;
|
||||
|
||||
struct list_head ras_list;
|
||||
};
|
||||
|
||||
static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev)
|
||||
@ -1321,6 +1317,10 @@ void amdgpu_device_invalidate_hdp(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring);
|
||||
|
||||
void amdgpu_device_halt(struct amdgpu_device *adev);
|
||||
u32 amdgpu_device_pcie_port_rreg(struct amdgpu_device *adev,
|
||||
u32 reg);
|
||||
void amdgpu_device_pcie_port_wreg(struct amdgpu_device *adev,
|
||||
u32 reg, u32 v);
|
||||
|
||||
/* atpx handler */
|
||||
#if defined(CONFIG_VGA_SWITCHEROO)
|
||||
@ -1408,12 +1408,10 @@ int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_sta
|
||||
int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev);
|
||||
|
||||
void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps);
|
||||
bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev);
|
||||
void amdgpu_acpi_detect(void);
|
||||
#else
|
||||
static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; }
|
||||
static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { }
|
||||
static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; }
|
||||
static inline void amdgpu_acpi_detect(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,
|
||||
@ -1422,6 +1420,14 @@ static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev,
|
||||
enum amdgpu_ss ss_state) { return 0; }
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND)
|
||||
bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev);
|
||||
bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev);
|
||||
#else
|
||||
static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; }
|
||||
static inline bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) { return false; }
|
||||
#endif
|
||||
|
||||
int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser,
|
||||
uint64_t addr, struct amdgpu_bo **bo,
|
||||
struct amdgpu_bo_va_mapping **mapping);
|
||||
@ -1452,6 +1458,15 @@ int amdgpu_device_set_cg_state(struct amdgpu_device *adev,
|
||||
int amdgpu_device_set_pg_state(struct amdgpu_device *adev,
|
||||
enum amd_powergating_state state);
|
||||
|
||||
static inline bool amdgpu_device_has_timeouts_enabled(struct amdgpu_device *adev)
|
||||
{
|
||||
return amdgpu_gpu_recovery != 0 &&
|
||||
adev->gfx_timeout != MAX_SCHEDULE_TIMEOUT &&
|
||||
adev->compute_timeout != MAX_SCHEDULE_TIMEOUT &&
|
||||
adev->sdma_timeout != MAX_SCHEDULE_TIMEOUT &&
|
||||
adev->video_timeout != MAX_SCHEDULE_TIMEOUT;
|
||||
}
|
||||
|
||||
#include "amdgpu_object.h"
|
||||
|
||||
static inline bool amdgpu_is_tmz(struct amdgpu_device *adev)
|
||||
|
@ -1031,6 +1031,20 @@ void amdgpu_acpi_detect(void)
|
||||
}
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SUSPEND)
|
||||
/**
|
||||
* amdgpu_acpi_is_s3_active
|
||||
*
|
||||
* @adev: amdgpu_device_pointer
|
||||
*
|
||||
* returns true if supported, false if not.
|
||||
*/
|
||||
bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev)
|
||||
{
|
||||
return !(adev->flags & AMD_IS_APU) ||
|
||||
(pm_suspend_target_state == PM_SUSPEND_MEM);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_acpi_is_s0ix_active
|
||||
*
|
||||
@ -1040,11 +1054,24 @@ void amdgpu_acpi_detect(void)
|
||||
*/
|
||||
bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_AMD_PMC) && IS_ENABLED(CONFIG_SUSPEND)
|
||||
if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) {
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return pm_suspend_target_state == PM_SUSPEND_TO_IDLE;
|
||||
if (!(adev->flags & AMD_IS_APU) ||
|
||||
(pm_suspend_target_state != PM_SUSPEND_TO_IDLE))
|
||||
return false;
|
||||
|
||||
if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) {
|
||||
dev_warn_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;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !IS_ENABLED(CONFIG_AMD_PMC)
|
||||
dev_warn_once(adev->dev,
|
||||
"Power consumption will be higher as the kernel has not been compiled with CONFIG_AMD_PMC.\n");
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif /* CONFIG_AMD_PMC */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SUSPEND */
|
||||
|
@ -131,6 +131,7 @@ struct amdkfd_process_info {
|
||||
atomic_t evicted_bos;
|
||||
struct delayed_work restore_userptr_work;
|
||||
struct pid *pid;
|
||||
bool block_mmu_notifications;
|
||||
};
|
||||
|
||||
int amdgpu_amdkfd_init(void);
|
||||
@ -268,7 +269,7 @@ uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *drm_priv);
|
||||
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,
|
||||
uint64_t *offset, uint32_t flags);
|
||||
uint64_t *offset, uint32_t flags, bool criu_resume);
|
||||
int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
||||
struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv,
|
||||
uint64_t *size);
|
||||
@ -297,6 +298,10 @@ 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,
|
||||
bool reset);
|
||||
bool amdgpu_amdkfd_bo_mapped_to_dev(struct amdgpu_device *adev, struct kgd_mem *mem);
|
||||
void amdgpu_amdkfd_block_mmu_notifications(void *p);
|
||||
int amdgpu_amdkfd_criu_resume(void *p);
|
||||
|
||||
#if IS_ENABLED(CONFIG_HSA_AMD)
|
||||
void amdgpu_amdkfd_gpuvm_init_mem_limits(void);
|
||||
void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev,
|
||||
|
@ -37,10 +37,7 @@ const struct kfd2kgd_calls aldebaran_kfd2kgd = {
|
||||
.hqd_sdma_is_occupied = kgd_arcturus_hqd_sdma_is_occupied,
|
||||
.hqd_destroy = kgd_gfx_v9_hqd_destroy,
|
||||
.hqd_sdma_destroy = kgd_arcturus_hqd_sdma_destroy,
|
||||
.address_watch_disable = kgd_gfx_v9_address_watch_disable,
|
||||
.address_watch_execute = kgd_gfx_v9_address_watch_execute,
|
||||
.wave_control_execute = kgd_gfx_v9_wave_control_execute,
|
||||
.address_watch_get_offset = kgd_gfx_v9_address_watch_get_offset,
|
||||
.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,
|
||||
|
@ -289,10 +289,7 @@ const struct kfd2kgd_calls arcturus_kfd2kgd = {
|
||||
.hqd_sdma_is_occupied = kgd_arcturus_hqd_sdma_is_occupied,
|
||||
.hqd_destroy = kgd_gfx_v9_hqd_destroy,
|
||||
.hqd_sdma_destroy = kgd_arcturus_hqd_sdma_destroy,
|
||||
.address_watch_disable = kgd_gfx_v9_address_watch_disable,
|
||||
.address_watch_execute = kgd_gfx_v9_address_watch_execute,
|
||||
.wave_control_execute = kgd_gfx_v9_wave_control_execute,
|
||||
.address_watch_get_offset = kgd_gfx_v9_address_watch_get_offset,
|
||||
.get_atc_vmid_pasid_mapping_info =
|
||||
kgd_gfx_v9_get_atc_vmid_pasid_mapping_info,
|
||||
.set_vm_context_page_table_base =
|
||||
|
@ -671,20 +671,6 @@ static bool get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||
return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
|
||||
}
|
||||
|
||||
static int kgd_address_watch_disable(struct amdgpu_device *adev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_address_watch_execute(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
uint32_t cntl_val,
|
||||
uint32_t addr_hi,
|
||||
uint32_t addr_lo)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_wave_control_execute(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
@ -709,13 +695,6 @@ static int kgd_wave_control_execute(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t kgd_address_watch_get_offset(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
unsigned int reg_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_vm_context_page_table_base(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t page_table_base)
|
||||
{
|
||||
@ -767,10 +746,7 @@ const struct kfd2kgd_calls gfx_v10_kfd2kgd = {
|
||||
.hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied,
|
||||
.hqd_destroy = kgd_hqd_destroy,
|
||||
.hqd_sdma_destroy = kgd_hqd_sdma_destroy,
|
||||
.address_watch_disable = kgd_address_watch_disable,
|
||||
.address_watch_execute = kgd_address_watch_execute,
|
||||
.wave_control_execute = kgd_wave_control_execute,
|
||||
.address_watch_get_offset = kgd_address_watch_get_offset,
|
||||
.get_atc_vmid_pasid_mapping_info =
|
||||
get_atc_vmid_pasid_mapping_info,
|
||||
.set_vm_context_page_table_base = set_vm_context_page_table_base,
|
||||
|
@ -582,21 +582,6 @@ static int hqd_sdma_destroy_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int address_watch_disable_v10_3(struct amdgpu_device *adev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int address_watch_execute_v10_3(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
uint32_t cntl_val,
|
||||
uint32_t addr_hi,
|
||||
uint32_t addr_lo)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wave_control_execute_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
@ -621,13 +606,6 @@ static int wave_control_execute_v10_3(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t address_watch_get_offset_v10_3(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
unsigned int reg_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_vm_context_page_table_base_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t page_table_base)
|
||||
{
|
||||
@ -809,10 +787,7 @@ const struct kfd2kgd_calls gfx_v10_3_kfd2kgd = {
|
||||
.hqd_sdma_is_occupied = hqd_sdma_is_occupied_v10_3,
|
||||
.hqd_destroy = hqd_destroy_v10_3,
|
||||
.hqd_sdma_destroy = hqd_sdma_destroy_v10_3,
|
||||
.address_watch_disable = address_watch_disable_v10_3,
|
||||
.address_watch_execute = address_watch_execute_v10_3,
|
||||
.wave_control_execute = wave_control_execute_v10_3,
|
||||
.address_watch_get_offset = address_watch_get_offset_v10_3,
|
||||
.get_atc_vmid_pasid_mapping_info = NULL,
|
||||
.set_vm_context_page_table_base = set_vm_context_page_table_base_v10_3,
|
||||
.program_trap_handler_settings = program_trap_handler_settings_v10_3,
|
||||
|
@ -45,43 +45,6 @@ enum {
|
||||
MAX_WATCH_ADDRESSES = 4
|
||||
};
|
||||
|
||||
enum {
|
||||
ADDRESS_WATCH_REG_ADDR_HI = 0,
|
||||
ADDRESS_WATCH_REG_ADDR_LO,
|
||||
ADDRESS_WATCH_REG_CNTL,
|
||||
ADDRESS_WATCH_REG_MAX
|
||||
};
|
||||
|
||||
/* not defined in the CI/KV reg file */
|
||||
enum {
|
||||
ADDRESS_WATCH_REG_CNTL_ATC_BIT = 0x10000000UL,
|
||||
ADDRESS_WATCH_REG_CNTL_DEFAULT_MASK = 0x00FFFFFF,
|
||||
ADDRESS_WATCH_REG_ADDLOW_MASK_EXTENSION = 0x03000000,
|
||||
/* extend the mask to 26 bits to match the low address field */
|
||||
ADDRESS_WATCH_REG_ADDLOW_SHIFT = 6,
|
||||
ADDRESS_WATCH_REG_ADDHIGH_MASK = 0xFFFF
|
||||
};
|
||||
|
||||
static const uint32_t watchRegs[MAX_WATCH_ADDRESSES * ADDRESS_WATCH_REG_MAX] = {
|
||||
mmTCP_WATCH0_ADDR_H, mmTCP_WATCH0_ADDR_L, mmTCP_WATCH0_CNTL,
|
||||
mmTCP_WATCH1_ADDR_H, mmTCP_WATCH1_ADDR_L, mmTCP_WATCH1_CNTL,
|
||||
mmTCP_WATCH2_ADDR_H, mmTCP_WATCH2_ADDR_L, mmTCP_WATCH2_CNTL,
|
||||
mmTCP_WATCH3_ADDR_H, mmTCP_WATCH3_ADDR_L, mmTCP_WATCH3_CNTL
|
||||
};
|
||||
|
||||
union TCP_WATCH_CNTL_BITS {
|
||||
struct {
|
||||
uint32_t mask:24;
|
||||
uint32_t vmid:4;
|
||||
uint32_t atc:1;
|
||||
uint32_t mode:2;
|
||||
uint32_t valid:1;
|
||||
} bitfields, bits;
|
||||
uint32_t u32All;
|
||||
signed int i32All;
|
||||
float f32All;
|
||||
};
|
||||
|
||||
static void lock_srbm(struct amdgpu_device *adev, uint32_t mec, uint32_t pipe,
|
||||
uint32_t queue, uint32_t vmid)
|
||||
{
|
||||
@ -529,55 +492,6 @@ static int kgd_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_address_watch_disable(struct amdgpu_device *adev)
|
||||
{
|
||||
union TCP_WATCH_CNTL_BITS cntl;
|
||||
unsigned int i;
|
||||
|
||||
cntl.u32All = 0;
|
||||
|
||||
cntl.bitfields.valid = 0;
|
||||
cntl.bitfields.mask = ADDRESS_WATCH_REG_CNTL_DEFAULT_MASK;
|
||||
cntl.bitfields.atc = 1;
|
||||
|
||||
/* Turning off this address until we set all the registers */
|
||||
for (i = 0; i < MAX_WATCH_ADDRESSES; i++)
|
||||
WREG32(watchRegs[i * ADDRESS_WATCH_REG_MAX +
|
||||
ADDRESS_WATCH_REG_CNTL], cntl.u32All);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_address_watch_execute(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
uint32_t cntl_val,
|
||||
uint32_t addr_hi,
|
||||
uint32_t addr_lo)
|
||||
{
|
||||
union TCP_WATCH_CNTL_BITS cntl;
|
||||
|
||||
cntl.u32All = cntl_val;
|
||||
|
||||
/* Turning off this watch point until we set all the registers */
|
||||
cntl.bitfields.valid = 0;
|
||||
WREG32(watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX +
|
||||
ADDRESS_WATCH_REG_CNTL], cntl.u32All);
|
||||
|
||||
WREG32(watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX +
|
||||
ADDRESS_WATCH_REG_ADDR_HI], addr_hi);
|
||||
|
||||
WREG32(watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX +
|
||||
ADDRESS_WATCH_REG_ADDR_LO], addr_lo);
|
||||
|
||||
/* Enable the watch point */
|
||||
cntl.bitfields.valid = 1;
|
||||
|
||||
WREG32(watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX +
|
||||
ADDRESS_WATCH_REG_CNTL], cntl.u32All);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_wave_control_execute(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
@ -602,13 +516,6 @@ static int kgd_wave_control_execute(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t kgd_address_watch_get_offset(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
unsigned int reg_offset)
|
||||
{
|
||||
return watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX + reg_offset];
|
||||
}
|
||||
|
||||
static bool get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||
uint8_t vmid, uint16_t *p_pasid)
|
||||
{
|
||||
@ -665,10 +572,7 @@ const struct kfd2kgd_calls gfx_v7_kfd2kgd = {
|
||||
.hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied,
|
||||
.hqd_destroy = kgd_hqd_destroy,
|
||||
.hqd_sdma_destroy = kgd_hqd_sdma_destroy,
|
||||
.address_watch_disable = kgd_address_watch_disable,
|
||||
.address_watch_execute = kgd_address_watch_execute,
|
||||
.wave_control_execute = kgd_wave_control_execute,
|
||||
.address_watch_get_offset = kgd_address_watch_get_offset,
|
||||
.get_atc_vmid_pasid_mapping_info = get_atc_vmid_pasid_mapping_info,
|
||||
.set_scratch_backing_va = set_scratch_backing_va,
|
||||
.set_vm_context_page_table_base = set_vm_context_page_table_base,
|
||||
|
@ -538,20 +538,6 @@ static bool get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||
return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
|
||||
}
|
||||
|
||||
static int kgd_address_watch_disable(struct amdgpu_device *adev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_address_watch_execute(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
uint32_t cntl_val,
|
||||
uint32_t addr_hi,
|
||||
uint32_t addr_lo)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_wave_control_execute(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
@ -576,13 +562,6 @@ static int kgd_wave_control_execute(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t kgd_address_watch_get_offset(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
unsigned int reg_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_scratch_backing_va(struct amdgpu_device *adev,
|
||||
uint64_t va, uint32_t vmid)
|
||||
{
|
||||
@ -614,10 +593,7 @@ const struct kfd2kgd_calls gfx_v8_kfd2kgd = {
|
||||
.hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied,
|
||||
.hqd_destroy = kgd_hqd_destroy,
|
||||
.hqd_sdma_destroy = kgd_hqd_sdma_destroy,
|
||||
.address_watch_disable = kgd_address_watch_disable,
|
||||
.address_watch_execute = kgd_address_watch_execute,
|
||||
.wave_control_execute = kgd_wave_control_execute,
|
||||
.address_watch_get_offset = kgd_address_watch_get_offset,
|
||||
.get_atc_vmid_pasid_mapping_info =
|
||||
get_atc_vmid_pasid_mapping_info,
|
||||
.set_scratch_backing_va = set_scratch_backing_va,
|
||||
|
@ -622,20 +622,6 @@ bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||
return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
|
||||
}
|
||||
|
||||
int kgd_gfx_v9_address_watch_disable(struct amdgpu_device *adev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kgd_gfx_v9_address_watch_execute(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
uint32_t cntl_val,
|
||||
uint32_t addr_hi,
|
||||
uint32_t addr_lo)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kgd_gfx_v9_wave_control_execute(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
@ -660,13 +646,6 @@ int kgd_gfx_v9_wave_control_execute(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t kgd_gfx_v9_address_watch_get_offset(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
unsigned int reg_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kgd_gfx_v9_set_vm_context_page_table_base(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t page_table_base)
|
||||
{
|
||||
@ -888,10 +867,7 @@ const struct kfd2kgd_calls gfx_v9_kfd2kgd = {
|
||||
.hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied,
|
||||
.hqd_destroy = kgd_gfx_v9_hqd_destroy,
|
||||
.hqd_sdma_destroy = kgd_hqd_sdma_destroy,
|
||||
.address_watch_disable = kgd_gfx_v9_address_watch_disable,
|
||||
.address_watch_execute = kgd_gfx_v9_address_watch_execute,
|
||||
.wave_control_execute = kgd_gfx_v9_wave_control_execute,
|
||||
.address_watch_get_offset = kgd_gfx_v9_address_watch_get_offset,
|
||||
.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,
|
||||
|
@ -46,19 +46,9 @@ 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);
|
||||
int kgd_gfx_v9_address_watch_disable(struct amdgpu_device *adev);
|
||||
int kgd_gfx_v9_address_watch_execute(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
uint32_t cntl_val,
|
||||
uint32_t addr_hi,
|
||||
uint32_t addr_lo);
|
||||
int kgd_gfx_v9_wave_control_execute(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd);
|
||||
uint32_t kgd_gfx_v9_address_watch_get_offset(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
unsigned int reg_offset);
|
||||
|
||||
bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||
uint8_t vmid, uint16_t *p_pasid);
|
||||
|
||||
|
@ -778,7 +778,7 @@ unwind:
|
||||
continue;
|
||||
if (attachment[i]->bo_va) {
|
||||
amdgpu_bo_reserve(bo[i], true);
|
||||
amdgpu_vm_bo_rmv(adev, attachment[i]->bo_va);
|
||||
amdgpu_vm_bo_del(adev, attachment[i]->bo_va);
|
||||
amdgpu_bo_unreserve(bo[i]);
|
||||
list_del(&attachment[i]->list);
|
||||
}
|
||||
@ -795,7 +795,7 @@ static void kfd_mem_detach(struct kfd_mem_attachment *attachment)
|
||||
|
||||
pr_debug("\t remove VA 0x%llx in entry %p\n",
|
||||
attachment->va, attachment);
|
||||
amdgpu_vm_bo_rmv(attachment->adev, attachment->bo_va);
|
||||
amdgpu_vm_bo_del(attachment->adev, attachment->bo_va);
|
||||
drm_gem_object_put(&bo->tbo.base);
|
||||
list_del(&attachment->list);
|
||||
kfree(attachment);
|
||||
@ -842,7 +842,8 @@ static void remove_kgd_mem_from_kfd_bo_list(struct kgd_mem *mem,
|
||||
*
|
||||
* Returns 0 for success, negative errno for errors.
|
||||
*/
|
||||
static int init_user_pages(struct kgd_mem *mem, uint64_t user_addr)
|
||||
static int init_user_pages(struct kgd_mem *mem, uint64_t user_addr,
|
||||
bool criu_resume)
|
||||
{
|
||||
struct amdkfd_process_info *process_info = mem->process_info;
|
||||
struct amdgpu_bo *bo = mem->bo;
|
||||
@ -864,6 +865,18 @@ static int init_user_pages(struct kgd_mem *mem, uint64_t user_addr)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (criu_resume) {
|
||||
/*
|
||||
* During a CRIU restore operation, the userptr buffer objects
|
||||
* will be validated in the restore_userptr_work worker at a
|
||||
* later stage when it is scheduled by another ioctl called by
|
||||
* CRIU master process for the target pid for restore.
|
||||
*/
|
||||
atomic_inc(&mem->invalid);
|
||||
mutex_unlock(&process_info->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = amdgpu_ttm_tt_get_user_pages(bo, bo->tbo.ttm->pages);
|
||||
if (ret) {
|
||||
pr_err("%s: Failed to get user pages: %d\n", __func__, ret);
|
||||
@ -1452,10 +1465,39 @@ uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *drm_priv)
|
||||
return avm->pd_phys_addr;
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_block_mmu_notifications(void *p)
|
||||
{
|
||||
struct amdkfd_process_info *pinfo = (struct amdkfd_process_info *)p;
|
||||
|
||||
mutex_lock(&pinfo->lock);
|
||||
WRITE_ONCE(pinfo->block_mmu_notifications, true);
|
||||
mutex_unlock(&pinfo->lock);
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_criu_resume(void *p)
|
||||
{
|
||||
int ret = 0;
|
||||
struct amdkfd_process_info *pinfo = (struct amdkfd_process_info *)p;
|
||||
|
||||
mutex_lock(&pinfo->lock);
|
||||
pr_debug("scheduling work\n");
|
||||
atomic_inc(&pinfo->evicted_bos);
|
||||
if (!READ_ONCE(pinfo->block_mmu_notifications)) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
WRITE_ONCE(pinfo->block_mmu_notifications, false);
|
||||
schedule_delayed_work(&pinfo->restore_userptr_work, 0);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&pinfo->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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,
|
||||
uint64_t *offset, uint32_t flags)
|
||||
uint64_t *offset, uint32_t flags, bool criu_resume)
|
||||
{
|
||||
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
|
||||
enum ttm_bo_type bo_type = ttm_bo_type_device;
|
||||
@ -1558,7 +1600,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, user_addr);
|
||||
|
||||
if (user_addr) {
|
||||
ret = init_user_pages(*mem, user_addr);
|
||||
pr_debug("creating userptr BO for user_addr = %llu\n", user_addr);
|
||||
ret = init_user_pages(*mem, user_addr, criu_resume);
|
||||
if (ret)
|
||||
goto allocate_init_user_pages_failed;
|
||||
} else if (flags & (KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL |
|
||||
@ -1813,12 +1856,6 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
|
||||
true);
|
||||
ret = unreserve_bo_and_vms(&ctx, false, false);
|
||||
|
||||
/* Only apply no TLB flush on Aldebaran to
|
||||
* workaround regressions on other Asics.
|
||||
*/
|
||||
if (table_freed && (adev->asic_type != CHIP_ALDEBARAN))
|
||||
*table_freed = true;
|
||||
|
||||
goto out;
|
||||
|
||||
out_unreserve:
|
||||
@ -2068,6 +2105,10 @@ int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem,
|
||||
int evicted_bos;
|
||||
int r = 0;
|
||||
|
||||
/* Do not process MMU notifications until stage-4 IOCTL is received */
|
||||
if (READ_ONCE(process_info->block_mmu_notifications))
|
||||
return 0;
|
||||
|
||||
atomic_inc(&mem->invalid);
|
||||
evicted_bos = atomic_inc_return(&process_info->evicted_bos);
|
||||
if (evicted_bos == 1) {
|
||||
@ -2635,3 +2676,14 @@ int amdgpu_amdkfd_get_tile_config(struct amdgpu_device *adev,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool amdgpu_amdkfd_bo_mapped_to_dev(struct amdgpu_device *adev, struct kgd_mem *mem)
|
||||
{
|
||||
struct kfd_mem_attachment *entry;
|
||||
|
||||
list_for_each_entry(entry, &mem->attachments, list) {
|
||||
if (entry->is_mapped && entry->adev == adev)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1083,6 +1083,7 @@ int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_AMDGPU_SI
|
||||
int amdgpu_atombios_get_memory_pll_dividers(struct amdgpu_device *adev,
|
||||
u32 clock,
|
||||
bool strobe_mode,
|
||||
@ -1503,6 +1504,7 @@ int amdgpu_atombios_init_mc_reg_table(struct amdgpu_device *adev,
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool amdgpu_atombios_has_gpu_virtualization_table(struct amdgpu_device *adev)
|
||||
{
|
||||
|
@ -160,6 +160,7 @@ int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev,
|
||||
bool strobe_mode,
|
||||
struct atom_clock_dividers *dividers);
|
||||
|
||||
#ifdef CONFIG_DRM_AMDGPU_SI
|
||||
int amdgpu_atombios_get_memory_pll_dividers(struct amdgpu_device *adev,
|
||||
u32 clock,
|
||||
bool strobe_mode,
|
||||
@ -179,6 +180,17 @@ int amdgpu_atombios_get_voltage_table(struct amdgpu_device *adev,
|
||||
int amdgpu_atombios_init_mc_reg_table(struct amdgpu_device *adev,
|
||||
u8 module_index,
|
||||
struct atom_mc_reg_table *reg_table);
|
||||
int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type,
|
||||
u16 voltage_id, u16 *voltage);
|
||||
int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device *adev,
|
||||
u16 *voltage,
|
||||
u16 leakage_idx);
|
||||
void amdgpu_atombios_get_default_voltages(struct amdgpu_device *adev,
|
||||
u16 *vddc, u16 *vddci, u16 *mvdd);
|
||||
int amdgpu_atombios_get_svi2_info(struct amdgpu_device *adev,
|
||||
u8 voltage_type,
|
||||
u8 *svd_gpio_id, u8 *svc_gpio_id);
|
||||
#endif
|
||||
|
||||
bool amdgpu_atombios_has_gpu_virtualization_table(struct amdgpu_device *adev);
|
||||
|
||||
@ -190,21 +202,11 @@ void amdgpu_atombios_scratch_regs_set_backlight_level(struct amdgpu_device *adev
|
||||
bool amdgpu_atombios_scratch_need_asic_init(struct amdgpu_device *adev);
|
||||
|
||||
void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le);
|
||||
int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type,
|
||||
u16 voltage_id, u16 *voltage);
|
||||
int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device *adev,
|
||||
u16 *voltage,
|
||||
u16 leakage_idx);
|
||||
void amdgpu_atombios_get_default_voltages(struct amdgpu_device *adev,
|
||||
u16 *vddc, u16 *vddci, u16 *mvdd);
|
||||
int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev,
|
||||
u8 clock_type,
|
||||
u32 clock,
|
||||
bool strobe_mode,
|
||||
struct atom_clock_dividers *dividers);
|
||||
int amdgpu_atombios_get_svi2_info(struct amdgpu_device *adev,
|
||||
u8 voltage_type,
|
||||
u8 *svd_gpio_id, u8 *svc_gpio_id);
|
||||
|
||||
int amdgpu_atombios_get_data_table(struct amdgpu_device *adev,
|
||||
uint32_t table,
|
||||
|
@ -464,3 +464,41 @@ success:
|
||||
adev->is_atom_fw = (adev->asic_type >= CHIP_VEGA10) ? true : false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* helper function for soc15 and onwards to read bios from rom */
|
||||
bool amdgpu_soc15_read_bios_from_rom(struct amdgpu_device *adev,
|
||||
u8 *bios, u32 length_bytes)
|
||||
{
|
||||
u32 *dw_ptr;
|
||||
u32 i, length_dw;
|
||||
u32 rom_index_offset;
|
||||
u32 rom_data_offset;
|
||||
|
||||
if (bios == NULL)
|
||||
return false;
|
||||
if (length_bytes == 0)
|
||||
return false;
|
||||
/* APU vbios image is part of sbios image */
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return false;
|
||||
if (!adev->smuio.funcs ||
|
||||
!adev->smuio.funcs->get_rom_index_offset ||
|
||||
!adev->smuio.funcs->get_rom_data_offset)
|
||||
return false;
|
||||
|
||||
dw_ptr = (u32 *)bios;
|
||||
length_dw = ALIGN(length_bytes, 4) / 4;
|
||||
|
||||
rom_index_offset =
|
||||
adev->smuio.funcs->get_rom_index_offset(adev);
|
||||
rom_data_offset =
|
||||
adev->smuio.funcs->get_rom_data_offset(adev);
|
||||
|
||||
/* set rom index to 0 */
|
||||
WREG32(rom_index_offset, 0);
|
||||
/* read out the rom data */
|
||||
for (i = 0; i < length_dw; i++)
|
||||
dw_ptr[i] = RREG32(rom_data_offset);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -127,8 +127,6 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, union drm_amdgpu_cs
|
||||
goto free_chunk;
|
||||
}
|
||||
|
||||
mutex_lock(&p->ctx->lock);
|
||||
|
||||
/* skip guilty context job */
|
||||
if (atomic_read(&p->ctx->guilty) == 1) {
|
||||
ret = -ECANCELED;
|
||||
@ -585,6 +583,16 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
|
||||
}
|
||||
}
|
||||
|
||||
/* Move fence waiting after getting reservation lock of
|
||||
* PD root. Then there is no need on a ctx mutex lock.
|
||||
*/
|
||||
r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entity);
|
||||
if (unlikely(r != 0)) {
|
||||
if (r != -ERESTARTSYS)
|
||||
DRM_ERROR("amdgpu_ctx_wait_prev_fence failed.\n");
|
||||
goto error_validate;
|
||||
}
|
||||
|
||||
amdgpu_cs_get_threshold_for_moves(p->adev, &p->bytes_moved_threshold,
|
||||
&p->bytes_moved_vis_threshold);
|
||||
p->bytes_moved = 0;
|
||||
@ -700,7 +708,6 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error,
|
||||
dma_fence_put(parser->fence);
|
||||
|
||||
if (parser->ctx) {
|
||||
mutex_unlock(&parser->ctx->lock);
|
||||
amdgpu_ctx_put(parser->ctx);
|
||||
}
|
||||
if (parser->bo_list)
|
||||
@ -944,7 +951,7 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev,
|
||||
if (parser->job->uf_addr && ring->funcs->no_user_fence)
|
||||
return -EINVAL;
|
||||
|
||||
return amdgpu_ctx_wait_prev_fence(parser->ctx, parser->entity);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_cs_process_fence_dep(struct amdgpu_cs_parser *p,
|
||||
@ -1360,7 +1367,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
goto out;
|
||||
|
||||
r = amdgpu_cs_submit(&parser, cs);
|
||||
|
||||
out:
|
||||
amdgpu_cs_parser_fini(&parser, r, reserved_buffers);
|
||||
|
||||
@ -1506,6 +1512,7 @@ int amdgpu_cs_fence_to_handle_ioctl(struct drm_device *dev, void *data,
|
||||
return 0;
|
||||
|
||||
default:
|
||||
dma_fence_put(fence);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ int amdgpu_map_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
|
||||
if (r) {
|
||||
DRM_ERROR("failed to do bo_map on static CSA, err=%d\n", r);
|
||||
amdgpu_vm_bo_rmv(adev, *bo_va);
|
||||
amdgpu_vm_bo_del(adev, *bo_va);
|
||||
ttm_eu_backoff_reservation(&ticket, &list);
|
||||
return r;
|
||||
}
|
||||
|
@ -230,13 +230,13 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev,
|
||||
|
||||
kref_init(&ctx->refcount);
|
||||
spin_lock_init(&ctx->ring_lock);
|
||||
mutex_init(&ctx->lock);
|
||||
|
||||
ctx->reset_counter = atomic_read(&adev->gpu_reset_counter);
|
||||
ctx->reset_counter_query = ctx->reset_counter;
|
||||
ctx->vram_lost_counter = atomic_read(&adev->vram_lost_counter);
|
||||
ctx->init_priority = priority;
|
||||
ctx->override_priority = AMDGPU_CTX_PRIORITY_UNSET;
|
||||
ctx->stable_pstate = AMDGPU_CTX_STABLE_PSTATE_NONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -255,6 +255,86 @@ static void amdgpu_ctx_fini_entity(struct amdgpu_ctx_entity *entity)
|
||||
kfree(entity);
|
||||
}
|
||||
|
||||
static int amdgpu_ctx_get_stable_pstate(struct amdgpu_ctx *ctx,
|
||||
u32 *stable_pstate)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx->adev;
|
||||
enum amd_dpm_forced_level current_level;
|
||||
|
||||
if (!ctx)
|
||||
return -EINVAL;
|
||||
|
||||
current_level = amdgpu_dpm_get_performance_level(adev);
|
||||
|
||||
switch (current_level) {
|
||||
case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
|
||||
*stable_pstate = AMDGPU_CTX_STABLE_PSTATE_STANDARD;
|
||||
break;
|
||||
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
|
||||
*stable_pstate = AMDGPU_CTX_STABLE_PSTATE_MIN_SCLK;
|
||||
break;
|
||||
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
|
||||
*stable_pstate = AMDGPU_CTX_STABLE_PSTATE_MIN_MCLK;
|
||||
break;
|
||||
case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
|
||||
*stable_pstate = AMDGPU_CTX_STABLE_PSTATE_PEAK;
|
||||
break;
|
||||
default:
|
||||
*stable_pstate = AMDGPU_CTX_STABLE_PSTATE_NONE;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx,
|
||||
u32 stable_pstate)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx->adev;
|
||||
enum amd_dpm_forced_level level;
|
||||
int r;
|
||||
|
||||
if (!ctx)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&adev->pm.stable_pstate_ctx_lock);
|
||||
if (adev->pm.stable_pstate_ctx && adev->pm.stable_pstate_ctx != ctx) {
|
||||
r = -EBUSY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch (stable_pstate) {
|
||||
case AMDGPU_CTX_STABLE_PSTATE_NONE:
|
||||
level = AMD_DPM_FORCED_LEVEL_AUTO;
|
||||
break;
|
||||
case AMDGPU_CTX_STABLE_PSTATE_STANDARD:
|
||||
level = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD;
|
||||
break;
|
||||
case AMDGPU_CTX_STABLE_PSTATE_MIN_SCLK:
|
||||
level = AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK;
|
||||
break;
|
||||
case AMDGPU_CTX_STABLE_PSTATE_MIN_MCLK:
|
||||
level = AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK;
|
||||
break;
|
||||
case AMDGPU_CTX_STABLE_PSTATE_PEAK:
|
||||
level = AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
|
||||
break;
|
||||
default:
|
||||
r = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
r = amdgpu_dpm_force_performance_level(adev, level);
|
||||
|
||||
if (level == AMD_DPM_FORCED_LEVEL_AUTO)
|
||||
adev->pm.stable_pstate_ctx = NULL;
|
||||
else
|
||||
adev->pm.stable_pstate_ctx = ctx;
|
||||
done:
|
||||
mutex_unlock(&adev->pm.stable_pstate_ctx_lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void amdgpu_ctx_fini(struct kref *ref)
|
||||
{
|
||||
struct amdgpu_ctx *ctx = container_of(ref, struct amdgpu_ctx, refcount);
|
||||
@ -270,8 +350,7 @@ static void amdgpu_ctx_fini(struct kref *ref)
|
||||
ctx->entities[i][j] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_destroy(&ctx->lock);
|
||||
amdgpu_ctx_set_stable_pstate(ctx, AMDGPU_CTX_STABLE_PSTATE_NONE);
|
||||
kfree(ctx);
|
||||
}
|
||||
|
||||
@ -467,11 +546,41 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int amdgpu_ctx_stable_pstate(struct amdgpu_device *adev,
|
||||
struct amdgpu_fpriv *fpriv, uint32_t id,
|
||||
bool set, u32 *stable_pstate)
|
||||
{
|
||||
struct amdgpu_ctx *ctx;
|
||||
struct amdgpu_ctx_mgr *mgr;
|
||||
int r;
|
||||
|
||||
if (!fpriv)
|
||||
return -EINVAL;
|
||||
|
||||
mgr = &fpriv->ctx_mgr;
|
||||
mutex_lock(&mgr->lock);
|
||||
ctx = idr_find(&mgr->ctx_handles, id);
|
||||
if (!ctx) {
|
||||
mutex_unlock(&mgr->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (set)
|
||||
r = amdgpu_ctx_set_stable_pstate(ctx, *stable_pstate);
|
||||
else
|
||||
r = amdgpu_ctx_get_stable_pstate(ctx, stable_pstate);
|
||||
|
||||
mutex_unlock(&mgr->lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *filp)
|
||||
{
|
||||
int r;
|
||||
uint32_t id;
|
||||
uint32_t id, stable_pstate;
|
||||
int32_t priority;
|
||||
|
||||
union drm_amdgpu_ctx *args = data;
|
||||
@ -500,6 +609,20 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
|
||||
case AMDGPU_CTX_OP_QUERY_STATE2:
|
||||
r = amdgpu_ctx_query2(adev, fpriv, id, &args->out);
|
||||
break;
|
||||
case AMDGPU_CTX_OP_GET_STABLE_PSTATE:
|
||||
if (args->in.flags)
|
||||
return -EINVAL;
|
||||
r = amdgpu_ctx_stable_pstate(adev, fpriv, id, false, &stable_pstate);
|
||||
args->out.pstate.flags = stable_pstate;
|
||||
break;
|
||||
case AMDGPU_CTX_OP_SET_STABLE_PSTATE:
|
||||
if (args->in.flags & ~AMDGPU_CTX_STABLE_PSTATE_FLAGS_MASK)
|
||||
return -EINVAL;
|
||||
stable_pstate = args->in.flags & AMDGPU_CTX_STABLE_PSTATE_FLAGS_MASK;
|
||||
if (stable_pstate > AMDGPU_CTX_STABLE_PSTATE_PEAK)
|
||||
return -EINVAL;
|
||||
r = amdgpu_ctx_stable_pstate(adev, fpriv, id, true, &stable_pstate);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -49,10 +49,10 @@ struct amdgpu_ctx {
|
||||
bool preamble_presented;
|
||||
int32_t init_priority;
|
||||
int32_t override_priority;
|
||||
struct mutex lock;
|
||||
atomic_t guilty;
|
||||
unsigned long ras_counter_ce;
|
||||
unsigned long ras_counter_ue;
|
||||
uint32_t stable_pstate;
|
||||
};
|
||||
|
||||
struct amdgpu_ctx_mgr {
|
||||
|
@ -1120,8 +1120,10 @@ static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf,
|
||||
return -EINVAL;
|
||||
|
||||
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
while (size) {
|
||||
uint32_t value;
|
||||
@ -1585,22 +1587,25 @@ static int amdgpu_debugfs_sclk_set(void *data, u64 val)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (is_support_sw_smu(adev)) {
|
||||
ret = smu_get_dpm_freq_range(&adev->smu, SMU_SCLK, &min_freq, &max_freq);
|
||||
if (ret || val > max_freq || val < min_freq)
|
||||
return -EINVAL;
|
||||
ret = smu_set_soft_freq_range(&adev->smu, SMU_SCLK, (uint32_t)val, (uint32_t)val);
|
||||
} else {
|
||||
return 0;
|
||||
ret = amdgpu_dpm_get_dpm_freq_range(adev, PP_SCLK, &min_freq, &max_freq);
|
||||
if (ret == -EOPNOTSUPP) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
if (ret || val > max_freq || val < min_freq) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = amdgpu_dpm_set_soft_freq_range(adev, PP_SCLK, (uint32_t)val, (uint32_t)val);
|
||||
if (ret)
|
||||
ret = -EINVAL;
|
||||
|
||||
out:
|
||||
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
|
||||
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
|
||||
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_ib_preempt, NULL,
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <linux/console.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
@ -55,7 +56,6 @@
|
||||
#include "soc15.h"
|
||||
#include "nv.h"
|
||||
#include "bif/bif_4_1_d.h"
|
||||
#include <linux/pci.h>
|
||||
#include <linux/firmware.h>
|
||||
#include "amdgpu_vf_error.h"
|
||||
|
||||
@ -566,7 +566,7 @@ void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
|
||||
adev->gfx.rlc.funcs &&
|
||||
adev->gfx.rlc.funcs->is_rlcg_access_range) {
|
||||
if (adev->gfx.rlc.funcs->is_rlcg_access_range(adev, reg))
|
||||
return adev->gfx.rlc.funcs->sriov_wreg(adev, reg, v, 0, 0);
|
||||
return amdgpu_sriov_wreg(adev, reg, v, 0, 0);
|
||||
} else if ((reg * 4) >= adev->rmmio_size) {
|
||||
adev->pcie_wreg(adev, reg * 4, v);
|
||||
} else {
|
||||
@ -2073,6 +2073,8 @@ out:
|
||||
*/
|
||||
static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct drm_device *dev = adev_to_drm(adev);
|
||||
struct pci_dev *parent;
|
||||
int i, r;
|
||||
|
||||
amdgpu_device_enable_virtual_display(adev);
|
||||
@ -2137,6 +2139,16 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
||||
break;
|
||||
}
|
||||
|
||||
if (amdgpu_has_atpx() &&
|
||||
(amdgpu_is_atpx_hybrid() ||
|
||||
amdgpu_has_atpx_dgpu_power_cntl()) &&
|
||||
((adev->flags & AMD_IS_APU) == 0) &&
|
||||
!pci_is_thunderbolt_attached(to_pci_dev(dev->dev)))
|
||||
adev->flags |= AMD_IS_PX;
|
||||
|
||||
parent = pci_upstream_bridge(adev->pdev);
|
||||
adev->has_pr3 = parent ? pci_pr3_present(parent) : false;
|
||||
|
||||
amdgpu_amdkfd_device_probe(adev);
|
||||
|
||||
adev->pm.pp_feature = amdgpu_pp_feature_mask;
|
||||
@ -2624,7 +2636,7 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
|
||||
/* For passthrough configuration on arcturus and aldebaran, enable special handling SBR */
|
||||
if (amdgpu_passthrough(adev) && ((adev->asic_type == CHIP_ARCTURUS && adev->gmc.xgmi.num_physical_nodes > 1)||
|
||||
adev->asic_type == CHIP_ALDEBARAN ))
|
||||
smu_handle_passthrough_sbr(&adev->smu, true);
|
||||
amdgpu_dpm_handle_passthrough_sbr(adev, true);
|
||||
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
mutex_lock(&mgpu_info.mutex);
|
||||
@ -2708,11 +2720,11 @@ static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
amdgpu_amdkfd_suspend(adev, false);
|
||||
|
||||
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
|
||||
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
|
||||
|
||||
amdgpu_amdkfd_suspend(adev, false);
|
||||
|
||||
/* Workaroud for ASICs need to disable SMC first */
|
||||
amdgpu_device_smu_fini_early(adev);
|
||||
|
||||
@ -2881,7 +2893,7 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
|
||||
int i, r;
|
||||
|
||||
if (adev->in_s0ix)
|
||||
amdgpu_gfx_state_change_set(adev, sGpuChangeState_D3Entry);
|
||||
amdgpu_dpm_gfx_state_change(adev, sGpuChangeState_D3Entry);
|
||||
|
||||
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
|
||||
if (!adev->ip_blocks[i].status.valid)
|
||||
@ -3307,9 +3319,9 @@ static void amdgpu_device_xgmi_reset_func(struct work_struct *__work)
|
||||
if (adev->asic_reset_res)
|
||||
goto fail;
|
||||
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->reset_ras_error_count)
|
||||
adev->mmhub.ras_funcs->reset_ras_error_count(adev);
|
||||
if (adev->mmhub.ras && adev->mmhub.ras->ras_block.hw_ops &&
|
||||
adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count)
|
||||
adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count(adev);
|
||||
} else {
|
||||
|
||||
task_barrier_full(&hive->tb);
|
||||
@ -3497,8 +3509,9 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
init_rwsem(&adev->reset_sem);
|
||||
mutex_init(&adev->psp.mutex);
|
||||
mutex_init(&adev->notifier_lock);
|
||||
mutex_init(&adev->pm.stable_pstate_ctx_lock);
|
||||
|
||||
amdgpu_device_init_apu_flags(adev);
|
||||
amdgpu_device_init_apu_flags(adev);
|
||||
|
||||
r = amdgpu_device_check_arguments(adev);
|
||||
if (r)
|
||||
@ -3519,6 +3532,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
|
||||
INIT_LIST_HEAD(&adev->reset_list);
|
||||
|
||||
INIT_LIST_HEAD(&adev->ras_list);
|
||||
|
||||
INIT_DELAYED_WORK(&adev->delayed_init_work,
|
||||
amdgpu_device_delayed_init_work_handler);
|
||||
INIT_DELAYED_WORK(&adev->gfx.gfx_off_delay_work,
|
||||
@ -4044,7 +4059,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
|
||||
return 0;
|
||||
|
||||
if (adev->in_s0ix)
|
||||
amdgpu_gfx_state_change_set(adev, sGpuChangeState_D0Entry);
|
||||
amdgpu_dpm_gfx_state_change(adev, sGpuChangeState_D0Entry);
|
||||
|
||||
/* post card */
|
||||
if (amdgpu_device_need_post(adev)) {
|
||||
@ -4645,9 +4660,9 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle,
|
||||
|
||||
if (!r && amdgpu_ras_intr_triggered()) {
|
||||
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
|
||||
if (tmp_adev->mmhub.ras_funcs &&
|
||||
tmp_adev->mmhub.ras_funcs->reset_ras_error_count)
|
||||
tmp_adev->mmhub.ras_funcs->reset_ras_error_count(tmp_adev);
|
||||
if (tmp_adev->mmhub.ras && tmp_adev->mmhub.ras->ras_block.hw_ops &&
|
||||
tmp_adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count)
|
||||
tmp_adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count(tmp_adev);
|
||||
}
|
||||
|
||||
amdgpu_ras_intr_cleared();
|
||||
@ -5726,3 +5741,36 @@ void amdgpu_device_halt(struct amdgpu_device *adev)
|
||||
pci_disable_device(pdev);
|
||||
pci_wait_for_pending_transaction(pdev);
|
||||
}
|
||||
|
||||
u32 amdgpu_device_pcie_port_rreg(struct amdgpu_device *adev,
|
||||
u32 reg)
|
||||
{
|
||||
unsigned long flags, address, data;
|
||||
u32 r;
|
||||
|
||||
address = adev->nbio.funcs->get_pcie_port_index_offset(adev);
|
||||
data = adev->nbio.funcs->get_pcie_port_data_offset(adev);
|
||||
|
||||
spin_lock_irqsave(&adev->pcie_idx_lock, flags);
|
||||
WREG32(address, reg * 4);
|
||||
(void)RREG32(address);
|
||||
r = RREG32(data);
|
||||
spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
void amdgpu_device_pcie_port_wreg(struct amdgpu_device *adev,
|
||||
u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags, address, data;
|
||||
|
||||
address = adev->nbio.funcs->get_pcie_port_index_offset(adev);
|
||||
data = adev->nbio.funcs->get_pcie_port_data_offset(adev);
|
||||
|
||||
spin_lock_irqsave(&adev->pcie_idx_lock, flags);
|
||||
WREG32(address, reg * 4);
|
||||
(void)RREG32(address);
|
||||
WREG32(data, v);
|
||||
(void)RREG32(data);
|
||||
spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
|
||||
}
|
||||
|
@ -674,6 +674,7 @@ static int amdgpu_discovery_set_common_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(10, 1, 1):
|
||||
case IP_VERSION(10, 1, 2):
|
||||
case IP_VERSION(10, 1, 3):
|
||||
case IP_VERSION(10, 1, 4):
|
||||
case IP_VERSION(10, 3, 0):
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 2):
|
||||
@ -709,6 +710,7 @@ static int amdgpu_discovery_set_gmc_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(10, 1, 1):
|
||||
case IP_VERSION(10, 1, 2):
|
||||
case IP_VERSION(10, 1, 3):
|
||||
case IP_VERSION(10, 1, 4):
|
||||
case IP_VERSION(10, 3, 0):
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 2):
|
||||
@ -846,8 +848,14 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) {
|
||||
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!amdgpu_device_has_dc_support(adev))
|
||||
return 0;
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC)
|
||||
} else if (adev->ip_versions[DCE_HWIP][0]) {
|
||||
if (adev->ip_versions[DCE_HWIP][0]) {
|
||||
switch (adev->ip_versions[DCE_HWIP][0]) {
|
||||
case IP_VERSION(1, 0, 0):
|
||||
case IP_VERSION(1, 0, 1):
|
||||
@ -882,8 +890,8 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
|
||||
adev->ip_versions[DCI_HWIP][0]);
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -904,6 +912,7 @@ static int amdgpu_discovery_set_gc_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(10, 1, 2):
|
||||
case IP_VERSION(10, 1, 1):
|
||||
case IP_VERSION(10, 1, 3):
|
||||
case IP_VERSION(10, 1, 4):
|
||||
case IP_VERSION(10, 3, 0):
|
||||
case IP_VERSION(10, 3, 2):
|
||||
case IP_VERSION(10, 3, 1):
|
||||
@ -1038,6 +1047,7 @@ static int amdgpu_discovery_set_mes_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(10, 1, 1):
|
||||
case IP_VERSION(10, 1, 2):
|
||||
case IP_VERSION(10, 1, 3):
|
||||
case IP_VERSION(10, 1, 4):
|
||||
case IP_VERSION(10, 3, 0):
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 2):
|
||||
@ -1217,11 +1227,6 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
return -EINVAL;
|
||||
|
||||
amdgpu_discovery_harvest_ip(adev);
|
||||
|
||||
if (!adev->mman.discovery_bin) {
|
||||
DRM_ERROR("ip discovery uninitialized\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1242,6 +1247,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(10, 1, 1):
|
||||
case IP_VERSION(10, 1, 2):
|
||||
case IP_VERSION(10, 1, 3):
|
||||
case IP_VERSION(10, 1, 4):
|
||||
case IP_VERSION(10, 3, 0):
|
||||
case IP_VERSION(10, 3, 2):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
@ -1258,6 +1264,20 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (adev->ip_versions[GC_HWIP][0]) {
|
||||
case IP_VERSION(9, 1, 0):
|
||||
case IP_VERSION(9, 2, 2):
|
||||
case IP_VERSION(9, 3, 0):
|
||||
case IP_VERSION(10, 1, 3):
|
||||
case IP_VERSION(10, 1, 4):
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
adev->flags |= AMD_IS_APU;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (adev->ip_versions[XGMI_HWIP][0] == IP_VERSION(4, 8, 0))
|
||||
adev->gmc.xgmi.supported = true;
|
||||
|
||||
|
@ -512,19 +512,24 @@ uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev,
|
||||
case CHIP_STONEY:
|
||||
domain |= AMDGPU_GEM_DOMAIN_GTT;
|
||||
break;
|
||||
case CHIP_RAVEN:
|
||||
/* enable S/G on PCO and RV2 */
|
||||
if ((adev->apu_flags & AMD_APU_IS_RAVEN2) ||
|
||||
(adev->apu_flags & AMD_APU_IS_PICASSO))
|
||||
domain |= AMDGPU_GEM_DOMAIN_GTT;
|
||||
break;
|
||||
case CHIP_RENOIR:
|
||||
case CHIP_VANGOGH:
|
||||
case CHIP_YELLOW_CARP:
|
||||
domain |= AMDGPU_GEM_DOMAIN_GTT;
|
||||
break;
|
||||
|
||||
default:
|
||||
switch (adev->ip_versions[DCE_HWIP][0]) {
|
||||
case IP_VERSION(1, 0, 0):
|
||||
case IP_VERSION(1, 0, 1):
|
||||
/* enable S/G on PCO and RV2 */
|
||||
if ((adev->apu_flags & AMD_APU_IS_RAVEN2) ||
|
||||
(adev->apu_flags & AMD_APU_IS_PICASSO))
|
||||
domain |= AMDGPU_GEM_DOMAIN_GTT;
|
||||
break;
|
||||
case IP_VERSION(2, 1, 0):
|
||||
case IP_VERSION(3, 0, 1):
|
||||
case IP_VERSION(3, 1, 2):
|
||||
case IP_VERSION(3, 1, 3):
|
||||
domain |= AMDGPU_GEM_DOMAIN_GTT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -99,9 +99,10 @@
|
||||
* - 3.42.0 - Add 16bpc fixed point display support
|
||||
* - 3.43.0 - Add device hot plug/unplug support
|
||||
* - 3.44.0 - DCN3 supports DCC independent block settings: !64B && 128B, 64B && 128B
|
||||
* - 3.45.0 - Add context ioctl stable pstate interface
|
||||
*/
|
||||
#define KMS_DRIVER_MAJOR 3
|
||||
#define KMS_DRIVER_MINOR 44
|
||||
#define KMS_DRIVER_MINOR 45
|
||||
#define KMS_DRIVER_PATCHLEVEL 0
|
||||
|
||||
int amdgpu_vram_limit;
|
||||
@ -174,7 +175,6 @@ int amdgpu_mes;
|
||||
int amdgpu_noretry = -1;
|
||||
int amdgpu_force_asic_type = -1;
|
||||
int amdgpu_tmz = -1; /* auto */
|
||||
uint amdgpu_freesync_vid_mode;
|
||||
int amdgpu_reset_method = -1; /* auto */
|
||||
int amdgpu_num_kcq = -1;
|
||||
int amdgpu_smartshift_bias;
|
||||
@ -843,32 +843,6 @@ module_param_named(backlight, amdgpu_backlight, bint, 0444);
|
||||
MODULE_PARM_DESC(tmz, "Enable TMZ feature (-1 = auto (default), 0 = off, 1 = on)");
|
||||
module_param_named(tmz, amdgpu_tmz, int, 0444);
|
||||
|
||||
/**
|
||||
* DOC: freesync_video (uint)
|
||||
* Enable the optimization to adjust front porch timing to achieve seamless
|
||||
* mode change experience when setting a freesync supported mode for which full
|
||||
* modeset is not needed.
|
||||
*
|
||||
* The Display Core will add a set of modes derived from the base FreeSync
|
||||
* video mode into the corresponding connector's mode list based on commonly
|
||||
* used refresh rates and VRR range of the connected display, when users enable
|
||||
* this feature. From the userspace perspective, they can see a seamless mode
|
||||
* change experience when the change between different refresh rates under the
|
||||
* same resolution. Additionally, userspace applications such as Video playback
|
||||
* can read this modeset list and change the refresh rate based on the video
|
||||
* frame rate. Finally, the userspace can also derive an appropriate mode for a
|
||||
* particular refresh rate based on the FreeSync Mode and add it to the
|
||||
* connector's mode list.
|
||||
*
|
||||
* Note: This is an experimental feature.
|
||||
*
|
||||
* The default value: 0 (off).
|
||||
*/
|
||||
MODULE_PARM_DESC(
|
||||
freesync_video,
|
||||
"Enable freesync modesetting optimization feature (0 = off (default), 1 = on)");
|
||||
module_param_named(freesync_video, amdgpu_freesync_vid_mode, uint, 0444);
|
||||
|
||||
/**
|
||||
* DOC: reset_method (int)
|
||||
* GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco, 5 = pci)
|
||||
@ -1942,10 +1916,10 @@ static const struct pci_device_id pciidlist[] = {
|
||||
{0x1002, 0x73FF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
|
||||
|
||||
/* Aldebaran */
|
||||
{0x1002, 0x7408, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT},
|
||||
{0x1002, 0x740C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT},
|
||||
{0x1002, 0x740F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT},
|
||||
{0x1002, 0x7410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT},
|
||||
{0x1002, 0x7408, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN},
|
||||
{0x1002, 0x740C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN},
|
||||
{0x1002, 0x740F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN},
|
||||
{0x1002, 0x7410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN},
|
||||
|
||||
/* CYAN_SKILLFISH */
|
||||
{0x1002, 0x13FE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
|
||||
@ -1994,6 +1968,28 @@ static bool amdgpu_is_fw_framebuffer(resource_size_t base,
|
||||
return found;
|
||||
}
|
||||
|
||||
static void amdgpu_get_secondary_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
struct pci_dev *p = NULL;
|
||||
int i;
|
||||
|
||||
/* 0 - GPU
|
||||
* 1 - audio
|
||||
* 2 - USB
|
||||
* 3 - UCSI
|
||||
*/
|
||||
for (i = 1; i < 4; i++) {
|
||||
p = pci_get_domain_bus_and_slot(pci_domain_nr(adev->pdev->bus),
|
||||
adev->pdev->bus->number, i);
|
||||
if (p) {
|
||||
pm_runtime_get_sync(&p->dev);
|
||||
pm_runtime_mark_last_busy(&p->dev);
|
||||
pm_runtime_put_autosuspend(&p->dev);
|
||||
pci_dev_put(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int amdgpu_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
@ -2126,6 +2122,48 @@ retry_init:
|
||||
if (ret)
|
||||
DRM_ERROR("Creating debugfs files failed (%d).\n", ret);
|
||||
|
||||
if (adev->runpm) {
|
||||
/* only need to skip on ATPX */
|
||||
if (amdgpu_device_supports_px(ddev))
|
||||
dev_pm_set_driver_flags(ddev->dev, DPM_FLAG_NO_DIRECT_COMPLETE);
|
||||
/* we want direct complete for BOCO */
|
||||
if (amdgpu_device_supports_boco(ddev))
|
||||
dev_pm_set_driver_flags(ddev->dev, DPM_FLAG_SMART_PREPARE |
|
||||
DPM_FLAG_SMART_SUSPEND |
|
||||
DPM_FLAG_MAY_SKIP_RESUME);
|
||||
pm_runtime_use_autosuspend(ddev->dev);
|
||||
pm_runtime_set_autosuspend_delay(ddev->dev, 5000);
|
||||
|
||||
pm_runtime_allow(ddev->dev);
|
||||
|
||||
pm_runtime_mark_last_busy(ddev->dev);
|
||||
pm_runtime_put_autosuspend(ddev->dev);
|
||||
|
||||
/*
|
||||
* For runpm implemented via BACO, PMFW will handle the
|
||||
* timing for BACO in and out:
|
||||
* - put ASIC into BACO state only when both video and
|
||||
* audio functions are in D3 state.
|
||||
* - pull ASIC out of BACO state when either video or
|
||||
* audio function is in D0 state.
|
||||
* Also, at startup, PMFW assumes both functions are in
|
||||
* D0 state.
|
||||
*
|
||||
* So if snd driver was loaded prior to amdgpu driver
|
||||
* and audio function was put into D3 state, there will
|
||||
* be no PMFW-aware D-state transition(D0->D3) on runpm
|
||||
* suspend. Thus the BACO will be not correctly kicked in.
|
||||
*
|
||||
* Via amdgpu_get_secondary_funcs(), the audio dev is put
|
||||
* into D0 state. Then there will be a PMFW-aware D-state
|
||||
* transition(D0->D3) on runpm suspend.
|
||||
*/
|
||||
if (amdgpu_device_supports_baco(ddev) &&
|
||||
!(adev->flags & AMD_IS_APU) &&
|
||||
(adev->asic_type >= CHIP_NAVI10))
|
||||
amdgpu_get_secondary_funcs(adev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_pci:
|
||||
@ -2137,8 +2175,15 @@ static void
|
||||
amdgpu_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
|
||||
drm_dev_unplug(dev);
|
||||
|
||||
if (adev->runpm) {
|
||||
pm_runtime_get_sync(dev->dev);
|
||||
pm_runtime_forbid(dev->dev);
|
||||
}
|
||||
|
||||
amdgpu_driver_unload_kms(dev);
|
||||
|
||||
/*
|
||||
@ -2246,13 +2291,20 @@ static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work)
|
||||
static int amdgpu_pmops_prepare(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(drm_dev);
|
||||
|
||||
/* Return a positive number here so
|
||||
* DPM_FLAG_SMART_SUSPEND works properly
|
||||
*/
|
||||
if (amdgpu_device_supports_boco(drm_dev))
|
||||
return pm_runtime_suspended(dev) &&
|
||||
pm_suspend_via_firmware();
|
||||
return pm_runtime_suspended(dev);
|
||||
|
||||
/* if we will not support s3 or s2i for the device
|
||||
* then skip suspend
|
||||
*/
|
||||
if (!amdgpu_acpi_is_s0ix_active(adev) &&
|
||||
!amdgpu_acpi_is_s3_active(adev))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "amdgpu_eeprom.h"
|
||||
|
||||
#define FRU_EEPROM_MADDR 0x60000
|
||||
#define I2C_PRODUCT_INFO_OFFSET 0xC0
|
||||
|
||||
static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
|
||||
{
|
||||
@ -40,7 +39,13 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
|
||||
*/
|
||||
struct atom_context *atom_ctx = adev->mode_info.atom_context;
|
||||
|
||||
/* VBIOS is of the format ###-DXXXYY-##. For SKU identification,
|
||||
/* The i2c access is blocked on VF
|
||||
* TODO: Need other way to get the info
|
||||
*/
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return false;
|
||||
|
||||
/* VBIOS is of the format ###-DXXXYYYY-##. For SKU identification,
|
||||
* we can use just the "DXXX" portion. If there were more models, we
|
||||
* could convert the 3 characters to a hex integer and use a switch
|
||||
* for ease/speed/readability. For now, 2 string comparisons are
|
||||
@ -59,17 +64,24 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
|
||||
case CHIP_ALDEBARAN:
|
||||
/* All Aldebaran SKUs have the FRU */
|
||||
return true;
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
if (strnstr(atom_ctx->vbios_version, "D603",
|
||||
sizeof(atom_ctx->vbios_version)))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
|
||||
unsigned char *buff)
|
||||
unsigned char *buf, size_t buf_size)
|
||||
{
|
||||
int ret, size;
|
||||
int ret;
|
||||
u8 size;
|
||||
|
||||
ret = amdgpu_eeprom_read(&adev->pm.smu_i2c, addrptr, buff, 1);
|
||||
ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr, buf, 1);
|
||||
if (ret < 1) {
|
||||
DRM_WARN("FRU: Failed to get size field");
|
||||
return ret;
|
||||
@ -78,9 +90,11 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
|
||||
/* The size returned by the i2c requires subtraction of 0xC0 since the
|
||||
* size apparently always reports as 0xC0+actual size.
|
||||
*/
|
||||
size = buff[0] - I2C_PRODUCT_INFO_OFFSET;
|
||||
size = buf[0] & 0x3F;
|
||||
size = min_t(size_t, size, buf_size);
|
||||
|
||||
ret = amdgpu_eeprom_read(&adev->pm.smu_i2c, addrptr + 1, buff, size);
|
||||
ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr + 1,
|
||||
buf, size);
|
||||
if (ret < 1) {
|
||||
DRM_WARN("FRU: Failed to get data field");
|
||||
return ret;
|
||||
@ -91,19 +105,15 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
|
||||
|
||||
int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
||||
{
|
||||
unsigned char buff[AMDGPU_PRODUCT_NAME_LEN+2];
|
||||
unsigned char buf[AMDGPU_PRODUCT_NAME_LEN];
|
||||
u32 addrptr;
|
||||
int size, len;
|
||||
int offset = 2;
|
||||
|
||||
if (!is_fru_eeprom_supported(adev))
|
||||
return 0;
|
||||
|
||||
if (adev->asic_type == CHIP_ALDEBARAN)
|
||||
offset = 0;
|
||||
|
||||
/* If algo exists, it means that the i2c_adapter's initialized */
|
||||
if (!adev->pm.smu_i2c.algo) {
|
||||
if (!adev->pm.fru_eeprom_i2c_bus || !adev->pm.fru_eeprom_i2c_bus->algo) {
|
||||
DRM_WARN("Cannot access FRU, EEPROM accessor not initialized");
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -121,7 +131,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
||||
* and the language field, so just start from 0xb, manufacturer size
|
||||
*/
|
||||
addrptr = FRU_EEPROM_MADDR + 0xb;
|
||||
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
|
||||
size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf));
|
||||
if (size < 1) {
|
||||
DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size);
|
||||
return -EINVAL;
|
||||
@ -131,7 +141,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
||||
* size field being 1 byte. This pattern continues below.
|
||||
*/
|
||||
addrptr += size + 1;
|
||||
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
|
||||
size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf));
|
||||
if (size < 1) {
|
||||
DRM_ERROR("Failed to read FRU product name, ret:%d", size);
|
||||
return -EINVAL;
|
||||
@ -143,12 +153,11 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
||||
AMDGPU_PRODUCT_NAME_LEN);
|
||||
len = AMDGPU_PRODUCT_NAME_LEN - 1;
|
||||
}
|
||||
/* Start at 2 due to buff using fields 0 and 1 for the address */
|
||||
memcpy(adev->product_name, &buff[offset], len);
|
||||
memcpy(adev->product_name, buf, len);
|
||||
adev->product_name[len] = '\0';
|
||||
|
||||
addrptr += size + 1;
|
||||
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
|
||||
size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf));
|
||||
if (size < 1) {
|
||||
DRM_ERROR("Failed to read FRU product number, ret:%d", size);
|
||||
return -EINVAL;
|
||||
@ -162,11 +171,11 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
||||
DRM_WARN("FRU Product Number is larger than 16 characters. This is likely a mistake");
|
||||
len = sizeof(adev->product_number) - 1;
|
||||
}
|
||||
memcpy(adev->product_number, &buff[offset], len);
|
||||
memcpy(adev->product_number, buf, len);
|
||||
adev->product_number[len] = '\0';
|
||||
|
||||
addrptr += size + 1;
|
||||
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
|
||||
size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf));
|
||||
|
||||
if (size < 1) {
|
||||
DRM_ERROR("Failed to read FRU product version, ret:%d", size);
|
||||
@ -174,7 +183,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
addrptr += size + 1;
|
||||
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
|
||||
size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf));
|
||||
|
||||
if (size < 1) {
|
||||
DRM_ERROR("Failed to read FRU serial number, ret:%d", size);
|
||||
@ -189,7 +198,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
||||
DRM_WARN("FRU Serial Number is larger than 16 characters. This is likely a mistake");
|
||||
len = sizeof(adev->serial) - 1;
|
||||
}
|
||||
memcpy(adev->serial, &buff[offset], len);
|
||||
memcpy(adev->serial, buf, len);
|
||||
adev->serial[len] = '\0';
|
||||
|
||||
return 0;
|
||||
|
@ -150,7 +150,7 @@ void amdgpu_gart_table_vram_free(struct amdgpu_device *adev)
|
||||
* replaces them with the dummy page (all asics).
|
||||
* Returns 0 for success, -EINVAL for failure.
|
||||
*/
|
||||
int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
|
||||
void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages)
|
||||
{
|
||||
unsigned t;
|
||||
@ -161,13 +161,11 @@ int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
|
||||
uint64_t flags = 0;
|
||||
int idx;
|
||||
|
||||
if (!adev->gart.ready) {
|
||||
WARN(1, "trying to unbind memory from uninitialized GART !\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!adev->gart.ptr)
|
||||
return;
|
||||
|
||||
if (!drm_dev_enter(adev_to_drm(adev), &idx))
|
||||
return 0;
|
||||
return;
|
||||
|
||||
t = offset / AMDGPU_GPU_PAGE_SIZE;
|
||||
p = t / AMDGPU_GPU_PAGES_IN_CPU_PAGE;
|
||||
@ -188,7 +186,6 @@ int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
|
||||
amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
|
||||
|
||||
drm_dev_exit(idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -204,7 +201,7 @@ int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
|
||||
* Map the dma_addresses into GART entries (all asics).
|
||||
* Returns 0 for success, -EINVAL for failure.
|
||||
*/
|
||||
int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
|
||||
void amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags,
|
||||
void *dst)
|
||||
{
|
||||
@ -212,13 +209,8 @@ int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
|
||||
unsigned i, j, t;
|
||||
int idx;
|
||||
|
||||
if (!adev->gart.ready) {
|
||||
WARN(1, "trying to bind memory to uninitialized GART !\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!drm_dev_enter(adev_to_drm(adev), &idx))
|
||||
return 0;
|
||||
return;
|
||||
|
||||
t = offset / AMDGPU_GPU_PAGE_SIZE;
|
||||
|
||||
@ -230,7 +222,6 @@ int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
|
||||
}
|
||||
}
|
||||
drm_dev_exit(idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -246,20 +237,14 @@ int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
|
||||
* (all asics).
|
||||
* Returns 0 for success, -EINVAL for failure.
|
||||
*/
|
||||
int amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset,
|
||||
void amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr,
|
||||
uint64_t flags)
|
||||
{
|
||||
if (!adev->gart.ready) {
|
||||
WARN(1, "trying to bind memory to uninitialized GART !\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!adev->gart.ptr)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
return amdgpu_gart_map(adev, offset, pages, dma_addr, flags,
|
||||
adev->gart.ptr);
|
||||
amdgpu_gart_map(adev, offset, pages, dma_addr, flags, adev->gart.ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -274,6 +259,9 @@ void amdgpu_gart_invalidate_tlb(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!adev->gart.ptr)
|
||||
return;
|
||||
|
||||
mb();
|
||||
amdgpu_device_flush_hdp(adev, NULL);
|
||||
for (i = 0; i < adev->num_vmhubs; i++)
|
||||
|
@ -46,7 +46,6 @@ struct amdgpu_gart {
|
||||
unsigned num_gpu_pages;
|
||||
unsigned num_cpu_pages;
|
||||
unsigned table_size;
|
||||
bool ready;
|
||||
|
||||
/* Asic default pte flags */
|
||||
uint64_t gart_pte_flags;
|
||||
@ -58,12 +57,12 @@ int amdgpu_gart_table_vram_pin(struct amdgpu_device *adev);
|
||||
void amdgpu_gart_table_vram_unpin(struct amdgpu_device *adev);
|
||||
int amdgpu_gart_init(struct amdgpu_device *adev);
|
||||
void amdgpu_gart_dummy_page_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages);
|
||||
int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags,
|
||||
void *dst);
|
||||
int amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags);
|
||||
void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages);
|
||||
void amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags,
|
||||
void *dst);
|
||||
void amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags);
|
||||
void amdgpu_gart_invalidate_tlb(struct amdgpu_device *adev);
|
||||
#endif
|
||||
|
@ -222,7 +222,7 @@ static void amdgpu_gem_object_close(struct drm_gem_object *obj,
|
||||
if (!bo_va || --bo_va->ref_count)
|
||||
goto out_unlock;
|
||||
|
||||
amdgpu_vm_bo_rmv(adev, bo_va);
|
||||
amdgpu_vm_bo_del(adev, bo_va);
|
||||
if (!amdgpu_vm_ready(vm))
|
||||
goto out_unlock;
|
||||
|
||||
|
@ -615,14 +615,14 @@ int amdgpu_get_gfx_off_status(struct amdgpu_device *adev, uint32_t *value)
|
||||
|
||||
mutex_lock(&adev->gfx.gfx_off_mutex);
|
||||
|
||||
r = smu_get_status_gfxoff(adev, value);
|
||||
r = amdgpu_dpm_get_status_gfxoff(adev, value);
|
||||
|
||||
mutex_unlock(&adev->gfx.gfx_off_mutex);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev)
|
||||
int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev, void *ras_info)
|
||||
{
|
||||
int r;
|
||||
struct ras_fs_if fs_info = {
|
||||
@ -695,9 +695,9 @@ int amdgpu_gfx_process_ras_data_cb(struct amdgpu_device *adev,
|
||||
*/
|
||||
if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX)) {
|
||||
kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->query_ras_error_count)
|
||||
adev->gfx.ras_funcs->query_ras_error_count(adev, err_data);
|
||||
if (adev->gfx.ras && adev->gfx.ras->ras_block.hw_ops &&
|
||||
adev->gfx.ras->ras_block.hw_ops->query_ras_error_count)
|
||||
adev->gfx.ras->ras_block.hw_ops->query_ras_error_count(adev, err_data);
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
}
|
||||
return AMDGPU_RAS_SUCCESS;
|
||||
@ -852,19 +852,3 @@ int amdgpu_gfx_get_num_kcq(struct amdgpu_device *adev)
|
||||
}
|
||||
return amdgpu_num_kcq;
|
||||
}
|
||||
|
||||
/* amdgpu_gfx_state_change_set - Handle gfx power state change set
|
||||
* @adev: amdgpu_device pointer
|
||||
* @state: gfx power state(1 -sGpuChangeState_D0Entry and 2 -sGpuChangeState_D3Entry)
|
||||
*
|
||||
*/
|
||||
|
||||
void amdgpu_gfx_state_change_set(struct amdgpu_device *adev, enum gfx_change_state state)
|
||||
{
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
if (adev->powerplay.pp_funcs &&
|
||||
adev->powerplay.pp_funcs->gfx_state_change_set)
|
||||
((adev)->powerplay.pp_funcs->gfx_state_change_set(
|
||||
(adev)->powerplay.pp_handle, state));
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "amdgpu_ring.h"
|
||||
#include "amdgpu_rlc.h"
|
||||
#include "soc15.h"
|
||||
#include "amdgpu_ras.h"
|
||||
|
||||
/* GFX current status */
|
||||
#define AMDGPU_GFX_NORMAL_MODE 0x00000000L
|
||||
@ -47,12 +48,6 @@ enum amdgpu_gfx_pipe_priority {
|
||||
AMDGPU_GFX_PIPE_PRIO_HIGH = AMDGPU_RING_PRIO_2
|
||||
};
|
||||
|
||||
/* Argument for PPSMC_MSG_GpuChangeState */
|
||||
enum gfx_change_state {
|
||||
sGpuChangeState_D0Entry = 1,
|
||||
sGpuChangeState_D3Entry,
|
||||
};
|
||||
|
||||
#define AMDGPU_GFX_QUEUE_PRIORITY_MINIMUM 0
|
||||
#define AMDGPU_GFX_QUEUE_PRIORITY_MAXIMUM 15
|
||||
|
||||
@ -204,16 +199,8 @@ struct amdgpu_cu_info {
|
||||
uint32_t bitmap[4][4];
|
||||
};
|
||||
|
||||
struct amdgpu_gfx_ras_funcs {
|
||||
int (*ras_late_init)(struct amdgpu_device *adev);
|
||||
void (*ras_fini)(struct amdgpu_device *adev);
|
||||
int (*ras_error_inject)(struct amdgpu_device *adev,
|
||||
void *inject_if);
|
||||
int (*query_ras_error_count)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
void (*reset_ras_error_count)(struct amdgpu_device *adev);
|
||||
void (*query_ras_error_status)(struct amdgpu_device *adev);
|
||||
void (*reset_ras_error_status)(struct amdgpu_device *adev);
|
||||
struct amdgpu_gfx_ras {
|
||||
struct amdgpu_ras_block_object ras_block;
|
||||
void (*enable_watchdog_timer)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
@ -337,7 +324,7 @@ struct amdgpu_gfx {
|
||||
|
||||
/*ras */
|
||||
struct ras_common_if *ras_if;
|
||||
const struct amdgpu_gfx_ras_funcs *ras_funcs;
|
||||
struct amdgpu_gfx_ras *ras;
|
||||
};
|
||||
|
||||
#define amdgpu_gfx_get_gpu_clock_counter(adev) (adev)->gfx.funcs->get_gpu_clock_counter((adev))
|
||||
@ -399,7 +386,7 @@ bool amdgpu_gfx_is_me_queue_enabled(struct amdgpu_device *adev, int me,
|
||||
int pipe, int queue);
|
||||
void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable);
|
||||
int amdgpu_get_gfx_off_status(struct amdgpu_device *adev, uint32_t *value);
|
||||
int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev);
|
||||
int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev, void *ras_info);
|
||||
void amdgpu_gfx_ras_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_gfx_process_ras_data_cb(struct amdgpu_device *adev,
|
||||
void *err_data,
|
||||
@ -410,5 +397,4 @@ int amdgpu_gfx_cp_ecc_error_irq(struct amdgpu_device *adev,
|
||||
uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg);
|
||||
void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v);
|
||||
int amdgpu_gfx_get_num_kcq(struct amdgpu_device *adev);
|
||||
void amdgpu_gfx_state_change_set(struct amdgpu_device *adev, enum gfx_change_state state);
|
||||
#endif
|
||||
|
@ -436,58 +436,58 @@ void amdgpu_gmc_filter_faults_remove(struct amdgpu_device *adev, uint64_t addr,
|
||||
} while (fault->timestamp < tmp);
|
||||
}
|
||||
|
||||
int amdgpu_gmc_ras_early_init(struct amdgpu_device *adev)
|
||||
{
|
||||
if (!adev->gmc.xgmi.connected_to_cpu) {
|
||||
adev->gmc.xgmi.ras = &xgmi_ras;
|
||||
amdgpu_ras_register_ras_block(adev, &adev->gmc.xgmi.ras->ras_block);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->ras_late_init) {
|
||||
r = adev->umc.ras_funcs->ras_late_init(adev);
|
||||
if (adev->umc.ras && adev->umc.ras->ras_block.ras_late_init) {
|
||||
r = adev->umc.ras->ras_block.ras_late_init(adev, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->ras_late_init) {
|
||||
r = adev->mmhub.ras_funcs->ras_late_init(adev);
|
||||
if (adev->mmhub.ras && adev->mmhub.ras->ras_block.ras_late_init) {
|
||||
r = adev->mmhub.ras->ras_block.ras_late_init(adev, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!adev->gmc.xgmi.connected_to_cpu)
|
||||
adev->gmc.xgmi.ras_funcs = &xgmi_ras_funcs;
|
||||
|
||||
if (adev->gmc.xgmi.ras_funcs &&
|
||||
adev->gmc.xgmi.ras_funcs->ras_late_init) {
|
||||
r = adev->gmc.xgmi.ras_funcs->ras_late_init(adev);
|
||||
if (adev->gmc.xgmi.ras && adev->gmc.xgmi.ras->ras_block.ras_late_init) {
|
||||
r = adev->gmc.xgmi.ras->ras_block.ras_late_init(adev, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (adev->hdp.ras_funcs &&
|
||||
adev->hdp.ras_funcs->ras_late_init) {
|
||||
r = adev->hdp.ras_funcs->ras_late_init(adev);
|
||||
if (adev->hdp.ras && adev->hdp.ras->ras_block.ras_late_init) {
|
||||
r = adev->hdp.ras->ras_block.ras_late_init(adev, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (adev->mca.mp0.ras_funcs &&
|
||||
adev->mca.mp0.ras_funcs->ras_late_init) {
|
||||
r = adev->mca.mp0.ras_funcs->ras_late_init(adev);
|
||||
if (adev->mca.mp0.ras && adev->mca.mp0.ras->ras_block.ras_late_init) {
|
||||
r = adev->mca.mp0.ras->ras_block.ras_late_init(adev, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (adev->mca.mp1.ras_funcs &&
|
||||
adev->mca.mp1.ras_funcs->ras_late_init) {
|
||||
r = adev->mca.mp1.ras_funcs->ras_late_init(adev);
|
||||
if (adev->mca.mp1.ras && adev->mca.mp1.ras->ras_block.ras_late_init) {
|
||||
r = adev->mca.mp1.ras->ras_block.ras_late_init(adev, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (adev->mca.mpio.ras_funcs &&
|
||||
adev->mca.mpio.ras_funcs->ras_late_init) {
|
||||
r = adev->mca.mpio.ras_funcs->ras_late_init(adev);
|
||||
if (adev->mca.mpio.ras && adev->mca.mpio.ras->ras_block.ras_late_init) {
|
||||
r = adev->mca.mpio.ras->ras_block.ras_late_init(adev, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
@ -497,21 +497,17 @@ int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev)
|
||||
|
||||
void amdgpu_gmc_ras_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->ras_fini)
|
||||
adev->umc.ras_funcs->ras_fini(adev);
|
||||
if (adev->umc.ras && adev->umc.ras->ras_block.ras_fini)
|
||||
adev->umc.ras->ras_block.ras_fini(adev);
|
||||
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->ras_fini)
|
||||
adev->mmhub.ras_funcs->ras_fini(adev);
|
||||
if (adev->mmhub.ras && adev->mmhub.ras->ras_block.ras_fini)
|
||||
adev->mmhub.ras->ras_block.ras_fini(adev);
|
||||
|
||||
if (adev->gmc.xgmi.ras_funcs &&
|
||||
adev->gmc.xgmi.ras_funcs->ras_fini)
|
||||
adev->gmc.xgmi.ras_funcs->ras_fini(adev);
|
||||
if (adev->gmc.xgmi.ras && adev->gmc.xgmi.ras->ras_block.ras_fini)
|
||||
adev->gmc.xgmi.ras->ras_block.ras_fini(adev);
|
||||
|
||||
if (adev->hdp.ras_funcs &&
|
||||
adev->hdp.ras_funcs->ras_fini)
|
||||
adev->hdp.ras_funcs->ras_fini(adev);
|
||||
if (adev->hdp.ras && adev->hdp.ras->ras_block.ras_fini)
|
||||
adev->hdp.ras->ras_block.ras_fini(adev);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -831,3 +827,49 @@ void amdgpu_gmc_get_reserved_allocation(struct amdgpu_device *adev)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int amdgpu_gmc_vram_checking(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_bo *vram_bo = NULL;
|
||||
uint64_t vram_gpu = 0;
|
||||
void *vram_ptr = NULL;
|
||||
|
||||
int ret, size = 0x100000;
|
||||
uint8_t cptr[10];
|
||||
|
||||
ret = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&vram_bo,
|
||||
&vram_gpu,
|
||||
&vram_ptr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memset(vram_ptr, 0x86, size);
|
||||
memset(cptr, 0x86, 10);
|
||||
|
||||
/**
|
||||
* Check the start, the mid, and the end of the memory if the content of
|
||||
* each byte is the pattern "0x86". If yes, we suppose the vram bo is
|
||||
* workable.
|
||||
*
|
||||
* Note: If check the each byte of whole 1M bo, it will cost too many
|
||||
* seconds, so here, we just pick up three parts for emulation.
|
||||
*/
|
||||
ret = memcmp(vram_ptr, cptr, 10);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = memcmp(vram_ptr + (size / 2), cptr, 10);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = memcmp(vram_ptr + size - 10, cptr, 10);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
amdgpu_bo_free_kernel(&vram_bo, &vram_gpu,
|
||||
&vram_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "amdgpu_irq.h"
|
||||
#include "amdgpu_ras.h"
|
||||
|
||||
/* VA hole for 48bit addresses on Vega10 */
|
||||
#define AMDGPU_GMC_HOLE_START 0x0000800000000000ULL
|
||||
@ -135,12 +136,8 @@ struct amdgpu_gmc_funcs {
|
||||
unsigned int (*get_vbios_fb_size)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
struct amdgpu_xgmi_ras_funcs {
|
||||
int (*ras_late_init)(struct amdgpu_device *adev);
|
||||
void (*ras_fini)(struct amdgpu_device *adev);
|
||||
int (*query_ras_error_count)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
void (*reset_ras_error_count)(struct amdgpu_device *adev);
|
||||
struct amdgpu_xgmi_ras {
|
||||
struct amdgpu_ras_block_object ras_block;
|
||||
};
|
||||
|
||||
struct amdgpu_xgmi {
|
||||
@ -159,7 +156,7 @@ struct amdgpu_xgmi {
|
||||
struct ras_common_if *ras_if;
|
||||
bool connected_to_cpu;
|
||||
bool pending_reset;
|
||||
const struct amdgpu_xgmi_ras_funcs *ras_funcs;
|
||||
struct amdgpu_xgmi_ras *ras;
|
||||
};
|
||||
|
||||
struct amdgpu_gmc {
|
||||
@ -321,6 +318,7 @@ bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev,
|
||||
uint16_t pasid, uint64_t timestamp);
|
||||
void amdgpu_gmc_filter_faults_remove(struct amdgpu_device *adev, uint64_t addr,
|
||||
uint16_t pasid);
|
||||
int amdgpu_gmc_ras_early_init(struct amdgpu_device *adev);
|
||||
int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev);
|
||||
void amdgpu_gmc_ras_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev);
|
||||
@ -339,4 +337,5 @@ void amdgpu_gmc_init_pdb0(struct amdgpu_device *adev);
|
||||
uint64_t amdgpu_gmc_vram_mc2pa(struct amdgpu_device *adev, uint64_t mc_addr);
|
||||
uint64_t amdgpu_gmc_vram_pa(struct amdgpu_device *adev, struct amdgpu_bo *bo);
|
||||
uint64_t amdgpu_gmc_vram_cpu_pa(struct amdgpu_device *adev, struct amdgpu_bo *bo);
|
||||
int amdgpu_gmc_vram_checking(struct amdgpu_device *adev);
|
||||
#endif
|
||||
|
@ -222,26 +222,21 @@ uint64_t amdgpu_gtt_mgr_usage(struct amdgpu_gtt_mgr *mgr)
|
||||
*
|
||||
* Re-init the gart for each known BO in the GTT.
|
||||
*/
|
||||
int amdgpu_gtt_mgr_recover(struct amdgpu_gtt_mgr *mgr)
|
||||
void amdgpu_gtt_mgr_recover(struct amdgpu_gtt_mgr *mgr)
|
||||
{
|
||||
struct amdgpu_gtt_node *node;
|
||||
struct drm_mm_node *mm_node;
|
||||
struct amdgpu_device *adev;
|
||||
int r = 0;
|
||||
|
||||
adev = container_of(mgr, typeof(*adev), mman.gtt_mgr);
|
||||
spin_lock(&mgr->lock);
|
||||
drm_mm_for_each_node(mm_node, &mgr->mm) {
|
||||
node = container_of(mm_node, typeof(*node), base.mm_nodes[0]);
|
||||
r = amdgpu_ttm_recover_gart(node->tbo);
|
||||
if (r)
|
||||
break;
|
||||
amdgpu_ttm_recover_gart(node->tbo);
|
||||
}
|
||||
spin_unlock(&mgr->lock);
|
||||
|
||||
amdgpu_gart_invalidate_tlb(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_ras.h"
|
||||
|
||||
int amdgpu_hdp_ras_late_init(struct amdgpu_device *adev)
|
||||
int amdgpu_hdp_ras_late_init(struct amdgpu_device *adev, void *ras_info)
|
||||
{
|
||||
int r;
|
||||
struct ras_ih_if ih_info = {
|
||||
|
@ -22,13 +22,10 @@
|
||||
*/
|
||||
#ifndef __AMDGPU_HDP_H__
|
||||
#define __AMDGPU_HDP_H__
|
||||
#include "amdgpu_ras.h"
|
||||
|
||||
struct amdgpu_hdp_ras_funcs {
|
||||
int (*ras_late_init)(struct amdgpu_device *adev);
|
||||
void (*ras_fini)(struct amdgpu_device *adev);
|
||||
void (*query_ras_error_count)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
void (*reset_ras_error_count)(struct amdgpu_device *adev);
|
||||
struct amdgpu_hdp_ras {
|
||||
struct amdgpu_ras_block_object ras_block;
|
||||
};
|
||||
|
||||
struct amdgpu_hdp_funcs {
|
||||
@ -43,9 +40,9 @@ struct amdgpu_hdp_funcs {
|
||||
struct amdgpu_hdp {
|
||||
struct ras_common_if *ras_if;
|
||||
const struct amdgpu_hdp_funcs *funcs;
|
||||
const struct amdgpu_hdp_ras_funcs *ras_funcs;
|
||||
struct amdgpu_hdp_ras *ras;
|
||||
};
|
||||
|
||||
int amdgpu_hdp_ras_late_init(struct amdgpu_device *adev);
|
||||
int amdgpu_hdp_ras_late_init(struct amdgpu_device *adev, void *ras_info);
|
||||
void amdgpu_hdp_ras_fini(struct amdgpu_device *adev);
|
||||
#endif /* __AMDGPU_HDP_H__ */
|
||||
|
@ -199,13 +199,13 @@ static irqreturn_t amdgpu_irq_handler(int irq, void *arg)
|
||||
* ack the interrupt if it is there
|
||||
*/
|
||||
if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__PCIE_BIF)) {
|
||||
if (adev->nbio.ras_funcs &&
|
||||
adev->nbio.ras_funcs->handle_ras_controller_intr_no_bifring)
|
||||
adev->nbio.ras_funcs->handle_ras_controller_intr_no_bifring(adev);
|
||||
if (adev->nbio.ras &&
|
||||
adev->nbio.ras->handle_ras_controller_intr_no_bifring)
|
||||
adev->nbio.ras->handle_ras_controller_intr_no_bifring(adev);
|
||||
|
||||
if (adev->nbio.ras_funcs &&
|
||||
adev->nbio.ras_funcs->handle_ras_err_event_athub_intr_no_bifring)
|
||||
adev->nbio.ras_funcs->handle_ras_err_event_athub_intr_no_bifring(adev);
|
||||
if (adev->nbio.ras &&
|
||||
adev->nbio.ras->handle_ras_err_event_athub_intr_no_bifring)
|
||||
adev->nbio.ras->handle_ras_err_event_athub_intr_no_bifring(adev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -87,11 +87,6 @@ void amdgpu_driver_unload_kms(struct drm_device *dev)
|
||||
if (adev->rmmio == NULL)
|
||||
return;
|
||||
|
||||
if (adev->runpm) {
|
||||
pm_runtime_get_sync(dev->dev);
|
||||
pm_runtime_forbid(dev->dev);
|
||||
}
|
||||
|
||||
if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DRV_UNLOAD))
|
||||
DRM_WARN("smart shift update failed\n");
|
||||
|
||||
@ -124,22 +119,6 @@ void amdgpu_register_gpu_instance(struct amdgpu_device *adev)
|
||||
mutex_unlock(&mgpu_info.mutex);
|
||||
}
|
||||
|
||||
static void amdgpu_get_audio_func(struct amdgpu_device *adev)
|
||||
{
|
||||
struct pci_dev *p = NULL;
|
||||
|
||||
p = pci_get_domain_bus_and_slot(pci_domain_nr(adev->pdev->bus),
|
||||
adev->pdev->bus->number, 1);
|
||||
if (p) {
|
||||
pm_runtime_get_sync(&p->dev);
|
||||
|
||||
pm_runtime_mark_last_busy(&p->dev);
|
||||
pm_runtime_put_autosuspend(&p->dev);
|
||||
|
||||
pci_dev_put(p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_driver_load_kms - Main load function for KMS.
|
||||
*
|
||||
@ -152,21 +131,10 @@ static void amdgpu_get_audio_func(struct amdgpu_device *adev)
|
||||
int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
struct pci_dev *parent;
|
||||
int r, acpi_status;
|
||||
|
||||
dev = adev_to_drm(adev);
|
||||
|
||||
if (amdgpu_has_atpx() &&
|
||||
(amdgpu_is_atpx_hybrid() ||
|
||||
amdgpu_has_atpx_dgpu_power_cntl()) &&
|
||||
((flags & AMD_IS_APU) == 0) &&
|
||||
!pci_is_thunderbolt_attached(to_pci_dev(dev->dev)))
|
||||
flags |= AMD_IS_PX;
|
||||
|
||||
parent = pci_upstream_bridge(adev->pdev);
|
||||
adev->has_pr3 = parent ? pci_pr3_present(parent) : false;
|
||||
|
||||
/* amdgpu_device_init should report only fatal error
|
||||
* like memory allocation failure or iomapping failure,
|
||||
* or memory manager initialization failure, it must
|
||||
@ -224,58 +192,12 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags)
|
||||
if (acpi_status)
|
||||
dev_dbg(dev->dev, "Error during ACPI methods call\n");
|
||||
|
||||
if (adev->runpm) {
|
||||
/* only need to skip on ATPX */
|
||||
if (amdgpu_device_supports_px(dev))
|
||||
dev_pm_set_driver_flags(dev->dev, DPM_FLAG_NO_DIRECT_COMPLETE);
|
||||
/* we want direct complete for BOCO */
|
||||
if (amdgpu_device_supports_boco(dev))
|
||||
dev_pm_set_driver_flags(dev->dev, DPM_FLAG_SMART_PREPARE |
|
||||
DPM_FLAG_SMART_SUSPEND |
|
||||
DPM_FLAG_MAY_SKIP_RESUME);
|
||||
pm_runtime_use_autosuspend(dev->dev);
|
||||
pm_runtime_set_autosuspend_delay(dev->dev, 5000);
|
||||
|
||||
pm_runtime_allow(dev->dev);
|
||||
|
||||
pm_runtime_mark_last_busy(dev->dev);
|
||||
pm_runtime_put_autosuspend(dev->dev);
|
||||
|
||||
/*
|
||||
* For runpm implemented via BACO, PMFW will handle the
|
||||
* timing for BACO in and out:
|
||||
* - put ASIC into BACO state only when both video and
|
||||
* audio functions are in D3 state.
|
||||
* - pull ASIC out of BACO state when either video or
|
||||
* audio function is in D0 state.
|
||||
* Also, at startup, PMFW assumes both functions are in
|
||||
* D0 state.
|
||||
*
|
||||
* So if snd driver was loaded prior to amdgpu driver
|
||||
* and audio function was put into D3 state, there will
|
||||
* be no PMFW-aware D-state transition(D0->D3) on runpm
|
||||
* suspend. Thus the BACO will be not correctly kicked in.
|
||||
*
|
||||
* Via amdgpu_get_audio_func(), the audio dev is put
|
||||
* into D0 state. Then there will be a PMFW-aware D-state
|
||||
* transition(D0->D3) on runpm suspend.
|
||||
*/
|
||||
if (amdgpu_device_supports_baco(dev) &&
|
||||
!(adev->flags & AMD_IS_APU) &&
|
||||
(adev->asic_type >= CHIP_NAVI10))
|
||||
amdgpu_get_audio_func(adev);
|
||||
}
|
||||
|
||||
if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DRV_LOAD))
|
||||
DRM_WARN("smart shift update failed\n");
|
||||
|
||||
out:
|
||||
if (r) {
|
||||
/* balance pm_runtime_get_sync in amdgpu_driver_unload_kms */
|
||||
if (adev->rmmio && adev->runpm)
|
||||
pm_runtime_put_noidle(dev->dev);
|
||||
if (r)
|
||||
amdgpu_driver_unload_kms(dev);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -406,6 +328,10 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
|
||||
fw_info->ver = adev->psp.toc.fw_version;
|
||||
fw_info->feature = adev->psp.toc.feature_version;
|
||||
break;
|
||||
case AMDGPU_INFO_FW_CAP:
|
||||
fw_info->ver = adev->psp.cap_fw_version;
|
||||
fw_info->feature = adev->psp.cap_feature_version;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1268,18 +1194,20 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
|
||||
if (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_VCE) != NULL)
|
||||
amdgpu_vce_free_handles(adev, file_priv);
|
||||
|
||||
amdgpu_vm_bo_rmv(adev, fpriv->prt_va);
|
||||
|
||||
if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) {
|
||||
/* TODO: how to handle reserve failure */
|
||||
BUG_ON(amdgpu_bo_reserve(adev->virt.csa_obj, true));
|
||||
amdgpu_vm_bo_rmv(adev, fpriv->csa_va);
|
||||
amdgpu_vm_bo_del(adev, fpriv->csa_va);
|
||||
fpriv->csa_va = NULL;
|
||||
amdgpu_bo_unreserve(adev->virt.csa_obj);
|
||||
}
|
||||
|
||||
pasid = fpriv->vm.pasid;
|
||||
pd = amdgpu_bo_ref(fpriv->vm.root.bo);
|
||||
if (!WARN_ON(amdgpu_bo_reserve(pd, true))) {
|
||||
amdgpu_vm_bo_del(adev, fpriv->prt_va);
|
||||
amdgpu_bo_unreserve(pd);
|
||||
}
|
||||
|
||||
amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr);
|
||||
amdgpu_vm_fini(adev, &fpriv->vm);
|
||||
@ -1427,8 +1355,7 @@ static int amdgpu_debugfs_firmware_info_show(struct seq_file *m, void *unused)
|
||||
struct drm_amdgpu_info_firmware fw_info;
|
||||
struct drm_amdgpu_query_fw query_fw;
|
||||
struct atom_context *ctx = adev->mode_info.atom_context;
|
||||
uint8_t smu_minor, smu_debug;
|
||||
uint16_t smu_major;
|
||||
uint8_t smu_program, smu_major, smu_minor, smu_debug;
|
||||
int ret, i;
|
||||
|
||||
static const char *ta_fw_name[TA_FW_TYPE_MAX_INDEX] = {
|
||||
@ -1574,11 +1501,12 @@ static int amdgpu_debugfs_firmware_info_show(struct seq_file *m, void *unused)
|
||||
ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
|
||||
if (ret)
|
||||
return ret;
|
||||
smu_major = (fw_info.ver >> 16) & 0xffff;
|
||||
smu_program = (fw_info.ver >> 24) & 0xff;
|
||||
smu_major = (fw_info.ver >> 16) & 0xff;
|
||||
smu_minor = (fw_info.ver >> 8) & 0xff;
|
||||
smu_debug = (fw_info.ver >> 0) & 0xff;
|
||||
seq_printf(m, "SMC feature version: %u, firmware version: 0x%08x (%d.%d.%d)\n",
|
||||
fw_info.feature, fw_info.ver, smu_major, smu_minor, smu_debug);
|
||||
seq_printf(m, "SMC feature version: %u, program: %d, firmware version: 0x%08x (%d.%d.%d)\n",
|
||||
fw_info.feature, smu_program, fw_info.ver, smu_major, smu_minor, smu_debug);
|
||||
|
||||
/* SDMA */
|
||||
query_fw.fw_type = AMDGPU_INFO_FW_SDMA;
|
||||
@ -1623,6 +1551,16 @@ static int amdgpu_debugfs_firmware_info_show(struct seq_file *m, void *unused)
|
||||
seq_printf(m, "TOC feature version: %u, firmware version: 0x%08x\n",
|
||||
fw_info.feature, fw_info.ver);
|
||||
|
||||
/* CAP */
|
||||
if (adev->psp.cap_fw) {
|
||||
query_fw.fw_type = AMDGPU_INFO_FW_CAP;
|
||||
ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
|
||||
if (ret)
|
||||
return ret;
|
||||
seq_printf(m, "CAP feature version: %u, firmware version: 0x%08x\n",
|
||||
fw_info.feature, fw_info.ver);
|
||||
}
|
||||
|
||||
seq_printf(m, "VBIOS version: %s\n", ctx->vbios_version);
|
||||
|
||||
return 0;
|
||||
|
@ -74,20 +74,23 @@ void amdgpu_mca_query_ras_error_count(struct amdgpu_device *adev,
|
||||
int amdgpu_mca_ras_late_init(struct amdgpu_device *adev,
|
||||
struct amdgpu_mca_ras *mca_dev)
|
||||
{
|
||||
char sysfs_name[32] = {0};
|
||||
int r;
|
||||
struct ras_ih_if ih_info = {
|
||||
.cb = NULL,
|
||||
};
|
||||
struct ras_fs_if fs_info = {
|
||||
.sysfs_name = mca_dev->ras_funcs->sysfs_name,
|
||||
struct ras_fs_if fs_info= {
|
||||
.sysfs_name = sysfs_name,
|
||||
};
|
||||
|
||||
snprintf(sysfs_name, sizeof(sysfs_name), "%s_err_count", mca_dev->ras->ras_block.name);
|
||||
|
||||
if (!mca_dev->ras_if) {
|
||||
mca_dev->ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
|
||||
if (!mca_dev->ras_if)
|
||||
return -ENOMEM;
|
||||
mca_dev->ras_if->block = mca_dev->ras_funcs->ras_block;
|
||||
mca_dev->ras_if->sub_block_index = mca_dev->ras_funcs->ras_sub_block;
|
||||
mca_dev->ras_if->block = mca_dev->ras->ras_block.block;
|
||||
mca_dev->ras_if->sub_block_index = mca_dev->ras->ras_block.sub_block_index;
|
||||
mca_dev->ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
|
||||
}
|
||||
ih_info.head = fs_info.head = *mca_dev->ras_if;
|
||||
|
@ -21,21 +21,13 @@
|
||||
#ifndef __AMDGPU_MCA_H__
|
||||
#define __AMDGPU_MCA_H__
|
||||
|
||||
struct amdgpu_mca_ras_funcs {
|
||||
int (*ras_late_init)(struct amdgpu_device *adev);
|
||||
void (*ras_fini)(struct amdgpu_device *adev);
|
||||
void (*query_ras_error_count)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
void (*query_ras_error_address)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
uint32_t ras_block;
|
||||
uint32_t ras_sub_block;
|
||||
const char* sysfs_name;
|
||||
struct amdgpu_mca_ras_block {
|
||||
struct amdgpu_ras_block_object ras_block;
|
||||
};
|
||||
|
||||
struct amdgpu_mca_ras {
|
||||
struct ras_common_if *ras_if;
|
||||
const struct amdgpu_mca_ras_funcs *ras_funcs;
|
||||
struct amdgpu_mca_ras_block *ras;
|
||||
};
|
||||
|
||||
struct amdgpu_mca_funcs {
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_ras.h"
|
||||
|
||||
int amdgpu_mmhub_ras_late_init(struct amdgpu_device *adev)
|
||||
int amdgpu_mmhub_ras_late_init(struct amdgpu_device *adev, void *ras_info)
|
||||
{
|
||||
int r;
|
||||
struct ras_ih_if ih_info = {
|
||||
|
@ -21,14 +21,8 @@
|
||||
#ifndef __AMDGPU_MMHUB_H__
|
||||
#define __AMDGPU_MMHUB_H__
|
||||
|
||||
struct amdgpu_mmhub_ras_funcs {
|
||||
int (*ras_late_init)(struct amdgpu_device *adev);
|
||||
void (*ras_fini)(struct amdgpu_device *adev);
|
||||
void (*query_ras_error_count)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
void (*query_ras_error_status)(struct amdgpu_device *adev);
|
||||
void (*reset_ras_error_count)(struct amdgpu_device *adev);
|
||||
void (*reset_ras_error_status)(struct amdgpu_device *adev);
|
||||
struct amdgpu_mmhub_ras {
|
||||
struct amdgpu_ras_block_object ras_block;
|
||||
};
|
||||
|
||||
struct amdgpu_mmhub_funcs {
|
||||
@ -50,10 +44,10 @@ struct amdgpu_mmhub_funcs {
|
||||
struct amdgpu_mmhub {
|
||||
struct ras_common_if *ras_if;
|
||||
const struct amdgpu_mmhub_funcs *funcs;
|
||||
const struct amdgpu_mmhub_ras_funcs *ras_funcs;
|
||||
struct amdgpu_mmhub_ras *ras;
|
||||
};
|
||||
|
||||
int amdgpu_mmhub_ras_late_init(struct amdgpu_device *adev);
|
||||
int amdgpu_mmhub_ras_late_init(struct amdgpu_device *adev, void *ras_info);
|
||||
void amdgpu_mmhub_ras_fini(struct amdgpu_device *adev);
|
||||
#endif
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_ras.h"
|
||||
|
||||
int amdgpu_nbio_ras_late_init(struct amdgpu_device *adev)
|
||||
int amdgpu_nbio_ras_late_init(struct amdgpu_device *adev, void *ras_info)
|
||||
{
|
||||
int r;
|
||||
struct ras_ih_if ih_info = {
|
||||
|
@ -47,15 +47,12 @@ struct nbio_hdp_flush_reg {
|
||||
u32 ref_and_mask_sdma7;
|
||||
};
|
||||
|
||||
struct amdgpu_nbio_ras_funcs {
|
||||
struct amdgpu_nbio_ras {
|
||||
struct amdgpu_ras_block_object ras_block;
|
||||
void (*handle_ras_controller_intr_no_bifring)(struct amdgpu_device *adev);
|
||||
void (*handle_ras_err_event_athub_intr_no_bifring)(struct amdgpu_device *adev);
|
||||
int (*init_ras_controller_interrupt)(struct amdgpu_device *adev);
|
||||
int (*init_ras_err_event_athub_interrupt)(struct amdgpu_device *adev);
|
||||
void (*query_ras_error_count)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
int (*ras_late_init)(struct amdgpu_device *adev);
|
||||
void (*ras_fini)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
struct amdgpu_nbio_funcs {
|
||||
@ -104,9 +101,9 @@ struct amdgpu_nbio {
|
||||
struct amdgpu_irq_src ras_err_event_athub_irq;
|
||||
struct ras_common_if *ras_if;
|
||||
const struct amdgpu_nbio_funcs *funcs;
|
||||
const struct amdgpu_nbio_ras_funcs *ras_funcs;
|
||||
struct amdgpu_nbio_ras *ras;
|
||||
};
|
||||
|
||||
int amdgpu_nbio_ras_late_init(struct amdgpu_device *adev);
|
||||
int amdgpu_nbio_ras_late_init(struct amdgpu_device *adev, void *ras_info);
|
||||
void amdgpu_nbio_ras_fini(struct amdgpu_device *adev);
|
||||
#endif
|
||||
|
@ -575,6 +575,9 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
|
||||
if (!amdgpu_bo_support_uswc(bo->flags))
|
||||
bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC;
|
||||
|
||||
if (adev->ras_enabled)
|
||||
bo->flags |= AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE;
|
||||
|
||||
bo->tbo.bdev = &adev->mman.bdev;
|
||||
if (bp->domain & (AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA |
|
||||
AMDGPU_GEM_DOMAIN_GDS))
|
||||
@ -1303,7 +1306,8 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)
|
||||
!(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE))
|
||||
return;
|
||||
|
||||
dma_resv_lock(bo->base.resv, NULL);
|
||||
if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv)))
|
||||
return;
|
||||
|
||||
r = amdgpu_fill_buffer(abo, AMDGPU_POISON, bo->base.resv, &fence);
|
||||
if (!WARN_ON(r)) {
|
||||
|
@ -137,7 +137,8 @@ static int psp_early_init(void *handle)
|
||||
psp->autoload_supported = true;
|
||||
break;
|
||||
case IP_VERSION(11, 0, 8):
|
||||
if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) {
|
||||
if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2 ||
|
||||
adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 4)) {
|
||||
psp_v11_0_8_set_psp_funcs(psp);
|
||||
psp->autoload_supported = false;
|
||||
}
|
||||
@ -259,6 +260,32 @@ static bool psp_get_runtime_db_entry(struct amdgpu_device *adev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psp_init_sriov_microcode(struct psp_context *psp)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
int ret = 0;
|
||||
|
||||
switch (adev->ip_versions[MP0_HWIP][0]) {
|
||||
case IP_VERSION(9, 0, 0):
|
||||
ret = psp_init_cap_microcode(psp, "vega10");
|
||||
break;
|
||||
case IP_VERSION(11, 0, 9):
|
||||
ret = psp_init_cap_microcode(psp, "navi12");
|
||||
break;
|
||||
case IP_VERSION(11, 0, 7):
|
||||
ret = psp_init_cap_microcode(psp, "sienna_cichlid");
|
||||
break;
|
||||
case IP_VERSION(13, 0, 2):
|
||||
ret = psp_init_ta_microcode(psp, "aldebaran");
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psp_sw_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
@ -273,19 +300,13 @@ static int psp_sw_init(void *handle)
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
ret = psp_init_sriov_microcode(psp);
|
||||
else
|
||||
ret = psp_init_microcode(psp);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to load psp firmware!\n");
|
||||
return ret;
|
||||
}
|
||||
} else if (amdgpu_sriov_vf(adev) &&
|
||||
adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2)) {
|
||||
ret = psp_init_ta_microcode(psp, "aldebaran");
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to initialize ta microcode!\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to load psp firmware!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(&boot_cfg_entry, 0, sizeof(boot_cfg_entry));
|
||||
@ -353,6 +374,10 @@ static int psp_sw_fini(void *handle)
|
||||
release_firmware(psp->ta_fw);
|
||||
psp->ta_fw = NULL;
|
||||
}
|
||||
if (adev->psp.cap_fw) {
|
||||
release_firmware(psp->cap_fw);
|
||||
psp->cap_fw = NULL;
|
||||
}
|
||||
|
||||
if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 0) ||
|
||||
adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 7))
|
||||
@ -491,7 +516,10 @@ psp_cmd_submit_buf(struct psp_context *psp,
|
||||
DRM_WARN("psp gfx command %s(0x%X) failed and response status is (0x%X)\n",
|
||||
psp_gfx_cmd_name(psp->cmd_buf_mem->cmd_id), psp->cmd_buf_mem->cmd_id,
|
||||
psp->cmd_buf_mem->resp.status);
|
||||
if (!timeout) {
|
||||
/* If we load CAP FW, PSP must return 0 under SRIOV
|
||||
* also return failure in case of timeout
|
||||
*/
|
||||
if ((ucode && (ucode->ucode_id == AMDGPU_UCODE_ID_CAP)) || !timeout) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
@ -914,19 +942,15 @@ static void psp_prep_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd,
|
||||
static int psp_ta_init_shared_buf(struct psp_context *psp,
|
||||
struct ta_mem_context *mem_ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Allocate 16k memory aligned to 4k from Frame Buffer (local
|
||||
* physical) for ta to host memory
|
||||
*/
|
||||
ret = amdgpu_bo_create_kernel(psp->adev, mem_ctx->shared_mem_size,
|
||||
return amdgpu_bo_create_kernel(psp->adev, mem_ctx->shared_mem_size,
|
||||
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&mem_ctx->shared_bo,
|
||||
&mem_ctx->shared_mc_addr,
|
||||
&mem_ctx->shared_buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void psp_ta_free_shared_buf(struct ta_mem_context *mem_ctx)
|
||||
@ -1308,6 +1332,11 @@ static void psp_ras_ta_check_status(struct psp_context *psp)
|
||||
break;
|
||||
case TA_RAS_STATUS__SUCCESS:
|
||||
break;
|
||||
case TA_RAS_STATUS__TEE_ERROR_ACCESS_DENIED:
|
||||
if (ras_cmd->cmd_id == TA_RAS_COMMAND__TRIGGER_ERROR)
|
||||
dev_warn(psp->adev->dev,
|
||||
"RAS WARNING: Inject error to critical region is not allowed\n");
|
||||
break;
|
||||
default:
|
||||
dev_warn(psp->adev->dev,
|
||||
"RAS WARNING: ras status = 0x%X\n", ras_cmd->ras_status);
|
||||
@ -1520,7 +1549,9 @@ int psp_ras_trigger_error(struct psp_context *psp,
|
||||
if (amdgpu_ras_intr_triggered())
|
||||
return 0;
|
||||
|
||||
if (ras_cmd->ras_status)
|
||||
if (ras_cmd->ras_status == TA_RAS_STATUS__TEE_ERROR_ACCESS_DENIED)
|
||||
return -EACCES;
|
||||
else if (ras_cmd->ras_status)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@ -2051,6 +2082,9 @@ static int psp_get_fw_type(struct amdgpu_firmware_info *ucode,
|
||||
enum psp_gfx_fw_type *type)
|
||||
{
|
||||
switch (ucode->ucode_id) {
|
||||
case AMDGPU_UCODE_ID_CAP:
|
||||
*type = GFX_FW_TYPE_CAP;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_SDMA0:
|
||||
*type = GFX_FW_TYPE_SDMA0;
|
||||
break;
|
||||
@ -3217,6 +3251,58 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
int psp_init_cap_microcode(struct psp_context *psp,
|
||||
const char *chip_name)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char fw_name[PSP_FW_NAME_LEN];
|
||||
const struct psp_firmware_header_v1_0 *cap_hdr_v1_0;
|
||||
struct amdgpu_firmware_info *info = NULL;
|
||||
int err = 0;
|
||||
|
||||
if (!chip_name) {
|
||||
dev_err(adev->dev, "invalid chip name for cap microcode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
dev_err(adev->dev, "cap microcode should only be loaded under SRIOV\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_cap.bin", chip_name);
|
||||
err = request_firmware(&adev->psp.cap_fw, fw_name, adev->dev);
|
||||
if (err) {
|
||||
dev_warn(adev->dev, "cap microcode does not exist, skip\n");
|
||||
err = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = amdgpu_ucode_validate(adev->psp.cap_fw);
|
||||
if (err) {
|
||||
dev_err(adev->dev, "fail to initialize cap microcode\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CAP];
|
||||
info->ucode_id = AMDGPU_UCODE_ID_CAP;
|
||||
info->fw = adev->psp.cap_fw;
|
||||
cap_hdr_v1_0 = (const struct psp_firmware_header_v1_0 *)
|
||||
adev->psp.cap_fw->data;
|
||||
adev->firmware.fw_size += ALIGN(
|
||||
le32_to_cpu(cap_hdr_v1_0->header.ucode_size_bytes), PAGE_SIZE);
|
||||
adev->psp.cap_fw_version = le32_to_cpu(cap_hdr_v1_0->header.ucode_version);
|
||||
adev->psp.cap_feature_version = le32_to_cpu(cap_hdr_v1_0->sos.fw_version);
|
||||
adev->psp.cap_ucode_size = le32_to_cpu(cap_hdr_v1_0->header.ucode_size_bytes);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
release_firmware(adev->psp.cap_fw);
|
||||
adev->psp.cap_fw = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int psp_set_clockgating_state(void *handle,
|
||||
enum amd_clockgating_state state)
|
||||
{
|
||||
|
@ -306,6 +306,9 @@ struct psp_context
|
||||
/* toc firmware */
|
||||
const struct firmware *toc_fw;
|
||||
|
||||
/* cap firmware */
|
||||
const struct firmware *cap_fw;
|
||||
|
||||
/* fence buffer */
|
||||
struct amdgpu_bo *fence_buf_bo;
|
||||
uint64_t fence_buf_mc_addr;
|
||||
@ -327,6 +330,10 @@ struct psp_context
|
||||
const struct firmware *ta_fw;
|
||||
uint32_t ta_fw_version;
|
||||
|
||||
uint32_t cap_fw_version;
|
||||
uint32_t cap_feature_version;
|
||||
uint32_t cap_ucode_size;
|
||||
|
||||
struct ta_context asd_context;
|
||||
struct psp_xgmi_context xgmi_context;
|
||||
struct psp_ras_context ras_context;
|
||||
@ -440,6 +447,8 @@ int psp_init_sos_microcode(struct psp_context *psp,
|
||||
const char *chip_name);
|
||||
int psp_init_ta_microcode(struct psp_context *psp,
|
||||
const char *chip_name);
|
||||
int psp_init_cap_microcode(struct psp_context *psp,
|
||||
const char *chip_name);
|
||||
int psp_get_fw_attestation_records_addr(struct psp_context *psp,
|
||||
uint64_t *output_ptr);
|
||||
|
||||
|
@ -75,6 +75,13 @@ const char *ras_mca_block_string[] = {
|
||||
"mca_iohc",
|
||||
};
|
||||
|
||||
struct amdgpu_ras_block_list {
|
||||
/* ras block link */
|
||||
struct list_head node;
|
||||
|
||||
struct amdgpu_ras_block_object *ras_obj;
|
||||
};
|
||||
|
||||
const char *get_ras_block_str(struct ras_common_if *ras_block)
|
||||
{
|
||||
if (!ras_block)
|
||||
@ -89,6 +96,9 @@ const char *get_ras_block_str(struct ras_common_if *ras_block)
|
||||
return ras_block_string[ras_block->block];
|
||||
}
|
||||
|
||||
#define ras_block_str(_BLOCK_) \
|
||||
(((_BLOCK_) < ARRAY_SIZE(ras_block_string)) ? ras_block_string[_BLOCK_] : "Out Of Range")
|
||||
|
||||
#define ras_err_str(i) (ras_error_string[ffs(i)])
|
||||
|
||||
#define RAS_DEFAULT_FLAGS (AMDGPU_RAS_FLAG_INIT_BY_VBIOS)
|
||||
@ -155,14 +165,9 @@ static int amdgpu_reserve_page_direct(struct amdgpu_device *adev, uint64_t addre
|
||||
}
|
||||
|
||||
memset(&err_rec, 0x0, sizeof(struct eeprom_table_record));
|
||||
|
||||
err_rec.address = address;
|
||||
err_rec.retired_page = address >> AMDGPU_GPU_PAGE_SHIFT;
|
||||
err_rec.ts = (uint64_t)ktime_get_real_seconds();
|
||||
err_rec.err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE;
|
||||
|
||||
err_data.err_addr = &err_rec;
|
||||
err_data.err_addr_cnt = 1;
|
||||
amdgpu_umc_fill_error_record(&err_data, address,
|
||||
(address >> AMDGPU_GPU_PAGE_SHIFT), 0, 0);
|
||||
|
||||
if (amdgpu_bad_page_threshold != 0) {
|
||||
amdgpu_ras_add_bad_pages(adev, err_data.err_addr,
|
||||
@ -452,7 +457,7 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f,
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
return ret;
|
||||
|
||||
return size;
|
||||
}
|
||||
@ -866,30 +871,47 @@ static int amdgpu_ras_enable_all_features(struct amdgpu_device *adev,
|
||||
}
|
||||
/* feature ctl end */
|
||||
|
||||
|
||||
static void amdgpu_ras_mca_query_error_status(struct amdgpu_device *adev,
|
||||
struct ras_common_if *ras_block,
|
||||
struct ras_err_data *err_data)
|
||||
static int amdgpu_ras_block_match_default(struct amdgpu_ras_block_object *block_obj,
|
||||
enum amdgpu_ras_block block)
|
||||
{
|
||||
switch (ras_block->sub_block_index) {
|
||||
case AMDGPU_RAS_MCA_BLOCK__MP0:
|
||||
if (adev->mca.mp0.ras_funcs &&
|
||||
adev->mca.mp0.ras_funcs->query_ras_error_count)
|
||||
adev->mca.mp0.ras_funcs->query_ras_error_count(adev, &err_data);
|
||||
break;
|
||||
case AMDGPU_RAS_MCA_BLOCK__MP1:
|
||||
if (adev->mca.mp1.ras_funcs &&
|
||||
adev->mca.mp1.ras_funcs->query_ras_error_count)
|
||||
adev->mca.mp1.ras_funcs->query_ras_error_count(adev, &err_data);
|
||||
break;
|
||||
case AMDGPU_RAS_MCA_BLOCK__MPIO:
|
||||
if (adev->mca.mpio.ras_funcs &&
|
||||
adev->mca.mpio.ras_funcs->query_ras_error_count)
|
||||
adev->mca.mpio.ras_funcs->query_ras_error_count(adev, &err_data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (!block_obj)
|
||||
return -EINVAL;
|
||||
|
||||
if (block_obj->block == block)
|
||||
return 0;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct amdgpu_ras_block_object *amdgpu_ras_get_ras_block(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block, uint32_t sub_block_index)
|
||||
{
|
||||
struct amdgpu_ras_block_list *node, *tmp;
|
||||
struct amdgpu_ras_block_object *obj;
|
||||
|
||||
if (block >= AMDGPU_RAS_BLOCK__LAST)
|
||||
return NULL;
|
||||
|
||||
if (!amdgpu_ras_is_supported(adev, block))
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry_safe(node, tmp, &adev->ras_list, node) {
|
||||
if (!node->ras_obj) {
|
||||
dev_warn(adev->dev, "Warning: abnormal ras list node.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
obj = node->ras_obj;
|
||||
if (obj->ras_block_match) {
|
||||
if (obj->ras_block_match(obj, block, sub_block_index) == 0)
|
||||
return obj;
|
||||
} else {
|
||||
if (amdgpu_ras_block_match_default(obj, block) == 0)
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void amdgpu_ras_get_ecc_info(struct amdgpu_device *adev, struct ras_err_data *err_data)
|
||||
@ -901,26 +923,26 @@ static void amdgpu_ras_get_ecc_info(struct amdgpu_device *adev, struct ras_err_d
|
||||
* choosing right query method according to
|
||||
* whether smu support query error information
|
||||
*/
|
||||
ret = smu_get_ecc_info(&adev->smu, (void *)&(ras->umc_ecc));
|
||||
ret = amdgpu_dpm_get_ecc_info(adev, (void *)&(ras->umc_ecc));
|
||||
if (ret == -EOPNOTSUPP) {
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->query_ras_error_count)
|
||||
adev->umc.ras_funcs->query_ras_error_count(adev, err_data);
|
||||
if (adev->umc.ras && adev->umc.ras->ras_block.hw_ops &&
|
||||
adev->umc.ras->ras_block.hw_ops->query_ras_error_count)
|
||||
adev->umc.ras->ras_block.hw_ops->query_ras_error_count(adev, err_data);
|
||||
|
||||
/* umc query_ras_error_address is also responsible for clearing
|
||||
* error status
|
||||
*/
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->query_ras_error_address)
|
||||
adev->umc.ras_funcs->query_ras_error_address(adev, err_data);
|
||||
if (adev->umc.ras && adev->umc.ras->ras_block.hw_ops &&
|
||||
adev->umc.ras->ras_block.hw_ops->query_ras_error_address)
|
||||
adev->umc.ras->ras_block.hw_ops->query_ras_error_address(adev, err_data);
|
||||
} else if (!ret) {
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->ecc_info_query_ras_error_count)
|
||||
adev->umc.ras_funcs->ecc_info_query_ras_error_count(adev, err_data);
|
||||
if (adev->umc.ras &&
|
||||
adev->umc.ras->ecc_info_query_ras_error_count)
|
||||
adev->umc.ras->ecc_info_query_ras_error_count(adev, err_data);
|
||||
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->ecc_info_query_ras_error_address)
|
||||
adev->umc.ras_funcs->ecc_info_query_ras_error_address(adev, err_data);
|
||||
if (adev->umc.ras &&
|
||||
adev->umc.ras->ecc_info_query_ras_error_address)
|
||||
adev->umc.ras->ecc_info_query_ras_error_address(adev, err_data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -928,62 +950,32 @@ static void amdgpu_ras_get_ecc_info(struct amdgpu_device *adev, struct ras_err_d
|
||||
int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
|
||||
struct ras_query_if *info)
|
||||
{
|
||||
struct amdgpu_ras_block_object *block_obj = NULL;
|
||||
struct ras_manager *obj = amdgpu_ras_find_obj(adev, &info->head);
|
||||
struct ras_err_data err_data = {0, 0, 0, NULL};
|
||||
int i;
|
||||
|
||||
if (!obj)
|
||||
return -EINVAL;
|
||||
|
||||
switch (info->head.block) {
|
||||
case AMDGPU_RAS_BLOCK__UMC:
|
||||
if (info->head.block == AMDGPU_RAS_BLOCK__UMC) {
|
||||
amdgpu_ras_get_ecc_info(adev, &err_data);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__SDMA:
|
||||
if (adev->sdma.funcs->query_ras_error_count) {
|
||||
for (i = 0; i < adev->sdma.num_instances; i++)
|
||||
adev->sdma.funcs->query_ras_error_count(adev, i,
|
||||
&err_data);
|
||||
} else {
|
||||
block_obj = amdgpu_ras_get_ras_block(adev, info->head.block, 0);
|
||||
if (!block_obj || !block_obj->hw_ops) {
|
||||
dev_dbg_once(adev->dev, "%s doesn't config RAS function\n",
|
||||
get_ras_block_str(&info->head));
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__GFX:
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->query_ras_error_count)
|
||||
adev->gfx.ras_funcs->query_ras_error_count(adev, &err_data);
|
||||
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->query_ras_error_status)
|
||||
adev->gfx.ras_funcs->query_ras_error_status(adev);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__MMHUB:
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->query_ras_error_count)
|
||||
adev->mmhub.ras_funcs->query_ras_error_count(adev, &err_data);
|
||||
if (block_obj->hw_ops->query_ras_error_count)
|
||||
block_obj->hw_ops->query_ras_error_count(adev, &err_data);
|
||||
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->query_ras_error_status)
|
||||
adev->mmhub.ras_funcs->query_ras_error_status(adev);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__PCIE_BIF:
|
||||
if (adev->nbio.ras_funcs &&
|
||||
adev->nbio.ras_funcs->query_ras_error_count)
|
||||
adev->nbio.ras_funcs->query_ras_error_count(adev, &err_data);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__XGMI_WAFL:
|
||||
if (adev->gmc.xgmi.ras_funcs &&
|
||||
adev->gmc.xgmi.ras_funcs->query_ras_error_count)
|
||||
adev->gmc.xgmi.ras_funcs->query_ras_error_count(adev, &err_data);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__HDP:
|
||||
if (adev->hdp.ras_funcs &&
|
||||
adev->hdp.ras_funcs->query_ras_error_count)
|
||||
adev->hdp.ras_funcs->query_ras_error_count(adev, &err_data);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__MCA:
|
||||
amdgpu_ras_mca_query_error_status(adev, &info->head, &err_data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if ((info->head.block == AMDGPU_RAS_BLOCK__SDMA) ||
|
||||
(info->head.block == AMDGPU_RAS_BLOCK__GFX) ||
|
||||
(info->head.block == AMDGPU_RAS_BLOCK__MMHUB)) {
|
||||
if (block_obj->hw_ops->query_ras_error_status)
|
||||
block_obj->hw_ops->query_ras_error_status(adev);
|
||||
}
|
||||
}
|
||||
|
||||
obj->err_data.ue_count += err_data.ue_count;
|
||||
@ -1040,70 +1032,29 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
|
||||
int amdgpu_ras_reset_error_status(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block)
|
||||
{
|
||||
struct amdgpu_ras_block_object *block_obj = amdgpu_ras_get_ras_block(adev, block, 0);
|
||||
|
||||
if (!amdgpu_ras_is_supported(adev, block))
|
||||
return -EINVAL;
|
||||
|
||||
switch (block) {
|
||||
case AMDGPU_RAS_BLOCK__GFX:
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->reset_ras_error_count)
|
||||
adev->gfx.ras_funcs->reset_ras_error_count(adev);
|
||||
if (!block_obj || !block_obj->hw_ops) {
|
||||
dev_dbg_once(adev->dev, "%s doesn't config RAS function\n",
|
||||
ras_block_str(block));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->reset_ras_error_status)
|
||||
adev->gfx.ras_funcs->reset_ras_error_status(adev);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__MMHUB:
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->reset_ras_error_count)
|
||||
adev->mmhub.ras_funcs->reset_ras_error_count(adev);
|
||||
if (block_obj->hw_ops->reset_ras_error_count)
|
||||
block_obj->hw_ops->reset_ras_error_count(adev);
|
||||
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->reset_ras_error_status)
|
||||
adev->mmhub.ras_funcs->reset_ras_error_status(adev);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__SDMA:
|
||||
if (adev->sdma.funcs->reset_ras_error_count)
|
||||
adev->sdma.funcs->reset_ras_error_count(adev);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__HDP:
|
||||
if (adev->hdp.ras_funcs &&
|
||||
adev->hdp.ras_funcs->reset_ras_error_count)
|
||||
adev->hdp.ras_funcs->reset_ras_error_count(adev);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if ((block == AMDGPU_RAS_BLOCK__GFX) ||
|
||||
(block == AMDGPU_RAS_BLOCK__MMHUB)) {
|
||||
if (block_obj->hw_ops->reset_ras_error_status)
|
||||
block_obj->hw_ops->reset_ras_error_status(adev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Trigger XGMI/WAFL error */
|
||||
static int amdgpu_ras_error_inject_xgmi(struct amdgpu_device *adev,
|
||||
struct ta_ras_trigger_error_input *block_info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_DISALLOW))
|
||||
dev_warn(adev->dev, "Failed to disallow df cstate");
|
||||
|
||||
if (amdgpu_dpm_allow_xgmi_power_down(adev, false))
|
||||
dev_warn(adev->dev, "Failed to disallow XGMI power down");
|
||||
|
||||
ret = psp_ras_trigger_error(&adev->psp, block_info);
|
||||
|
||||
if (amdgpu_ras_intr_triggered())
|
||||
return ret;
|
||||
|
||||
if (amdgpu_dpm_allow_xgmi_power_down(adev, true))
|
||||
dev_warn(adev->dev, "Failed to allow XGMI power down");
|
||||
|
||||
if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_ALLOW))
|
||||
dev_warn(adev->dev, "Failed to allow df cstate");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* wrapper of psp_ras_trigger_error */
|
||||
int amdgpu_ras_error_inject(struct amdgpu_device *adev,
|
||||
struct ras_inject_if *info)
|
||||
@ -1116,11 +1067,20 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev,
|
||||
.address = info->address,
|
||||
.value = info->value,
|
||||
};
|
||||
int ret = 0;
|
||||
int ret = -EINVAL;
|
||||
struct amdgpu_ras_block_object *block_obj = amdgpu_ras_get_ras_block(adev,
|
||||
info->head.block,
|
||||
info->head.sub_block_index);
|
||||
|
||||
if (!obj)
|
||||
return -EINVAL;
|
||||
|
||||
if (!block_obj || !block_obj->hw_ops) {
|
||||
dev_dbg_once(adev->dev, "%s doesn't config RAS function\n",
|
||||
get_ras_block_str(&info->head));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Calculate XGMI relative offset */
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
block_info.address =
|
||||
@ -1128,28 +1088,15 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev,
|
||||
block_info.address);
|
||||
}
|
||||
|
||||
switch (info->head.block) {
|
||||
case AMDGPU_RAS_BLOCK__GFX:
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->ras_error_inject)
|
||||
ret = adev->gfx.ras_funcs->ras_error_inject(adev, info);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__UMC:
|
||||
case AMDGPU_RAS_BLOCK__SDMA:
|
||||
case AMDGPU_RAS_BLOCK__MMHUB:
|
||||
case AMDGPU_RAS_BLOCK__PCIE_BIF:
|
||||
case AMDGPU_RAS_BLOCK__MCA:
|
||||
ret = psp_ras_trigger_error(&adev->psp, &block_info);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__XGMI_WAFL:
|
||||
ret = amdgpu_ras_error_inject_xgmi(adev, &block_info);
|
||||
break;
|
||||
default:
|
||||
dev_info(adev->dev, "%s error injection is not supported yet\n",
|
||||
get_ras_block_str(&info->head));
|
||||
ret = -EINVAL;
|
||||
if (info->head.block == AMDGPU_RAS_BLOCK__GFX) {
|
||||
if (block_obj->hw_ops->ras_error_inject)
|
||||
ret = block_obj->hw_ops->ras_error_inject(adev, info);
|
||||
} else {
|
||||
/* If defined special ras_error_inject(e.g: xgmi), implement special ras_error_inject */
|
||||
if (block_obj->hw_ops->ras_error_inject)
|
||||
ret = block_obj->hw_ops->ras_error_inject(adev, &block_info);
|
||||
else /*If not defined .ras_error_inject, use default ras_error_inject*/
|
||||
ret = psp_ras_trigger_error(&adev->psp, &block_info);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
@ -1766,24 +1713,28 @@ static void amdgpu_ras_log_on_err_counter(struct amdgpu_device *adev)
|
||||
static void amdgpu_ras_error_status_query(struct amdgpu_device *adev,
|
||||
struct ras_query_if *info)
|
||||
{
|
||||
struct amdgpu_ras_block_object *block_obj;
|
||||
/*
|
||||
* Only two block need to query read/write
|
||||
* RspStatus at current state
|
||||
*/
|
||||
switch (info->head.block) {
|
||||
case AMDGPU_RAS_BLOCK__GFX:
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->query_ras_error_status)
|
||||
adev->gfx.ras_funcs->query_ras_error_status(adev);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__MMHUB:
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->query_ras_error_status)
|
||||
adev->mmhub.ras_funcs->query_ras_error_status(adev);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if ((info->head.block != AMDGPU_RAS_BLOCK__GFX) &&
|
||||
(info->head.block != AMDGPU_RAS_BLOCK__MMHUB))
|
||||
return;
|
||||
|
||||
block_obj = amdgpu_ras_get_ras_block(adev,
|
||||
info->head.block,
|
||||
info->head.sub_block_index);
|
||||
|
||||
if (!block_obj || !block_obj->hw_ops) {
|
||||
dev_dbg_once(adev->dev, "%s doesn't config RAS function\n",
|
||||
get_ras_block_str(&info->head));
|
||||
return;
|
||||
}
|
||||
|
||||
if (block_obj->hw_ops->query_ras_error_status)
|
||||
block_obj->hw_ops->query_ras_error_status(adev);
|
||||
|
||||
}
|
||||
|
||||
static void amdgpu_ras_query_err_status(struct amdgpu_device *adev)
|
||||
@ -2141,8 +2092,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
|
||||
if (ret)
|
||||
goto free;
|
||||
|
||||
if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->send_hbm_bad_pages_num)
|
||||
adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.ras_num_recs);
|
||||
amdgpu_dpm_send_hbm_bad_pages_num(adev, con->eeprom_control.ras_num_recs);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_MCE_AMD
|
||||
@ -2348,24 +2298,26 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
|
||||
case CHIP_VEGA20:
|
||||
case CHIP_ARCTURUS:
|
||||
case CHIP_ALDEBARAN:
|
||||
if (!adev->gmc.xgmi.connected_to_cpu)
|
||||
adev->nbio.ras_funcs = &nbio_v7_4_ras_funcs;
|
||||
if (!adev->gmc.xgmi.connected_to_cpu) {
|
||||
adev->nbio.ras = &nbio_v7_4_ras;
|
||||
amdgpu_ras_register_ras_block(adev, &adev->nbio.ras->ras_block);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* nbio ras is not available */
|
||||
break;
|
||||
}
|
||||
|
||||
if (adev->nbio.ras_funcs &&
|
||||
adev->nbio.ras_funcs->init_ras_controller_interrupt) {
|
||||
r = adev->nbio.ras_funcs->init_ras_controller_interrupt(adev);
|
||||
if (adev->nbio.ras &&
|
||||
adev->nbio.ras->init_ras_controller_interrupt) {
|
||||
r = adev->nbio.ras->init_ras_controller_interrupt(adev);
|
||||
if (r)
|
||||
goto release_con;
|
||||
}
|
||||
|
||||
if (adev->nbio.ras_funcs &&
|
||||
adev->nbio.ras_funcs->init_ras_err_event_athub_interrupt) {
|
||||
r = adev->nbio.ras_funcs->init_ras_err_event_athub_interrupt(adev);
|
||||
if (adev->nbio.ras &&
|
||||
adev->nbio.ras->init_ras_err_event_athub_interrupt) {
|
||||
r = adev->nbio.ras->init_ras_err_event_athub_interrupt(adev);
|
||||
if (r)
|
||||
goto release_con;
|
||||
}
|
||||
@ -2377,12 +2329,12 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
|
||||
}
|
||||
else if (adev->df.funcs &&
|
||||
adev->df.funcs->query_ras_poison_mode &&
|
||||
adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->query_ras_poison_mode) {
|
||||
adev->umc.ras &&
|
||||
adev->umc.ras->query_ras_poison_mode) {
|
||||
df_poison =
|
||||
adev->df.funcs->query_ras_poison_mode(adev);
|
||||
umc_poison =
|
||||
adev->umc.ras_funcs->query_ras_poison_mode(adev);
|
||||
adev->umc.ras->query_ras_poison_mode(adev);
|
||||
/* Only poison is set in both DF and UMC, we can support it */
|
||||
if (df_poison && umc_poison)
|
||||
con->poison_supported = true;
|
||||
@ -2585,6 +2537,7 @@ int amdgpu_ras_pre_fini(struct amdgpu_device *adev)
|
||||
|
||||
int amdgpu_ras_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras_block_list *ras_node, *tmp;
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
|
||||
if (!adev->ras_enabled || !con)
|
||||
@ -2603,6 +2556,12 @@ int amdgpu_ras_fini(struct amdgpu_device *adev)
|
||||
amdgpu_ras_set_context(adev, NULL);
|
||||
kfree(con);
|
||||
|
||||
/* Clear ras blocks from ras_list and free ras block list node */
|
||||
list_for_each_entry_safe(ras_node, tmp, &adev->ras_list, node) {
|
||||
list_del(&ras_node->node);
|
||||
kfree(ras_node);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2717,8 +2676,6 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb,
|
||||
dev_info(adev->dev, "Uncorrectable error detected in UMC inst: %d, chan_idx: %d",
|
||||
umc_inst, ch_inst);
|
||||
|
||||
memset(&err_rec, 0x0, sizeof(struct eeprom_table_record));
|
||||
|
||||
/*
|
||||
* Translate UMC channel address to Physical address
|
||||
*/
|
||||
@ -2730,16 +2687,10 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb,
|
||||
ADDR_OF_256B_BLOCK(channel_index) |
|
||||
OFFSET_IN_256B_BLOCK(m->addr);
|
||||
|
||||
err_rec.address = m->addr;
|
||||
err_rec.retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT;
|
||||
err_rec.ts = (uint64_t)ktime_get_real_seconds();
|
||||
err_rec.err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE;
|
||||
err_rec.cu = 0;
|
||||
err_rec.mem_channel = channel_index;
|
||||
err_rec.mcumc_id = umc_inst;
|
||||
|
||||
memset(&err_rec, 0x0, sizeof(struct eeprom_table_record));
|
||||
err_data.err_addr = &err_rec;
|
||||
err_data.err_addr_cnt = 1;
|
||||
amdgpu_umc_fill_error_record(&err_data, m->addr,
|
||||
retired_page, channel_index, umc_inst);
|
||||
|
||||
if (amdgpu_bad_page_threshold != 0) {
|
||||
amdgpu_ras_add_bad_pages(adev, err_data.err_addr,
|
||||
@ -2777,3 +2728,63 @@ static void amdgpu_register_bad_pages_mca_notifier(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct amdgpu_ras *amdgpu_ras_get_context(struct amdgpu_device *adev)
|
||||
{
|
||||
if (!adev)
|
||||
return NULL;
|
||||
|
||||
return adev->psp.ras_context.ras;
|
||||
}
|
||||
|
||||
int amdgpu_ras_set_context(struct amdgpu_device *adev, struct amdgpu_ras *ras_con)
|
||||
{
|
||||
if (!adev)
|
||||
return -EINVAL;
|
||||
|
||||
adev->psp.ras_context.ras = ras_con;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check if ras is supported on block, say, sdma, gfx */
|
||||
int amdgpu_ras_is_supported(struct amdgpu_device *adev,
|
||||
unsigned int block)
|
||||
{
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
|
||||
if (block >= AMDGPU_RAS_BLOCK_COUNT)
|
||||
return 0;
|
||||
return ras && (adev->ras_enabled & (1 << block));
|
||||
}
|
||||
|
||||
int amdgpu_ras_reset_gpu(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
|
||||
if (atomic_cmpxchg(&ras->in_recovery, 0, 1) == 0)
|
||||
schedule_work(&ras->recovery_work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Register each ip ras block into amdgpu ras */
|
||||
int amdgpu_ras_register_ras_block(struct amdgpu_device *adev,
|
||||
struct amdgpu_ras_block_object *ras_block_obj)
|
||||
{
|
||||
struct amdgpu_ras_block_list *ras_node;
|
||||
if (!adev || !ras_block_obj)
|
||||
return -EINVAL;
|
||||
|
||||
if (!amdgpu_ras_asic_supported(adev))
|
||||
return 0;
|
||||
|
||||
ras_node = kzalloc(sizeof(*ras_node), GFP_KERNEL);
|
||||
if (!ras_node)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&ras_node->node);
|
||||
ras_node->ras_obj = ras_block_obj;
|
||||
list_add_tail(&ras_node->node, &adev->ras_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -26,11 +26,11 @@
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/list.h>
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_psp.h"
|
||||
#include "ta_ras_if.h"
|
||||
#include "amdgpu_ras_eeprom.h"
|
||||
|
||||
struct amdgpu_iv_entry;
|
||||
|
||||
#define AMDGPU_RAS_FLAG_INIT_BY_VBIOS (0x1 << 0)
|
||||
|
||||
enum amdgpu_ras_block {
|
||||
@ -484,6 +484,31 @@ struct ras_debug_if {
|
||||
};
|
||||
int op;
|
||||
};
|
||||
|
||||
struct amdgpu_ras_block_object {
|
||||
/* block name */
|
||||
char name[32];
|
||||
|
||||
enum amdgpu_ras_block block;
|
||||
|
||||
uint32_t sub_block_index;
|
||||
|
||||
int (*ras_block_match)(struct amdgpu_ras_block_object *block_obj,
|
||||
enum amdgpu_ras_block block, uint32_t sub_block_index);
|
||||
int (*ras_late_init)(struct amdgpu_device *adev, void *ras_info);
|
||||
void (*ras_fini)(struct amdgpu_device *adev);
|
||||
const struct amdgpu_ras_block_hw_ops *hw_ops;
|
||||
};
|
||||
|
||||
struct amdgpu_ras_block_hw_ops {
|
||||
int (*ras_error_inject)(struct amdgpu_device *adev, void *inject_if);
|
||||
void (*query_ras_error_count)(struct amdgpu_device *adev, void *ras_error_status);
|
||||
void (*query_ras_error_status)(struct amdgpu_device *adev);
|
||||
void (*query_ras_error_address)(struct amdgpu_device *adev, void *ras_error_status);
|
||||
void (*reset_ras_error_count)(struct amdgpu_device *adev);
|
||||
void (*reset_ras_error_status)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
/* work flow
|
||||
* vbios
|
||||
* 1: ras feature enable (enabled by default)
|
||||
@ -498,19 +523,6 @@ struct ras_debug_if {
|
||||
* 8: feature disable
|
||||
*/
|
||||
|
||||
#define amdgpu_ras_get_context(adev) ((adev)->psp.ras_context.ras)
|
||||
#define amdgpu_ras_set_context(adev, ras_con) ((adev)->psp.ras_context.ras = (ras_con))
|
||||
|
||||
/* check if ras is supported on block, say, sdma, gfx */
|
||||
static inline int amdgpu_ras_is_supported(struct amdgpu_device *adev,
|
||||
unsigned int block)
|
||||
{
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
|
||||
if (block >= AMDGPU_RAS_BLOCK_COUNT)
|
||||
return 0;
|
||||
return ras && (adev->ras_enabled & (1 << block));
|
||||
}
|
||||
|
||||
int amdgpu_ras_recovery_init(struct amdgpu_device *adev);
|
||||
|
||||
@ -527,15 +539,6 @@ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev,
|
||||
|
||||
int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev);
|
||||
|
||||
static inline int amdgpu_ras_reset_gpu(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
|
||||
if (atomic_cmpxchg(&ras->in_recovery, 0, 1) == 0)
|
||||
schedule_work(&ras->recovery_work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline enum ta_ras_block
|
||||
amdgpu_ras_block_to_ta(enum amdgpu_ras_block block) {
|
||||
switch (block) {
|
||||
@ -667,4 +670,14 @@ const char *get_ras_block_str(struct ras_common_if *ras_block);
|
||||
|
||||
bool amdgpu_ras_is_poison_mode_supported(struct amdgpu_device *adev);
|
||||
|
||||
int amdgpu_ras_is_supported(struct amdgpu_device *adev, unsigned int block);
|
||||
|
||||
int amdgpu_ras_reset_gpu(struct amdgpu_device *adev);
|
||||
|
||||
struct amdgpu_ras* amdgpu_ras_get_context(struct amdgpu_device *adev);
|
||||
|
||||
int amdgpu_ras_set_context(struct amdgpu_device *adev, struct amdgpu_ras *ras_con);
|
||||
|
||||
int amdgpu_ras_register_ras_block(struct amdgpu_device *adev,
|
||||
struct amdgpu_ras_block_object *ras_block_obj);
|
||||
#endif
|
||||
|
@ -194,7 +194,7 @@ static int __write_table_header(struct amdgpu_ras_eeprom_control *control)
|
||||
|
||||
/* i2c may be unstable in gpu reset */
|
||||
down_read(&adev->reset_sem);
|
||||
res = amdgpu_eeprom_write(&adev->pm.smu_i2c,
|
||||
res = amdgpu_eeprom_write(adev->pm.ras_eeprom_i2c_bus,
|
||||
control->i2c_address +
|
||||
control->ras_header_offset,
|
||||
buf, RAS_TABLE_HEADER_SIZE);
|
||||
@ -263,6 +263,7 @@ static int amdgpu_ras_eeprom_correct_header_tag(
|
||||
*/
|
||||
int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control)
|
||||
{
|
||||
struct amdgpu_device *adev = to_amdgpu_device(control);
|
||||
struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
|
||||
u8 csum;
|
||||
int res;
|
||||
@ -282,6 +283,8 @@ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control)
|
||||
control->ras_num_recs = 0;
|
||||
control->ras_fri = 0;
|
||||
|
||||
amdgpu_dpm_send_hbm_bad_pages_num(adev, control->ras_num_recs);
|
||||
|
||||
amdgpu_ras_debugfs_set_ret_size(control);
|
||||
|
||||
mutex_unlock(&control->ras_tbl_mutex);
|
||||
@ -389,7 +392,7 @@ static int __amdgpu_ras_eeprom_write(struct amdgpu_ras_eeprom_control *control,
|
||||
/* i2c may be unstable in gpu reset */
|
||||
down_read(&adev->reset_sem);
|
||||
buf_size = num * RAS_TABLE_RECORD_SIZE;
|
||||
res = amdgpu_eeprom_write(&adev->pm.smu_i2c,
|
||||
res = amdgpu_eeprom_write(adev->pm.ras_eeprom_i2c_bus,
|
||||
control->i2c_address +
|
||||
RAS_INDEX_TO_OFFSET(control, fri),
|
||||
buf, buf_size);
|
||||
@ -548,7 +551,7 @@ amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control)
|
||||
}
|
||||
|
||||
down_read(&adev->reset_sem);
|
||||
res = amdgpu_eeprom_read(&adev->pm.smu_i2c,
|
||||
res = amdgpu_eeprom_read(adev->pm.ras_eeprom_i2c_bus,
|
||||
control->i2c_address +
|
||||
control->ras_record_offset,
|
||||
buf, buf_size);
|
||||
@ -644,7 +647,7 @@ static int __amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control,
|
||||
/* i2c may be unstable in gpu reset */
|
||||
down_read(&adev->reset_sem);
|
||||
buf_size = num * RAS_TABLE_RECORD_SIZE;
|
||||
res = amdgpu_eeprom_read(&adev->pm.smu_i2c,
|
||||
res = amdgpu_eeprom_read(adev->pm.ras_eeprom_i2c_bus,
|
||||
control->i2c_address +
|
||||
RAS_INDEX_TO_OFFSET(control, fri),
|
||||
buf, buf_size);
|
||||
@ -1009,7 +1012,7 @@ static int __verify_ras_table_checksum(struct amdgpu_ras_eeprom_control *control
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = amdgpu_eeprom_read(&adev->pm.smu_i2c,
|
||||
res = amdgpu_eeprom_read(adev->pm.ras_eeprom_i2c_bus,
|
||||
control->i2c_address +
|
||||
control->ras_header_offset,
|
||||
buf, buf_size);
|
||||
@ -1045,7 +1048,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
|
||||
return 0;
|
||||
|
||||
/* Verify i2c adapter is initialized */
|
||||
if (!adev->pm.smu_i2c.algo)
|
||||
if (!adev->pm.ras_eeprom_i2c_bus || !adev->pm.ras_eeprom_i2c_bus->algo)
|
||||
return -ENOENT;
|
||||
|
||||
if (!__get_eeprom_i2c_addr(adev, control))
|
||||
@ -1057,7 +1060,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
|
||||
mutex_init(&control->ras_tbl_mutex);
|
||||
|
||||
/* Read the table header from EEPROM address */
|
||||
res = amdgpu_eeprom_read(&adev->pm.smu_i2c,
|
||||
res = amdgpu_eeprom_read(adev->pm.ras_eeprom_i2c_bus,
|
||||
control->i2c_address + control->ras_header_offset,
|
||||
buf, RAS_TABLE_HEADER_SIZE);
|
||||
if (res < RAS_TABLE_HEADER_SIZE) {
|
||||
|
@ -127,11 +127,19 @@ struct amdgpu_rlc_funcs {
|
||||
void (*reset)(struct amdgpu_device *adev);
|
||||
void (*start)(struct amdgpu_device *adev);
|
||||
void (*update_spm_vmid)(struct amdgpu_device *adev, unsigned vmid);
|
||||
void (*sriov_wreg)(struct amdgpu_device *adev, u32 offset, u32 v, u32 acc_flags, u32 hwip);
|
||||
u32 (*sriov_rreg)(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip);
|
||||
bool (*is_rlcg_access_range)(struct amdgpu_device *adev, uint32_t reg);
|
||||
};
|
||||
|
||||
struct amdgpu_rlcg_reg_access_ctrl {
|
||||
uint32_t scratch_reg0;
|
||||
uint32_t scratch_reg1;
|
||||
uint32_t scratch_reg2;
|
||||
uint32_t scratch_reg3;
|
||||
uint32_t grbm_cntl;
|
||||
uint32_t grbm_idx;
|
||||
uint32_t spare_int;
|
||||
};
|
||||
|
||||
struct amdgpu_rlc {
|
||||
/* for power gating */
|
||||
struct amdgpu_bo *save_restore_obj;
|
||||
@ -191,6 +199,10 @@ struct amdgpu_rlc {
|
||||
struct amdgpu_bo *rlc_toc_bo;
|
||||
uint64_t rlc_toc_gpu_addr;
|
||||
void *rlc_toc_buf;
|
||||
|
||||
bool rlcg_reg_access_supported;
|
||||
/* registers for rlcg indirect reg access */
|
||||
struct amdgpu_rlcg_reg_access_ctrl reg_access_ctrl;
|
||||
};
|
||||
|
||||
void amdgpu_gfx_rlc_enter_safe_mode(struct amdgpu_device *adev);
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#ifndef __AMDGPU_SDMA_H__
|
||||
#define __AMDGPU_SDMA_H__
|
||||
#include "amdgpu_ras.h"
|
||||
|
||||
/* max number of IP instances */
|
||||
#define AMDGPU_MAX_SDMA_INSTANCES 8
|
||||
@ -50,13 +51,8 @@ struct amdgpu_sdma_instance {
|
||||
bool burst_nop;
|
||||
};
|
||||
|
||||
struct amdgpu_sdma_ras_funcs {
|
||||
int (*ras_late_init)(struct amdgpu_device *adev,
|
||||
void *ras_ih_info);
|
||||
void (*ras_fini)(struct amdgpu_device *adev);
|
||||
int (*query_ras_error_count)(struct amdgpu_device *adev,
|
||||
uint32_t instance, void *ras_error_status);
|
||||
void (*reset_ras_error_count)(struct amdgpu_device *adev);
|
||||
struct amdgpu_sdma_ras {
|
||||
struct amdgpu_ras_block_object ras_block;
|
||||
};
|
||||
|
||||
struct amdgpu_sdma {
|
||||
@ -73,7 +69,7 @@ struct amdgpu_sdma {
|
||||
uint32_t srbm_soft_reset;
|
||||
bool has_page_queue;
|
||||
struct ras_common_if *ras_if;
|
||||
const struct amdgpu_sdma_ras_funcs *funcs;
|
||||
struct amdgpu_sdma_ras *ras;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -358,11 +358,10 @@ TRACE_EVENT(amdgpu_vm_update_ptes,
|
||||
}
|
||||
),
|
||||
TP_printk("pid:%u vm_ctx:0x%llx start:0x%010llx end:0x%010llx,"
|
||||
" flags:0x%llx, incr:%llu, dst:\n%s%s", __entry->pid,
|
||||
" flags:0x%llx, incr:%llu, dst:\n%s", __entry->pid,
|
||||
__entry->vm_ctx, __entry->start, __entry->end,
|
||||
__entry->flags, __entry->incr, __print_array(
|
||||
__get_dynamic_array(dst), min(__entry->nptes, 32u), 8),
|
||||
__entry->nptes > 32 ? "..." : "")
|
||||
__get_dynamic_array(dst), __entry->nptes, 8))
|
||||
);
|
||||
|
||||
TRACE_EVENT(amdgpu_vm_set_ptes,
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include <drm/ttm/ttm_range_manager.h>
|
||||
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_drv.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_object.h"
|
||||
@ -170,10 +171,10 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
|
||||
* @bo: buffer object to map
|
||||
* @mem: memory object to map
|
||||
* @mm_cur: range to map
|
||||
* @num_pages: number of pages to map
|
||||
* @window: which GART window to use
|
||||
* @ring: DMA ring to use for the copy
|
||||
* @tmz: if we should setup a TMZ enabled mapping
|
||||
* @size: in number of bytes to map, out number of bytes mapped
|
||||
* @addr: resulting address inside the MC address space
|
||||
*
|
||||
* Setup one of the GART windows to access a specific piece of memory or return
|
||||
@ -182,15 +183,14 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
|
||||
static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo,
|
||||
struct ttm_resource *mem,
|
||||
struct amdgpu_res_cursor *mm_cur,
|
||||
unsigned num_pages, unsigned window,
|
||||
struct amdgpu_ring *ring, bool tmz,
|
||||
uint64_t *addr)
|
||||
unsigned window, struct amdgpu_ring *ring,
|
||||
bool tmz, uint64_t *size, uint64_t *addr)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_job *job;
|
||||
unsigned num_dw, num_bytes;
|
||||
struct dma_fence *fence;
|
||||
unsigned offset, num_pages, num_dw, num_bytes;
|
||||
uint64_t src_addr, dst_addr;
|
||||
struct dma_fence *fence;
|
||||
struct amdgpu_job *job;
|
||||
void *cpu_addr;
|
||||
uint64_t flags;
|
||||
unsigned int i;
|
||||
@ -198,7 +198,9 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo,
|
||||
|
||||
BUG_ON(adev->mman.buffer_funcs->copy_max_bytes <
|
||||
AMDGPU_GTT_MAX_TRANSFER_SIZE * 8);
|
||||
BUG_ON(mem->mem_type == AMDGPU_PL_PREEMPT);
|
||||
|
||||
if (WARN_ON(mem->mem_type == AMDGPU_PL_PREEMPT))
|
||||
return -EINVAL;
|
||||
|
||||
/* Map only what can't be accessed directly */
|
||||
if (!tmz && mem->start != AMDGPU_BO_INVALID_OFFSET) {
|
||||
@ -207,10 +209,22 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If start begins at an offset inside the page, then adjust the size
|
||||
* and addr accordingly
|
||||
*/
|
||||
offset = mm_cur->start & ~PAGE_MASK;
|
||||
|
||||
num_pages = PFN_UP(*size + offset);
|
||||
num_pages = min_t(uint32_t, num_pages, AMDGPU_GTT_MAX_TRANSFER_SIZE);
|
||||
|
||||
*size = min(*size, (uint64_t)num_pages * PAGE_SIZE - offset);
|
||||
|
||||
*addr = adev->gmc.gart_start;
|
||||
*addr += (u64)window * AMDGPU_GTT_MAX_TRANSFER_SIZE *
|
||||
AMDGPU_GPU_PAGE_SIZE;
|
||||
*addr += mm_cur->start & ~PAGE_MASK;
|
||||
*addr += offset;
|
||||
|
||||
num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8);
|
||||
num_bytes = num_pages * 8 * AMDGPU_GPU_PAGES_IN_CPU_PAGE;
|
||||
@ -241,10 +255,7 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo,
|
||||
dma_addr_t *dma_addr;
|
||||
|
||||
dma_addr = &bo->ttm->dma_address[mm_cur->start >> PAGE_SHIFT];
|
||||
r = amdgpu_gart_map(adev, 0, num_pages, dma_addr, flags,
|
||||
cpu_addr);
|
||||
if (r)
|
||||
goto error_free;
|
||||
amdgpu_gart_map(adev, 0, num_pages, dma_addr, flags, cpu_addr);
|
||||
} else {
|
||||
dma_addr_t dma_address;
|
||||
|
||||
@ -252,11 +263,8 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo,
|
||||
dma_address += adev->vm_manager.vram_base_offset;
|
||||
|
||||
for (i = 0; i < num_pages; ++i) {
|
||||
r = amdgpu_gart_map(adev, i << PAGE_SHIFT, 1,
|
||||
&dma_address, flags, cpu_addr);
|
||||
if (r)
|
||||
goto error_free;
|
||||
|
||||
amdgpu_gart_map(adev, i << PAGE_SHIFT, 1, &dma_address,
|
||||
flags, cpu_addr);
|
||||
dma_address += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
@ -297,9 +305,6 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
|
||||
struct dma_resv *resv,
|
||||
struct dma_fence **f)
|
||||
{
|
||||
const uint32_t GTT_MAX_BYTES = (AMDGPU_GTT_MAX_TRANSFER_SIZE *
|
||||
AMDGPU_GPU_PAGE_SIZE);
|
||||
|
||||
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
|
||||
struct amdgpu_res_cursor src_mm, dst_mm;
|
||||
struct dma_fence *fence = NULL;
|
||||
@ -315,29 +320,20 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
|
||||
|
||||
mutex_lock(&adev->mman.gtt_window_lock);
|
||||
while (src_mm.remaining) {
|
||||
uint32_t src_page_offset = src_mm.start & ~PAGE_MASK;
|
||||
uint32_t dst_page_offset = dst_mm.start & ~PAGE_MASK;
|
||||
uint64_t from, to, cur_size;
|
||||
struct dma_fence *next;
|
||||
uint32_t cur_size;
|
||||
uint64_t from, to;
|
||||
|
||||
/* Copy size cannot exceed GTT_MAX_BYTES. So if src or dst
|
||||
* begins at an offset, then adjust the size accordingly
|
||||
*/
|
||||
cur_size = max(src_page_offset, dst_page_offset);
|
||||
cur_size = min(min3(src_mm.size, dst_mm.size, size),
|
||||
(uint64_t)(GTT_MAX_BYTES - cur_size));
|
||||
/* Never copy more than 256MiB at once to avoid a timeout */
|
||||
cur_size = min3(src_mm.size, dst_mm.size, 256ULL << 20);
|
||||
|
||||
/* Map src to window 0 and dst to window 1. */
|
||||
r = amdgpu_ttm_map_buffer(src->bo, src->mem, &src_mm,
|
||||
PFN_UP(cur_size + src_page_offset),
|
||||
0, ring, tmz, &from);
|
||||
0, ring, tmz, &cur_size, &from);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
r = amdgpu_ttm_map_buffer(dst->bo, dst->mem, &dst_mm,
|
||||
PFN_UP(cur_size + dst_page_offset),
|
||||
1, ring, tmz, &to);
|
||||
1, ring, tmz, &cur_size, &to);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
@ -396,8 +392,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
|
||||
(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE)) {
|
||||
struct dma_fence *wipe_fence = NULL;
|
||||
|
||||
r = amdgpu_fill_buffer(ttm_to_amdgpu_bo(bo), AMDGPU_POISON,
|
||||
NULL, &wipe_fence);
|
||||
r = amdgpu_fill_buffer(abo, AMDGPU_POISON, NULL, &wipe_fence);
|
||||
if (r) {
|
||||
goto error;
|
||||
} else if (wipe_fence) {
|
||||
@ -821,14 +816,13 @@ static void amdgpu_ttm_tt_unpin_userptr(struct ttm_device *bdev,
|
||||
#endif
|
||||
}
|
||||
|
||||
static int amdgpu_ttm_gart_bind(struct amdgpu_device *adev,
|
||||
struct ttm_buffer_object *tbo,
|
||||
uint64_t flags)
|
||||
static void amdgpu_ttm_gart_bind(struct amdgpu_device *adev,
|
||||
struct ttm_buffer_object *tbo,
|
||||
uint64_t flags)
|
||||
{
|
||||
struct amdgpu_bo *abo = ttm_to_amdgpu_bo(tbo);
|
||||
struct ttm_tt *ttm = tbo->ttm;
|
||||
struct amdgpu_ttm_tt *gtt = (void *)ttm;
|
||||
int r;
|
||||
|
||||
if (amdgpu_bo_encrypted(abo))
|
||||
flags |= AMDGPU_PTE_TMZ;
|
||||
@ -836,10 +830,8 @@ static int amdgpu_ttm_gart_bind(struct amdgpu_device *adev,
|
||||
if (abo->flags & AMDGPU_GEM_CREATE_CP_MQD_GFX9) {
|
||||
uint64_t page_idx = 1;
|
||||
|
||||
r = amdgpu_gart_bind(adev, gtt->offset, page_idx,
|
||||
gtt->ttm.dma_address, flags);
|
||||
if (r)
|
||||
goto gart_bind_fail;
|
||||
amdgpu_gart_bind(adev, gtt->offset, page_idx,
|
||||
gtt->ttm.dma_address, flags);
|
||||
|
||||
/* The memory type of the first page defaults to UC. Now
|
||||
* modify the memory type to NC from the second page of
|
||||
@ -848,21 +840,13 @@ static int amdgpu_ttm_gart_bind(struct amdgpu_device *adev,
|
||||
flags &= ~AMDGPU_PTE_MTYPE_VG10_MASK;
|
||||
flags |= AMDGPU_PTE_MTYPE_VG10(AMDGPU_MTYPE_NC);
|
||||
|
||||
r = amdgpu_gart_bind(adev,
|
||||
gtt->offset + (page_idx << PAGE_SHIFT),
|
||||
ttm->num_pages - page_idx,
|
||||
&(gtt->ttm.dma_address[page_idx]), flags);
|
||||
amdgpu_gart_bind(adev, gtt->offset + (page_idx << PAGE_SHIFT),
|
||||
ttm->num_pages - page_idx,
|
||||
&(gtt->ttm.dma_address[page_idx]), flags);
|
||||
} else {
|
||||
r = amdgpu_gart_bind(adev, gtt->offset, ttm->num_pages,
|
||||
gtt->ttm.dma_address, flags);
|
||||
amdgpu_gart_bind(adev, gtt->offset, ttm->num_pages,
|
||||
gtt->ttm.dma_address, flags);
|
||||
}
|
||||
|
||||
gart_bind_fail:
|
||||
if (r)
|
||||
DRM_ERROR("failed to bind %u pages at 0x%08llX\n",
|
||||
ttm->num_pages, gtt->offset);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -878,7 +862,7 @@ static int amdgpu_ttm_backend_bind(struct ttm_device *bdev,
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bdev);
|
||||
struct amdgpu_ttm_tt *gtt = (void*)ttm;
|
||||
uint64_t flags;
|
||||
int r = 0;
|
||||
int r;
|
||||
|
||||
if (!bo_mem)
|
||||
return -EINVAL;
|
||||
@ -925,14 +909,10 @@ static int amdgpu_ttm_backend_bind(struct ttm_device *bdev,
|
||||
|
||||
/* bind pages into GART page tables */
|
||||
gtt->offset = (u64)bo_mem->start << PAGE_SHIFT;
|
||||
r = amdgpu_gart_bind(adev, gtt->offset, ttm->num_pages,
|
||||
gtt->ttm.dma_address, flags);
|
||||
|
||||
if (r)
|
||||
DRM_ERROR("failed to bind %u pages at 0x%08llX\n",
|
||||
ttm->num_pages, gtt->offset);
|
||||
amdgpu_gart_bind(adev, gtt->offset, ttm->num_pages,
|
||||
gtt->ttm.dma_address, flags);
|
||||
gtt->bound = true;
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -982,12 +962,7 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo)
|
||||
|
||||
/* Bind pages */
|
||||
gtt->offset = (u64)tmp->start << PAGE_SHIFT;
|
||||
r = amdgpu_ttm_gart_bind(adev, bo, flags);
|
||||
if (unlikely(r)) {
|
||||
ttm_resource_free(bo, &tmp);
|
||||
return r;
|
||||
}
|
||||
|
||||
amdgpu_ttm_gart_bind(adev, bo, flags);
|
||||
amdgpu_gart_invalidate_tlb(adev);
|
||||
ttm_resource_free(bo, &bo->resource);
|
||||
ttm_bo_assign_mem(bo, tmp);
|
||||
@ -1001,19 +976,16 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo)
|
||||
* Called by amdgpu_gtt_mgr_recover() from amdgpu_device_reset() to
|
||||
* rebind GTT pages during a GPU reset.
|
||||
*/
|
||||
int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo)
|
||||
void amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo)
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev);
|
||||
uint64_t flags;
|
||||
int r;
|
||||
|
||||
if (!tbo->ttm)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
flags = amdgpu_ttm_tt_pte_flags(adev, tbo->ttm, tbo->resource);
|
||||
r = amdgpu_ttm_gart_bind(adev, tbo, flags);
|
||||
|
||||
return r;
|
||||
amdgpu_ttm_gart_bind(adev, tbo, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1027,7 +999,6 @@ static void amdgpu_ttm_backend_unbind(struct ttm_device *bdev,
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bdev);
|
||||
struct amdgpu_ttm_tt *gtt = (void *)ttm;
|
||||
int r;
|
||||
|
||||
/* if the pages have userptr pinning then clear that first */
|
||||
if (gtt->userptr) {
|
||||
@ -1047,10 +1018,7 @@ static void amdgpu_ttm_backend_unbind(struct ttm_device *bdev,
|
||||
return;
|
||||
|
||||
/* unbind shouldn't be done for GDS/GWS/OA in ttm_bo_clean_mm */
|
||||
r = amdgpu_gart_unbind(adev, gtt->offset, ttm->num_pages);
|
||||
if (r)
|
||||
DRM_ERROR("failed to unbind %u pages at 0x%08llX\n",
|
||||
gtt->ttm.num_pages, gtt->offset);
|
||||
amdgpu_gart_unbind(adev, gtt->offset, ttm->num_pages);
|
||||
gtt->bound = false;
|
||||
}
|
||||
|
||||
@ -1168,6 +1136,26 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_device *bdev,
|
||||
return ttm_pool_free(&adev->mman.bdev.pool, ttm);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_ttm_tt_get_userptr - Return the userptr GTT ttm_tt for the current
|
||||
* task
|
||||
*
|
||||
* @tbo: The ttm_buffer_object that contains the userptr
|
||||
* @user_addr: The returned value
|
||||
*/
|
||||
int amdgpu_ttm_tt_get_userptr(const struct ttm_buffer_object *tbo,
|
||||
uint64_t *user_addr)
|
||||
{
|
||||
struct amdgpu_ttm_tt *gtt;
|
||||
|
||||
if (!tbo->ttm)
|
||||
return -EINVAL;
|
||||
|
||||
gtt = (void *)tbo->ttm;
|
||||
*user_addr = gtt->userptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_ttm_tt_set_userptr - Initialize userptr GTT ttm_tt for the current
|
||||
* task
|
||||
@ -1433,6 +1421,63 @@ static void amdgpu_ttm_vram_mm_access(struct amdgpu_device *adev, loff_t pos,
|
||||
}
|
||||
}
|
||||
|
||||
static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo,
|
||||
unsigned long offset, void *buf, int len, int write)
|
||||
{
|
||||
struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev);
|
||||
struct amdgpu_res_cursor src_mm;
|
||||
struct amdgpu_job *job;
|
||||
struct dma_fence *fence;
|
||||
uint64_t src_addr, dst_addr;
|
||||
unsigned int num_dw;
|
||||
int r, idx;
|
||||
|
||||
if (len != PAGE_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
if (!adev->mman.sdma_access_ptr)
|
||||
return -EACCES;
|
||||
|
||||
if (!drm_dev_enter(adev_to_drm(adev), &idx))
|
||||
return -ENODEV;
|
||||
|
||||
if (write)
|
||||
memcpy(adev->mman.sdma_access_ptr, buf, len);
|
||||
|
||||
num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8);
|
||||
r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, AMDGPU_IB_POOL_DELAYED, &job);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
amdgpu_res_first(abo->tbo.resource, offset, len, &src_mm);
|
||||
src_addr = amdgpu_ttm_domain_start(adev, bo->resource->mem_type) + src_mm.start;
|
||||
dst_addr = amdgpu_bo_gpu_offset(adev->mman.sdma_access_bo);
|
||||
if (write)
|
||||
swap(src_addr, dst_addr);
|
||||
|
||||
amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, dst_addr, PAGE_SIZE, false);
|
||||
|
||||
amdgpu_ring_pad_ib(adev->mman.buffer_funcs_ring, &job->ibs[0]);
|
||||
WARN_ON(job->ibs[0].length_dw > num_dw);
|
||||
|
||||
r = amdgpu_job_submit(job, &adev->mman.entity, AMDGPU_FENCE_OWNER_UNDEFINED, &fence);
|
||||
if (r) {
|
||||
amdgpu_job_free(job);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!dma_fence_wait_timeout(fence, false, adev->sdma_timeout))
|
||||
r = -ETIMEDOUT;
|
||||
dma_fence_put(fence);
|
||||
|
||||
if (!(r || write))
|
||||
memcpy(buf, adev->mman.sdma_access_ptr, len);
|
||||
out:
|
||||
drm_dev_exit(idx);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_ttm_access_memory - Read or Write memory that backs a buffer object.
|
||||
*
|
||||
@ -1457,6 +1502,10 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo,
|
||||
if (bo->resource->mem_type != TTM_PL_VRAM)
|
||||
return -EIO;
|
||||
|
||||
if (amdgpu_device_has_timeouts_enabled(adev) &&
|
||||
!amdgpu_ttm_access_memory_sdma(bo, offset, buf, len, write))
|
||||
return len;
|
||||
|
||||
amdgpu_res_first(bo->resource, offset, len, &cursor);
|
||||
while (cursor.remaining) {
|
||||
size_t count, size = cursor.size;
|
||||
@ -1797,6 +1846,12 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (amdgpu_bo_create_kernel(adev, PAGE_SIZE, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->mman.sdma_access_bo, NULL,
|
||||
&adev->mman.sdma_access_ptr))
|
||||
DRM_WARN("Debug VRAM access will use slowpath MM access\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1818,6 +1873,8 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
|
||||
if (adev->mman.stolen_reserved_size)
|
||||
amdgpu_bo_free_kernel(&adev->mman.stolen_reserved_memory,
|
||||
NULL, NULL);
|
||||
amdgpu_bo_free_kernel(&adev->mman.sdma_access_bo, NULL,
|
||||
&adev->mman.sdma_access_ptr);
|
||||
amdgpu_ttm_fw_reserve_vram_fini(adev);
|
||||
|
||||
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
|
||||
@ -1888,23 +1945,55 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
|
||||
adev->mman.buffer_funcs_enabled = enable;
|
||||
}
|
||||
|
||||
static int amdgpu_ttm_prepare_job(struct amdgpu_device *adev,
|
||||
bool direct_submit,
|
||||
unsigned int num_dw,
|
||||
struct dma_resv *resv,
|
||||
bool vm_needs_flush,
|
||||
struct amdgpu_job **job)
|
||||
{
|
||||
enum amdgpu_ib_pool_type pool = direct_submit ?
|
||||
AMDGPU_IB_POOL_DIRECT :
|
||||
AMDGPU_IB_POOL_DELAYED;
|
||||
int r;
|
||||
|
||||
r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, pool, job);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (vm_needs_flush) {
|
||||
(*job)->vm_pd_addr = amdgpu_gmc_pd_addr(adev->gmc.pdb0_bo ?
|
||||
adev->gmc.pdb0_bo :
|
||||
adev->gart.bo);
|
||||
(*job)->vm_needs_flush = true;
|
||||
}
|
||||
if (resv) {
|
||||
r = amdgpu_sync_resv(adev, &(*job)->sync, resv,
|
||||
AMDGPU_SYNC_ALWAYS,
|
||||
AMDGPU_FENCE_OWNER_UNDEFINED);
|
||||
if (r) {
|
||||
DRM_ERROR("sync failed (%d).\n", r);
|
||||
amdgpu_job_free(*job);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset,
|
||||
uint64_t dst_offset, uint32_t byte_count,
|
||||
struct dma_resv *resv,
|
||||
struct dma_fence **fence, bool direct_submit,
|
||||
bool vm_needs_flush, bool tmz)
|
||||
{
|
||||
enum amdgpu_ib_pool_type pool = direct_submit ? AMDGPU_IB_POOL_DIRECT :
|
||||
AMDGPU_IB_POOL_DELAYED;
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_job *job;
|
||||
|
||||
uint32_t max_bytes;
|
||||
unsigned num_loops, num_dw;
|
||||
struct amdgpu_job *job;
|
||||
uint32_t max_bytes;
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
if (direct_submit && !ring->sched.ready) {
|
||||
if (!direct_submit && !ring->sched.ready) {
|
||||
DRM_ERROR("Trying to move memory with ring turned off.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1912,26 +2001,11 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset,
|
||||
max_bytes = adev->mman.buffer_funcs->copy_max_bytes;
|
||||
num_loops = DIV_ROUND_UP(byte_count, max_bytes);
|
||||
num_dw = ALIGN(num_loops * adev->mman.buffer_funcs->copy_num_dw, 8);
|
||||
|
||||
r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, pool, &job);
|
||||
r = amdgpu_ttm_prepare_job(adev, direct_submit, num_dw,
|
||||
resv, vm_needs_flush, &job);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (vm_needs_flush) {
|
||||
job->vm_pd_addr = amdgpu_gmc_pd_addr(adev->gmc.pdb0_bo ?
|
||||
adev->gmc.pdb0_bo : adev->gart.bo);
|
||||
job->vm_needs_flush = true;
|
||||
}
|
||||
if (resv) {
|
||||
r = amdgpu_sync_resv(adev, &job->sync, resv,
|
||||
AMDGPU_SYNC_ALWAYS,
|
||||
AMDGPU_FENCE_OWNER_UNDEFINED);
|
||||
if (r) {
|
||||
DRM_ERROR("sync failed (%d).\n", r);
|
||||
goto error_free;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < num_loops; i++) {
|
||||
uint32_t cur_size_in_bytes = min(byte_count, max_bytes);
|
||||
|
||||
@ -1961,77 +2035,35 @@ error_free:
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_fill_buffer(struct amdgpu_bo *bo,
|
||||
uint32_t src_data,
|
||||
struct dma_resv *resv,
|
||||
struct dma_fence **fence)
|
||||
static int amdgpu_ttm_fill_mem(struct amdgpu_ring *ring, uint32_t src_data,
|
||||
uint64_t dst_addr, uint32_t byte_count,
|
||||
struct dma_resv *resv,
|
||||
struct dma_fence **fence,
|
||||
bool vm_needs_flush)
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
uint32_t max_bytes = adev->mman.buffer_funcs->fill_max_bytes;
|
||||
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
|
||||
|
||||
struct amdgpu_res_cursor cursor;
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
unsigned int num_loops, num_dw;
|
||||
uint64_t num_bytes;
|
||||
|
||||
struct amdgpu_job *job;
|
||||
uint32_t max_bytes;
|
||||
unsigned int i;
|
||||
int r;
|
||||
|
||||
if (!adev->mman.buffer_funcs_enabled) {
|
||||
DRM_ERROR("Trying to clear memory with ring turned off.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (bo->tbo.resource->mem_type == AMDGPU_PL_PREEMPT) {
|
||||
DRM_ERROR("Trying to clear preemptible memory.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (bo->tbo.resource->mem_type == TTM_PL_TT) {
|
||||
r = amdgpu_ttm_alloc_gart(&bo->tbo);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
num_bytes = bo->tbo.resource->num_pages << PAGE_SHIFT;
|
||||
num_loops = 0;
|
||||
|
||||
amdgpu_res_first(bo->tbo.resource, 0, num_bytes, &cursor);
|
||||
while (cursor.remaining) {
|
||||
num_loops += DIV_ROUND_UP_ULL(cursor.size, max_bytes);
|
||||
amdgpu_res_next(&cursor, cursor.size);
|
||||
}
|
||||
num_dw = num_loops * adev->mman.buffer_funcs->fill_num_dw;
|
||||
|
||||
/* for IB padding */
|
||||
num_dw += 64;
|
||||
|
||||
r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, AMDGPU_IB_POOL_DELAYED,
|
||||
&job);
|
||||
max_bytes = adev->mman.buffer_funcs->fill_max_bytes;
|
||||
num_loops = DIV_ROUND_UP_ULL(byte_count, max_bytes);
|
||||
num_dw = ALIGN(num_loops * adev->mman.buffer_funcs->fill_num_dw, 8);
|
||||
r = amdgpu_ttm_prepare_job(adev, false, num_dw, resv, vm_needs_flush,
|
||||
&job);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (resv) {
|
||||
r = amdgpu_sync_resv(adev, &job->sync, resv,
|
||||
AMDGPU_SYNC_ALWAYS,
|
||||
AMDGPU_FENCE_OWNER_UNDEFINED);
|
||||
if (r) {
|
||||
DRM_ERROR("sync failed (%d).\n", r);
|
||||
goto error_free;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < num_loops; i++) {
|
||||
uint32_t cur_size = min(byte_count, max_bytes);
|
||||
|
||||
amdgpu_res_first(bo->tbo.resource, 0, num_bytes, &cursor);
|
||||
while (cursor.remaining) {
|
||||
uint32_t cur_size = min_t(uint64_t, cursor.size, max_bytes);
|
||||
uint64_t dst_addr = cursor.start;
|
||||
|
||||
dst_addr += amdgpu_ttm_domain_start(adev,
|
||||
bo->tbo.resource->mem_type);
|
||||
amdgpu_emit_fill_buffer(adev, &job->ibs[0], src_data, dst_addr,
|
||||
cur_size);
|
||||
|
||||
amdgpu_res_next(&cursor, cur_size);
|
||||
dst_addr += cur_size;
|
||||
byte_count -= cur_size;
|
||||
}
|
||||
|
||||
amdgpu_ring_pad_ib(ring, &job->ibs[0]);
|
||||
@ -2048,6 +2080,55 @@ error_free:
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_fill_buffer(struct amdgpu_bo *bo,
|
||||
uint32_t src_data,
|
||||
struct dma_resv *resv,
|
||||
struct dma_fence **f)
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
|
||||
struct dma_fence *fence = NULL;
|
||||
struct amdgpu_res_cursor dst;
|
||||
int r;
|
||||
|
||||
if (!adev->mman.buffer_funcs_enabled) {
|
||||
DRM_ERROR("Trying to clear memory with ring turned off.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &dst);
|
||||
|
||||
mutex_lock(&adev->mman.gtt_window_lock);
|
||||
while (dst.remaining) {
|
||||
struct dma_fence *next;
|
||||
uint64_t cur_size, to;
|
||||
|
||||
/* Never fill more than 256MiB at once to avoid timeouts */
|
||||
cur_size = min(dst.size, 256ULL << 20);
|
||||
|
||||
r = amdgpu_ttm_map_buffer(&bo->tbo, bo->tbo.resource, &dst,
|
||||
1, ring, false, &cur_size, &to);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
r = amdgpu_ttm_fill_mem(ring, src_data, to, cur_size, resv,
|
||||
&next, true);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
dma_fence_put(fence);
|
||||
fence = next;
|
||||
|
||||
amdgpu_res_next(&dst, cur_size);
|
||||
}
|
||||
error:
|
||||
mutex_unlock(&adev->mman.gtt_window_lock);
|
||||
if (f)
|
||||
*f = dma_fence_get(fence);
|
||||
dma_fence_put(fence);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_ttm_evict_resources - evict memory buffers
|
||||
* @adev: amdgpu device object
|
||||
|
@ -98,6 +98,10 @@ struct amdgpu_mman {
|
||||
u64 fw_vram_usage_size;
|
||||
struct amdgpu_bo *fw_vram_usage_reserved_bo;
|
||||
void *fw_vram_usage_va;
|
||||
|
||||
/* PAGE_SIZE'd BO for process memory r/w over SDMA. */
|
||||
struct amdgpu_bo *sdma_access_bo;
|
||||
void *sdma_access_ptr;
|
||||
};
|
||||
|
||||
struct amdgpu_copy_mem {
|
||||
@ -115,7 +119,7 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev);
|
||||
|
||||
bool amdgpu_gtt_mgr_has_gart_addr(struct ttm_resource *mem);
|
||||
uint64_t amdgpu_gtt_mgr_usage(struct amdgpu_gtt_mgr *mgr);
|
||||
int amdgpu_gtt_mgr_recover(struct amdgpu_gtt_mgr *mgr);
|
||||
void amdgpu_gtt_mgr_recover(struct amdgpu_gtt_mgr *mgr);
|
||||
|
||||
uint64_t amdgpu_preempt_mgr_usage(struct ttm_resource_manager *man);
|
||||
|
||||
@ -158,7 +162,7 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo,
|
||||
struct dma_fence **fence);
|
||||
|
||||
int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo);
|
||||
int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo);
|
||||
void amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo);
|
||||
uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, uint32_t type);
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_AMDGPU_USERPTR)
|
||||
@ -177,6 +181,8 @@ static inline bool amdgpu_ttm_tt_get_user_pages_done(struct ttm_tt *ttm)
|
||||
#endif
|
||||
|
||||
void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct page **pages);
|
||||
int amdgpu_ttm_tt_get_userptr(const struct ttm_buffer_object *tbo,
|
||||
uint64_t *user_addr);
|
||||
int amdgpu_ttm_tt_set_userptr(struct ttm_buffer_object *bo,
|
||||
uint64_t addr, uint32_t flags);
|
||||
bool amdgpu_ttm_tt_has_userptr(struct ttm_tt *ttm);
|
||||
|
@ -378,6 +378,7 @@ enum AMDGPU_UCODE_ID {
|
||||
AMDGPU_UCODE_ID_VCN0_RAM,
|
||||
AMDGPU_UCODE_ID_VCN1_RAM,
|
||||
AMDGPU_UCODE_ID_DMCUB,
|
||||
AMDGPU_UCODE_ID_CAP,
|
||||
AMDGPU_UCODE_ID_MAXIMUM,
|
||||
};
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu.h"
|
||||
|
||||
static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
|
||||
void *ras_error_status,
|
||||
@ -33,14 +33,14 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
|
||||
int ret = 0;
|
||||
|
||||
kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
|
||||
ret = smu_get_ecc_info(&adev->smu, (void *)&(con->umc_ecc));
|
||||
ret = amdgpu_dpm_get_ecc_info(adev, (void *)&(con->umc_ecc));
|
||||
if (ret == -EOPNOTSUPP) {
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->query_ras_error_count)
|
||||
adev->umc.ras_funcs->query_ras_error_count(adev, ras_error_status);
|
||||
if (adev->umc.ras && adev->umc.ras->ras_block.hw_ops &&
|
||||
adev->umc.ras->ras_block.hw_ops->query_ras_error_count)
|
||||
adev->umc.ras->ras_block.hw_ops->query_ras_error_count(adev, ras_error_status);
|
||||
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->query_ras_error_address &&
|
||||
if (adev->umc.ras && adev->umc.ras->ras_block.hw_ops &&
|
||||
adev->umc.ras->ras_block.hw_ops->query_ras_error_address &&
|
||||
adev->umc.max_ras_err_cnt_per_query) {
|
||||
err_data->err_addr =
|
||||
kcalloc(adev->umc.max_ras_err_cnt_per_query,
|
||||
@ -56,15 +56,15 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
|
||||
/* umc query_ras_error_address is also responsible for clearing
|
||||
* error status
|
||||
*/
|
||||
adev->umc.ras_funcs->query_ras_error_address(adev, ras_error_status);
|
||||
adev->umc.ras->ras_block.hw_ops->query_ras_error_address(adev, ras_error_status);
|
||||
}
|
||||
} else if (!ret) {
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->ecc_info_query_ras_error_count)
|
||||
adev->umc.ras_funcs->ecc_info_query_ras_error_count(adev, ras_error_status);
|
||||
if (adev->umc.ras &&
|
||||
adev->umc.ras->ecc_info_query_ras_error_count)
|
||||
adev->umc.ras->ecc_info_query_ras_error_count(adev, ras_error_status);
|
||||
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->ecc_info_query_ras_error_address &&
|
||||
if (adev->umc.ras &&
|
||||
adev->umc.ras->ecc_info_query_ras_error_address &&
|
||||
adev->umc.max_ras_err_cnt_per_query) {
|
||||
err_data->err_addr =
|
||||
kcalloc(adev->umc.max_ras_err_cnt_per_query,
|
||||
@ -80,7 +80,7 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
|
||||
/* umc query_ras_error_address is also responsible for clearing
|
||||
* error status
|
||||
*/
|
||||
adev->umc.ras_funcs->ecc_info_query_ras_error_address(adev, ras_error_status);
|
||||
adev->umc.ras->ecc_info_query_ras_error_address(adev, ras_error_status);
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,8 +96,7 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
|
||||
err_data->err_addr_cnt);
|
||||
amdgpu_ras_save_bad_pages(adev);
|
||||
|
||||
if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->send_hbm_bad_pages_num)
|
||||
adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.ras_num_recs);
|
||||
amdgpu_dpm_send_hbm_bad_pages_num(adev, con->eeprom_control.ras_num_recs);
|
||||
}
|
||||
|
||||
if (reset)
|
||||
@ -137,7 +136,7 @@ static int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev,
|
||||
return amdgpu_umc_do_page_retirement(adev, ras_error_status, entry, true);
|
||||
}
|
||||
|
||||
int amdgpu_umc_ras_late_init(struct amdgpu_device *adev)
|
||||
int amdgpu_umc_ras_late_init(struct amdgpu_device *adev, void *ras_info)
|
||||
{
|
||||
int r;
|
||||
struct ras_fs_if fs_info = {
|
||||
@ -173,9 +172,9 @@ int amdgpu_umc_ras_late_init(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
/* ras init of specific umc version */
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->err_cnt_init)
|
||||
adev->umc.ras_funcs->err_cnt_init(adev);
|
||||
if (adev->umc.ras &&
|
||||
adev->umc.ras->err_cnt_init)
|
||||
adev->umc.ras->err_cnt_init(adev);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -219,3 +218,24 @@ int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev,
|
||||
amdgpu_ras_interrupt_dispatch(adev, &ih_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_umc_fill_error_record(struct ras_err_data *err_data,
|
||||
uint64_t err_addr,
|
||||
uint64_t retired_page,
|
||||
uint32_t channel_index,
|
||||
uint32_t umc_inst)
|
||||
{
|
||||
struct eeprom_table_record *err_rec =
|
||||
&err_data->err_addr[err_data->err_addr_cnt];
|
||||
|
||||
err_rec->address = err_addr;
|
||||
/* page frame address is saved */
|
||||
err_rec->retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT;
|
||||
err_rec->ts = (uint64_t)ktime_get_real_seconds();
|
||||
err_rec->err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE;
|
||||
err_rec->cu = 0;
|
||||
err_rec->mem_channel = channel_index;
|
||||
err_rec->mcumc_id = umc_inst;
|
||||
|
||||
err_data->err_addr_cnt++;
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
#ifndef __AMDGPU_UMC_H__
|
||||
#define __AMDGPU_UMC_H__
|
||||
#include "amdgpu_ras.h"
|
||||
|
||||
/*
|
||||
* (addr / 256) * 4096, the higher 26 bits in ErrorAddr
|
||||
@ -40,14 +41,9 @@
|
||||
#define LOOP_UMC_CH_INST(ch_inst) for ((ch_inst) = 0; (ch_inst) < adev->umc.channel_inst_num; (ch_inst)++)
|
||||
#define LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) LOOP_UMC_INST((umc_inst)) LOOP_UMC_CH_INST((ch_inst))
|
||||
|
||||
struct amdgpu_umc_ras_funcs {
|
||||
struct amdgpu_umc_ras {
|
||||
struct amdgpu_ras_block_object ras_block;
|
||||
void (*err_cnt_init)(struct amdgpu_device *adev);
|
||||
int (*ras_late_init)(struct amdgpu_device *adev);
|
||||
void (*ras_fini)(struct amdgpu_device *adev);
|
||||
void (*query_ras_error_count)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
void (*query_ras_error_address)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
bool (*query_ras_poison_mode)(struct amdgpu_device *adev);
|
||||
void (*ecc_info_query_ras_error_count)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
@ -73,10 +69,10 @@ struct amdgpu_umc {
|
||||
struct ras_common_if *ras_if;
|
||||
|
||||
const struct amdgpu_umc_funcs *funcs;
|
||||
const struct amdgpu_umc_ras_funcs *ras_funcs;
|
||||
struct amdgpu_umc_ras *ras;
|
||||
};
|
||||
|
||||
int amdgpu_umc_ras_late_init(struct amdgpu_device *adev);
|
||||
int amdgpu_umc_ras_late_init(struct amdgpu_device *adev, void *ras_info);
|
||||
void amdgpu_umc_ras_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_umc_poison_handler(struct amdgpu_device *adev,
|
||||
void *ras_error_status,
|
||||
@ -84,4 +80,9 @@ int amdgpu_umc_poison_handler(struct amdgpu_device *adev,
|
||||
int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry);
|
||||
void amdgpu_umc_fill_error_record(struct ras_err_data *err_data,
|
||||
uint64_t err_addr,
|
||||
uint64_t retired_page,
|
||||
uint32_t channel_index,
|
||||
uint32_t umc_inst);
|
||||
#endif
|
||||
|
@ -834,6 +834,7 @@ static int amdgpu_uvd_cs_msg(struct amdgpu_uvd_cs_ctx *ctx,
|
||||
handle = msg[2];
|
||||
|
||||
if (handle == 0) {
|
||||
amdgpu_bo_kunmap(bo);
|
||||
DRM_ERROR("Invalid UVD handle!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -892,6 +893,7 @@ static int amdgpu_uvd_cs_msg(struct amdgpu_uvd_cs_ctx *ctx,
|
||||
DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
|
||||
}
|
||||
|
||||
amdgpu_bo_kunmap(bo);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -820,3 +820,148 @@ void amdgpu_virt_update_sriov_video_codec(struct amdgpu_device *adev,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev,
|
||||
u32 acc_flags, u32 hwip,
|
||||
bool write, u32 *rlcg_flag)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
switch (hwip) {
|
||||
case GC_HWIP:
|
||||
if (amdgpu_sriov_reg_indirect_gc(adev)) {
|
||||
*rlcg_flag =
|
||||
write ? AMDGPU_RLCG_GC_WRITE : AMDGPU_RLCG_GC_READ;
|
||||
ret = true;
|
||||
/* only in new version, AMDGPU_REGS_NO_KIQ and
|
||||
* AMDGPU_REGS_RLC are enabled simultaneously */
|
||||
} else if ((acc_flags & AMDGPU_REGS_RLC) &&
|
||||
!(acc_flags & AMDGPU_REGS_NO_KIQ)) {
|
||||
*rlcg_flag = AMDGPU_RLCG_GC_WRITE_LEGACY;
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
case MMHUB_HWIP:
|
||||
if (amdgpu_sriov_reg_indirect_mmhub(adev) &&
|
||||
(acc_flags & AMDGPU_REGS_RLC) && write) {
|
||||
*rlcg_flag = AMDGPU_RLCG_MMHUB_WRITE;
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 flag)
|
||||
{
|
||||
struct amdgpu_rlcg_reg_access_ctrl *reg_access_ctrl;
|
||||
uint32_t timeout = 50000;
|
||||
uint32_t i, tmp;
|
||||
uint32_t ret = 0;
|
||||
static void *scratch_reg0;
|
||||
static void *scratch_reg1;
|
||||
static void *scratch_reg2;
|
||||
static void *scratch_reg3;
|
||||
static void *spare_int;
|
||||
|
||||
if (!adev->gfx.rlc.rlcg_reg_access_supported) {
|
||||
dev_err(adev->dev,
|
||||
"indirect registers access through rlcg is not available\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
reg_access_ctrl = &adev->gfx.rlc.reg_access_ctrl;
|
||||
scratch_reg0 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg0;
|
||||
scratch_reg1 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg1;
|
||||
scratch_reg2 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg2;
|
||||
scratch_reg3 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg3;
|
||||
if (reg_access_ctrl->spare_int)
|
||||
spare_int = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->spare_int;
|
||||
|
||||
if (offset == reg_access_ctrl->grbm_cntl) {
|
||||
/* if the target reg offset is grbm_cntl, write to scratch_reg2 */
|
||||
writel(v, scratch_reg2);
|
||||
writel(v, ((void __iomem *)adev->rmmio) + (offset * 4));
|
||||
} else if (offset == reg_access_ctrl->grbm_idx) {
|
||||
/* if the target reg offset is grbm_idx, write to scratch_reg3 */
|
||||
writel(v, scratch_reg3);
|
||||
writel(v, ((void __iomem *)adev->rmmio) + (offset * 4));
|
||||
} else {
|
||||
/*
|
||||
* SCRATCH_REG0 = read/write value
|
||||
* SCRATCH_REG1[30:28] = command
|
||||
* SCRATCH_REG1[19:0] = address in dword
|
||||
* SCRATCH_REG1[26:24] = Error reporting
|
||||
*/
|
||||
writel(v, scratch_reg0);
|
||||
writel((offset | flag), scratch_reg1);
|
||||
if (reg_access_ctrl->spare_int)
|
||||
writel(1, spare_int);
|
||||
|
||||
for (i = 0; i < timeout; i++) {
|
||||
tmp = readl(scratch_reg1);
|
||||
if (!(tmp & flag))
|
||||
break;
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
if (i >= timeout) {
|
||||
if (amdgpu_sriov_rlcg_error_report_enabled(adev)) {
|
||||
if (tmp & AMDGPU_RLCG_VFGATE_DISABLED) {
|
||||
dev_err(adev->dev,
|
||||
"vfgate is disabled, rlcg failed to program reg: 0x%05x\n", offset);
|
||||
} else if (tmp & AMDGPU_RLCG_WRONG_OPERATION_TYPE) {
|
||||
dev_err(adev->dev,
|
||||
"wrong operation type, rlcg failed to program reg: 0x%05x\n", offset);
|
||||
} else if (tmp & AMDGPU_RLCG_REG_NOT_IN_RANGE) {
|
||||
dev_err(adev->dev,
|
||||
"regiser is not in range, rlcg failed to program reg: 0x%05x\n", offset);
|
||||
} else {
|
||||
dev_err(adev->dev,
|
||||
"unknown error type, rlcg failed to program reg: 0x%05x\n", offset);
|
||||
}
|
||||
} else {
|
||||
dev_err(adev->dev,
|
||||
"timeout: rlcg faled to program reg: 0x%05x\n", offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = readl(scratch_reg0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void amdgpu_sriov_wreg(struct amdgpu_device *adev,
|
||||
u32 offset, u32 value,
|
||||
u32 acc_flags, u32 hwip)
|
||||
{
|
||||
u32 rlcg_flag;
|
||||
|
||||
if (!amdgpu_sriov_runtime(adev) &&
|
||||
amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, true, &rlcg_flag)) {
|
||||
amdgpu_virt_rlcg_reg_rw(adev, offset, value, rlcg_flag);
|
||||
return;
|
||||
}
|
||||
|
||||
if (acc_flags & AMDGPU_REGS_NO_KIQ)
|
||||
WREG32_NO_KIQ(offset, value);
|
||||
else
|
||||
WREG32(offset, value);
|
||||
}
|
||||
|
||||
u32 amdgpu_sriov_rreg(struct amdgpu_device *adev,
|
||||
u32 offset, u32 acc_flags, u32 hwip)
|
||||
{
|
||||
u32 rlcg_flag;
|
||||
|
||||
if (!amdgpu_sriov_runtime(adev) &&
|
||||
amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, false, &rlcg_flag))
|
||||
return amdgpu_virt_rlcg_reg_rw(adev, offset, 0, rlcg_flag);
|
||||
|
||||
if (acc_flags & AMDGPU_REGS_NO_KIQ)
|
||||
return RREG32_NO_KIQ(offset);
|
||||
else
|
||||
return RREG32(offset);
|
||||
}
|
||||
|
@ -32,6 +32,17 @@
|
||||
#define AMDGPU_PASSTHROUGH_MODE (1 << 3) /* thw whole GPU is pass through for VM */
|
||||
#define AMDGPU_SRIOV_CAPS_RUNTIME (1 << 4) /* is out of full access mode */
|
||||
|
||||
/* flags for indirect register access path supported by rlcg for sriov */
|
||||
#define AMDGPU_RLCG_GC_WRITE_LEGACY (0x8 << 28)
|
||||
#define AMDGPU_RLCG_GC_WRITE (0x0 << 28)
|
||||
#define AMDGPU_RLCG_GC_READ (0x1 << 28)
|
||||
#define AMDGPU_RLCG_MMHUB_WRITE (0x2 << 28)
|
||||
|
||||
/* error code for indirect register access path supported by rlcg for sriov */
|
||||
#define AMDGPU_RLCG_VFGATE_DISABLED 0x4000000
|
||||
#define AMDGPU_RLCG_WRONG_OPERATION_TYPE 0x2000000
|
||||
#define AMDGPU_RLCG_REG_NOT_IN_RANGE 0x1000000
|
||||
|
||||
/* all asic after AI use this offset */
|
||||
#define mmRCC_IOV_FUNC_IDENTIFIER 0xDE5
|
||||
/* tonga/fiji use this offset */
|
||||
@ -275,13 +286,18 @@ struct amdgpu_video_codec_info;
|
||||
(amdgpu_sriov_vf((adev)) && \
|
||||
((adev)->virt.reg_access & (AMDGIM_FEATURE_GC_REG_RLC_EN)))
|
||||
|
||||
#define amdgpu_sriov_rlcg_error_report_enabled(adev) \
|
||||
(amdgpu_sriov_reg_indirect_mmhub(adev) || amdgpu_sriov_reg_indirect_gc(adev))
|
||||
|
||||
#define amdgpu_passthrough(adev) \
|
||||
((adev)->virt.caps & AMDGPU_PASSTHROUGH_MODE)
|
||||
|
||||
static inline bool is_virtual_machine(void)
|
||||
{
|
||||
#ifdef CONFIG_X86
|
||||
#if defined(CONFIG_X86)
|
||||
return boot_cpu_has(X86_FEATURE_HYPERVISOR);
|
||||
#elif defined(CONFIG_ARM64)
|
||||
return !is_kernel_in_hyp_mode();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
@ -293,7 +309,6 @@ static inline bool is_virtual_machine(void)
|
||||
((!amdgpu_in_reset(adev)) && adev->virt.tdr_debug)
|
||||
#define amdgpu_sriov_is_normal(adev) \
|
||||
((!amdgpu_in_reset(adev)) && (!adev->virt.tdr_debug))
|
||||
|
||||
bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_init_setting(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev,
|
||||
@ -321,4 +336,9 @@ enum amdgpu_sriov_vf_mode amdgpu_virt_get_sriov_vf_mode(struct amdgpu_device *ad
|
||||
void amdgpu_virt_update_sriov_video_codec(struct amdgpu_device *adev,
|
||||
struct amdgpu_video_codec_info *encode, uint32_t encode_array_size,
|
||||
struct amdgpu_video_codec_info *decode, uint32_t decode_array_size);
|
||||
void amdgpu_sriov_wreg(struct amdgpu_device *adev,
|
||||
u32 offset, u32 value,
|
||||
u32 acc_flags, u32 hwip);
|
||||
u32 amdgpu_sriov_rreg(struct amdgpu_device *adev,
|
||||
u32 offset, u32 acc_flags, u32 hwip);
|
||||
#endif
|
||||
|
@ -375,6 +375,8 @@ static void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base,
|
||||
if (bo->tbo.base.resv != vm->root.bo->tbo.base.resv)
|
||||
return;
|
||||
|
||||
dma_resv_assert_held(vm->root.bo->tbo.base.resv);
|
||||
|
||||
vm->bulk_moveable = false;
|
||||
if (bo->tbo.type == ttm_bo_type_kernel && bo->parent)
|
||||
amdgpu_vm_bo_relocated(base);
|
||||
@ -1634,7 +1636,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params,
|
||||
nptes = max(nptes, 1u);
|
||||
|
||||
trace_amdgpu_vm_update_ptes(params, frag_start, upd_end,
|
||||
nptes, dst, incr, upd_flags,
|
||||
min(nptes, 32u), dst, incr, upd_flags,
|
||||
vm->task_info.pid,
|
||||
vm->immediate.fence_context);
|
||||
amdgpu_vm_update_flags(params, to_amdgpu_bo_vm(pt),
|
||||
@ -2257,6 +2259,7 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
|
||||
if (!bo)
|
||||
return bo_va;
|
||||
|
||||
dma_resv_assert_held(bo->tbo.base.resv);
|
||||
if (amdgpu_dmabuf_is_xgmi_accessible(adev, bo)) {
|
||||
bo_va->is_xgmi = true;
|
||||
/* Power up XGMI if it can be potentially used */
|
||||
@ -2634,7 +2637,7 @@ void amdgpu_vm_bo_trace_cs(struct amdgpu_vm *vm, struct ww_acquire_ctx *ticket)
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_vm_bo_rmv - remove a bo to a specific vm
|
||||
* amdgpu_vm_bo_del - remove a bo from a specific vm
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @bo_va: requested bo_va
|
||||
@ -2643,7 +2646,7 @@ void amdgpu_vm_bo_trace_cs(struct amdgpu_vm *vm, struct ww_acquire_ctx *ticket)
|
||||
*
|
||||
* Object have to be reserved!
|
||||
*/
|
||||
void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
|
||||
void amdgpu_vm_bo_del(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va *bo_va)
|
||||
{
|
||||
struct amdgpu_bo_va_mapping *mapping, *next;
|
||||
@ -2651,7 +2654,10 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm = bo_va->base.vm;
|
||||
struct amdgpu_vm_bo_base **base;
|
||||
|
||||
dma_resv_assert_held(vm->root.bo->tbo.base.resv);
|
||||
|
||||
if (bo) {
|
||||
dma_resv_assert_held(bo->tbo.base.resv);
|
||||
if (bo->tbo.base.resv == vm->root.bo->tbo.base.resv)
|
||||
vm->bulk_moveable = false;
|
||||
|
||||
|
@ -435,7 +435,7 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va_mapping *amdgpu_vm_bo_lookup_mapping(struct amdgpu_vm *vm,
|
||||
uint64_t addr);
|
||||
void amdgpu_vm_bo_trace_cs(struct amdgpu_vm *vm, struct ww_acquire_ctx *ticket);
|
||||
void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
|
||||
void amdgpu_vm_bo_del(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va *bo_va);
|
||||
void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size,
|
||||
uint32_t fragment_size_default, unsigned max_level,
|
||||
|
@ -281,7 +281,7 @@ int amdgpu_vram_mgr_reserve_range(struct amdgpu_vram_mgr *mgr,
|
||||
rsv->mm_node.size = size >> PAGE_SHIFT;
|
||||
|
||||
spin_lock(&mgr->lock);
|
||||
list_add_tail(&mgr->reservations_pending, &rsv->node);
|
||||
list_add_tail(&rsv->node, &mgr->reservations_pending);
|
||||
amdgpu_vram_mgr_do_reserve(&mgr->manager);
|
||||
spin_unlock(&mgr->lock);
|
||||
|
||||
|
@ -732,7 +732,7 @@ int amdgpu_xgmi_remove_device(struct amdgpu_device *adev)
|
||||
return psp_xgmi_terminate(&adev->psp);
|
||||
}
|
||||
|
||||
static int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev)
|
||||
static int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev, void *ras_info)
|
||||
{
|
||||
int r;
|
||||
struct ras_ih_if ih_info = {
|
||||
@ -746,7 +746,7 @@ static int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev)
|
||||
adev->gmc.xgmi.num_physical_nodes == 0)
|
||||
return 0;
|
||||
|
||||
adev->gmc.xgmi.ras_funcs->reset_ras_error_count(adev);
|
||||
adev->gmc.xgmi.ras->ras_block.hw_ops->reset_ras_error_count(adev);
|
||||
|
||||
if (!adev->gmc.xgmi.ras_if) {
|
||||
adev->gmc.xgmi.ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
|
||||
@ -865,7 +865,7 @@ static int amdgpu_xgmi_query_pcs_error_status(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
|
||||
static void amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
{
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
@ -874,7 +874,7 @@ static int amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
|
||||
uint32_t ue_cnt = 0, ce_cnt = 0;
|
||||
|
||||
if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__XGMI_WAFL))
|
||||
return -EINVAL;
|
||||
return ;
|
||||
|
||||
err_data->ue_count = 0;
|
||||
err_data->ce_count = 0;
|
||||
@ -940,17 +940,51 @@ static int amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
|
||||
break;
|
||||
}
|
||||
|
||||
adev->gmc.xgmi.ras_funcs->reset_ras_error_count(adev);
|
||||
adev->gmc.xgmi.ras->ras_block.hw_ops->reset_ras_error_count(adev);
|
||||
|
||||
err_data->ue_count += ue_cnt;
|
||||
err_data->ce_count += ce_cnt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct amdgpu_xgmi_ras_funcs xgmi_ras_funcs = {
|
||||
.ras_late_init = amdgpu_xgmi_ras_late_init,
|
||||
.ras_fini = amdgpu_xgmi_ras_fini,
|
||||
/* Trigger XGMI/WAFL error */
|
||||
static int amdgpu_ras_error_inject_xgmi(struct amdgpu_device *adev, void *inject_if)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ta_ras_trigger_error_input *block_info =
|
||||
(struct ta_ras_trigger_error_input *)inject_if;
|
||||
|
||||
if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_DISALLOW))
|
||||
dev_warn(adev->dev, "Failed to disallow df cstate");
|
||||
|
||||
if (amdgpu_dpm_allow_xgmi_power_down(adev, false))
|
||||
dev_warn(adev->dev, "Failed to disallow XGMI power down");
|
||||
|
||||
ret = psp_ras_trigger_error(&adev->psp, block_info);
|
||||
|
||||
if (amdgpu_ras_intr_triggered())
|
||||
return ret;
|
||||
|
||||
if (amdgpu_dpm_allow_xgmi_power_down(adev, true))
|
||||
dev_warn(adev->dev, "Failed to allow XGMI power down");
|
||||
|
||||
if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_ALLOW))
|
||||
dev_warn(adev->dev, "Failed to allow df cstate");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct amdgpu_ras_block_hw_ops xgmi_ras_hw_ops = {
|
||||
.query_ras_error_count = amdgpu_xgmi_query_ras_error_count,
|
||||
.reset_ras_error_count = amdgpu_xgmi_reset_ras_error_count,
|
||||
.ras_error_inject = amdgpu_ras_error_inject_xgmi,
|
||||
};
|
||||
|
||||
struct amdgpu_xgmi_ras xgmi_ras = {
|
||||
.ras_block = {
|
||||
.name = "xgmi",
|
||||
.block = AMDGPU_RAS_BLOCK__XGMI_WAFL,
|
||||
.hw_ops = &xgmi_ras_hw_ops,
|
||||
.ras_late_init = amdgpu_xgmi_ras_late_init,
|
||||
.ras_fini = amdgpu_xgmi_ras_fini,
|
||||
},
|
||||
};
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
#include <drm/task_barrier.h>
|
||||
#include "amdgpu_psp.h"
|
||||
|
||||
#include "amdgpu_ras.h"
|
||||
|
||||
struct amdgpu_hive_info {
|
||||
struct kobject kobj;
|
||||
@ -50,7 +50,7 @@ struct amdgpu_pcs_ras_field {
|
||||
uint32_t pcs_err_shift;
|
||||
};
|
||||
|
||||
extern const struct amdgpu_xgmi_ras_funcs xgmi_ras_funcs;
|
||||
extern struct amdgpu_xgmi_ras xgmi_ras;
|
||||
struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev);
|
||||
void amdgpu_put_xgmi_hive(struct amdgpu_hive_info *hive);
|
||||
int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev);
|
||||
|
@ -68,12 +68,13 @@ int athub_v1_0_set_clockgating(struct amdgpu_device *adev,
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA10:
|
||||
case CHIP_VEGA12:
|
||||
case CHIP_VEGA20:
|
||||
case CHIP_RAVEN:
|
||||
case CHIP_RENOIR:
|
||||
switch (adev->ip_versions[ATHUB_HWIP][0]) {
|
||||
case IP_VERSION(9, 0, 0):
|
||||
case IP_VERSION(9, 1, 0):
|
||||
case IP_VERSION(9, 2, 0):
|
||||
case IP_VERSION(9, 3, 0):
|
||||
case IP_VERSION(9, 4, 0):
|
||||
case IP_VERSION(1, 5, 0):
|
||||
athub_update_medium_grain_clock_gating(adev,
|
||||
state == AMD_CG_STATE_GATE);
|
||||
athub_update_medium_grain_light_sleep(adev,
|
||||
|
@ -78,6 +78,7 @@ int athub_v2_0_set_clockgating(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
|
||||
switch (adev->ip_versions[ATHUB_HWIP][0]) {
|
||||
case IP_VERSION(1, 3, 1):
|
||||
case IP_VERSION(2, 0, 0):
|
||||
case IP_VERSION(2, 0, 2):
|
||||
athub_v2_0_update_medium_grain_clock_gating(adev,
|
||||
|
@ -74,6 +74,7 @@ int athub_v2_1_set_clockgating(struct amdgpu_device *adev,
|
||||
case IP_VERSION(2, 1, 0):
|
||||
case IP_VERSION(2, 1, 1):
|
||||
case IP_VERSION(2, 1, 2):
|
||||
case IP_VERSION(2, 4, 0):
|
||||
athub_v2_1_update_medium_grain_clock_gating(adev, state == AMD_CG_STATE_GATE);
|
||||
athub_v2_1_update_medium_grain_light_sleep(adev, state == AMD_CG_STATE_GATE);
|
||||
break;
|
||||
|
@ -2532,7 +2532,7 @@ static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
break;
|
||||
}
|
||||
/* adjust pm to dpms */
|
||||
amdgpu_pm_compute_clocks(adev);
|
||||
amdgpu_dpm_compute_clocks(adev);
|
||||
}
|
||||
|
||||
static void dce_v10_0_crtc_prepare(struct drm_crtc *crtc)
|
||||
|
@ -2608,7 +2608,7 @@ static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
break;
|
||||
}
|
||||
/* adjust pm to dpms */
|
||||
amdgpu_pm_compute_clocks(adev);
|
||||
amdgpu_dpm_compute_clocks(adev);
|
||||
}
|
||||
|
||||
static void dce_v11_0_crtc_prepare(struct drm_crtc *crtc)
|
||||
|
@ -2424,7 +2424,7 @@ static void dce_v6_0_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
break;
|
||||
}
|
||||
/* adjust pm to dpms */
|
||||
amdgpu_pm_compute_clocks(adev);
|
||||
amdgpu_dpm_compute_clocks(adev);
|
||||
}
|
||||
|
||||
static void dce_v6_0_crtc_prepare(struct drm_crtc *crtc)
|
||||
|
@ -2433,7 +2433,7 @@ static void dce_v8_0_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
break;
|
||||
}
|
||||
/* adjust pm to dpms */
|
||||
amdgpu_pm_compute_clocks(adev);
|
||||
amdgpu_dpm_compute_clocks(adev);
|
||||
}
|
||||
|
||||
static void dce_v8_0_crtc_prepare(struct drm_crtc *crtc)
|
||||
|
@ -458,7 +458,7 @@ static int df_v3_6_pmc_add_cntr(struct amdgpu_device *adev,
|
||||
|
||||
#define DEFERRED_ARM_MASK (1 << 31)
|
||||
static int df_v3_6_pmc_set_deferred(struct amdgpu_device *adev,
|
||||
int counter_idx, uint64_t config,
|
||||
uint64_t config, int counter_idx,
|
||||
bool is_deferred)
|
||||
{
|
||||
|
||||
@ -476,8 +476,8 @@ static int df_v3_6_pmc_set_deferred(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
static bool df_v3_6_pmc_is_deferred(struct amdgpu_device *adev,
|
||||
int counter_idx,
|
||||
uint64_t config)
|
||||
uint64_t config,
|
||||
int counter_idx)
|
||||
{
|
||||
return (df_v3_6_pmc_has_counter(adev, config, counter_idx) &&
|
||||
(adev->df_perfmon_config_assign_mask[counter_idx]
|
||||
|
@ -56,10 +56,6 @@
|
||||
#define GFX10_NUM_GFX_RINGS_Sienna_Cichlid 1
|
||||
#define GFX10_MEC_HPD_SIZE 2048
|
||||
|
||||
#define RLCG_VFGATE_DISABLED 0x4000000
|
||||
#define RLCG_WRONG_OPERATION_TYPE 0x2000000
|
||||
#define RLCG_NOT_IN_RANGE 0x1000000
|
||||
|
||||
#define F32_CE_PROGRAM_RAM_SIZE 65536
|
||||
#define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L
|
||||
|
||||
@ -180,14 +176,6 @@
|
||||
#define mmRLC_SPARE_INT_0_Sienna_Cichlid 0x4ca5
|
||||
#define mmRLC_SPARE_INT_0_Sienna_Cichlid_BASE_IDX 1
|
||||
|
||||
#define GFX_RLCG_GC_WRITE_OLD (0x8 << 28)
|
||||
#define GFX_RLCG_GC_WRITE (0x0 << 28)
|
||||
#define GFX_RLCG_GC_READ (0x1 << 28)
|
||||
#define GFX_RLCG_MMHUB_WRITE (0x2 << 28)
|
||||
|
||||
#define RLCG_ERROR_REPORT_ENABLED(adev) \
|
||||
(amdgpu_sriov_reg_indirect_mmhub(adev) || amdgpu_sriov_reg_indirect_gc(adev))
|
||||
|
||||
MODULE_FIRMWARE("amdgpu/navi10_ce.bin");
|
||||
MODULE_FIRMWARE("amdgpu/navi10_pfp.bin");
|
||||
MODULE_FIRMWARE("amdgpu/navi10_me.bin");
|
||||
@ -1463,143 +1451,6 @@ static const struct soc15_reg_golden golden_settings_gc_10_1_2[] =
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffffffff, 0x00c00000)
|
||||
};
|
||||
|
||||
static bool gfx_v10_get_rlcg_flag(struct amdgpu_device *adev, u32 acc_flags, u32 hwip,
|
||||
int write, u32 *rlcg_flag)
|
||||
{
|
||||
switch (hwip) {
|
||||
case GC_HWIP:
|
||||
if (amdgpu_sriov_reg_indirect_gc(adev)) {
|
||||
*rlcg_flag = write ? GFX_RLCG_GC_WRITE : GFX_RLCG_GC_READ;
|
||||
|
||||
return true;
|
||||
/* only in new version, AMDGPU_REGS_NO_KIQ and AMDGPU_REGS_RLC enabled simultaneously */
|
||||
} else if ((acc_flags & AMDGPU_REGS_RLC) && !(acc_flags & AMDGPU_REGS_NO_KIQ)) {
|
||||
*rlcg_flag = GFX_RLCG_GC_WRITE_OLD;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
case MMHUB_HWIP:
|
||||
if (amdgpu_sriov_reg_indirect_mmhub(adev) &&
|
||||
(acc_flags & AMDGPU_REGS_RLC) && write) {
|
||||
*rlcg_flag = GFX_RLCG_MMHUB_WRITE;
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG("Not program register by RLCG\n");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static u32 gfx_v10_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32_t flag)
|
||||
{
|
||||
static void *scratch_reg0;
|
||||
static void *scratch_reg1;
|
||||
static void *scratch_reg2;
|
||||
static void *scratch_reg3;
|
||||
static void *spare_int;
|
||||
static uint32_t grbm_cntl;
|
||||
static uint32_t grbm_idx;
|
||||
uint32_t i = 0;
|
||||
uint32_t retries = 50000;
|
||||
u32 ret = 0;
|
||||
u32 tmp;
|
||||
|
||||
scratch_reg0 = adev->rmmio +
|
||||
(adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG0_BASE_IDX] + mmSCRATCH_REG0) * 4;
|
||||
scratch_reg1 = adev->rmmio +
|
||||
(adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG1_BASE_IDX] + mmSCRATCH_REG1) * 4;
|
||||
scratch_reg2 = adev->rmmio +
|
||||
(adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG0_BASE_IDX] + mmSCRATCH_REG2) * 4;
|
||||
scratch_reg3 = adev->rmmio +
|
||||
(adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG1_BASE_IDX] + mmSCRATCH_REG3) * 4;
|
||||
|
||||
if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0)) {
|
||||
spare_int = adev->rmmio +
|
||||
(adev->reg_offset[GC_HWIP][0][mmRLC_SPARE_INT_0_Sienna_Cichlid_BASE_IDX]
|
||||
+ mmRLC_SPARE_INT_0_Sienna_Cichlid) * 4;
|
||||
} else {
|
||||
spare_int = adev->rmmio +
|
||||
(adev->reg_offset[GC_HWIP][0][mmRLC_SPARE_INT_BASE_IDX] + mmRLC_SPARE_INT) * 4;
|
||||
}
|
||||
|
||||
grbm_cntl = adev->reg_offset[GC_HWIP][0][mmGRBM_GFX_CNTL_BASE_IDX] + mmGRBM_GFX_CNTL;
|
||||
grbm_idx = adev->reg_offset[GC_HWIP][0][mmGRBM_GFX_INDEX_BASE_IDX] + mmGRBM_GFX_INDEX;
|
||||
|
||||
if (offset == grbm_cntl || offset == grbm_idx) {
|
||||
if (offset == grbm_cntl)
|
||||
writel(v, scratch_reg2);
|
||||
else if (offset == grbm_idx)
|
||||
writel(v, scratch_reg3);
|
||||
|
||||
writel(v, ((void __iomem *)adev->rmmio) + (offset * 4));
|
||||
} else {
|
||||
writel(v, scratch_reg0);
|
||||
writel(offset | flag, scratch_reg1);
|
||||
writel(1, spare_int);
|
||||
|
||||
for (i = 0; i < retries; i++) {
|
||||
tmp = readl(scratch_reg1);
|
||||
if (!(tmp & flag))
|
||||
break;
|
||||
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
if (i >= retries) {
|
||||
if (RLCG_ERROR_REPORT_ENABLED(adev)) {
|
||||
if (tmp & RLCG_VFGATE_DISABLED)
|
||||
pr_err("The vfgate is disabled, program reg:0x%05x failed!\n", offset);
|
||||
else if (tmp & RLCG_WRONG_OPERATION_TYPE)
|
||||
pr_err("Wrong operation type, program reg:0x%05x failed!\n", offset);
|
||||
else if (tmp & RLCG_NOT_IN_RANGE)
|
||||
pr_err("The register is not in range, program reg:0x%05x failed!\n", offset);
|
||||
else
|
||||
pr_err("Unknown error type, program reg:0x%05x failed!\n", offset);
|
||||
} else
|
||||
pr_err("timeout: rlcg program reg:0x%05x failed!\n", offset);
|
||||
}
|
||||
}
|
||||
|
||||
ret = readl(scratch_reg0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void gfx_v10_sriov_wreg(struct amdgpu_device *adev, u32 offset, u32 value, u32 acc_flags, u32 hwip)
|
||||
{
|
||||
u32 rlcg_flag;
|
||||
|
||||
if (!amdgpu_sriov_runtime(adev) &&
|
||||
gfx_v10_get_rlcg_flag(adev, acc_flags, hwip, 1, &rlcg_flag)) {
|
||||
gfx_v10_rlcg_rw(adev, offset, value, rlcg_flag);
|
||||
return;
|
||||
}
|
||||
|
||||
if (acc_flags & AMDGPU_REGS_NO_KIQ)
|
||||
WREG32_NO_KIQ(offset, value);
|
||||
else
|
||||
WREG32(offset, value);
|
||||
}
|
||||
|
||||
static u32 gfx_v10_sriov_rreg(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip)
|
||||
{
|
||||
u32 rlcg_flag;
|
||||
|
||||
if (!amdgpu_sriov_runtime(adev) &&
|
||||
gfx_v10_get_rlcg_flag(adev, acc_flags, hwip, 0, &rlcg_flag))
|
||||
return gfx_v10_rlcg_rw(adev, offset, 0, rlcg_flag);
|
||||
|
||||
if (acc_flags & AMDGPU_REGS_NO_KIQ)
|
||||
return RREG32_NO_KIQ(offset);
|
||||
else
|
||||
return RREG32(offset);
|
||||
}
|
||||
|
||||
static const struct soc15_reg_golden golden_settings_gc_10_1_nv14[] =
|
||||
{
|
||||
/* Pending on emulation bring up */
|
||||
@ -3790,6 +3641,7 @@ static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev)
|
||||
(const u32)ARRAY_SIZE(golden_settings_gc_10_3_5));
|
||||
break;
|
||||
case IP_VERSION(10, 1, 3):
|
||||
case IP_VERSION(10, 1, 4):
|
||||
soc15_program_register_sequence(adev,
|
||||
golden_settings_gc_10_0_cyan_skillfish,
|
||||
(const u32)ARRAY_SIZE(golden_settings_gc_10_0_cyan_skillfish));
|
||||
@ -3968,6 +3820,7 @@ static void gfx_v10_0_check_fw_write_wait(struct amdgpu_device *adev)
|
||||
case IP_VERSION(10, 1, 2):
|
||||
case IP_VERSION(10, 1, 1):
|
||||
case IP_VERSION(10, 1, 3):
|
||||
case IP_VERSION(10, 1, 4):
|
||||
if ((adev->gfx.me_fw_version >= 0x00000046) &&
|
||||
(adev->gfx.me_feature_version >= 27) &&
|
||||
(adev->gfx.pfp_fw_version >= 0x00000068) &&
|
||||
@ -4108,6 +3961,9 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
|
||||
else
|
||||
chip_name = "cyan_skillfish";
|
||||
break;
|
||||
case IP_VERSION(10, 1, 4):
|
||||
chip_name = "cyan_skillfish2";
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
@ -4448,6 +4304,30 @@ static void gfx_v10_0_rlc_fini(struct amdgpu_device *adev)
|
||||
(void **)&adev->gfx.rlc.cp_table_ptr);
|
||||
}
|
||||
|
||||
static void gfx_v10_0_init_rlcg_reg_access_ctrl(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_rlcg_reg_access_ctrl *reg_access_ctrl;
|
||||
|
||||
reg_access_ctrl = &adev->gfx.rlc.reg_access_ctrl;
|
||||
reg_access_ctrl->scratch_reg0 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG0);
|
||||
reg_access_ctrl->scratch_reg1 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG1);
|
||||
reg_access_ctrl->scratch_reg2 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG2);
|
||||
reg_access_ctrl->scratch_reg3 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG3);
|
||||
reg_access_ctrl->grbm_cntl = SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_CNTL);
|
||||
reg_access_ctrl->grbm_idx = SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_INDEX);
|
||||
switch (adev->ip_versions[GC_HWIP][0]) {
|
||||
case IP_VERSION(10, 3, 0):
|
||||
reg_access_ctrl->spare_int =
|
||||
SOC15_REG_OFFSET(GC, 0, mmRLC_SPARE_INT_0_Sienna_Cichlid);
|
||||
break;
|
||||
default:
|
||||
reg_access_ctrl->spare_int =
|
||||
SOC15_REG_OFFSET(GC, 0, mmRLC_SPARE_INT);
|
||||
break;
|
||||
}
|
||||
adev->gfx.rlc.rlcg_reg_access_supported = true;
|
||||
}
|
||||
|
||||
static int gfx_v10_0_rlc_init(struct amdgpu_device *adev)
|
||||
{
|
||||
const struct cs_section_def *cs_data;
|
||||
@ -4468,6 +4348,7 @@ static int gfx_v10_0_rlc_init(struct amdgpu_device *adev)
|
||||
if (adev->gfx.rlc.funcs->update_spm_vmid)
|
||||
adev->gfx.rlc.funcs->update_spm_vmid(adev, 0xf);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4689,6 +4570,7 @@ static void gfx_v10_0_gpu_early_init(struct amdgpu_device *adev)
|
||||
1 << REG_GET_FIELD(gb_addr_config, GB_ADDR_CONFIG, NUM_PKRS);
|
||||
break;
|
||||
case IP_VERSION(10, 1, 3):
|
||||
case IP_VERSION(10, 1, 4):
|
||||
adev->gfx.config.max_hw_contexts = 8;
|
||||
adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
|
||||
adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
|
||||
@ -4801,6 +4683,7 @@ static int gfx_v10_0_sw_init(void *handle)
|
||||
case IP_VERSION(10, 1, 1):
|
||||
case IP_VERSION(10, 1, 2):
|
||||
case IP_VERSION(10, 1, 3):
|
||||
case IP_VERSION(10, 1, 4):
|
||||
adev->gfx.me.num_me = 1;
|
||||
adev->gfx.me.num_pipe_per_me = 1;
|
||||
adev->gfx.me.num_queue_per_pipe = 1;
|
||||
@ -4865,10 +4748,14 @@ static int gfx_v10_0_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = gfx_v10_0_rlc_init(adev);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to init rlc BOs!\n");
|
||||
return r;
|
||||
if (adev->gfx.rlc.funcs) {
|
||||
if (adev->gfx.rlc.funcs->init) {
|
||||
r = adev->gfx.rlc.funcs->init(adev);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "Failed to init rlc BOs!\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r = gfx_v10_0_mec_init(adev);
|
||||
@ -7778,6 +7665,7 @@ static int gfx_v10_0_early_init(void *handle)
|
||||
case IP_VERSION(10, 1, 1):
|
||||
case IP_VERSION(10, 1, 2):
|
||||
case IP_VERSION(10, 1, 3):
|
||||
case IP_VERSION(10, 1, 4):
|
||||
adev->gfx.num_gfx_rings = GFX10_NUM_GFX_RINGS_NV1X;
|
||||
break;
|
||||
case IP_VERSION(10, 3, 0):
|
||||
@ -7801,6 +7689,9 @@ static int gfx_v10_0_early_init(void *handle)
|
||||
gfx_v10_0_set_gds_init(adev);
|
||||
gfx_v10_0_set_rlc_funcs(adev);
|
||||
|
||||
/* init rlcg reg access ctrl */
|
||||
gfx_v10_0_init_rlcg_reg_access_ctrl(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -8377,8 +8268,6 @@ static const struct amdgpu_rlc_funcs gfx_v10_0_rlc_funcs_sriov = {
|
||||
.reset = gfx_v10_0_rlc_reset,
|
||||
.start = gfx_v10_0_rlc_start,
|
||||
.update_spm_vmid = gfx_v10_0_update_spm_vmid,
|
||||
.sriov_wreg = gfx_v10_sriov_wreg,
|
||||
.sriov_rreg = gfx_v10_sriov_rreg,
|
||||
.is_rlcg_access_range = gfx_v10_0_is_rlcg_access_range,
|
||||
};
|
||||
|
||||
@ -9537,6 +9426,7 @@ static void gfx_v10_0_set_rlc_funcs(struct amdgpu_device *adev)
|
||||
case IP_VERSION(10, 1, 10):
|
||||
case IP_VERSION(10, 1, 1):
|
||||
case IP_VERSION(10, 1, 3):
|
||||
case IP_VERSION(10, 1, 4):
|
||||
case IP_VERSION(10, 3, 2):
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
|
@ -63,13 +63,6 @@
|
||||
#define mmGCEA_PROBE_MAP 0x070c
|
||||
#define mmGCEA_PROBE_MAP_BASE_IDX 0
|
||||
|
||||
#define GFX9_RLCG_GC_WRITE_OLD (0x8 << 28)
|
||||
#define GFX9_RLCG_GC_WRITE (0x0 << 28)
|
||||
#define GFX9_RLCG_GC_READ (0x1 << 28)
|
||||
#define GFX9_RLCG_VFGATE_DISABLED 0x4000000
|
||||
#define GFX9_RLCG_WRONG_OPERATION_TYPE 0x2000000
|
||||
#define GFX9_RLCG_NOT_IN_RANGE 0x1000000
|
||||
|
||||
MODULE_FIRMWARE("amdgpu/vega10_ce.bin");
|
||||
MODULE_FIRMWARE("amdgpu/vega10_pfp.bin");
|
||||
MODULE_FIRMWARE("amdgpu/vega10_me.bin");
|
||||
@ -746,128 +739,6 @@ static const u32 GFX_RLC_SRM_INDEX_CNTL_DATA_OFFSETS[] =
|
||||
mmRLC_SRM_INDEX_CNTL_DATA_7 - mmRLC_SRM_INDEX_CNTL_DATA_0,
|
||||
};
|
||||
|
||||
static u32 gfx_v9_0_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32_t flag)
|
||||
{
|
||||
static void *scratch_reg0;
|
||||
static void *scratch_reg1;
|
||||
static void *scratch_reg2;
|
||||
static void *scratch_reg3;
|
||||
static void *spare_int;
|
||||
static uint32_t grbm_cntl;
|
||||
static uint32_t grbm_idx;
|
||||
uint32_t i = 0;
|
||||
uint32_t retries = 50000;
|
||||
u32 ret = 0;
|
||||
u32 tmp;
|
||||
|
||||
scratch_reg0 = adev->rmmio + (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG0_BASE_IDX] + mmSCRATCH_REG0)*4;
|
||||
scratch_reg1 = adev->rmmio + (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG1_BASE_IDX] + mmSCRATCH_REG1)*4;
|
||||
scratch_reg2 = adev->rmmio + (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG2_BASE_IDX] + mmSCRATCH_REG2)*4;
|
||||
scratch_reg3 = adev->rmmio + (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG3_BASE_IDX] + mmSCRATCH_REG3)*4;
|
||||
spare_int = adev->rmmio + (adev->reg_offset[GC_HWIP][0][mmRLC_SPARE_INT_BASE_IDX] + mmRLC_SPARE_INT)*4;
|
||||
|
||||
grbm_cntl = adev->reg_offset[GC_HWIP][0][mmGRBM_GFX_CNTL_BASE_IDX] + mmGRBM_GFX_CNTL;
|
||||
grbm_idx = adev->reg_offset[GC_HWIP][0][mmGRBM_GFX_INDEX_BASE_IDX] + mmGRBM_GFX_INDEX;
|
||||
|
||||
if (offset == grbm_cntl || offset == grbm_idx) {
|
||||
if (offset == grbm_cntl)
|
||||
writel(v, scratch_reg2);
|
||||
else if (offset == grbm_idx)
|
||||
writel(v, scratch_reg3);
|
||||
|
||||
writel(v, ((void __iomem *)adev->rmmio) + (offset * 4));
|
||||
} else {
|
||||
/*
|
||||
* SCRATCH_REG0 = read/write value
|
||||
* SCRATCH_REG1[30:28] = command
|
||||
* SCRATCH_REG1[19:0] = address in dword
|
||||
* SCRATCH_REG1[26:24] = Error reporting
|
||||
*/
|
||||
writel(v, scratch_reg0);
|
||||
writel(offset | flag, scratch_reg1);
|
||||
writel(1, spare_int);
|
||||
|
||||
for (i = 0; i < retries; i++) {
|
||||
tmp = readl(scratch_reg1);
|
||||
if (!(tmp & flag))
|
||||
break;
|
||||
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
if (i >= retries) {
|
||||
if (amdgpu_sriov_reg_indirect_gc(adev)) {
|
||||
if (tmp & GFX9_RLCG_VFGATE_DISABLED)
|
||||
pr_err("The vfgate is disabled, program reg:0x%05x failed!\n", offset);
|
||||
else if (tmp & GFX9_RLCG_WRONG_OPERATION_TYPE)
|
||||
pr_err("Wrong operation type, program reg:0x%05x failed!\n", offset);
|
||||
else if (tmp & GFX9_RLCG_NOT_IN_RANGE)
|
||||
pr_err("The register is not in range, program reg:0x%05x failed!\n", offset);
|
||||
else
|
||||
pr_err("Unknown error type, program reg:0x%05x failed!\n", offset);
|
||||
} else
|
||||
pr_err("timeout: rlcg program reg:0x%05x failed!\n", offset);
|
||||
}
|
||||
}
|
||||
|
||||
ret = readl(scratch_reg0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool gfx_v9_0_get_rlcg_flag(struct amdgpu_device *adev, u32 acc_flags, u32 hwip,
|
||||
int write, u32 *rlcg_flag)
|
||||
{
|
||||
|
||||
switch (hwip) {
|
||||
case GC_HWIP:
|
||||
if (amdgpu_sriov_reg_indirect_gc(adev)) {
|
||||
*rlcg_flag = write ? GFX9_RLCG_GC_WRITE : GFX9_RLCG_GC_READ;
|
||||
|
||||
return true;
|
||||
/* only in new version, AMDGPU_REGS_NO_KIQ and AMDGPU_REGS_RLC enabled simultaneously */
|
||||
} else if ((acc_flags & AMDGPU_REGS_RLC) && !(acc_flags & AMDGPU_REGS_NO_KIQ) && write) {
|
||||
*rlcg_flag = GFX9_RLCG_GC_WRITE_OLD;
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static u32 gfx_v9_0_sriov_rreg(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip)
|
||||
{
|
||||
u32 rlcg_flag;
|
||||
|
||||
if (!amdgpu_sriov_runtime(adev) && gfx_v9_0_get_rlcg_flag(adev, acc_flags, hwip, 0, &rlcg_flag))
|
||||
return gfx_v9_0_rlcg_rw(adev, offset, 0, rlcg_flag);
|
||||
|
||||
if (acc_flags & AMDGPU_REGS_NO_KIQ)
|
||||
return RREG32_NO_KIQ(offset);
|
||||
else
|
||||
return RREG32(offset);
|
||||
}
|
||||
|
||||
static void gfx_v9_0_sriov_wreg(struct amdgpu_device *adev, u32 offset,
|
||||
u32 value, u32 acc_flags, u32 hwip)
|
||||
{
|
||||
u32 rlcg_flag;
|
||||
|
||||
if (!amdgpu_sriov_runtime(adev) && gfx_v9_0_get_rlcg_flag(adev, acc_flags, hwip, 1, &rlcg_flag)) {
|
||||
gfx_v9_0_rlcg_rw(adev, offset, value, rlcg_flag);
|
||||
return;
|
||||
}
|
||||
|
||||
if (acc_flags & AMDGPU_REGS_NO_KIQ)
|
||||
WREG32_NO_KIQ(offset, value);
|
||||
else
|
||||
WREG32(offset, value);
|
||||
}
|
||||
|
||||
#define VEGA10_GB_ADDR_CONFIG_GOLDEN 0x2a114042
|
||||
#define VEGA12_GB_ADDR_CONFIG_GOLDEN 0x24104041
|
||||
#define RAVEN_GB_ADDR_CONFIG_GOLDEN 0x24000042
|
||||
@ -882,7 +753,7 @@ static int gfx_v9_0_get_cu_info(struct amdgpu_device *adev,
|
||||
static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev);
|
||||
static void gfx_v9_0_ring_emit_de_meta(struct amdgpu_ring *ring);
|
||||
static u64 gfx_v9_0_ring_get_rptr_compute(struct amdgpu_ring *ring);
|
||||
static int gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev,
|
||||
static void gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
static int gfx_v9_0_ras_error_inject(struct amdgpu_device *adev,
|
||||
void *inject_if);
|
||||
@ -2008,6 +1879,21 @@ static int gfx_v9_0_cp_jump_table_num(struct amdgpu_device *adev)
|
||||
return 4;
|
||||
}
|
||||
|
||||
static void gfx_v9_0_init_rlcg_reg_access_ctrl(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_rlcg_reg_access_ctrl *reg_access_ctrl;
|
||||
|
||||
reg_access_ctrl = &adev->gfx.rlc.reg_access_ctrl;
|
||||
reg_access_ctrl->scratch_reg0 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG0);
|
||||
reg_access_ctrl->scratch_reg1 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG1);
|
||||
reg_access_ctrl->scratch_reg2 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG2);
|
||||
reg_access_ctrl->scratch_reg3 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG3);
|
||||
reg_access_ctrl->grbm_cntl = SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_CNTL);
|
||||
reg_access_ctrl->grbm_idx = SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_INDEX);
|
||||
reg_access_ctrl->spare_int = SOC15_REG_OFFSET(GC, 0, mmRLC_SPARE_INT);
|
||||
adev->gfx.rlc.rlcg_reg_access_supported = true;
|
||||
}
|
||||
|
||||
static int gfx_v9_0_rlc_init(struct amdgpu_device *adev)
|
||||
{
|
||||
const struct cs_section_def *cs_data;
|
||||
@ -2197,12 +2083,16 @@ static const struct amdgpu_gfx_funcs gfx_v9_0_gfx_funcs = {
|
||||
.select_me_pipe_q = &gfx_v9_0_select_me_pipe_q,
|
||||
};
|
||||
|
||||
static const struct amdgpu_gfx_ras_funcs gfx_v9_0_ras_funcs = {
|
||||
.ras_late_init = amdgpu_gfx_ras_late_init,
|
||||
.ras_fini = amdgpu_gfx_ras_fini,
|
||||
.ras_error_inject = &gfx_v9_0_ras_error_inject,
|
||||
.query_ras_error_count = &gfx_v9_0_query_ras_error_count,
|
||||
.reset_ras_error_count = &gfx_v9_0_reset_ras_error_count,
|
||||
const struct amdgpu_ras_block_hw_ops gfx_v9_0_ras_ops = {
|
||||
.ras_error_inject = &gfx_v9_0_ras_error_inject,
|
||||
.query_ras_error_count = &gfx_v9_0_query_ras_error_count,
|
||||
.reset_ras_error_count = &gfx_v9_0_reset_ras_error_count,
|
||||
};
|
||||
|
||||
static struct amdgpu_gfx_ras gfx_v9_0_ras = {
|
||||
.ras_block = {
|
||||
.hw_ops = &gfx_v9_0_ras_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
|
||||
@ -2231,7 +2121,7 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
|
||||
DRM_INFO("fix gfx.config for vega12\n");
|
||||
break;
|
||||
case IP_VERSION(9, 4, 0):
|
||||
adev->gfx.ras_funcs = &gfx_v9_0_ras_funcs;
|
||||
adev->gfx.ras = &gfx_v9_0_ras;
|
||||
adev->gfx.config.max_hw_contexts = 8;
|
||||
adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
|
||||
adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
|
||||
@ -2258,7 +2148,7 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
|
||||
gb_addr_config = RAVEN_GB_ADDR_CONFIG_GOLDEN;
|
||||
break;
|
||||
case IP_VERSION(9, 4, 1):
|
||||
adev->gfx.ras_funcs = &gfx_v9_4_ras_funcs;
|
||||
adev->gfx.ras = &gfx_v9_4_ras;
|
||||
adev->gfx.config.max_hw_contexts = 8;
|
||||
adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
|
||||
adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
|
||||
@ -2279,7 +2169,7 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
|
||||
gb_addr_config |= 0x22010042;
|
||||
break;
|
||||
case IP_VERSION(9, 4, 2):
|
||||
adev->gfx.ras_funcs = &gfx_v9_4_2_ras_funcs;
|
||||
adev->gfx.ras = &gfx_v9_4_2_ras;
|
||||
adev->gfx.config.max_hw_contexts = 8;
|
||||
adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
|
||||
adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
|
||||
@ -2298,6 +2188,25 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
|
||||
break;
|
||||
}
|
||||
|
||||
if (adev->gfx.ras) {
|
||||
err = amdgpu_ras_register_ras_block(adev, &adev->gfx.ras->ras_block);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to register gfx ras block!\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
strcpy(adev->gfx.ras->ras_block.name,"gfx");
|
||||
adev->gfx.ras->ras_block.block = AMDGPU_RAS_BLOCK__GFX;
|
||||
|
||||
/* If not define special ras_late_init function, use gfx default ras_late_init */
|
||||
if (!adev->gfx.ras->ras_block.ras_late_init)
|
||||
adev->gfx.ras->ras_block.ras_late_init = amdgpu_gfx_ras_late_init;
|
||||
|
||||
/* If not define special ras_fini function, use gfx default ras_fini */
|
||||
if (!adev->gfx.ras->ras_block.ras_fini)
|
||||
adev->gfx.ras->ras_block.ras_fini = amdgpu_gfx_ras_fini;
|
||||
}
|
||||
|
||||
adev->gfx.config.gb_addr_config = gb_addr_config;
|
||||
|
||||
adev->gfx.config.gb_addr_config_fields.num_pipes = 1 <<
|
||||
@ -2434,10 +2343,14 @@ static int gfx_v9_0_sw_init(void *handle)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = adev->gfx.rlc.funcs->init(adev);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to init rlc BOs!\n");
|
||||
return r;
|
||||
if (adev->gfx.rlc.funcs) {
|
||||
if (adev->gfx.rlc.funcs->init) {
|
||||
r = adev->gfx.rlc.funcs->init(adev);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "Failed to init rlc BOs!\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r = gfx_v9_0_mec_init(adev);
|
||||
@ -2513,9 +2426,8 @@ static int gfx_v9_0_sw_fini(void *handle)
|
||||
int i;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->ras_fini)
|
||||
adev->gfx.ras_funcs->ras_fini(adev);
|
||||
if (adev->gfx.ras && adev->gfx.ras->ras_block.ras_fini)
|
||||
adev->gfx.ras->ras_block.ras_fini(adev);
|
||||
|
||||
for (i = 0; i < adev->gfx.num_gfx_rings; i++)
|
||||
amdgpu_ring_fini(&adev->gfx.gfx_ring[i]);
|
||||
@ -4840,6 +4752,9 @@ static int gfx_v9_0_early_init(void *handle)
|
||||
gfx_v9_0_set_gds_init(adev);
|
||||
gfx_v9_0_set_rlc_funcs(adev);
|
||||
|
||||
/* init rlcg reg access ctrl */
|
||||
gfx_v9_0_init_rlcg_reg_access_ctrl(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4870,16 +4785,15 @@ static int gfx_v9_0_ecc_late_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->ras_late_init) {
|
||||
r = adev->gfx.ras_funcs->ras_late_init(adev);
|
||||
if (adev->gfx.ras && adev->gfx.ras->ras_block.ras_late_init) {
|
||||
r = adev->gfx.ras->ras_block.ras_late_init(adev, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->enable_watchdog_timer)
|
||||
adev->gfx.ras_funcs->enable_watchdog_timer(adev);
|
||||
if (adev->gfx.ras &&
|
||||
adev->gfx.ras->enable_watchdog_timer)
|
||||
adev->gfx.ras->enable_watchdog_timer(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -5250,8 +5164,6 @@ static const struct amdgpu_rlc_funcs gfx_v9_0_rlc_funcs = {
|
||||
.reset = gfx_v9_0_rlc_reset,
|
||||
.start = gfx_v9_0_rlc_start,
|
||||
.update_spm_vmid = gfx_v9_0_update_spm_vmid,
|
||||
.sriov_wreg = gfx_v9_0_sriov_wreg,
|
||||
.sriov_rreg = gfx_v9_0_sriov_rreg,
|
||||
.is_rlcg_access_range = gfx_v9_0_is_rlcg_access_range,
|
||||
};
|
||||
|
||||
@ -6819,7 +6731,7 @@ static void gfx_v9_0_reset_ras_error_count(struct amdgpu_device *adev)
|
||||
WREG32_SOC15(GC, 0, mmATC_L2_CACHE_4K_EDC_INDEX, 255);
|
||||
}
|
||||
|
||||
static int gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev,
|
||||
static void gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
{
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
@ -6828,7 +6740,7 @@ static int gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev,
|
||||
uint32_t reg_value;
|
||||
|
||||
if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX))
|
||||
return -EINVAL;
|
||||
return;
|
||||
|
||||
err_data->ue_count = 0;
|
||||
err_data->ce_count = 0;
|
||||
@ -6857,8 +6769,6 @@ static int gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev,
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
gfx_v9_0_query_utc_edc_status(adev, err_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gfx_v9_0_emit_mem_sync(struct amdgpu_ring *ring)
|
||||
|
@ -863,7 +863,7 @@ static int gfx_v9_4_ras_error_count(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v9_4_query_ras_error_count(struct amdgpu_device *adev,
|
||||
static void gfx_v9_4_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
{
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
@ -872,7 +872,7 @@ static int gfx_v9_4_query_ras_error_count(struct amdgpu_device *adev,
|
||||
uint32_t reg_value;
|
||||
|
||||
if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX))
|
||||
return -EINVAL;
|
||||
return;
|
||||
|
||||
err_data->ue_count = 0;
|
||||
err_data->ce_count = 0;
|
||||
@ -903,7 +903,6 @@ static int gfx_v9_4_query_ras_error_count(struct amdgpu_device *adev,
|
||||
|
||||
gfx_v9_4_query_utc_edc_status(adev, err_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gfx_v9_4_reset_ras_error_count(struct amdgpu_device *adev)
|
||||
@ -1029,11 +1028,16 @@ static void gfx_v9_4_query_ras_error_status(struct amdgpu_device *adev)
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
}
|
||||
|
||||
const struct amdgpu_gfx_ras_funcs gfx_v9_4_ras_funcs = {
|
||||
.ras_late_init = amdgpu_gfx_ras_late_init,
|
||||
.ras_fini = amdgpu_gfx_ras_fini,
|
||||
.ras_error_inject = &gfx_v9_4_ras_error_inject,
|
||||
.query_ras_error_count = &gfx_v9_4_query_ras_error_count,
|
||||
.reset_ras_error_count = &gfx_v9_4_reset_ras_error_count,
|
||||
.query_ras_error_status = &gfx_v9_4_query_ras_error_status,
|
||||
|
||||
const struct amdgpu_ras_block_hw_ops gfx_v9_4_ras_ops = {
|
||||
.ras_error_inject = &gfx_v9_4_ras_error_inject,
|
||||
.query_ras_error_count = &gfx_v9_4_query_ras_error_count,
|
||||
.reset_ras_error_count = &gfx_v9_4_reset_ras_error_count,
|
||||
.query_ras_error_status = &gfx_v9_4_query_ras_error_status,
|
||||
};
|
||||
|
||||
struct amdgpu_gfx_ras gfx_v9_4_ras = {
|
||||
.ras_block = {
|
||||
.hw_ops = &gfx_v9_4_ras_ops,
|
||||
},
|
||||
};
|
||||
|
@ -24,6 +24,6 @@
|
||||
#ifndef __GFX_V9_4_H__
|
||||
#define __GFX_V9_4_H__
|
||||
|
||||
extern const struct amdgpu_gfx_ras_funcs gfx_v9_4_ras_funcs;
|
||||
extern struct amdgpu_gfx_ras gfx_v9_4_ras;
|
||||
|
||||
#endif /* __GFX_V9_4_H__ */
|
||||
|
@ -1641,14 +1641,14 @@ static int gfx_v9_4_2_query_utc_edc_count(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v9_4_2_query_ras_error_count(struct amdgpu_device *adev,
|
||||
static void gfx_v9_4_2_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
{
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
uint32_t sec_count = 0, ded_count = 0;
|
||||
|
||||
if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX))
|
||||
return -EINVAL;
|
||||
return;
|
||||
|
||||
err_data->ue_count = 0;
|
||||
err_data->ce_count = 0;
|
||||
@ -1661,7 +1661,6 @@ static int gfx_v9_4_2_query_ras_error_count(struct amdgpu_device *adev,
|
||||
err_data->ce_count += sec_count;
|
||||
err_data->ue_count += ded_count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gfx_v9_4_2_reset_utc_err_status(struct amdgpu_device *adev)
|
||||
@ -1931,13 +1930,17 @@ static void gfx_v9_4_2_reset_sq_timeout_status(struct amdgpu_device *adev)
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
}
|
||||
|
||||
const struct amdgpu_gfx_ras_funcs gfx_v9_4_2_ras_funcs = {
|
||||
.ras_late_init = amdgpu_gfx_ras_late_init,
|
||||
.ras_fini = amdgpu_gfx_ras_fini,
|
||||
.ras_error_inject = &gfx_v9_4_2_ras_error_inject,
|
||||
.query_ras_error_count = &gfx_v9_4_2_query_ras_error_count,
|
||||
.reset_ras_error_count = &gfx_v9_4_2_reset_ras_error_count,
|
||||
.query_ras_error_status = &gfx_v9_4_2_query_ras_error_status,
|
||||
.reset_ras_error_status = &gfx_v9_4_2_reset_ras_error_status,
|
||||
struct amdgpu_ras_block_hw_ops gfx_v9_4_2_ras_ops = {
|
||||
.ras_error_inject = &gfx_v9_4_2_ras_error_inject,
|
||||
.query_ras_error_count = &gfx_v9_4_2_query_ras_error_count,
|
||||
.reset_ras_error_count = &gfx_v9_4_2_reset_ras_error_count,
|
||||
.query_ras_error_status = &gfx_v9_4_2_query_ras_error_status,
|
||||
.reset_ras_error_status = &gfx_v9_4_2_reset_ras_error_status,
|
||||
};
|
||||
|
||||
struct amdgpu_gfx_ras gfx_v9_4_2_ras = {
|
||||
.ras_block = {
|
||||
.hw_ops = &gfx_v9_4_2_ras_ops,
|
||||
},
|
||||
.enable_watchdog_timer = &gfx_v9_4_2_enable_watchdog_timer,
|
||||
};
|
||||
|
@ -31,6 +31,6 @@ void gfx_v9_4_2_init_golden_registers(struct amdgpu_device *adev,
|
||||
void gfx_v9_4_2_set_power_brake_sequence(struct amdgpu_device *adev);
|
||||
int gfx_v9_4_2_do_edc_gpr_workarounds(struct amdgpu_device *adev);
|
||||
|
||||
extern const struct amdgpu_gfx_ras_funcs gfx_v9_4_2_ras_funcs;
|
||||
extern struct amdgpu_gfx_ras gfx_v9_4_2_ras;
|
||||
|
||||
#endif /* __GFX_V9_4_2_H__ */
|
||||
|
@ -543,7 +543,9 @@ static void gfxhub_v2_1_utcl2_harvest(struct amdgpu_device *adev)
|
||||
adev->gfx.config.max_sh_per_se *
|
||||
adev->gfx.config.max_shader_engines);
|
||||
|
||||
if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 3)) {
|
||||
switch (adev->ip_versions[GC_HWIP][0]) {
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
/* Get SA disabled bitmap from eFuse setting */
|
||||
efuse_setting = RREG32_SOC15(GC, 0, mmCC_GC_SA_UNIT_DISABLE);
|
||||
efuse_setting &= CC_GC_SA_UNIT_DISABLE__SA_DISABLE_MASK;
|
||||
@ -566,6 +568,9 @@ static void gfxhub_v2_1_utcl2_harvest(struct amdgpu_device *adev)
|
||||
disabled_sa = tmp;
|
||||
|
||||
WREG32_SOC15(GC, 0, mmGCUTCL2_HARVEST_BYPASS_GROUPS_YELLOW_CARP, disabled_sa);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -664,11 +664,25 @@ static void gmc_v10_0_set_umc_funcs(struct amdgpu_device *adev)
|
||||
adev->umc.umc_inst_num = UMC_V8_7_UMC_INSTANCE_NUM;
|
||||
adev->umc.channel_offs = UMC_V8_7_PER_CHANNEL_OFFSET_SIENNA;
|
||||
adev->umc.channel_idx_tbl = &umc_v8_7_channel_idx_tbl[0][0];
|
||||
adev->umc.ras_funcs = &umc_v8_7_ras_funcs;
|
||||
adev->umc.ras = &umc_v8_7_ras;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (adev->umc.ras) {
|
||||
amdgpu_ras_register_ras_block(adev, &adev->umc.ras->ras_block);
|
||||
|
||||
strcpy(adev->umc.ras->ras_block.name, "umc");
|
||||
adev->umc.ras->ras_block.block = AMDGPU_RAS_BLOCK__UMC;
|
||||
|
||||
/* If don't define special ras_late_init function, use default ras_late_init */
|
||||
if (!adev->umc.ras->ras_block.ras_late_init)
|
||||
adev->umc.ras->ras_block.ras_late_init = amdgpu_umc_ras_late_init;
|
||||
|
||||
/* If don't define special ras_fini function, use default ras_fini */
|
||||
if (!adev->umc.ras->ras_block.ras_fini)
|
||||
adev->umc.ras->ras_block.ras_fini = amdgpu_umc_ras_fini;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -705,6 +719,7 @@ static void gmc_v10_0_set_gfxhub_funcs(struct amdgpu_device *adev)
|
||||
|
||||
static int gmc_v10_0_early_init(void *handle)
|
||||
{
|
||||
int r;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
gmc_v10_0_set_mmhub_funcs(adev);
|
||||
@ -720,6 +735,10 @@ static int gmc_v10_0_early_init(void *handle)
|
||||
adev->gmc.private_aperture_end =
|
||||
adev->gmc.private_aperture_start + (4ULL << 30) - 1;
|
||||
|
||||
r = amdgpu_gmc_ras_early_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -862,6 +881,7 @@ static int gmc_v10_0_sw_init(void *handle)
|
||||
case IP_VERSION(10, 1, 1):
|
||||
case IP_VERSION(10, 1, 2):
|
||||
case IP_VERSION(10, 1, 3):
|
||||
case IP_VERSION(10, 1, 4):
|
||||
case IP_VERSION(10, 3, 0):
|
||||
case IP_VERSION(10, 3, 2):
|
||||
case IP_VERSION(10, 3, 1):
|
||||
@ -986,14 +1006,7 @@ static int gmc_v10_0_gart_enable(struct amdgpu_device *adev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev))
|
||||
goto skip_pin_bo;
|
||||
|
||||
r = amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
skip_pin_bo:
|
||||
amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr);
|
||||
r = adev->gfxhub.funcs->gart_enable(adev);
|
||||
if (r)
|
||||
return r;
|
||||
@ -1019,8 +1032,6 @@ skip_pin_bo:
|
||||
(unsigned)(adev->gmc.gart_size >> 20),
|
||||
(unsigned long long)amdgpu_bo_gpu_offset(adev->gart.bo));
|
||||
|
||||
adev->gart.ready = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1043,6 +1054,12 @@ static int gmc_v10_0_hw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (amdgpu_emu_mode == 1) {
|
||||
r = amdgpu_gmc_vram_checking(adev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (adev->umc.funcs && adev->umc.funcs->init_registers)
|
||||
adev->umc.funcs->init_registers(adev);
|
||||
|
||||
@ -1140,6 +1157,10 @@ static void gmc_v10_0_get_clockgating_state(void *handle, u32 *flags)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 3) ||
|
||||
adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 4))
|
||||
return;
|
||||
|
||||
adev->mmhub.funcs->get_clockgating(adev, flags);
|
||||
|
||||
if (adev->ip_versions[ATHUB_HWIP][0] >= IP_VERSION(2, 1, 0))
|
||||
|
@ -469,16 +469,14 @@ static void gmc_v6_0_set_prt(struct amdgpu_device *adev, bool enable)
|
||||
static int gmc_v6_0_gart_enable(struct amdgpu_device *adev)
|
||||
{
|
||||
uint64_t table_addr;
|
||||
int r, i;
|
||||
u32 field;
|
||||
int i;
|
||||
|
||||
if (adev->gart.bo == NULL) {
|
||||
dev_err(adev->dev, "No VRAM object for PCIE GART.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
r = amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr);
|
||||
if (r)
|
||||
return r;
|
||||
amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr);
|
||||
|
||||
table_addr = amdgpu_bo_gpu_offset(adev->gart.bo);
|
||||
|
||||
@ -558,7 +556,6 @@ static int gmc_v6_0_gart_enable(struct amdgpu_device *adev)
|
||||
dev_info(adev->dev, "PCIE GART of %uM enabled (table at 0x%016llX).\n",
|
||||
(unsigned)(adev->gmc.gart_size >> 20),
|
||||
(unsigned long long)table_addr);
|
||||
adev->gart.ready = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -922,7 +919,10 @@ static int gmc_v6_0_hw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return r;
|
||||
if (amdgpu_emu_mode == 1)
|
||||
return amdgpu_gmc_vram_checking(adev);
|
||||
else
|
||||
return r;
|
||||
}
|
||||
|
||||
static int gmc_v6_0_hw_fini(void *handle)
|
||||
|
@ -613,17 +613,14 @@ static void gmc_v7_0_set_prt(struct amdgpu_device *adev, bool enable)
|
||||
static int gmc_v7_0_gart_enable(struct amdgpu_device *adev)
|
||||
{
|
||||
uint64_t table_addr;
|
||||
int r, i;
|
||||
u32 tmp, field;
|
||||
int i;
|
||||
|
||||
if (adev->gart.bo == NULL) {
|
||||
dev_err(adev->dev, "No VRAM object for PCIE GART.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
r = amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr);
|
||||
table_addr = amdgpu_bo_gpu_offset(adev->gart.bo);
|
||||
|
||||
/* Setup TLB control */
|
||||
@ -712,7 +709,6 @@ static int gmc_v7_0_gart_enable(struct amdgpu_device *adev)
|
||||
DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
|
||||
(unsigned)(adev->gmc.gart_size >> 20),
|
||||
(unsigned long long)table_addr);
|
||||
adev->gart.ready = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1111,7 +1107,10 @@ static int gmc_v7_0_hw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return r;
|
||||
if (amdgpu_emu_mode == 1)
|
||||
return amdgpu_gmc_vram_checking(adev);
|
||||
else
|
||||
return r;
|
||||
}
|
||||
|
||||
static int gmc_v7_0_hw_fini(void *handle)
|
||||
|
@ -837,17 +837,14 @@ static void gmc_v8_0_set_prt(struct amdgpu_device *adev, bool enable)
|
||||
static int gmc_v8_0_gart_enable(struct amdgpu_device *adev)
|
||||
{
|
||||
uint64_t table_addr;
|
||||
int r, i;
|
||||
u32 tmp, field;
|
||||
int i;
|
||||
|
||||
if (adev->gart.bo == NULL) {
|
||||
dev_err(adev->dev, "No VRAM object for PCIE GART.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
r = amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr);
|
||||
table_addr = amdgpu_bo_gpu_offset(adev->gart.bo);
|
||||
|
||||
/* Setup TLB control */
|
||||
@ -953,7 +950,6 @@ static int gmc_v8_0_gart_enable(struct amdgpu_device *adev)
|
||||
DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
|
||||
(unsigned)(adev->gmc.gart_size >> 20),
|
||||
(unsigned long long)table_addr);
|
||||
adev->gart.ready = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1242,7 +1238,10 @@ static int gmc_v8_0_hw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return r;
|
||||
if (amdgpu_emu_mode == 1)
|
||||
return amdgpu_gmc_vram_checking(adev);
|
||||
else
|
||||
return r;
|
||||
}
|
||||
|
||||
static int gmc_v8_0_hw_fini(void *handle)
|
||||
|
@ -1202,7 +1202,7 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
|
||||
adev->umc.umc_inst_num = UMC_V6_1_UMC_INSTANCE_NUM;
|
||||
adev->umc.channel_offs = UMC_V6_1_PER_CHANNEL_OFFSET_VG20;
|
||||
adev->umc.channel_idx_tbl = &umc_v6_1_channel_idx_tbl[0][0];
|
||||
adev->umc.ras_funcs = &umc_v6_1_ras_funcs;
|
||||
adev->umc.ras = &umc_v6_1_ras;
|
||||
break;
|
||||
case IP_VERSION(6, 1, 2):
|
||||
adev->umc.max_ras_err_cnt_per_query = UMC_V6_1_TOTAL_CHANNEL_NUM;
|
||||
@ -1210,15 +1210,16 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
|
||||
adev->umc.umc_inst_num = UMC_V6_1_UMC_INSTANCE_NUM;
|
||||
adev->umc.channel_offs = UMC_V6_1_PER_CHANNEL_OFFSET_ARCT;
|
||||
adev->umc.channel_idx_tbl = &umc_v6_1_channel_idx_tbl[0][0];
|
||||
adev->umc.ras_funcs = &umc_v6_1_ras_funcs;
|
||||
adev->umc.ras = &umc_v6_1_ras;
|
||||
break;
|
||||
case IP_VERSION(6, 7, 0):
|
||||
adev->umc.max_ras_err_cnt_per_query = UMC_V6_7_TOTAL_CHANNEL_NUM;
|
||||
adev->umc.max_ras_err_cnt_per_query =
|
||||
UMC_V6_7_TOTAL_CHANNEL_NUM * UMC_V6_7_BAD_PAGE_NUM_PER_CHANNEL;
|
||||
adev->umc.channel_inst_num = UMC_V6_7_CHANNEL_INSTANCE_NUM;
|
||||
adev->umc.umc_inst_num = UMC_V6_7_UMC_INSTANCE_NUM;
|
||||
adev->umc.channel_offs = UMC_V6_7_PER_CHANNEL_OFFSET;
|
||||
if (!adev->gmc.xgmi.connected_to_cpu)
|
||||
adev->umc.ras_funcs = &umc_v6_7_ras_funcs;
|
||||
adev->umc.ras = &umc_v6_7_ras;
|
||||
if (1 & adev->smuio.funcs->get_die_id(adev))
|
||||
adev->umc.channel_idx_tbl = &umc_v6_7_channel_idx_tbl_first[0][0];
|
||||
else
|
||||
@ -1227,6 +1228,21 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (adev->umc.ras) {
|
||||
amdgpu_ras_register_ras_block(adev, &adev->umc.ras->ras_block);
|
||||
|
||||
strcpy(adev->umc.ras->ras_block.name, "umc");
|
||||
adev->umc.ras->ras_block.block = AMDGPU_RAS_BLOCK__UMC;
|
||||
|
||||
/* If don't define special ras_late_init function, use default ras_late_init */
|
||||
if (!adev->umc.ras->ras_block.ras_late_init)
|
||||
adev->umc.ras->ras_block.ras_late_init = amdgpu_umc_ras_late_init;
|
||||
|
||||
/* If don't define special ras_fini function, use default ras_fini */
|
||||
if (!adev->umc.ras->ras_block.ras_fini)
|
||||
adev->umc.ras->ras_block.ras_fini = amdgpu_umc_ras_fini;
|
||||
}
|
||||
}
|
||||
|
||||
static void gmc_v9_0_set_mmhub_funcs(struct amdgpu_device *adev)
|
||||
@ -1248,18 +1264,33 @@ static void gmc_v9_0_set_mmhub_ras_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
switch (adev->ip_versions[MMHUB_HWIP][0]) {
|
||||
case IP_VERSION(9, 4, 0):
|
||||
adev->mmhub.ras_funcs = &mmhub_v1_0_ras_funcs;
|
||||
adev->mmhub.ras = &mmhub_v1_0_ras;
|
||||
break;
|
||||
case IP_VERSION(9, 4, 1):
|
||||
adev->mmhub.ras_funcs = &mmhub_v9_4_ras_funcs;
|
||||
adev->mmhub.ras = &mmhub_v9_4_ras;
|
||||
break;
|
||||
case IP_VERSION(9, 4, 2):
|
||||
adev->mmhub.ras_funcs = &mmhub_v1_7_ras_funcs;
|
||||
adev->mmhub.ras = &mmhub_v1_7_ras;
|
||||
break;
|
||||
default:
|
||||
/* mmhub ras is not available */
|
||||
break;
|
||||
}
|
||||
|
||||
if (adev->mmhub.ras) {
|
||||
amdgpu_ras_register_ras_block(adev, &adev->mmhub.ras->ras_block);
|
||||
|
||||
strcpy(adev->mmhub.ras->ras_block.name,"mmhub");
|
||||
adev->mmhub.ras->ras_block.block = AMDGPU_RAS_BLOCK__MMHUB;
|
||||
|
||||
/* If don't define special ras_late_init function, use default ras_late_init */
|
||||
if (!adev->mmhub.ras->ras_block.ras_late_init)
|
||||
adev->mmhub.ras->ras_block.ras_late_init = amdgpu_mmhub_ras_late_init;
|
||||
|
||||
/* If don't define special ras_fini function, use default ras_fini */
|
||||
if (!adev->mmhub.ras->ras_block.ras_fini)
|
||||
adev->mmhub.ras->ras_block.ras_fini = amdgpu_mmhub_ras_fini;
|
||||
}
|
||||
}
|
||||
|
||||
static void gmc_v9_0_set_gfxhub_funcs(struct amdgpu_device *adev)
|
||||
@ -1269,7 +1300,8 @@ static void gmc_v9_0_set_gfxhub_funcs(struct amdgpu_device *adev)
|
||||
|
||||
static void gmc_v9_0_set_hdp_ras_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->hdp.ras_funcs = &hdp_v4_0_ras_funcs;
|
||||
adev->hdp.ras = &hdp_v4_0_ras;
|
||||
amdgpu_ras_register_ras_block(adev, &adev->hdp.ras->ras_block);
|
||||
}
|
||||
|
||||
static void gmc_v9_0_set_mca_funcs(struct amdgpu_device *adev)
|
||||
@ -1287,6 +1319,7 @@ static void gmc_v9_0_set_mca_funcs(struct amdgpu_device *adev)
|
||||
|
||||
static int gmc_v9_0_early_init(void *handle)
|
||||
{
|
||||
int r;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
/* ARCT and VEGA20 don't have XGMI defined in their IP discovery tables */
|
||||
@ -1316,6 +1349,10 @@ static int gmc_v9_0_early_init(void *handle)
|
||||
adev->gmc.private_aperture_end =
|
||||
adev->gmc.private_aperture_start + (4ULL << 30) - 1;
|
||||
|
||||
r = amdgpu_gmc_ras_early_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1342,13 +1379,13 @@ static int gmc_v9_0_late_init(void *handle)
|
||||
}
|
||||
|
||||
if (!amdgpu_persistent_edc_harvesting_supported(adev)) {
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->reset_ras_error_count)
|
||||
adev->mmhub.ras_funcs->reset_ras_error_count(adev);
|
||||
if (adev->mmhub.ras && adev->mmhub.ras->ras_block.hw_ops &&
|
||||
adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count)
|
||||
adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count(adev);
|
||||
|
||||
if (adev->hdp.ras_funcs &&
|
||||
adev->hdp.ras_funcs->reset_ras_error_count)
|
||||
adev->hdp.ras_funcs->reset_ras_error_count(adev);
|
||||
if (adev->hdp.ras && adev->hdp.ras->ras_block.hw_ops &&
|
||||
adev->hdp.ras->ras_block.hw_ops->reset_ras_error_count)
|
||||
adev->hdp.ras->ras_block.hw_ops->reset_ras_error_count(adev);
|
||||
}
|
||||
|
||||
r = amdgpu_gmc_ras_late_init(adev);
|
||||
@ -1752,14 +1789,7 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev))
|
||||
goto skip_pin_bo;
|
||||
|
||||
r = amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
skip_pin_bo:
|
||||
amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr);
|
||||
r = adev->gfxhub.funcs->gart_enable(adev);
|
||||
if (r)
|
||||
return r;
|
||||
@ -1776,7 +1806,6 @@ skip_pin_bo:
|
||||
DRM_INFO("PTB located at 0x%016llX\n",
|
||||
(unsigned long long)amdgpu_bo_gpu_offset(adev->gart.bo));
|
||||
|
||||
adev->gart.ready = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1784,7 +1813,7 @@ static int gmc_v9_0_hw_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
bool value;
|
||||
int i;
|
||||
int i, r;
|
||||
|
||||
/* The sequence of these two function calls matters.*/
|
||||
gmc_v9_0_init_golden_registers(adev);
|
||||
@ -1819,7 +1848,14 @@ static int gmc_v9_0_hw_init(void *handle)
|
||||
if (adev->umc.funcs && adev->umc.funcs->init_registers)
|
||||
adev->umc.funcs->init_registers(adev);
|
||||
|
||||
return gmc_v9_0_gart_enable(adev);
|
||||
r = gmc_v9_0_gart_enable(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (amdgpu_emu_mode == 1)
|
||||
return amdgpu_gmc_vram_checking(adev);
|
||||
else
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,13 +150,21 @@ static void hdp_v4_0_init_registers(struct amdgpu_device *adev)
|
||||
WREG32_SOC15(HDP, 0, mmHDP_NONSURFACE_BASE_HI, (adev->gmc.vram_start >> 40));
|
||||
}
|
||||
|
||||
const struct amdgpu_hdp_ras_funcs hdp_v4_0_ras_funcs = {
|
||||
.ras_late_init = amdgpu_hdp_ras_late_init,
|
||||
.ras_fini = amdgpu_hdp_ras_fini,
|
||||
struct amdgpu_ras_block_hw_ops hdp_v4_0_ras_hw_ops = {
|
||||
.query_ras_error_count = hdp_v4_0_query_ras_error_count,
|
||||
.reset_ras_error_count = hdp_v4_0_reset_ras_error_count,
|
||||
};
|
||||
|
||||
struct amdgpu_hdp_ras hdp_v4_0_ras = {
|
||||
.ras_block = {
|
||||
.name = "hdp",
|
||||
.block = AMDGPU_RAS_BLOCK__HDP,
|
||||
.hw_ops = &hdp_v4_0_ras_hw_ops,
|
||||
.ras_late_init = amdgpu_hdp_ras_late_init,
|
||||
.ras_fini = amdgpu_hdp_ras_fini,
|
||||
},
|
||||
};
|
||||
|
||||
const struct amdgpu_hdp_funcs hdp_v4_0_funcs = {
|
||||
.flush_hdp = hdp_v4_0_flush_hdp,
|
||||
.invalidate_hdp = hdp_v4_0_invalidate_hdp,
|
||||
|
@ -27,6 +27,6 @@
|
||||
#include "soc15_common.h"
|
||||
|
||||
extern const struct amdgpu_hdp_funcs hdp_v4_0_funcs;
|
||||
extern const struct amdgpu_hdp_ras_funcs hdp_v4_0_ras_funcs;
|
||||
extern struct amdgpu_hdp_ras hdp_v4_0_ras;
|
||||
|
||||
#endif
|
||||
|
@ -50,11 +50,16 @@ static int jpeg_v3_0_early_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (adev->asic_type != CHIP_YELLOW_CARP) {
|
||||
u32 harvest = RREG32_SOC15(JPEG, 0, mmCC_UVD_HARVESTING);
|
||||
u32 harvest;
|
||||
|
||||
switch (adev->ip_versions[UVD_HWIP][0]) {
|
||||
case IP_VERSION(3, 1, 1):
|
||||
break;
|
||||
default:
|
||||
harvest = RREG32_SOC15(JPEG, 0, mmCC_UVD_HARVESTING);
|
||||
if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK)
|
||||
return -ENOENT;
|
||||
break;
|
||||
}
|
||||
|
||||
adev->jpeg.num_jpeg_inst = 1;
|
||||
|
@ -37,7 +37,7 @@ static void mca_v3_0_mp0_query_ras_error_count(struct amdgpu_device *adev,
|
||||
ras_error_status);
|
||||
}
|
||||
|
||||
static int mca_v3_0_mp0_ras_late_init(struct amdgpu_device *adev)
|
||||
static int mca_v3_0_mp0_ras_late_init(struct amdgpu_device *adev, void *ras_info)
|
||||
{
|
||||
return amdgpu_mca_ras_late_init(adev, &adev->mca.mp0);
|
||||
}
|
||||
@ -47,14 +47,35 @@ static void mca_v3_0_mp0_ras_fini(struct amdgpu_device *adev)
|
||||
amdgpu_mca_ras_fini(adev, &adev->mca.mp0);
|
||||
}
|
||||
|
||||
const struct amdgpu_mca_ras_funcs mca_v3_0_mp0_ras_funcs = {
|
||||
.ras_late_init = mca_v3_0_mp0_ras_late_init,
|
||||
.ras_fini = mca_v3_0_mp0_ras_fini,
|
||||
static int mca_v3_0_ras_block_match(struct amdgpu_ras_block_object *block_obj,
|
||||
enum amdgpu_ras_block block, uint32_t sub_block_index)
|
||||
{
|
||||
if (!block_obj)
|
||||
return -EINVAL;
|
||||
|
||||
if ((block_obj->block == block) &&
|
||||
(block_obj->sub_block_index == sub_block_index)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
const struct amdgpu_ras_block_hw_ops mca_v3_0_mp0_hw_ops = {
|
||||
.query_ras_error_count = mca_v3_0_mp0_query_ras_error_count,
|
||||
.query_ras_error_address = NULL,
|
||||
.ras_block = AMDGPU_RAS_BLOCK__MCA,
|
||||
.ras_sub_block = AMDGPU_RAS_MCA_BLOCK__MP0,
|
||||
.sysfs_name = "mp0_err_count",
|
||||
};
|
||||
|
||||
struct amdgpu_mca_ras_block mca_v3_0_mp0_ras = {
|
||||
.ras_block = {
|
||||
.block = AMDGPU_RAS_BLOCK__MCA,
|
||||
.sub_block_index = AMDGPU_RAS_MCA_BLOCK__MP0,
|
||||
.name = "mp0",
|
||||
.hw_ops = &mca_v3_0_mp0_hw_ops,
|
||||
.ras_block_match = mca_v3_0_ras_block_match,
|
||||
.ras_late_init = mca_v3_0_mp0_ras_late_init,
|
||||
.ras_fini = mca_v3_0_mp0_ras_fini,
|
||||
},
|
||||
};
|
||||
|
||||
static void mca_v3_0_mp1_query_ras_error_count(struct amdgpu_device *adev,
|
||||
@ -65,7 +86,7 @@ static void mca_v3_0_mp1_query_ras_error_count(struct amdgpu_device *adev,
|
||||
ras_error_status);
|
||||
}
|
||||
|
||||
static int mca_v3_0_mp1_ras_late_init(struct amdgpu_device *adev)
|
||||
static int mca_v3_0_mp1_ras_late_init(struct amdgpu_device *adev, void *ras_info)
|
||||
{
|
||||
return amdgpu_mca_ras_late_init(adev, &adev->mca.mp1);
|
||||
}
|
||||
@ -75,14 +96,21 @@ static void mca_v3_0_mp1_ras_fini(struct amdgpu_device *adev)
|
||||
amdgpu_mca_ras_fini(adev, &adev->mca.mp1);
|
||||
}
|
||||
|
||||
const struct amdgpu_mca_ras_funcs mca_v3_0_mp1_ras_funcs = {
|
||||
.ras_late_init = mca_v3_0_mp1_ras_late_init,
|
||||
.ras_fini = mca_v3_0_mp1_ras_fini,
|
||||
const struct amdgpu_ras_block_hw_ops mca_v3_0_mp1_hw_ops = {
|
||||
.query_ras_error_count = mca_v3_0_mp1_query_ras_error_count,
|
||||
.query_ras_error_address = NULL,
|
||||
.ras_block = AMDGPU_RAS_BLOCK__MCA,
|
||||
.ras_sub_block = AMDGPU_RAS_MCA_BLOCK__MP1,
|
||||
.sysfs_name = "mp1_err_count",
|
||||
};
|
||||
|
||||
struct amdgpu_mca_ras_block mca_v3_0_mp1_ras = {
|
||||
.ras_block = {
|
||||
.block = AMDGPU_RAS_BLOCK__MCA,
|
||||
.sub_block_index = AMDGPU_RAS_MCA_BLOCK__MP1,
|
||||
.name = "mp1",
|
||||
.hw_ops = &mca_v3_0_mp1_hw_ops,
|
||||
.ras_block_match = mca_v3_0_ras_block_match,
|
||||
.ras_late_init = mca_v3_0_mp1_ras_late_init,
|
||||
.ras_fini = mca_v3_0_mp1_ras_fini,
|
||||
},
|
||||
};
|
||||
|
||||
static void mca_v3_0_mpio_query_ras_error_count(struct amdgpu_device *adev,
|
||||
@ -93,7 +121,7 @@ static void mca_v3_0_mpio_query_ras_error_count(struct amdgpu_device *adev,
|
||||
ras_error_status);
|
||||
}
|
||||
|
||||
static int mca_v3_0_mpio_ras_late_init(struct amdgpu_device *adev)
|
||||
static int mca_v3_0_mpio_ras_late_init(struct amdgpu_device *adev, void *ras_info)
|
||||
{
|
||||
return amdgpu_mca_ras_late_init(adev, &adev->mca.mpio);
|
||||
}
|
||||
@ -103,14 +131,21 @@ static void mca_v3_0_mpio_ras_fini(struct amdgpu_device *adev)
|
||||
amdgpu_mca_ras_fini(adev, &adev->mca.mpio);
|
||||
}
|
||||
|
||||
const struct amdgpu_mca_ras_funcs mca_v3_0_mpio_ras_funcs = {
|
||||
.ras_late_init = mca_v3_0_mpio_ras_late_init,
|
||||
.ras_fini = mca_v3_0_mpio_ras_fini,
|
||||
const struct amdgpu_ras_block_hw_ops mca_v3_0_mpio_hw_ops = {
|
||||
.query_ras_error_count = mca_v3_0_mpio_query_ras_error_count,
|
||||
.query_ras_error_address = NULL,
|
||||
.ras_block = AMDGPU_RAS_BLOCK__MCA,
|
||||
.ras_sub_block = AMDGPU_RAS_MCA_BLOCK__MPIO,
|
||||
.sysfs_name = "mpio_err_count",
|
||||
};
|
||||
|
||||
struct amdgpu_mca_ras_block mca_v3_0_mpio_ras = {
|
||||
.ras_block = {
|
||||
.block = AMDGPU_RAS_BLOCK__MCA,
|
||||
.sub_block_index = AMDGPU_RAS_MCA_BLOCK__MPIO,
|
||||
.name = "mpio",
|
||||
.hw_ops = &mca_v3_0_mpio_hw_ops,
|
||||
.ras_block_match = mca_v3_0_ras_block_match,
|
||||
.ras_late_init = mca_v3_0_mpio_ras_late_init,
|
||||
.ras_fini = mca_v3_0_mpio_ras_fini,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -118,9 +153,12 @@ static void mca_v3_0_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_mca *mca = &adev->mca;
|
||||
|
||||
mca->mp0.ras_funcs = &mca_v3_0_mp0_ras_funcs;
|
||||
mca->mp1.ras_funcs = &mca_v3_0_mp1_ras_funcs;
|
||||
mca->mpio.ras_funcs = &mca_v3_0_mpio_ras_funcs;
|
||||
mca->mp0.ras = &mca_v3_0_mp0_ras;
|
||||
mca->mp1.ras = &mca_v3_0_mp1_ras;
|
||||
mca->mpio.ras = &mca_v3_0_mpio_ras;
|
||||
amdgpu_ras_register_ras_block(adev, &mca->mp0.ras->ras_block);
|
||||
amdgpu_ras_register_ras_block(adev, &mca->mp1.ras->ras_block);
|
||||
amdgpu_ras_register_ras_block(adev, &mca->mpio.ras->ras_block);
|
||||
}
|
||||
|
||||
const struct amdgpu_mca_funcs mca_v3_0_funcs = {
|
||||
|
@ -774,13 +774,17 @@ static void mmhub_v1_0_reset_ras_error_count(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
const struct amdgpu_mmhub_ras_funcs mmhub_v1_0_ras_funcs = {
|
||||
.ras_late_init = amdgpu_mmhub_ras_late_init,
|
||||
.ras_fini = amdgpu_mmhub_ras_fini,
|
||||
struct amdgpu_ras_block_hw_ops mmhub_v1_0_ras_hw_ops = {
|
||||
.query_ras_error_count = mmhub_v1_0_query_ras_error_count,
|
||||
.reset_ras_error_count = mmhub_v1_0_reset_ras_error_count,
|
||||
};
|
||||
|
||||
struct amdgpu_mmhub_ras mmhub_v1_0_ras = {
|
||||
.ras_block = {
|
||||
.hw_ops = &mmhub_v1_0_ras_hw_ops,
|
||||
},
|
||||
};
|
||||
|
||||
const struct amdgpu_mmhub_funcs mmhub_v1_0_funcs = {
|
||||
.get_fb_location = mmhub_v1_0_get_fb_location,
|
||||
.init = mmhub_v1_0_init,
|
||||
|
@ -24,6 +24,6 @@
|
||||
#define __MMHUB_V1_0_H__
|
||||
|
||||
extern const struct amdgpu_mmhub_funcs mmhub_v1_0_funcs;
|
||||
extern const struct amdgpu_mmhub_ras_funcs mmhub_v1_0_ras_funcs;
|
||||
extern struct amdgpu_mmhub_ras mmhub_v1_0_ras;
|
||||
|
||||
#endif
|
||||
|
@ -1321,15 +1321,19 @@ static void mmhub_v1_7_reset_ras_error_status(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
const struct amdgpu_mmhub_ras_funcs mmhub_v1_7_ras_funcs = {
|
||||
.ras_late_init = amdgpu_mmhub_ras_late_init,
|
||||
.ras_fini = amdgpu_mmhub_ras_fini,
|
||||
struct amdgpu_ras_block_hw_ops mmhub_v1_7_ras_hw_ops = {
|
||||
.query_ras_error_count = mmhub_v1_7_query_ras_error_count,
|
||||
.reset_ras_error_count = mmhub_v1_7_reset_ras_error_count,
|
||||
.query_ras_error_status = mmhub_v1_7_query_ras_error_status,
|
||||
.reset_ras_error_status = mmhub_v1_7_reset_ras_error_status,
|
||||
};
|
||||
|
||||
struct amdgpu_mmhub_ras mmhub_v1_7_ras = {
|
||||
.ras_block = {
|
||||
.hw_ops = &mmhub_v1_7_ras_hw_ops,
|
||||
},
|
||||
};
|
||||
|
||||
const struct amdgpu_mmhub_funcs mmhub_v1_7_funcs = {
|
||||
.get_fb_location = mmhub_v1_7_get_fb_location,
|
||||
.init = mmhub_v1_7_init,
|
||||
|
@ -24,6 +24,6 @@
|
||||
#define __MMHUB_V1_7_H__
|
||||
|
||||
extern const struct amdgpu_mmhub_funcs mmhub_v1_7_funcs;
|
||||
extern const struct amdgpu_mmhub_ras_funcs mmhub_v1_7_ras_funcs;
|
||||
extern struct amdgpu_mmhub_ras mmhub_v1_7_ras;
|
||||
|
||||
#endif
|
||||
|
@ -1655,14 +1655,18 @@ static void mmhub_v9_4_query_ras_error_status(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
const struct amdgpu_mmhub_ras_funcs mmhub_v9_4_ras_funcs = {
|
||||
.ras_late_init = amdgpu_mmhub_ras_late_init,
|
||||
.ras_fini = amdgpu_mmhub_ras_fini,
|
||||
const struct amdgpu_ras_block_hw_ops mmhub_v9_4_ras_hw_ops = {
|
||||
.query_ras_error_count = mmhub_v9_4_query_ras_error_count,
|
||||
.reset_ras_error_count = mmhub_v9_4_reset_ras_error_count,
|
||||
.query_ras_error_status = mmhub_v9_4_query_ras_error_status,
|
||||
};
|
||||
|
||||
struct amdgpu_mmhub_ras mmhub_v9_4_ras = {
|
||||
.ras_block = {
|
||||
.hw_ops = &mmhub_v9_4_ras_hw_ops,
|
||||
},
|
||||
};
|
||||
|
||||
const struct amdgpu_mmhub_funcs mmhub_v9_4_funcs = {
|
||||
.get_fb_location = mmhub_v9_4_get_fb_location,
|
||||
.init = mmhub_v9_4_init,
|
||||
|
@ -24,6 +24,6 @@
|
||||
#define __MMHUB_V9_4_H__
|
||||
|
||||
extern const struct amdgpu_mmhub_funcs mmhub_v9_4_funcs;
|
||||
extern const struct amdgpu_mmhub_ras_funcs mmhub_v9_4_ras_funcs;
|
||||
extern struct amdgpu_mmhub_ras mmhub_v9_4_ras;
|
||||
|
||||
#endif
|
||||
|
@ -544,7 +544,7 @@ static int xgpu_vi_mailbox_rcv_irq(struct amdgpu_device *adev,
|
||||
{
|
||||
int r;
|
||||
|
||||
/* trigger gpu-reset by hypervisor only if TDR disbaled */
|
||||
/* trigger gpu-reset by hypervisor only if TDR disabled */
|
||||
if (!amdgpu_gpu_recovery) {
|
||||
/* see what event we get */
|
||||
r = xgpu_vi_mailbox_rcv_msg(adev, IDH_FLR_NOTIFICATION);
|
||||
|
@ -59,10 +59,15 @@ static u32 nbio_v7_2_get_rev_id(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
if (adev->asic_type == CHIP_YELLOW_CARP)
|
||||
switch (adev->ip_versions[NBIO_HWIP][0]) {
|
||||
case IP_VERSION(7, 2, 1):
|
||||
case IP_VERSION(7, 5, 0):
|
||||
tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_YC);
|
||||
else
|
||||
break;
|
||||
default:
|
||||
tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0);
|
||||
break;
|
||||
}
|
||||
|
||||
tmp &= RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_ATI_REV_ID_DEV0_F0_MASK;
|
||||
tmp >>= RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_ATI_REV_ID_DEV0_F0__SHIFT;
|
||||
@ -72,20 +77,25 @@ static u32 nbio_v7_2_get_rev_id(struct amdgpu_device *adev)
|
||||
|
||||
static void nbio_v7_2_mc_access_enable(struct amdgpu_device *adev, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
if (adev->asic_type == CHIP_YELLOW_CARP)
|
||||
switch (adev->ip_versions[NBIO_HWIP][0]) {
|
||||
case IP_VERSION(7, 2, 1):
|
||||
case IP_VERSION(7, 5, 0):
|
||||
if (enable)
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN_YC,
|
||||
BIF_BX0_BIF_FB_EN__FB_READ_EN_MASK |
|
||||
BIF_BX0_BIF_FB_EN__FB_WRITE_EN_MASK);
|
||||
else
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN_YC, 0);
|
||||
break;
|
||||
default:
|
||||
if (enable)
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN,
|
||||
BIF_BX0_BIF_FB_EN__FB_READ_EN_MASK |
|
||||
BIF_BX0_BIF_FB_EN__FB_WRITE_EN_MASK);
|
||||
else
|
||||
if (adev->asic_type == CHIP_YELLOW_CARP)
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN_YC, 0);
|
||||
else
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 nbio_v7_2_get_memsize(struct amdgpu_device *adev)
|
||||
@ -250,7 +260,9 @@ static void nbio_v7_2_update_medium_grain_light_sleep(struct amdgpu_device *adev
|
||||
{
|
||||
uint32_t def, data;
|
||||
|
||||
if (adev->asic_type == CHIP_YELLOW_CARP) {
|
||||
switch (adev->ip_versions[NBIO_HWIP][0]) {
|
||||
case IP_VERSION(7, 2, 1):
|
||||
case IP_VERSION(7, 5, 0):
|
||||
def = data = RREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regPCIE_CNTL2));
|
||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_BIF_LS))
|
||||
data |= PCIE_CNTL2__SLV_MEM_LS_EN_MASK;
|
||||
@ -260,8 +272,8 @@ static void nbio_v7_2_update_medium_grain_light_sleep(struct amdgpu_device *adev
|
||||
if (def != data)
|
||||
WREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regPCIE_CNTL2), data);
|
||||
|
||||
data = RREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regBIF1_PCIE_TX_POWER_CTRL_1));
|
||||
def = data;
|
||||
def = data = RREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0,
|
||||
regBIF1_PCIE_TX_POWER_CTRL_1));
|
||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_BIF_LS))
|
||||
data |= (BIF1_PCIE_TX_POWER_CTRL_1__MST_MEM_LS_EN_MASK |
|
||||
BIF1_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_LS_EN_MASK);
|
||||
@ -272,7 +284,8 @@ static void nbio_v7_2_update_medium_grain_light_sleep(struct amdgpu_device *adev
|
||||
if (def != data)
|
||||
WREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regBIF1_PCIE_TX_POWER_CTRL_1),
|
||||
data);
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
def = data = RREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regPCIE_CNTL2));
|
||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_BIF_LS))
|
||||
data |= (PCIE_CNTL2__SLV_MEM_LS_EN_MASK |
|
||||
@ -285,6 +298,7 @@ static void nbio_v7_2_update_medium_grain_light_sleep(struct amdgpu_device *adev
|
||||
|
||||
if (def != data)
|
||||
WREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regPCIE_CNTL2), data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -352,7 +366,9 @@ const struct nbio_hdp_flush_reg nbio_v7_2_hdp_flush_reg = {
|
||||
static void nbio_v7_2_init_registers(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t def, data;
|
||||
if (adev->asic_type == CHIP_YELLOW_CARP) {
|
||||
switch (adev->ip_versions[NBIO_HWIP][0]) {
|
||||
case IP_VERSION(7, 2, 1):
|
||||
case IP_VERSION(7, 5, 0):
|
||||
def = data = RREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regBIF1_PCIE_MST_CTRL_3));
|
||||
data = REG_SET_FIELD(data, BIF1_PCIE_MST_CTRL_3,
|
||||
CI_SWUS_MAX_READ_REQUEST_SIZE_MODE, 1);
|
||||
@ -361,7 +377,8 @@ static void nbio_v7_2_init_registers(struct amdgpu_device *adev)
|
||||
|
||||
if (def != data)
|
||||
WREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regBIF1_PCIE_MST_CTRL_3), data);
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
def = data = RREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regPCIE_CONFIG_CNTL));
|
||||
data = REG_SET_FIELD(data, PCIE_CONFIG_CNTL,
|
||||
CI_SWUS_MAX_READ_REQUEST_SIZE_MODE, 1);
|
||||
@ -370,6 +387,7 @@ static void nbio_v7_2_init_registers(struct amdgpu_device *adev)
|
||||
|
||||
if (def != data)
|
||||
WREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regPCIE_CONFIG_CNTL), data);
|
||||
break;
|
||||
}
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
|
@ -658,16 +658,25 @@ static void nbio_v7_4_enable_doorbell_interrupt(struct amdgpu_device *adev,
|
||||
DOORBELL_INTERRUPT_DISABLE, enable ? 0 : 1);
|
||||
}
|
||||
|
||||
const struct amdgpu_nbio_ras_funcs nbio_v7_4_ras_funcs = {
|
||||
const struct amdgpu_ras_block_hw_ops nbio_v7_4_ras_hw_ops = {
|
||||
.query_ras_error_count = nbio_v7_4_query_ras_error_count,
|
||||
};
|
||||
|
||||
struct amdgpu_nbio_ras nbio_v7_4_ras = {
|
||||
.ras_block = {
|
||||
.name = "pcie_bif",
|
||||
.block = AMDGPU_RAS_BLOCK__PCIE_BIF,
|
||||
.hw_ops = &nbio_v7_4_ras_hw_ops,
|
||||
.ras_late_init = amdgpu_nbio_ras_late_init,
|
||||
.ras_fini = amdgpu_nbio_ras_fini,
|
||||
},
|
||||
.handle_ras_controller_intr_no_bifring = nbio_v7_4_handle_ras_controller_intr_no_bifring,
|
||||
.handle_ras_err_event_athub_intr_no_bifring = nbio_v7_4_handle_ras_err_event_athub_intr_no_bifring,
|
||||
.init_ras_controller_interrupt = nbio_v7_4_init_ras_controller_interrupt,
|
||||
.init_ras_err_event_athub_interrupt = nbio_v7_4_init_ras_err_event_athub_interrupt,
|
||||
.query_ras_error_count = nbio_v7_4_query_ras_error_count,
|
||||
.ras_late_init = amdgpu_nbio_ras_late_init,
|
||||
.ras_fini = amdgpu_nbio_ras_fini,
|
||||
};
|
||||
|
||||
|
||||
static void nbio_v7_4_program_ltr(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t def, data;
|
||||
|
@ -29,6 +29,6 @@
|
||||
extern const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg;
|
||||
extern const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg_ald;
|
||||
extern const struct amdgpu_nbio_funcs nbio_v7_4_funcs;
|
||||
extern const struct amdgpu_nbio_ras_funcs nbio_v7_4_ras_funcs;
|
||||
extern struct amdgpu_nbio_ras nbio_v7_4_ras;
|
||||
|
||||
#endif
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user