Merge drm/drm-next into drm-intel-gt-next
Matt needed some buddy allocator changes for landing DG2 small BAR support patches. Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
This commit is contained in:
@@ -71,6 +71,7 @@ config DRM_DEBUG_SELFTEST
|
||||
select DRM_DP_HELPER
|
||||
select DRM_LIB_RANDOM
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_BUDDY
|
||||
select DRM_EXPORT_FOR_TESTS if m
|
||||
default n
|
||||
help
|
||||
@@ -403,6 +404,8 @@ source "drivers/gpu/drm/xlnx/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/gud/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/solomon/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/sprd/Kconfig"
|
||||
|
||||
config DRM_HYPERV
|
||||
|
||||
@@ -132,4 +132,5 @@ obj-$(CONFIG_DRM_TIDSS) += tidss/
|
||||
obj-y += xlnx/
|
||||
obj-y += gud/
|
||||
obj-$(CONFIG_DRM_HYPERV) += hyperv/
|
||||
obj-y += solomon/
|
||||
obj-$(CONFIG_DRM_SPRD) += sprd/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -771,6 +771,8 @@ struct amd_powerplay {
|
||||
const struct amd_pm_funcs *pp_funcs;
|
||||
};
|
||||
|
||||
struct ip_discovery_top;
|
||||
|
||||
/* polaris10 kickers */
|
||||
#define ASICID_IS_P20(did, rid) (((did == 0x67DF) && \
|
||||
((rid == 0xE3) || \
|
||||
@@ -813,6 +815,8 @@ struct amd_powerplay {
|
||||
#define AMDGPU_RESET_MAGIC_NUM 64
|
||||
#define AMDGPU_MAX_DF_PERFMONS 4
|
||||
#define AMDGPU_PRODUCT_NAME_LEN 64
|
||||
struct amdgpu_reset_domain;
|
||||
|
||||
struct amdgpu_device {
|
||||
struct device *dev;
|
||||
struct pci_dev *pdev;
|
||||
@@ -950,12 +954,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;
|
||||
@@ -1054,9 +1052,7 @@ struct amdgpu_device {
|
||||
bool in_s4;
|
||||
bool in_s0ix;
|
||||
|
||||
atomic_t in_gpu_reset;
|
||||
enum pp_mp1_state mp1_state;
|
||||
struct rw_semaphore reset_sem;
|
||||
struct amdgpu_doorbell_index doorbell_index;
|
||||
|
||||
struct mutex notifier_lock;
|
||||
@@ -1100,6 +1096,12 @@ struct amdgpu_device {
|
||||
uint32_t ip_versions[MAX_HWIP][HWIP_MAX_INSTANCE];
|
||||
|
||||
bool ram_is_direct_mapped;
|
||||
|
||||
struct list_head ras_list;
|
||||
|
||||
struct ip_discovery_top *ip_top;
|
||||
|
||||
struct amdgpu_reset_domain *reset_domain;
|
||||
};
|
||||
|
||||
static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev)
|
||||
@@ -1293,9 +1295,12 @@ bool amdgpu_device_has_job_running(struct amdgpu_device *adev);
|
||||
bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev);
|
||||
int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
struct amdgpu_job* job);
|
||||
int amdgpu_device_gpu_recover_imp(struct amdgpu_device *adev,
|
||||
struct amdgpu_job *job);
|
||||
void amdgpu_device_pci_config_reset(struct amdgpu_device *adev);
|
||||
int amdgpu_device_pci_reset(struct amdgpu_device *adev);
|
||||
bool amdgpu_device_need_post(struct amdgpu_device *adev);
|
||||
bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev);
|
||||
|
||||
void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes,
|
||||
u64 num_vis_bytes);
|
||||
@@ -1321,6 +1326,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 +1417,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 +1429,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 +1467,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)
|
||||
@@ -1459,8 +1483,6 @@ static inline bool amdgpu_is_tmz(struct amdgpu_device *adev)
|
||||
return adev->gmc.tmz_enabled;
|
||||
}
|
||||
|
||||
static inline int amdgpu_in_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
return atomic_read(&adev->in_gpu_reset);
|
||||
}
|
||||
int amdgpu_in_reset(struct amdgpu_device *adev);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
@@ -736,7 +715,7 @@ static void get_wave_count(struct amdgpu_device *adev, int queue_idx,
|
||||
* process whose pasid is provided as a parameter. The process could have ZERO
|
||||
* or more queues running and submitting waves to compute units.
|
||||
*
|
||||
* @kgd: Handle of device from which to get number of waves in flight
|
||||
* @adev: Handle of device from which to get number of waves in flight
|
||||
* @pasid: Identifies the process for which this query call is invoked
|
||||
* @pasid_wave_cnt: Output parameter updated with number of waves in flight that
|
||||
* belong to process with given pasid
|
||||
@@ -745,7 +724,7 @@ static void get_wave_count(struct amdgpu_device *adev, int queue_idx,
|
||||
*
|
||||
* Note: It's possible that the device has too many queues (oversubscription)
|
||||
* in which case a VMID could be remapped to a different PASID. This could lead
|
||||
* to an iaccurate wave count. Following is a high-level sequence:
|
||||
* to an inaccurate wave count. Following is a high-level sequence:
|
||||
* Time T1: vmid = getVmid(); vmid is associated with Pasid P1
|
||||
* Time T2: passId = getPasId(vmid); vmid is associated with Pasid P2
|
||||
* In the sequence above wave count obtained from time T1 will be incorrectly
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ static size_t amdgpu_amdkfd_acc_size(uint64_t size)
|
||||
}
|
||||
|
||||
/**
|
||||
* @amdgpu_amdkfd_reserve_mem_limit() - Decrease available memory by size
|
||||
* amdgpu_amdkfd_reserve_mem_limit() - Decrease available memory by size
|
||||
* of buffer including any reserved for control structures
|
||||
*
|
||||
* @adev: Device to which allocated BO belongs to
|
||||
@@ -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;
|
||||
@@ -314,7 +312,7 @@ static void amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
total_vram = adev->gmc.real_vram_size - atomic64_read(&adev->vram_pin_size);
|
||||
used_vram = amdgpu_vram_mgr_usage(&adev->mman.vram_mgr);
|
||||
used_vram = ttm_resource_manager_usage(&adev->mman.vram_mgr.manager);
|
||||
free_vram = used_vram >= total_vram ? 0 : total_vram - used_vram;
|
||||
|
||||
spin_lock(&adev->mm_stats.lock);
|
||||
@@ -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,21 @@ 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);
|
||||
if (!r)
|
||||
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 {
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
#include "amdgpu_fw_attestation.h"
|
||||
#include "amdgpu_umr.h"
|
||||
|
||||
#include "amdgpu_reset.h"
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
||||
/**
|
||||
@@ -728,7 +730,7 @@ static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf,
|
||||
return -ENOMEM;
|
||||
|
||||
/* version, increment each time something is added */
|
||||
config[no_regs++] = 3;
|
||||
config[no_regs++] = 4;
|
||||
config[no_regs++] = adev->gfx.config.max_shader_engines;
|
||||
config[no_regs++] = adev->gfx.config.max_tile_pipes;
|
||||
config[no_regs++] = adev->gfx.config.max_cu_per_sh;
|
||||
@@ -768,6 +770,9 @@ static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf,
|
||||
config[no_regs++] = adev->pdev->subsystem_device;
|
||||
config[no_regs++] = adev->pdev->subsystem_vendor;
|
||||
|
||||
/* rev==4 APU flag */
|
||||
config[no_regs++] = adev->flags & AMD_IS_APU ? 1 : 0;
|
||||
|
||||
while (size && (*pos < no_regs * 4)) {
|
||||
uint32_t value;
|
||||
|
||||
@@ -1120,8 +1125,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;
|
||||
@@ -1279,7 +1286,7 @@ static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused)
|
||||
}
|
||||
|
||||
/* Avoid accidently unparking the sched thread during GPU reset */
|
||||
r = down_write_killable(&adev->reset_sem);
|
||||
r = down_write_killable(&adev->reset_domain->sem);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@@ -1308,7 +1315,7 @@ static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused)
|
||||
kthread_unpark(ring->sched.thread);
|
||||
}
|
||||
|
||||
up_write(&adev->reset_sem);
|
||||
up_write(&adev->reset_domain->sem);
|
||||
|
||||
pm_runtime_mark_last_busy(dev->dev);
|
||||
pm_runtime_put_autosuspend(dev->dev);
|
||||
@@ -1517,7 +1524,7 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Avoid accidently unparking the sched thread during GPU reset */
|
||||
r = down_read_killable(&adev->reset_sem);
|
||||
r = down_read_killable(&adev->reset_domain->sem);
|
||||
if (r)
|
||||
goto pro_end;
|
||||
|
||||
@@ -1560,7 +1567,7 @@ failure:
|
||||
/* restart the scheduler */
|
||||
kthread_unpark(ring->sched.thread);
|
||||
|
||||
up_read(&adev->reset_sem);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
|
||||
ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched);
|
||||
|
||||
@@ -1585,22 +1592,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"
|
||||
|
||||
@@ -88,6 +88,8 @@ MODULE_FIRMWARE("amdgpu/vangogh_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/yellow_carp_gpu_info.bin");
|
||||
|
||||
#define AMDGPU_RESUME_MS 2000
|
||||
#define AMDGPU_MAX_RETRY_LIMIT 2
|
||||
#define AMDGPU_RETRY_SRIOV_RESET(r) ((r) == -EBUSY || (r) == -ETIMEDOUT || (r) == -EINVAL)
|
||||
|
||||
const char *amdgpu_asic_name[] = {
|
||||
"TAHITI",
|
||||
@@ -424,10 +426,10 @@ bool amdgpu_device_skip_hw_access(struct amdgpu_device *adev)
|
||||
* the lock.
|
||||
*/
|
||||
if (in_task()) {
|
||||
if (down_read_trylock(&adev->reset_sem))
|
||||
up_read(&adev->reset_sem);
|
||||
if (down_read_trylock(&adev->reset_domain->sem))
|
||||
up_read(&adev->reset_domain->sem);
|
||||
else
|
||||
lockdep_assert_held(&adev->reset_sem);
|
||||
lockdep_assert_held(&adev->reset_domain->sem);
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
@@ -453,9 +455,9 @@ uint32_t amdgpu_device_rreg(struct amdgpu_device *adev,
|
||||
if ((reg * 4) < adev->rmmio_size) {
|
||||
if (!(acc_flags & AMDGPU_REGS_NO_KIQ) &&
|
||||
amdgpu_sriov_runtime(adev) &&
|
||||
down_read_trylock(&adev->reset_sem)) {
|
||||
down_read_trylock(&adev->reset_domain->sem)) {
|
||||
ret = amdgpu_kiq_rreg(adev, reg);
|
||||
up_read(&adev->reset_sem);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
} else {
|
||||
ret = readl(((void __iomem *)adev->rmmio) + (reg * 4));
|
||||
}
|
||||
@@ -538,9 +540,9 @@ void amdgpu_device_wreg(struct amdgpu_device *adev,
|
||||
if ((reg * 4) < adev->rmmio_size) {
|
||||
if (!(acc_flags & AMDGPU_REGS_NO_KIQ) &&
|
||||
amdgpu_sriov_runtime(adev) &&
|
||||
down_read_trylock(&adev->reset_sem)) {
|
||||
down_read_trylock(&adev->reset_domain->sem)) {
|
||||
amdgpu_kiq_wreg(adev, reg, v);
|
||||
up_read(&adev->reset_sem);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
} else {
|
||||
writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
|
||||
}
|
||||
@@ -554,7 +556,11 @@ void amdgpu_device_wreg(struct amdgpu_device *adev,
|
||||
/**
|
||||
* amdgpu_mm_wreg_mmio_rlc - write register either with direct/indirect mmio or with RLC path if in range
|
||||
*
|
||||
* this function is invoked only the debugfs register access
|
||||
* @adev: amdgpu_device pointer
|
||||
* @reg: mmio/rlc register
|
||||
* @v: value to write
|
||||
*
|
||||
* this function is invoked only for the debugfs register access
|
||||
*/
|
||||
void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
|
||||
uint32_t reg, uint32_t v)
|
||||
@@ -566,7 +572,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 {
|
||||
@@ -1312,6 +1318,31 @@ bool amdgpu_device_need_post(struct amdgpu_device *adev)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_should_use_aspm - check if the device should program ASPM
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Confirm whether the module parameter and pcie bridge agree that ASPM should
|
||||
* be set for this device.
|
||||
*
|
||||
* Returns true if it should be used or false if not.
|
||||
*/
|
||||
bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev)
|
||||
{
|
||||
switch (amdgpu_aspm) {
|
||||
case -1:
|
||||
break;
|
||||
case 0:
|
||||
return false;
|
||||
case 1:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return pcie_aspm_enabled(adev->pdev);
|
||||
}
|
||||
|
||||
/* if we get transitioned to only one device, take VGA back */
|
||||
/**
|
||||
* amdgpu_device_vga_set_decode - enable/disable vga decode
|
||||
@@ -1446,7 +1477,8 @@ static int amdgpu_device_init_apu_flags(struct amdgpu_device *adev)
|
||||
case CHIP_YELLOW_CARP:
|
||||
break;
|
||||
case CHIP_CYAN_SKILLFISH:
|
||||
if (adev->pdev->device == 0x13FE)
|
||||
if ((adev->pdev->device == 0x13FE) ||
|
||||
(adev->pdev->device == 0x143F))
|
||||
adev->apu_flags |= AMD_APU_IS_CYAN_SKILLFISH2;
|
||||
break;
|
||||
default:
|
||||
@@ -2073,6 +2105,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 +2171,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;
|
||||
@@ -2287,6 +2331,49 @@ static int amdgpu_device_fw_loading(struct amdgpu_device *adev)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int amdgpu_device_init_schedulers(struct amdgpu_device *adev)
|
||||
{
|
||||
long timeout;
|
||||
int r, i;
|
||||
|
||||
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
|
||||
struct amdgpu_ring *ring = adev->rings[i];
|
||||
|
||||
/* No need to setup the GPU scheduler for rings that don't need it */
|
||||
if (!ring || ring->no_scheduler)
|
||||
continue;
|
||||
|
||||
switch (ring->funcs->type) {
|
||||
case AMDGPU_RING_TYPE_GFX:
|
||||
timeout = adev->gfx_timeout;
|
||||
break;
|
||||
case AMDGPU_RING_TYPE_COMPUTE:
|
||||
timeout = adev->compute_timeout;
|
||||
break;
|
||||
case AMDGPU_RING_TYPE_SDMA:
|
||||
timeout = adev->sdma_timeout;
|
||||
break;
|
||||
default:
|
||||
timeout = adev->video_timeout;
|
||||
break;
|
||||
}
|
||||
|
||||
r = drm_sched_init(&ring->sched, &amdgpu_sched_ops,
|
||||
ring->num_hw_submission, amdgpu_job_hang_limit,
|
||||
timeout, adev->reset_domain->wq,
|
||||
ring->sched_score, ring->name,
|
||||
adev->dev);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to create scheduler on ring %s.\n",
|
||||
ring->name);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* amdgpu_device_ip_init - run init for hardware IPs
|
||||
*
|
||||
@@ -2398,8 +2485,28 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
||||
if (r)
|
||||
goto init_failed;
|
||||
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1)
|
||||
amdgpu_xgmi_add_device(adev);
|
||||
/**
|
||||
* In case of XGMI grab extra reference for reset domain for this device
|
||||
*/
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
if (amdgpu_xgmi_add_device(adev) == 0) {
|
||||
struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev);
|
||||
|
||||
if (!hive->reset_domain ||
|
||||
!amdgpu_reset_get_reset_domain(hive->reset_domain)) {
|
||||
r = -ENOENT;
|
||||
goto init_failed;
|
||||
}
|
||||
|
||||
/* Drop the early temporary reset domain we created for device */
|
||||
amdgpu_reset_put_reset_domain(adev->reset_domain);
|
||||
adev->reset_domain = hive->reset_domain;
|
||||
}
|
||||
}
|
||||
|
||||
r = amdgpu_device_init_schedulers(adev);
|
||||
if (r)
|
||||
goto init_failed;
|
||||
|
||||
/* Don't init kfd if whole hive need to be reset during init */
|
||||
if (!adev->gmc.xgmi.pending_reset)
|
||||
@@ -2610,6 +2717,12 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
|
||||
adev->ip_blocks[i].status.late_initialized = true;
|
||||
}
|
||||
|
||||
r = amdgpu_ras_late_init(adev);
|
||||
if (r) {
|
||||
DRM_ERROR("amdgpu_ras_late_init failed %d", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
amdgpu_ras_set_error_query_ready(adev, true);
|
||||
|
||||
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_GATE);
|
||||
@@ -2624,7 +2737,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 +2821,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 +2994,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 +3420,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);
|
||||
@@ -3493,12 +3606,11 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
mutex_init(&adev->mn_lock);
|
||||
mutex_init(&adev->virt.vf_errors.lock);
|
||||
hash_init(adev->mn_hash);
|
||||
atomic_set(&adev->in_gpu_reset, 0);
|
||||
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 +3631,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,
|
||||
@@ -3577,6 +3691,15 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset domain needs to be present early, before XGMI hive discovered
|
||||
* (if any) and intitialized to use reset sem and in_gpu reset flag
|
||||
* early on during init.
|
||||
*/
|
||||
adev->reset_domain = amdgpu_reset_create_reset_domain(SINGLE_DEVICE ,"amdgpu-reset-dev");
|
||||
if (!adev->reset_domain)
|
||||
return -ENOMEM;
|
||||
|
||||
/* early init functions */
|
||||
r = amdgpu_device_ip_early_init(adev);
|
||||
if (r)
|
||||
@@ -3953,6 +4076,9 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
|
||||
if (adev->mman.discovery_bin)
|
||||
amdgpu_discovery_fini(adev);
|
||||
|
||||
amdgpu_reset_put_reset_domain(adev->reset_domain);
|
||||
adev->reset_domain = NULL;
|
||||
|
||||
kfree(adev->pci_state);
|
||||
|
||||
}
|
||||
@@ -4044,7 +4170,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)) {
|
||||
@@ -4347,7 +4473,9 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
|
||||
{
|
||||
int r;
|
||||
struct amdgpu_hive_info *hive = NULL;
|
||||
int retry_limit = 0;
|
||||
|
||||
retry:
|
||||
amdgpu_amdkfd_pre_reset(adev);
|
||||
|
||||
amdgpu_amdkfd_pre_reset(adev);
|
||||
@@ -4396,6 +4524,14 @@ error:
|
||||
}
|
||||
amdgpu_virt_release_full_gpu(adev, true);
|
||||
|
||||
if (AMDGPU_RETRY_SRIOV_RESET(r)) {
|
||||
if (retry_limit < AMDGPU_MAX_RETRY_LIMIT) {
|
||||
retry_limit++;
|
||||
goto retry;
|
||||
} else
|
||||
DRM_ERROR("GPU reset retry is beyond the retry limit\n");
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -4645,9 +4781,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();
|
||||
@@ -4754,17 +4890,8 @@ end:
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool amdgpu_device_lock_adev(struct amdgpu_device *adev,
|
||||
struct amdgpu_hive_info *hive)
|
||||
static void amdgpu_device_set_mp1_state(struct amdgpu_device *adev)
|
||||
{
|
||||
if (atomic_cmpxchg(&adev->in_gpu_reset, 0, 1) != 0)
|
||||
return false;
|
||||
|
||||
if (hive) {
|
||||
down_write_nest_lock(&adev->reset_sem, &hive->hive_lock);
|
||||
} else {
|
||||
down_write(&adev->reset_sem);
|
||||
}
|
||||
|
||||
switch (amdgpu_asic_reset_method(adev)) {
|
||||
case AMD_RESET_METHOD_MODE1:
|
||||
@@ -4777,56 +4904,12 @@ static bool amdgpu_device_lock_adev(struct amdgpu_device *adev,
|
||||
adev->mp1_state = PP_MP1_STATE_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void amdgpu_device_unlock_adev(struct amdgpu_device *adev)
|
||||
static void amdgpu_device_unset_mp1_state(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_vf_error_trans_all(adev);
|
||||
adev->mp1_state = PP_MP1_STATE_NONE;
|
||||
atomic_set(&adev->in_gpu_reset, 0);
|
||||
up_write(&adev->reset_sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* to lockup a list of amdgpu devices in a hive safely, if not a hive
|
||||
* with multiple nodes, it will be similar as amdgpu_device_lock_adev.
|
||||
*
|
||||
* unlock won't require roll back.
|
||||
*/
|
||||
static int amdgpu_device_lock_hive_adev(struct amdgpu_device *adev, struct amdgpu_hive_info *hive)
|
||||
{
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
|
||||
if (!amdgpu_sriov_vf(adev) && (adev->gmc.xgmi.num_physical_nodes > 1)) {
|
||||
if (!hive) {
|
||||
dev_err(adev->dev, "Hive is NULL while device has multiple xgmi nodes");
|
||||
return -ENODEV;
|
||||
}
|
||||
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) {
|
||||
if (!amdgpu_device_lock_adev(tmp_adev, hive))
|
||||
goto roll_back;
|
||||
}
|
||||
} else if (!amdgpu_device_lock_adev(adev, hive))
|
||||
return -EAGAIN;
|
||||
|
||||
return 0;
|
||||
roll_back:
|
||||
if (!list_is_first(&tmp_adev->gmc.xgmi.head, &hive->device_list)) {
|
||||
/*
|
||||
* if the lockup iteration break in the middle of a hive,
|
||||
* it may means there may has a race issue,
|
||||
* or a hive device locked up independently.
|
||||
* we may be in trouble and may not, so will try to roll back
|
||||
* the lock and give out a warnning.
|
||||
*/
|
||||
dev_warn(tmp_adev->dev, "Hive lock iteration broke in the middle. Rolling back to unlock");
|
||||
list_for_each_entry_continue_reverse(tmp_adev, &hive->device_list, gmc.xgmi.head) {
|
||||
amdgpu_device_unlock_adev(tmp_adev);
|
||||
}
|
||||
}
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static void amdgpu_device_resume_display_audio(struct amdgpu_device *adev)
|
||||
@@ -4960,7 +5043,7 @@ retry:
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_gpu_recover - reset the asic and recover scheduler
|
||||
* amdgpu_device_gpu_recover_imp - reset the asic and recover scheduler
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @job: which job trigger hang
|
||||
@@ -4970,7 +5053,7 @@ retry:
|
||||
* Returns 0 for success or an error on failure.
|
||||
*/
|
||||
|
||||
int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
int amdgpu_device_gpu_recover_imp(struct amdgpu_device *adev,
|
||||
struct amdgpu_job *job)
|
||||
{
|
||||
struct list_head device_list, *device_list_handle = NULL;
|
||||
@@ -5004,26 +5087,10 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
dev_info(adev->dev, "GPU %s begin!\n",
|
||||
need_emergency_restart ? "jobs stop":"reset");
|
||||
|
||||
/*
|
||||
* Here we trylock to avoid chain of resets executing from
|
||||
* either trigger by jobs on different adevs in XGMI hive or jobs on
|
||||
* different schedulers for same device while this TO handler is running.
|
||||
* We always reset all schedulers for device and all devices for XGMI
|
||||
* hive so that should take care of them too.
|
||||
*/
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
hive = amdgpu_get_xgmi_hive(adev);
|
||||
if (hive) {
|
||||
if (atomic_cmpxchg(&hive->in_reset, 0, 1) != 0) {
|
||||
DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress",
|
||||
job ? job->base.id : -1, hive->hive_id);
|
||||
amdgpu_put_xgmi_hive(hive);
|
||||
if (job && job->vm)
|
||||
drm_sched_increase_karma(&job->base);
|
||||
return 0;
|
||||
}
|
||||
if (hive)
|
||||
mutex_lock(&hive->hive_lock);
|
||||
}
|
||||
|
||||
reset_context.method = AMD_RESET_METHOD_NONE;
|
||||
reset_context.reset_req_dev = adev;
|
||||
@@ -5031,22 +5098,6 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
reset_context.hive = hive;
|
||||
clear_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
|
||||
|
||||
/*
|
||||
* lock the device before we try to operate the linked list
|
||||
* if didn't get the device lock, don't touch the linked list since
|
||||
* others may iterating it.
|
||||
*/
|
||||
r = amdgpu_device_lock_hive_adev(adev, hive);
|
||||
if (r) {
|
||||
dev_info(adev->dev, "Bailing on TDR for s_job:%llx, as another already in progress",
|
||||
job ? job->base.id : -1);
|
||||
|
||||
/* even we skipped this reset, still need to set the job to guilty */
|
||||
if (job && job->vm)
|
||||
drm_sched_increase_karma(&job->base);
|
||||
goto skip_recovery;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build list of devices to reset.
|
||||
* In case we are in XGMI hive mode, resort the device list
|
||||
@@ -5064,8 +5115,16 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
device_list_handle = &device_list;
|
||||
}
|
||||
|
||||
/* We need to lock reset domain only once both for XGMI and single device */
|
||||
tmp_adev = list_first_entry(device_list_handle, struct amdgpu_device,
|
||||
reset_list);
|
||||
amdgpu_device_lock_reset_domain(tmp_adev->reset_domain);
|
||||
|
||||
/* block all schedulers and reset given job's ring */
|
||||
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
|
||||
|
||||
amdgpu_device_set_mp1_state(tmp_adev);
|
||||
|
||||
/*
|
||||
* Try to put the audio codec into suspend state
|
||||
* before gpu reset started.
|
||||
@@ -5187,6 +5246,9 @@ skip_hw_reset:
|
||||
drm_helper_resume_force_mode(adev_to_drm(tmp_adev));
|
||||
}
|
||||
|
||||
if (tmp_adev->asic_reset_res)
|
||||
r = tmp_adev->asic_reset_res;
|
||||
|
||||
tmp_adev->asic_reset_res = 0;
|
||||
|
||||
if (r) {
|
||||
@@ -5214,21 +5276,55 @@ skip_sched_resume:
|
||||
|
||||
if (audio_suspended)
|
||||
amdgpu_device_resume_display_audio(tmp_adev);
|
||||
amdgpu_device_unlock_adev(tmp_adev);
|
||||
|
||||
amdgpu_device_unset_mp1_state(tmp_adev);
|
||||
}
|
||||
|
||||
skip_recovery:
|
||||
tmp_adev = list_first_entry(device_list_handle, struct amdgpu_device,
|
||||
reset_list);
|
||||
amdgpu_device_unlock_reset_domain(tmp_adev->reset_domain);
|
||||
|
||||
if (hive) {
|
||||
atomic_set(&hive->in_reset, 0);
|
||||
mutex_unlock(&hive->hive_lock);
|
||||
amdgpu_put_xgmi_hive(hive);
|
||||
}
|
||||
|
||||
if (r && r != -EAGAIN)
|
||||
if (r)
|
||||
dev_info(adev->dev, "GPU reset end with ret = %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
struct amdgpu_recover_work_struct {
|
||||
struct work_struct base;
|
||||
struct amdgpu_device *adev;
|
||||
struct amdgpu_job *job;
|
||||
int ret;
|
||||
};
|
||||
|
||||
static void amdgpu_device_queue_gpu_recover_work(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_recover_work_struct *recover_work = container_of(work, struct amdgpu_recover_work_struct, base);
|
||||
|
||||
recover_work->ret = amdgpu_device_gpu_recover_imp(recover_work->adev, recover_work->job);
|
||||
}
|
||||
/*
|
||||
* Serialize gpu recover into reset domain single threaded wq
|
||||
*/
|
||||
int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
struct amdgpu_job *job)
|
||||
{
|
||||
struct amdgpu_recover_work_struct work = {.adev = adev, .job = job};
|
||||
|
||||
INIT_WORK(&work.base, amdgpu_device_queue_gpu_recover_work);
|
||||
|
||||
if (!amdgpu_reset_domain_schedule(adev->reset_domain, &work.base))
|
||||
return -EAGAIN;
|
||||
|
||||
flush_work(&work.base);
|
||||
|
||||
return work.ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_get_pcie_info - fence pcie info about the PCIE slot
|
||||
*
|
||||
@@ -5416,20 +5512,6 @@ int amdgpu_device_baco_exit(struct drm_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amdgpu_cancel_all_tdr(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
|
||||
struct amdgpu_ring *ring = adev->rings[i];
|
||||
|
||||
if (!ring || !ring->sched.thread)
|
||||
continue;
|
||||
|
||||
cancel_delayed_work_sync(&ring->sched.work_tdr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_pci_error_detected - Called when a PCI error is detected.
|
||||
* @pdev: PCI device struct
|
||||
@@ -5460,14 +5542,11 @@ pci_ers_result_t amdgpu_pci_error_detected(struct pci_dev *pdev, pci_channel_sta
|
||||
/* Fatal error, prepare for slot reset */
|
||||
case pci_channel_io_frozen:
|
||||
/*
|
||||
* Cancel and wait for all TDRs in progress if failing to
|
||||
* set adev->in_gpu_reset in amdgpu_device_lock_adev
|
||||
*
|
||||
* Locking adev->reset_sem will prevent any external access
|
||||
* Locking adev->reset_domain->sem will prevent any external access
|
||||
* to GPU during PCI error recovery
|
||||
*/
|
||||
while (!amdgpu_device_lock_adev(adev, NULL))
|
||||
amdgpu_cancel_all_tdr(adev);
|
||||
amdgpu_device_lock_reset_domain(adev->reset_domain);
|
||||
amdgpu_device_set_mp1_state(adev);
|
||||
|
||||
/*
|
||||
* Block any work scheduling as we do for regular GPU reset
|
||||
@@ -5574,7 +5653,8 @@ out:
|
||||
DRM_INFO("PCIe error recovery succeeded\n");
|
||||
} else {
|
||||
DRM_ERROR("PCIe error recovery failed, err:%d", r);
|
||||
amdgpu_device_unlock_adev(adev);
|
||||
amdgpu_device_unset_mp1_state(adev);
|
||||
amdgpu_device_unlock_reset_domain(adev->reset_domain);
|
||||
}
|
||||
|
||||
return r ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
|
||||
@@ -5611,7 +5691,8 @@ void amdgpu_pci_resume(struct pci_dev *pdev)
|
||||
drm_sched_start(&ring->sched, true);
|
||||
}
|
||||
|
||||
amdgpu_device_unlock_adev(adev);
|
||||
amdgpu_device_unset_mp1_state(adev);
|
||||
amdgpu_device_unlock_reset_domain(adev->reset_domain);
|
||||
}
|
||||
|
||||
bool amdgpu_device_cache_pci_state(struct pci_dev *pdev)
|
||||
@@ -5688,6 +5769,11 @@ void amdgpu_device_invalidate_hdp(struct amdgpu_device *adev,
|
||||
amdgpu_asic_invalidate_hdp(adev, ring);
|
||||
}
|
||||
|
||||
int amdgpu_in_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
return atomic_read(&adev->reset_domain->in_gpu_reset);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_halt() - bring hardware to some kind of halt state
|
||||
*
|
||||
@@ -5726,3 +5812,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);
|
||||
}
|
||||
|
||||
@@ -360,8 +360,11 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void amdgpu_discovery_sysfs_fini(struct amdgpu_device *adev);
|
||||
|
||||
void amdgpu_discovery_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_discovery_sysfs_fini(adev);
|
||||
kfree(adev->mman.discovery_bin);
|
||||
adev->mman.discovery_bin = NULL;
|
||||
}
|
||||
@@ -382,6 +385,497 @@ static int amdgpu_discovery_validate_ip(const struct ip *ip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
struct ip_hw_instance {
|
||||
struct kobject kobj; /* ip_discovery/die/#die/#hw_id/#instance/<attrs...> */
|
||||
|
||||
int hw_id;
|
||||
u8 num_instance;
|
||||
u8 major, minor, revision;
|
||||
u8 harvest;
|
||||
|
||||
int num_base_addresses;
|
||||
u32 base_addr[];
|
||||
};
|
||||
|
||||
struct ip_hw_id {
|
||||
struct kset hw_id_kset; /* ip_discovery/die/#die/#hw_id/, contains ip_hw_instance */
|
||||
int hw_id;
|
||||
};
|
||||
|
||||
struct ip_die_entry {
|
||||
struct kset ip_kset; /* ip_discovery/die/#die/, contains ip_hw_id */
|
||||
u16 num_ips;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
struct ip_hw_instance_attr {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct ip_hw_instance *ip_hw_instance, char *buf);
|
||||
};
|
||||
|
||||
static ssize_t hw_id_show(struct ip_hw_instance *ip_hw_instance, char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "%d\n", ip_hw_instance->hw_id);
|
||||
}
|
||||
|
||||
static ssize_t num_instance_show(struct ip_hw_instance *ip_hw_instance, char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "%d\n", ip_hw_instance->num_instance);
|
||||
}
|
||||
|
||||
static ssize_t major_show(struct ip_hw_instance *ip_hw_instance, char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "%d\n", ip_hw_instance->major);
|
||||
}
|
||||
|
||||
static ssize_t minor_show(struct ip_hw_instance *ip_hw_instance, char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "%d\n", ip_hw_instance->minor);
|
||||
}
|
||||
|
||||
static ssize_t revision_show(struct ip_hw_instance *ip_hw_instance, char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "%d\n", ip_hw_instance->revision);
|
||||
}
|
||||
|
||||
static ssize_t harvest_show(struct ip_hw_instance *ip_hw_instance, char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "0x%01X\n", ip_hw_instance->harvest);
|
||||
}
|
||||
|
||||
static ssize_t num_base_addresses_show(struct ip_hw_instance *ip_hw_instance, char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "%d\n", ip_hw_instance->num_base_addresses);
|
||||
}
|
||||
|
||||
static ssize_t base_addr_show(struct ip_hw_instance *ip_hw_instance, char *buf)
|
||||
{
|
||||
ssize_t res, at;
|
||||
int ii;
|
||||
|
||||
for (res = at = ii = 0; ii < ip_hw_instance->num_base_addresses; ii++) {
|
||||
/* Here we satisfy the condition that, at + size <= PAGE_SIZE.
|
||||
*/
|
||||
if (at + 12 > PAGE_SIZE)
|
||||
break;
|
||||
res = sysfs_emit_at(buf, at, "0x%08X\n",
|
||||
ip_hw_instance->base_addr[ii]);
|
||||
if (res <= 0)
|
||||
break;
|
||||
at += res;
|
||||
}
|
||||
|
||||
return res < 0 ? res : at;
|
||||
}
|
||||
|
||||
static struct ip_hw_instance_attr ip_hw_attr[] = {
|
||||
__ATTR_RO(hw_id),
|
||||
__ATTR_RO(num_instance),
|
||||
__ATTR_RO(major),
|
||||
__ATTR_RO(minor),
|
||||
__ATTR_RO(revision),
|
||||
__ATTR_RO(harvest),
|
||||
__ATTR_RO(num_base_addresses),
|
||||
__ATTR_RO(base_addr),
|
||||
};
|
||||
|
||||
static struct attribute *ip_hw_instance_attrs[ARRAY_SIZE(ip_hw_attr) + 1];
|
||||
ATTRIBUTE_GROUPS(ip_hw_instance);
|
||||
|
||||
#define to_ip_hw_instance(x) container_of(x, struct ip_hw_instance, kobj)
|
||||
#define to_ip_hw_instance_attr(x) container_of(x, struct ip_hw_instance_attr, attr)
|
||||
|
||||
static ssize_t ip_hw_instance_attr_show(struct kobject *kobj,
|
||||
struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct ip_hw_instance *ip_hw_instance = to_ip_hw_instance(kobj);
|
||||
struct ip_hw_instance_attr *ip_hw_attr = to_ip_hw_instance_attr(attr);
|
||||
|
||||
if (!ip_hw_attr->show)
|
||||
return -EIO;
|
||||
|
||||
return ip_hw_attr->show(ip_hw_instance, buf);
|
||||
}
|
||||
|
||||
static const struct sysfs_ops ip_hw_instance_sysfs_ops = {
|
||||
.show = ip_hw_instance_attr_show,
|
||||
};
|
||||
|
||||
static void ip_hw_instance_release(struct kobject *kobj)
|
||||
{
|
||||
struct ip_hw_instance *ip_hw_instance = to_ip_hw_instance(kobj);
|
||||
|
||||
kfree(ip_hw_instance);
|
||||
}
|
||||
|
||||
static struct kobj_type ip_hw_instance_ktype = {
|
||||
.release = ip_hw_instance_release,
|
||||
.sysfs_ops = &ip_hw_instance_sysfs_ops,
|
||||
.default_groups = ip_hw_instance_groups,
|
||||
};
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
#define to_ip_hw_id(x) container_of(to_kset(x), struct ip_hw_id, hw_id_kset)
|
||||
|
||||
static void ip_hw_id_release(struct kobject *kobj)
|
||||
{
|
||||
struct ip_hw_id *ip_hw_id = to_ip_hw_id(kobj);
|
||||
|
||||
if (!list_empty(&ip_hw_id->hw_id_kset.list))
|
||||
DRM_ERROR("ip_hw_id->hw_id_kset is not empty");
|
||||
kfree(ip_hw_id);
|
||||
}
|
||||
|
||||
static struct kobj_type ip_hw_id_ktype = {
|
||||
.release = ip_hw_id_release,
|
||||
.sysfs_ops = &kobj_sysfs_ops,
|
||||
};
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
static void die_kobj_release(struct kobject *kobj);
|
||||
static void ip_disc_release(struct kobject *kobj);
|
||||
|
||||
struct ip_die_entry_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct ip_die_entry *ip_die_entry, char *buf);
|
||||
};
|
||||
|
||||
#define to_ip_die_entry_attr(x) container_of(x, struct ip_die_entry_attribute, attr)
|
||||
|
||||
static ssize_t num_ips_show(struct ip_die_entry *ip_die_entry, char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "%d\n", ip_die_entry->num_ips);
|
||||
}
|
||||
|
||||
/* If there are more ip_die_entry attrs, other than the number of IPs,
|
||||
* we can make this intro an array of attrs, and then initialize
|
||||
* ip_die_entry_attrs in a loop.
|
||||
*/
|
||||
static struct ip_die_entry_attribute num_ips_attr =
|
||||
__ATTR_RO(num_ips);
|
||||
|
||||
static struct attribute *ip_die_entry_attrs[] = {
|
||||
&num_ips_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(ip_die_entry); /* ip_die_entry_groups */
|
||||
|
||||
#define to_ip_die_entry(x) container_of(to_kset(x), struct ip_die_entry, ip_kset)
|
||||
|
||||
static ssize_t ip_die_entry_attr_show(struct kobject *kobj,
|
||||
struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct ip_die_entry_attribute *ip_die_entry_attr = to_ip_die_entry_attr(attr);
|
||||
struct ip_die_entry *ip_die_entry = to_ip_die_entry(kobj);
|
||||
|
||||
if (!ip_die_entry_attr->show)
|
||||
return -EIO;
|
||||
|
||||
return ip_die_entry_attr->show(ip_die_entry, buf);
|
||||
}
|
||||
|
||||
static void ip_die_entry_release(struct kobject *kobj)
|
||||
{
|
||||
struct ip_die_entry *ip_die_entry = to_ip_die_entry(kobj);
|
||||
|
||||
if (!list_empty(&ip_die_entry->ip_kset.list))
|
||||
DRM_ERROR("ip_die_entry->ip_kset is not empty");
|
||||
kfree(ip_die_entry);
|
||||
}
|
||||
|
||||
static const struct sysfs_ops ip_die_entry_sysfs_ops = {
|
||||
.show = ip_die_entry_attr_show,
|
||||
};
|
||||
|
||||
static struct kobj_type ip_die_entry_ktype = {
|
||||
.release = ip_die_entry_release,
|
||||
.sysfs_ops = &ip_die_entry_sysfs_ops,
|
||||
.default_groups = ip_die_entry_groups,
|
||||
};
|
||||
|
||||
static struct kobj_type die_kobj_ktype = {
|
||||
.release = die_kobj_release,
|
||||
.sysfs_ops = &kobj_sysfs_ops,
|
||||
};
|
||||
|
||||
static struct kobj_type ip_discovery_ktype = {
|
||||
.release = ip_disc_release,
|
||||
.sysfs_ops = &kobj_sysfs_ops,
|
||||
};
|
||||
|
||||
struct ip_discovery_top {
|
||||
struct kobject kobj; /* ip_discovery/ */
|
||||
struct kset die_kset; /* ip_discovery/die/, contains ip_die_entry */
|
||||
struct amdgpu_device *adev;
|
||||
};
|
||||
|
||||
static void die_kobj_release(struct kobject *kobj)
|
||||
{
|
||||
struct ip_discovery_top *ip_top = container_of(to_kset(kobj),
|
||||
struct ip_discovery_top,
|
||||
die_kset);
|
||||
if (!list_empty(&ip_top->die_kset.list))
|
||||
DRM_ERROR("ip_top->die_kset is not empty");
|
||||
}
|
||||
|
||||
static void ip_disc_release(struct kobject *kobj)
|
||||
{
|
||||
struct ip_discovery_top *ip_top = container_of(kobj, struct ip_discovery_top,
|
||||
kobj);
|
||||
struct amdgpu_device *adev = ip_top->adev;
|
||||
|
||||
adev->ip_top = NULL;
|
||||
kfree(ip_top);
|
||||
}
|
||||
|
||||
static int amdgpu_discovery_sysfs_ips(struct amdgpu_device *adev,
|
||||
struct ip_die_entry *ip_die_entry,
|
||||
const size_t _ip_offset, const int num_ips)
|
||||
{
|
||||
int ii, jj, kk, res;
|
||||
|
||||
DRM_DEBUG("num_ips:%d", num_ips);
|
||||
|
||||
/* Find all IPs of a given HW ID, and add their instance to
|
||||
* #die/#hw_id/#instance/<attributes>
|
||||
*/
|
||||
for (ii = 0; ii < HW_ID_MAX; ii++) {
|
||||
struct ip_hw_id *ip_hw_id = NULL;
|
||||
size_t ip_offset = _ip_offset;
|
||||
|
||||
for (jj = 0; jj < num_ips; jj++) {
|
||||
struct ip *ip;
|
||||
struct ip_hw_instance *ip_hw_instance;
|
||||
|
||||
ip = (struct ip *)(adev->mman.discovery_bin + ip_offset);
|
||||
if (amdgpu_discovery_validate_ip(ip) ||
|
||||
le16_to_cpu(ip->hw_id) != ii)
|
||||
goto next_ip;
|
||||
|
||||
DRM_DEBUG("match:%d @ ip_offset:%zu", ii, ip_offset);
|
||||
|
||||
/* We have a hw_id match; register the hw
|
||||
* block if not yet registered.
|
||||
*/
|
||||
if (!ip_hw_id) {
|
||||
ip_hw_id = kzalloc(sizeof(*ip_hw_id), GFP_KERNEL);
|
||||
if (!ip_hw_id)
|
||||
return -ENOMEM;
|
||||
ip_hw_id->hw_id = ii;
|
||||
|
||||
kobject_set_name(&ip_hw_id->hw_id_kset.kobj, "%d", ii);
|
||||
ip_hw_id->hw_id_kset.kobj.kset = &ip_die_entry->ip_kset;
|
||||
ip_hw_id->hw_id_kset.kobj.ktype = &ip_hw_id_ktype;
|
||||
res = kset_register(&ip_hw_id->hw_id_kset);
|
||||
if (res) {
|
||||
DRM_ERROR("Couldn't register ip_hw_id kset");
|
||||
kfree(ip_hw_id);
|
||||
return res;
|
||||
}
|
||||
if (hw_id_names[ii]) {
|
||||
res = sysfs_create_link(&ip_die_entry->ip_kset.kobj,
|
||||
&ip_hw_id->hw_id_kset.kobj,
|
||||
hw_id_names[ii]);
|
||||
if (res) {
|
||||
DRM_ERROR("Couldn't create IP link %s in IP Die:%s\n",
|
||||
hw_id_names[ii],
|
||||
kobject_name(&ip_die_entry->ip_kset.kobj));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now register its instance.
|
||||
*/
|
||||
ip_hw_instance = kzalloc(struct_size(ip_hw_instance,
|
||||
base_addr,
|
||||
ip->num_base_address),
|
||||
GFP_KERNEL);
|
||||
if (!ip_hw_instance) {
|
||||
DRM_ERROR("no memory for ip_hw_instance");
|
||||
return -ENOMEM;
|
||||
}
|
||||
ip_hw_instance->hw_id = le16_to_cpu(ip->hw_id); /* == ii */
|
||||
ip_hw_instance->num_instance = ip->number_instance;
|
||||
ip_hw_instance->major = ip->major;
|
||||
ip_hw_instance->minor = ip->minor;
|
||||
ip_hw_instance->revision = ip->revision;
|
||||
ip_hw_instance->harvest = ip->harvest;
|
||||
ip_hw_instance->num_base_addresses = ip->num_base_address;
|
||||
|
||||
for (kk = 0; kk < ip_hw_instance->num_base_addresses; kk++)
|
||||
ip_hw_instance->base_addr[kk] = ip->base_address[kk];
|
||||
|
||||
kobject_init(&ip_hw_instance->kobj, &ip_hw_instance_ktype);
|
||||
ip_hw_instance->kobj.kset = &ip_hw_id->hw_id_kset;
|
||||
res = kobject_add(&ip_hw_instance->kobj, NULL,
|
||||
"%d", ip_hw_instance->num_instance);
|
||||
next_ip:
|
||||
ip_offset += sizeof(*ip) + 4 * (ip->num_base_address - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_discovery_sysfs_recurse(struct amdgpu_device *adev)
|
||||
{
|
||||
struct binary_header *bhdr;
|
||||
struct ip_discovery_header *ihdr;
|
||||
struct die_header *dhdr;
|
||||
struct kset *die_kset = &adev->ip_top->die_kset;
|
||||
u16 num_dies, die_offset, num_ips;
|
||||
size_t ip_offset;
|
||||
int ii, res;
|
||||
|
||||
bhdr = (struct binary_header *)adev->mman.discovery_bin;
|
||||
ihdr = (struct ip_discovery_header *)(adev->mman.discovery_bin +
|
||||
le16_to_cpu(bhdr->table_list[IP_DISCOVERY].offset));
|
||||
num_dies = le16_to_cpu(ihdr->num_dies);
|
||||
|
||||
DRM_DEBUG("number of dies: %d\n", num_dies);
|
||||
|
||||
for (ii = 0; ii < num_dies; ii++) {
|
||||
struct ip_die_entry *ip_die_entry;
|
||||
|
||||
die_offset = le16_to_cpu(ihdr->die_info[ii].die_offset);
|
||||
dhdr = (struct die_header *)(adev->mman.discovery_bin + die_offset);
|
||||
num_ips = le16_to_cpu(dhdr->num_ips);
|
||||
ip_offset = die_offset + sizeof(*dhdr);
|
||||
|
||||
/* Add the die to the kset.
|
||||
*
|
||||
* dhdr->die_id == ii, which was checked in
|
||||
* amdgpu_discovery_reg_base_init().
|
||||
*/
|
||||
|
||||
ip_die_entry = kzalloc(sizeof(*ip_die_entry), GFP_KERNEL);
|
||||
if (!ip_die_entry)
|
||||
return -ENOMEM;
|
||||
|
||||
ip_die_entry->num_ips = num_ips;
|
||||
|
||||
kobject_set_name(&ip_die_entry->ip_kset.kobj, "%d", le16_to_cpu(dhdr->die_id));
|
||||
ip_die_entry->ip_kset.kobj.kset = die_kset;
|
||||
ip_die_entry->ip_kset.kobj.ktype = &ip_die_entry_ktype;
|
||||
res = kset_register(&ip_die_entry->ip_kset);
|
||||
if (res) {
|
||||
DRM_ERROR("Couldn't register ip_die_entry kset");
|
||||
kfree(ip_die_entry);
|
||||
return res;
|
||||
}
|
||||
|
||||
amdgpu_discovery_sysfs_ips(adev, ip_die_entry, ip_offset, num_ips);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_discovery_sysfs_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct kset *die_kset;
|
||||
int res, ii;
|
||||
|
||||
adev->ip_top = kzalloc(sizeof(*adev->ip_top), GFP_KERNEL);
|
||||
if (!adev->ip_top)
|
||||
return -ENOMEM;
|
||||
|
||||
adev->ip_top->adev = adev;
|
||||
|
||||
res = kobject_init_and_add(&adev->ip_top->kobj, &ip_discovery_ktype,
|
||||
&adev->dev->kobj, "ip_discovery");
|
||||
if (res) {
|
||||
DRM_ERROR("Couldn't init and add ip_discovery/");
|
||||
goto Err;
|
||||
}
|
||||
|
||||
die_kset = &adev->ip_top->die_kset;
|
||||
kobject_set_name(&die_kset->kobj, "%s", "die");
|
||||
die_kset->kobj.parent = &adev->ip_top->kobj;
|
||||
die_kset->kobj.ktype = &die_kobj_ktype;
|
||||
res = kset_register(&adev->ip_top->die_kset);
|
||||
if (res) {
|
||||
DRM_ERROR("Couldn't register die_kset");
|
||||
goto Err;
|
||||
}
|
||||
|
||||
for (ii = 0; ii < ARRAY_SIZE(ip_hw_attr); ii++)
|
||||
ip_hw_instance_attrs[ii] = &ip_hw_attr[ii].attr;
|
||||
ip_hw_instance_attrs[ii] = NULL;
|
||||
|
||||
res = amdgpu_discovery_sysfs_recurse(adev);
|
||||
|
||||
return res;
|
||||
Err:
|
||||
kobject_put(&adev->ip_top->kobj);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
#define list_to_kobj(el) container_of(el, struct kobject, entry)
|
||||
|
||||
static void amdgpu_discovery_sysfs_ip_hw_free(struct ip_hw_id *ip_hw_id)
|
||||
{
|
||||
struct list_head *el, *tmp;
|
||||
struct kset *hw_id_kset;
|
||||
|
||||
hw_id_kset = &ip_hw_id->hw_id_kset;
|
||||
spin_lock(&hw_id_kset->list_lock);
|
||||
list_for_each_prev_safe(el, tmp, &hw_id_kset->list) {
|
||||
list_del_init(el);
|
||||
spin_unlock(&hw_id_kset->list_lock);
|
||||
/* kobject is embedded in ip_hw_instance */
|
||||
kobject_put(list_to_kobj(el));
|
||||
spin_lock(&hw_id_kset->list_lock);
|
||||
}
|
||||
spin_unlock(&hw_id_kset->list_lock);
|
||||
kobject_put(&ip_hw_id->hw_id_kset.kobj);
|
||||
}
|
||||
|
||||
static void amdgpu_discovery_sysfs_die_free(struct ip_die_entry *ip_die_entry)
|
||||
{
|
||||
struct list_head *el, *tmp;
|
||||
struct kset *ip_kset;
|
||||
|
||||
ip_kset = &ip_die_entry->ip_kset;
|
||||
spin_lock(&ip_kset->list_lock);
|
||||
list_for_each_prev_safe(el, tmp, &ip_kset->list) {
|
||||
list_del_init(el);
|
||||
spin_unlock(&ip_kset->list_lock);
|
||||
amdgpu_discovery_sysfs_ip_hw_free(to_ip_hw_id(list_to_kobj(el)));
|
||||
spin_lock(&ip_kset->list_lock);
|
||||
}
|
||||
spin_unlock(&ip_kset->list_lock);
|
||||
kobject_put(&ip_die_entry->ip_kset.kobj);
|
||||
}
|
||||
|
||||
static void amdgpu_discovery_sysfs_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
struct list_head *el, *tmp;
|
||||
struct kset *die_kset;
|
||||
|
||||
die_kset = &adev->ip_top->die_kset;
|
||||
spin_lock(&die_kset->list_lock);
|
||||
list_for_each_prev_safe(el, tmp, &die_kset->list) {
|
||||
list_del_init(el);
|
||||
spin_unlock(&die_kset->list_lock);
|
||||
amdgpu_discovery_sysfs_die_free(to_ip_die_entry(list_to_kobj(el)));
|
||||
spin_lock(&die_kset->list_lock);
|
||||
}
|
||||
spin_unlock(&die_kset->list_lock);
|
||||
kobject_put(&adev->ip_top->die_kset.kobj);
|
||||
kobject_put(&adev->ip_top->kobj);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct binary_header *bhdr;
|
||||
@@ -492,6 +986,8 @@ next_ip:
|
||||
}
|
||||
}
|
||||
|
||||
amdgpu_discovery_sysfs_init(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -674,12 +1170,15 @@ 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):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
|
||||
break;
|
||||
default:
|
||||
@@ -709,12 +1208,15 @@ 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):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
|
||||
break;
|
||||
default:
|
||||
@@ -790,6 +1292,7 @@ static int amdgpu_discovery_set_psp_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(13, 0, 1):
|
||||
case IP_VERSION(13, 0, 2):
|
||||
case IP_VERSION(13, 0, 3):
|
||||
case IP_VERSION(13, 0, 8):
|
||||
amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
|
||||
break;
|
||||
default:
|
||||
@@ -831,6 +1334,7 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(13, 0, 1):
|
||||
case IP_VERSION(13, 0, 2):
|
||||
case IP_VERSION(13, 0, 3):
|
||||
case IP_VERSION(13, 0, 8):
|
||||
amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
|
||||
break;
|
||||
default:
|
||||
@@ -846,8 +1350,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):
|
||||
@@ -861,6 +1371,7 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(3, 0, 1):
|
||||
case IP_VERSION(3, 1, 2):
|
||||
case IP_VERSION(3, 1, 3):
|
||||
case IP_VERSION(3, 1, 6):
|
||||
amdgpu_device_ip_block_add(adev, &dm_ip_block);
|
||||
break;
|
||||
default:
|
||||
@@ -882,8 +1393,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,12 +1415,15 @@ 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):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
|
||||
break;
|
||||
default:
|
||||
@@ -946,6 +1460,7 @@ static int amdgpu_discovery_set_sdma_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(5, 2, 5):
|
||||
case IP_VERSION(5, 2, 3):
|
||||
case IP_VERSION(5, 2, 1):
|
||||
case IP_VERSION(5, 2, 7):
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
|
||||
break;
|
||||
default:
|
||||
@@ -1038,12 +1553,14 @@ 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):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
amdgpu_device_ip_block_add(adev, &mes_v10_1_ip_block);
|
||||
break;
|
||||
default:
|
||||
@@ -1217,11 +1734,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 +1754,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):
|
||||
@@ -1254,10 +1767,32 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(10, 3, 3):
|
||||
adev->family = AMDGPU_FAMILY_YC;
|
||||
break;
|
||||
case IP_VERSION(10, 3, 6):
|
||||
adev->family = AMDGPU_FAMILY_GC_10_3_6;
|
||||
break;
|
||||
case IP_VERSION(10, 3, 7):
|
||||
adev->family = AMDGPU_FAMILY_GC_10_3_7;
|
||||
break;
|
||||
default:
|
||||
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):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
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;
|
||||
|
||||
@@ -1286,6 +1821,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(7, 2, 0):
|
||||
case IP_VERSION(7, 2, 1):
|
||||
case IP_VERSION(7, 5, 0):
|
||||
case IP_VERSION(7, 5, 1):
|
||||
adev->nbio.funcs = &nbio_v7_2_funcs;
|
||||
adev->nbio.hdp_flush_reg = &nbio_v7_2_hdp_flush_reg;
|
||||
break;
|
||||
@@ -1368,6 +1904,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(11, 0, 11):
|
||||
case IP_VERSION(11, 5, 0):
|
||||
case IP_VERSION(13, 0, 1):
|
||||
case IP_VERSION(13, 0, 9):
|
||||
adev->smuio.funcs = &smuio_v11_0_6_funcs;
|
||||
break;
|
||||
case IP_VERSION(13, 0, 2):
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -956,7 +961,7 @@ static int amdgpu_display_verify_sizes(struct amdgpu_framebuffer *rfb)
|
||||
int ret;
|
||||
unsigned int i, block_width, block_height, block_size_log2;
|
||||
|
||||
if (!rfb->base.dev->mode_config.allow_fb_modifiers)
|
||||
if (rfb->base.dev->mode_config.fb_modifiers_not_supported)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < format_info->num_planes; ++i) {
|
||||
@@ -1143,7 +1148,7 @@ int amdgpu_display_framebuffer_init(struct drm_device *dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!dev->mode_config.allow_fb_modifiers) {
|
||||
if (dev->mode_config.fb_modifiers_not_supported) {
|
||||
drm_WARN_ONCE(dev, adev->family >= AMDGPU_FAMILY_AI,
|
||||
"GFX9+ requires FB check based on format modifier\n");
|
||||
ret = check_tiling_flags_gfx6(rfb);
|
||||
@@ -1151,7 +1156,7 @@ int amdgpu_display_framebuffer_init(struct drm_device *dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (dev->mode_config.allow_fb_modifiers &&
|
||||
if (!dev->mode_config.fb_modifiers_not_supported &&
|
||||
!(rfb->base.flags & DRM_MODE_FB_MODIFIERS)) {
|
||||
ret = convert_tiling_flags_to_modifier(rfb);
|
||||
if (ret) {
|
||||
|
||||
@@ -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,13 +1916,14 @@ 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},
|
||||
{0x1002, 0x143F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
|
||||
|
||||
/* BEIGE_GOBY */
|
||||
{0x1002, 0x7420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
|
||||
@@ -1994,6 +1969,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 +2123,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 +2176,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 +2292,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;
|
||||
}
|
||||
|
||||
@@ -446,24 +446,18 @@ int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
|
||||
* for the requested ring.
|
||||
*
|
||||
* @ring: ring to init the fence driver on
|
||||
* @num_hw_submission: number of entries on the hardware queue
|
||||
* @sched_score: optional score atomic shared with other schedulers
|
||||
*
|
||||
* Init the fence driver for the requested ring (all asics).
|
||||
* Helper function for amdgpu_fence_driver_init().
|
||||
*/
|
||||
int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
|
||||
unsigned num_hw_submission,
|
||||
atomic_t *sched_score)
|
||||
int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
long timeout;
|
||||
int r;
|
||||
|
||||
if (!adev)
|
||||
return -EINVAL;
|
||||
|
||||
if (!is_power_of_2(num_hw_submission))
|
||||
if (!is_power_of_2(ring->num_hw_submission))
|
||||
return -EINVAL;
|
||||
|
||||
ring->fence_drv.cpu_addr = NULL;
|
||||
@@ -474,41 +468,14 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
|
||||
|
||||
timer_setup(&ring->fence_drv.fallback_timer, amdgpu_fence_fallback, 0);
|
||||
|
||||
ring->fence_drv.num_fences_mask = num_hw_submission * 2 - 1;
|
||||
ring->fence_drv.num_fences_mask = ring->num_hw_submission * 2 - 1;
|
||||
spin_lock_init(&ring->fence_drv.lock);
|
||||
ring->fence_drv.fences = kcalloc(num_hw_submission * 2, sizeof(void *),
|
||||
ring->fence_drv.fences = kcalloc(ring->num_hw_submission * 2, sizeof(void *),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!ring->fence_drv.fences)
|
||||
return -ENOMEM;
|
||||
|
||||
/* No need to setup the GPU scheduler for rings that don't need it */
|
||||
if (ring->no_scheduler)
|
||||
return 0;
|
||||
|
||||
switch (ring->funcs->type) {
|
||||
case AMDGPU_RING_TYPE_GFX:
|
||||
timeout = adev->gfx_timeout;
|
||||
break;
|
||||
case AMDGPU_RING_TYPE_COMPUTE:
|
||||
timeout = adev->compute_timeout;
|
||||
break;
|
||||
case AMDGPU_RING_TYPE_SDMA:
|
||||
timeout = adev->sdma_timeout;
|
||||
break;
|
||||
default:
|
||||
timeout = adev->video_timeout;
|
||||
break;
|
||||
}
|
||||
|
||||
r = drm_sched_init(&ring->sched, &amdgpu_sched_ops,
|
||||
num_hw_submission, amdgpu_job_hang_limit,
|
||||
timeout, NULL, sched_score, ring->name);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to create scheduler on ring %s.\n",
|
||||
ring->name);
|
||||
return r;
|
||||
}
|
||||
|
||||
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,72 +615,40 @@ 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, struct ras_common_if *ras_block)
|
||||
{
|
||||
int r;
|
||||
struct ras_fs_if fs_info = {
|
||||
.sysfs_name = "gfx_err_count",
|
||||
};
|
||||
struct ras_ih_if ih_info = {
|
||||
.cb = amdgpu_gfx_process_ras_data_cb,
|
||||
};
|
||||
|
||||
if (!adev->gfx.ras_if) {
|
||||
adev->gfx.ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
|
||||
if (!adev->gfx.ras_if)
|
||||
return -ENOMEM;
|
||||
adev->gfx.ras_if->block = AMDGPU_RAS_BLOCK__GFX;
|
||||
adev->gfx.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
|
||||
adev->gfx.ras_if->sub_block_index = 0;
|
||||
}
|
||||
fs_info.head = ih_info.head = *adev->gfx.ras_if;
|
||||
r = amdgpu_ras_late_init(adev, adev->gfx.ras_if,
|
||||
&fs_info, &ih_info);
|
||||
r = amdgpu_ras_block_late_init(adev, ras_block);
|
||||
if (r)
|
||||
goto free;
|
||||
return r;
|
||||
|
||||
if (amdgpu_ras_is_supported(adev, adev->gfx.ras_if->block)) {
|
||||
if (amdgpu_ras_is_supported(adev, ras_block->block)) {
|
||||
if (!amdgpu_persistent_edc_harvesting_supported(adev))
|
||||
amdgpu_ras_reset_error_status(adev, AMDGPU_RAS_BLOCK__GFX);
|
||||
|
||||
r = amdgpu_irq_get(adev, &adev->gfx.cp_ecc_error_irq, 0);
|
||||
if (r)
|
||||
goto late_fini;
|
||||
} else {
|
||||
/* free gfx ras_if if ras is not supported */
|
||||
r = 0;
|
||||
goto free;
|
||||
}
|
||||
|
||||
return 0;
|
||||
late_fini:
|
||||
amdgpu_ras_late_fini(adev, adev->gfx.ras_if, &ih_info);
|
||||
free:
|
||||
kfree(adev->gfx.ras_if);
|
||||
adev->gfx.ras_if = NULL;
|
||||
amdgpu_ras_block_late_fini(adev, ras_block);
|
||||
return r;
|
||||
}
|
||||
|
||||
void amdgpu_gfx_ras_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX) &&
|
||||
adev->gfx.ras_if) {
|
||||
struct ras_common_if *ras_if = adev->gfx.ras_if;
|
||||
struct ras_ih_if ih_info = {
|
||||
.head = *ras_if,
|
||||
.cb = amdgpu_gfx_process_ras_data_cb,
|
||||
};
|
||||
|
||||
amdgpu_ras_late_fini(adev, ras_if, &ih_info);
|
||||
kfree(ras_if);
|
||||
}
|
||||
adev->gfx.ras_if)
|
||||
amdgpu_ras_block_late_fini(adev, adev->gfx.ras_if);
|
||||
}
|
||||
|
||||
int amdgpu_gfx_process_ras_data_cb(struct amdgpu_device *adev,
|
||||
@@ -695,9 +663,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 +820,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, struct ras_common_if *ras_block);
|
||||
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,82 +436,35 @@ void amdgpu_gmc_filter_faults_remove(struct amdgpu_device *adev, uint64_t addr,
|
||||
} while (fault->timestamp < tmp);
|
||||
}
|
||||
|
||||
int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev)
|
||||
int amdgpu_gmc_ras_early_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 (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 (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 (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 (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 (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 (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 (r)
|
||||
return r;
|
||||
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);
|
||||
adev->gmc.xgmi.ras_if = &adev->gmc.xgmi.ras->ras_block.ras_comm;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 +784,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
|
||||
|
||||
@@ -60,7 +60,7 @@ static ssize_t amdgpu_mem_info_gtt_total_show(struct device *dev,
|
||||
struct ttm_resource_manager *man;
|
||||
|
||||
man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT);
|
||||
return sysfs_emit(buf, "%llu\n", man->size * PAGE_SIZE);
|
||||
return sysfs_emit(buf, "%llu\n", man->size);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,8 +77,9 @@ static ssize_t amdgpu_mem_info_gtt_used_show(struct device *dev,
|
||||
{
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
struct ttm_resource_manager *man = &adev->mman.gtt_mgr.manager;
|
||||
|
||||
return sysfs_emit(buf, "%llu\n", amdgpu_gtt_mgr_usage(&adev->mman.gtt_mgr));
|
||||
return sysfs_emit(buf, "%llu\n", ttm_resource_manager_usage(man));
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(mem_info_gtt_total, S_IRUGO,
|
||||
@@ -130,20 +131,17 @@ static int amdgpu_gtt_mgr_new(struct ttm_resource_manager *man,
|
||||
struct amdgpu_gtt_node *node;
|
||||
int r;
|
||||
|
||||
if (!(place->flags & TTM_PL_FLAG_TEMPORARY) &&
|
||||
atomic64_add_return(num_pages, &mgr->used) > man->size) {
|
||||
atomic64_sub(num_pages, &mgr->used);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
node = kzalloc(struct_size(node, base.mm_nodes, 1), GFP_KERNEL);
|
||||
if (!node) {
|
||||
r = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
if (!node)
|
||||
return -ENOMEM;
|
||||
|
||||
node->tbo = tbo;
|
||||
ttm_resource_init(tbo, place, &node->base.base);
|
||||
if (!(place->flags & TTM_PL_FLAG_TEMPORARY) &&
|
||||
ttm_resource_manager_usage(man) > man->size) {
|
||||
r = -ENOSPC;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
if (place->lpfn) {
|
||||
spin_lock(&mgr->lock);
|
||||
@@ -169,11 +167,6 @@ static int amdgpu_gtt_mgr_new(struct ttm_resource_manager *man,
|
||||
err_free:
|
||||
ttm_resource_fini(man, &node->base.base);
|
||||
kfree(node);
|
||||
|
||||
err_out:
|
||||
if (!(place->flags & TTM_PL_FLAG_TEMPORARY))
|
||||
atomic64_sub(num_pages, &mgr->used);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -196,25 +189,10 @@ static void amdgpu_gtt_mgr_del(struct ttm_resource_manager *man,
|
||||
drm_mm_remove_node(&node->base.mm_nodes[0]);
|
||||
spin_unlock(&mgr->lock);
|
||||
|
||||
if (!(res->placement & TTM_PL_FLAG_TEMPORARY))
|
||||
atomic64_sub(res->num_pages, &mgr->used);
|
||||
|
||||
ttm_resource_fini(man, res);
|
||||
kfree(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_gtt_mgr_usage - return usage of GTT domain
|
||||
*
|
||||
* @mgr: amdgpu_gtt_mgr pointer
|
||||
*
|
||||
* Return how many bytes are used in the GTT domain
|
||||
*/
|
||||
uint64_t amdgpu_gtt_mgr_usage(struct amdgpu_gtt_mgr *mgr)
|
||||
{
|
||||
return atomic64_read(&mgr->used) * PAGE_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_gtt_mgr_recover - re-init gart
|
||||
*
|
||||
@@ -222,26 +200,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,9 +233,6 @@ static void amdgpu_gtt_mgr_debug(struct ttm_resource_manager *man,
|
||||
spin_lock(&mgr->lock);
|
||||
drm_mm_print(&mgr->mm, printer);
|
||||
spin_unlock(&mgr->lock);
|
||||
|
||||
drm_printf(printer, "man size:%llu pages, gtt used:%llu pages\n",
|
||||
man->size, atomic64_read(&mgr->used));
|
||||
}
|
||||
|
||||
static const struct ttm_resource_manager_func amdgpu_gtt_mgr_func = {
|
||||
@@ -288,14 +258,12 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size)
|
||||
man->use_tt = true;
|
||||
man->func = &amdgpu_gtt_mgr_func;
|
||||
|
||||
ttm_resource_manager_init(man, &adev->mman.bdev,
|
||||
gtt_size >> PAGE_SHIFT);
|
||||
ttm_resource_manager_init(man, &adev->mman.bdev, gtt_size);
|
||||
|
||||
start = AMDGPU_GTT_MAX_TRANSFER_SIZE * AMDGPU_GTT_NUM_TRANSFER_WINDOWS;
|
||||
size = (adev->gmc.gart_size >> PAGE_SHIFT) - start;
|
||||
drm_mm_init(&mgr->mm, start, size);
|
||||
spin_lock_init(&mgr->lock);
|
||||
atomic64_set(&mgr->used, 0);
|
||||
|
||||
ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_TT, &mgr->manager);
|
||||
ttm_resource_manager_set_used(man, true);
|
||||
|
||||
@@ -24,45 +24,9 @@
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_ras.h"
|
||||
|
||||
int amdgpu_hdp_ras_late_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
struct ras_ih_if ih_info = {
|
||||
.cb = NULL,
|
||||
};
|
||||
struct ras_fs_if fs_info = {
|
||||
.sysfs_name = "hdp_err_count",
|
||||
};
|
||||
|
||||
if (!adev->hdp.ras_if) {
|
||||
adev->hdp.ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
|
||||
if (!adev->hdp.ras_if)
|
||||
return -ENOMEM;
|
||||
adev->hdp.ras_if->block = AMDGPU_RAS_BLOCK__HDP;
|
||||
adev->hdp.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
|
||||
adev->hdp.ras_if->sub_block_index = 0;
|
||||
}
|
||||
ih_info.head = fs_info.head = *adev->hdp.ras_if;
|
||||
r = amdgpu_ras_late_init(adev, adev->hdp.ras_if,
|
||||
&fs_info, &ih_info);
|
||||
if (r || !amdgpu_ras_is_supported(adev, adev->hdp.ras_if->block)) {
|
||||
kfree(adev->hdp.ras_if);
|
||||
adev->hdp.ras_if = NULL;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void amdgpu_hdp_ras_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__HDP) &&
|
||||
adev->hdp.ras_if) {
|
||||
struct ras_common_if *ras_if = adev->hdp.ras_if;
|
||||
struct ras_ih_if ih_info = {
|
||||
.cb = NULL,
|
||||
};
|
||||
|
||||
amdgpu_ras_late_fini(adev, ras_if, &ih_info);
|
||||
kfree(ras_if);
|
||||
}
|
||||
adev->hdp.ras_if)
|
||||
amdgpu_ras_block_late_fini(adev, adev->hdp.ras_if);
|
||||
}
|
||||
|
||||
@@ -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, struct ras_common_if *ras_block);
|
||||
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;
|
||||
|
||||
@@ -37,6 +37,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
|
||||
struct amdgpu_task_info ti;
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
int idx;
|
||||
int r;
|
||||
|
||||
if (!drm_dev_enter(adev_to_drm(adev), &idx)) {
|
||||
DRM_INFO("%s - device unplugged skipping recovery on scheduler:%s",
|
||||
@@ -63,7 +64,9 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
|
||||
ti.process_name, ti.tgid, ti.task_name, ti.pid);
|
||||
|
||||
if (amdgpu_device_should_recover_gpu(ring->adev)) {
|
||||
amdgpu_device_gpu_recover(ring->adev, job);
|
||||
r = amdgpu_device_gpu_recover_imp(ring->adev, job);
|
||||
if (r)
|
||||
DRM_ERROR("GPU Recovery Failed: %d\n", r);
|
||||
} else {
|
||||
drm_sched_suspend_timeout(&ring->sched);
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -678,13 +604,13 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
ui64 = atomic64_read(&adev->num_vram_cpu_page_faults);
|
||||
return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
|
||||
case AMDGPU_INFO_VRAM_USAGE:
|
||||
ui64 = amdgpu_vram_mgr_usage(&adev->mman.vram_mgr);
|
||||
ui64 = ttm_resource_manager_usage(&adev->mman.vram_mgr.manager);
|
||||
return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
|
||||
case AMDGPU_INFO_VIS_VRAM_USAGE:
|
||||
ui64 = amdgpu_vram_mgr_vis_usage(&adev->mman.vram_mgr);
|
||||
return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
|
||||
case AMDGPU_INFO_GTT_USAGE:
|
||||
ui64 = amdgpu_gtt_mgr_usage(&adev->mman.gtt_mgr);
|
||||
ui64 = ttm_resource_manager_usage(&adev->mman.gtt_mgr.manager);
|
||||
return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
|
||||
case AMDGPU_INFO_GDS_CONFIG: {
|
||||
struct drm_amdgpu_info_gds gds_info;
|
||||
@@ -716,14 +642,17 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
case AMDGPU_INFO_MEMORY: {
|
||||
struct drm_amdgpu_memory_info mem;
|
||||
struct ttm_resource_manager *gtt_man =
|
||||
ttm_manager_type(&adev->mman.bdev, TTM_PL_TT);
|
||||
&adev->mman.gtt_mgr.manager;
|
||||
struct ttm_resource_manager *vram_man =
|
||||
&adev->mman.vram_mgr.manager;
|
||||
|
||||
memset(&mem, 0, sizeof(mem));
|
||||
mem.vram.total_heap_size = adev->gmc.real_vram_size;
|
||||
mem.vram.usable_heap_size = adev->gmc.real_vram_size -
|
||||
atomic64_read(&adev->vram_pin_size) -
|
||||
AMDGPU_VM_RESERVED_VRAM;
|
||||
mem.vram.heap_usage =
|
||||
amdgpu_vram_mgr_usage(&adev->mman.vram_mgr);
|
||||
ttm_resource_manager_usage(vram_man);
|
||||
mem.vram.max_allocation = mem.vram.usable_heap_size * 3 / 4;
|
||||
|
||||
mem.cpu_accessible_vram.total_heap_size =
|
||||
@@ -741,8 +670,7 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
mem.gtt.total_heap_size *= PAGE_SIZE;
|
||||
mem.gtt.usable_heap_size = mem.gtt.total_heap_size -
|
||||
atomic64_read(&adev->gart_pin_size);
|
||||
mem.gtt.heap_usage =
|
||||
amdgpu_gtt_mgr_usage(&adev->mman.gtt_mgr);
|
||||
mem.gtt.heap_usage = ttm_resource_manager_usage(gtt_man);
|
||||
mem.gtt.max_allocation = mem.gtt.usable_heap_size * 3 / 4;
|
||||
|
||||
return copy_to_user(out, &mem,
|
||||
@@ -1268,18 +1196,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 +1357,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 +1503,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 +1553,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;
|
||||
|
||||
@@ -71,47 +71,8 @@ void amdgpu_mca_query_ras_error_count(struct amdgpu_device *adev,
|
||||
amdgpu_mca_reset_error_count(adev, mc_status_addr);
|
||||
}
|
||||
|
||||
int amdgpu_mca_ras_late_init(struct amdgpu_device *adev,
|
||||
struct amdgpu_mca_ras *mca_dev)
|
||||
{
|
||||
int r;
|
||||
struct ras_ih_if ih_info = {
|
||||
.cb = NULL,
|
||||
};
|
||||
struct ras_fs_if fs_info = {
|
||||
.sysfs_name = mca_dev->ras_funcs->sysfs_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->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
|
||||
}
|
||||
ih_info.head = fs_info.head = *mca_dev->ras_if;
|
||||
r = amdgpu_ras_late_init(adev, mca_dev->ras_if,
|
||||
&fs_info, &ih_info);
|
||||
if (r || !amdgpu_ras_is_supported(adev, mca_dev->ras_if->block)) {
|
||||
kfree(mca_dev->ras_if);
|
||||
mca_dev->ras_if = NULL;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void amdgpu_mca_ras_fini(struct amdgpu_device *adev,
|
||||
struct amdgpu_mca_ras *mca_dev)
|
||||
{
|
||||
struct ras_ih_if ih_info = {
|
||||
.cb = NULL,
|
||||
};
|
||||
|
||||
if (!mca_dev->ras_if)
|
||||
return;
|
||||
|
||||
amdgpu_ras_late_fini(adev, mca_dev->ras_if, &ih_info);
|
||||
kfree(mca_dev->ras_if);
|
||||
mca_dev->ras_if = NULL;
|
||||
amdgpu_ras_block_late_fini(adev, 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 {
|
||||
@@ -64,9 +56,6 @@ void amdgpu_mca_query_ras_error_count(struct amdgpu_device *adev,
|
||||
uint64_t mc_status_addr,
|
||||
void *ras_error_status);
|
||||
|
||||
int amdgpu_mca_ras_late_init(struct amdgpu_device *adev,
|
||||
struct amdgpu_mca_ras *mca_dev);
|
||||
|
||||
void amdgpu_mca_ras_fini(struct amdgpu_device *adev,
|
||||
struct amdgpu_mca_ras *mca_dev);
|
||||
|
||||
|
||||
@@ -24,45 +24,9 @@
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_ras.h"
|
||||
|
||||
int amdgpu_mmhub_ras_late_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
struct ras_ih_if ih_info = {
|
||||
.cb = NULL,
|
||||
};
|
||||
struct ras_fs_if fs_info = {
|
||||
.sysfs_name = "mmhub_err_count",
|
||||
};
|
||||
|
||||
if (!adev->mmhub.ras_if) {
|
||||
adev->mmhub.ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
|
||||
if (!adev->mmhub.ras_if)
|
||||
return -ENOMEM;
|
||||
adev->mmhub.ras_if->block = AMDGPU_RAS_BLOCK__MMHUB;
|
||||
adev->mmhub.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
|
||||
adev->mmhub.ras_if->sub_block_index = 0;
|
||||
}
|
||||
ih_info.head = fs_info.head = *adev->mmhub.ras_if;
|
||||
r = amdgpu_ras_late_init(adev, adev->mmhub.ras_if,
|
||||
&fs_info, &ih_info);
|
||||
if (r || !amdgpu_ras_is_supported(adev, adev->mmhub.ras_if->block)) {
|
||||
kfree(adev->mmhub.ras_if);
|
||||
adev->mmhub.ras_if = NULL;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void amdgpu_mmhub_ras_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__MMHUB) &&
|
||||
adev->mmhub.ras_if) {
|
||||
struct ras_common_if *ras_if = adev->mmhub.ras_if;
|
||||
struct ras_ih_if ih_info = {
|
||||
.cb = NULL,
|
||||
};
|
||||
|
||||
amdgpu_ras_late_fini(adev, ras_if, &ih_info);
|
||||
kfree(ras_if);
|
||||
}
|
||||
adev->mmhub.ras_if)
|
||||
amdgpu_ras_block_late_fini(adev, adev->mmhub.ras_if);
|
||||
}
|
||||
|
||||
@@ -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,9 @@ 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);
|
||||
void amdgpu_mmhub_ras_fini(struct amdgpu_device *adev);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -22,61 +22,31 @@
|
||||
#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, struct ras_common_if *ras_block)
|
||||
{
|
||||
int r;
|
||||
struct ras_ih_if ih_info = {
|
||||
.cb = NULL,
|
||||
};
|
||||
struct ras_fs_if fs_info = {
|
||||
.sysfs_name = "pcie_bif_err_count",
|
||||
};
|
||||
|
||||
if (!adev->nbio.ras_if) {
|
||||
adev->nbio.ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
|
||||
if (!adev->nbio.ras_if)
|
||||
return -ENOMEM;
|
||||
adev->nbio.ras_if->block = AMDGPU_RAS_BLOCK__PCIE_BIF;
|
||||
adev->nbio.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
|
||||
adev->nbio.ras_if->sub_block_index = 0;
|
||||
}
|
||||
ih_info.head = fs_info.head = *adev->nbio.ras_if;
|
||||
r = amdgpu_ras_late_init(adev, adev->nbio.ras_if,
|
||||
&fs_info, &ih_info);
|
||||
r = amdgpu_ras_block_late_init(adev, ras_block);
|
||||
if (r)
|
||||
goto free;
|
||||
return r;
|
||||
|
||||
if (amdgpu_ras_is_supported(adev, adev->nbio.ras_if->block)) {
|
||||
if (amdgpu_ras_is_supported(adev, ras_block->block)) {
|
||||
r = amdgpu_irq_get(adev, &adev->nbio.ras_controller_irq, 0);
|
||||
if (r)
|
||||
goto late_fini;
|
||||
r = amdgpu_irq_get(adev, &adev->nbio.ras_err_event_athub_irq, 0);
|
||||
if (r)
|
||||
goto late_fini;
|
||||
} else {
|
||||
r = 0;
|
||||
goto free;
|
||||
}
|
||||
|
||||
return 0;
|
||||
late_fini:
|
||||
amdgpu_ras_late_fini(adev, adev->nbio.ras_if, &ih_info);
|
||||
free:
|
||||
kfree(adev->nbio.ras_if);
|
||||
adev->nbio.ras_if = NULL;
|
||||
amdgpu_ras_block_late_fini(adev, ras_block);
|
||||
return r;
|
||||
}
|
||||
|
||||
void amdgpu_nbio_ras_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__PCIE_BIF) &&
|
||||
adev->nbio.ras_if) {
|
||||
struct ras_common_if *ras_if = adev->nbio.ras_if;
|
||||
struct ras_ih_if ih_info = {
|
||||
.cb = NULL,
|
||||
};
|
||||
|
||||
amdgpu_ras_late_fini(adev, ras_if, &ih_info);
|
||||
kfree(ras_if);
|
||||
}
|
||||
adev->nbio.ras_if)
|
||||
amdgpu_ras_block_late_fini(adev, adev->nbio.ras_if);
|
||||
}
|
||||
|
||||
@@ -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, struct ras_common_if *ras_block);
|
||||
void amdgpu_nbio_ras_fini(struct amdgpu_device *adev);
|
||||
#endif
|
||||
|
||||
@@ -451,7 +451,7 @@ static bool amdgpu_bo_validate_size(struct amdgpu_device *adev,
|
||||
if (domain & AMDGPU_GEM_DOMAIN_GTT) {
|
||||
man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT);
|
||||
|
||||
if (size < (man->size << PAGE_SHIFT))
|
||||
if (size < man->size)
|
||||
return true;
|
||||
else
|
||||
goto fail;
|
||||
@@ -460,7 +460,7 @@ static bool amdgpu_bo_validate_size(struct amdgpu_device *adev,
|
||||
if (domain & AMDGPU_GEM_DOMAIN_VRAM) {
|
||||
man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM);
|
||||
|
||||
if (size < (man->size << PAGE_SHIFT))
|
||||
if (size < man->size)
|
||||
return true;
|
||||
else
|
||||
goto fail;
|
||||
@@ -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)) {
|
||||
|
||||
@@ -25,12 +25,6 @@
|
||||
|
||||
#include "amdgpu.h"
|
||||
|
||||
static inline struct amdgpu_preempt_mgr *
|
||||
to_preempt_mgr(struct ttm_resource_manager *man)
|
||||
{
|
||||
return container_of(man, struct amdgpu_preempt_mgr, manager);
|
||||
}
|
||||
|
||||
/**
|
||||
* DOC: mem_info_preempt_used
|
||||
*
|
||||
@@ -45,10 +39,9 @@ static ssize_t mem_info_preempt_used_show(struct device *dev,
|
||||
{
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
struct ttm_resource_manager *man;
|
||||
struct ttm_resource_manager *man = &adev->mman.preempt_mgr;
|
||||
|
||||
man = ttm_manager_type(&adev->mman.bdev, AMDGPU_PL_PREEMPT);
|
||||
return sysfs_emit(buf, "%llu\n", amdgpu_preempt_mgr_usage(man));
|
||||
return sysfs_emit(buf, "%llu\n", ttm_resource_manager_usage(man));
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(mem_info_preempt_used);
|
||||
@@ -68,16 +61,12 @@ static int amdgpu_preempt_mgr_new(struct ttm_resource_manager *man,
|
||||
const struct ttm_place *place,
|
||||
struct ttm_resource **res)
|
||||
{
|
||||
struct amdgpu_preempt_mgr *mgr = to_preempt_mgr(man);
|
||||
|
||||
*res = kzalloc(sizeof(**res), GFP_KERNEL);
|
||||
if (!*res)
|
||||
return -ENOMEM;
|
||||
|
||||
ttm_resource_init(tbo, place, *res);
|
||||
(*res)->start = AMDGPU_BO_INVALID_OFFSET;
|
||||
|
||||
atomic64_add((*res)->num_pages, &mgr->used);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -92,49 +81,13 @@ static int amdgpu_preempt_mgr_new(struct ttm_resource_manager *man,
|
||||
static void amdgpu_preempt_mgr_del(struct ttm_resource_manager *man,
|
||||
struct ttm_resource *res)
|
||||
{
|
||||
struct amdgpu_preempt_mgr *mgr = to_preempt_mgr(man);
|
||||
|
||||
atomic64_sub(res->num_pages, &mgr->used);
|
||||
ttm_resource_fini(man, res);
|
||||
kfree(res);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_preempt_mgr_usage - return usage of PREEMPT domain
|
||||
*
|
||||
* @man: TTM memory type manager
|
||||
*
|
||||
* Return how many bytes are used in the GTT domain
|
||||
*/
|
||||
uint64_t amdgpu_preempt_mgr_usage(struct ttm_resource_manager *man)
|
||||
{
|
||||
struct amdgpu_preempt_mgr *mgr = to_preempt_mgr(man);
|
||||
s64 result = atomic64_read(&mgr->used);
|
||||
|
||||
return (result > 0 ? result : 0) * PAGE_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_preempt_mgr_debug - dump VRAM table
|
||||
*
|
||||
* @man: TTM memory type manager
|
||||
* @printer: DRM printer to use
|
||||
*
|
||||
* Dump the table content using printk.
|
||||
*/
|
||||
static void amdgpu_preempt_mgr_debug(struct ttm_resource_manager *man,
|
||||
struct drm_printer *printer)
|
||||
{
|
||||
struct amdgpu_preempt_mgr *mgr = to_preempt_mgr(man);
|
||||
|
||||
drm_printf(printer, "man size:%llu pages, preempt used:%lld pages\n",
|
||||
man->size, (u64)atomic64_read(&mgr->used));
|
||||
}
|
||||
|
||||
static const struct ttm_resource_manager_func amdgpu_preempt_mgr_func = {
|
||||
.alloc = amdgpu_preempt_mgr_new,
|
||||
.free = amdgpu_preempt_mgr_del,
|
||||
.debug = amdgpu_preempt_mgr_debug
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -146,8 +99,7 @@ static const struct ttm_resource_manager_func amdgpu_preempt_mgr_func = {
|
||||
*/
|
||||
int amdgpu_preempt_mgr_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_preempt_mgr *mgr = &adev->mman.preempt_mgr;
|
||||
struct ttm_resource_manager *man = &mgr->manager;
|
||||
struct ttm_resource_manager *man = &adev->mman.preempt_mgr;
|
||||
int ret;
|
||||
|
||||
man->use_tt = true;
|
||||
@@ -155,16 +107,13 @@ int amdgpu_preempt_mgr_init(struct amdgpu_device *adev)
|
||||
|
||||
ttm_resource_manager_init(man, &adev->mman.bdev, (1 << 30));
|
||||
|
||||
atomic64_set(&mgr->used, 0);
|
||||
|
||||
ret = device_create_file(adev->dev, &dev_attr_mem_info_preempt_used);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to create device file mem_info_preempt_used\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ttm_set_driver_manager(&adev->mman.bdev, AMDGPU_PL_PREEMPT,
|
||||
&mgr->manager);
|
||||
ttm_set_driver_manager(&adev->mman.bdev, AMDGPU_PL_PREEMPT, man);
|
||||
ttm_resource_manager_set_used(man, true);
|
||||
return 0;
|
||||
}
|
||||
@@ -179,8 +128,7 @@ int amdgpu_preempt_mgr_init(struct amdgpu_device *adev)
|
||||
*/
|
||||
void amdgpu_preempt_mgr_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_preempt_mgr *mgr = &adev->mman.preempt_mgr;
|
||||
struct ttm_resource_manager *man = &mgr->manager;
|
||||
struct ttm_resource_manager *man = &adev->mman.preempt_mgr;
|
||||
int ret;
|
||||
|
||||
ttm_resource_manager_set_used(man, false);
|
||||
|
||||
@@ -133,6 +133,7 @@ static int psp_early_init(void *handle)
|
||||
break;
|
||||
case IP_VERSION(13, 0, 1):
|
||||
case IP_VERSION(13, 0, 3):
|
||||
case IP_VERSION(13, 0, 8):
|
||||
psp_v13_0_set_psp_funcs(psp);
|
||||
psp->autoload_supported = true;
|
||||
break;
|
||||
@@ -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->ras_comm.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)
|
||||
@@ -1329,18 +1276,17 @@ static int amdgpu_ras_sysfs_remove_feature_node(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
int amdgpu_ras_sysfs_create(struct amdgpu_device *adev,
|
||||
struct ras_fs_if *head)
|
||||
struct ras_common_if *head)
|
||||
{
|
||||
struct ras_manager *obj = amdgpu_ras_find_obj(adev, &head->head);
|
||||
struct ras_manager *obj = amdgpu_ras_find_obj(adev, head);
|
||||
|
||||
if (!obj || obj->attr_inuse)
|
||||
return -EINVAL;
|
||||
|
||||
get_obj(obj);
|
||||
|
||||
memcpy(obj->fs_data.sysfs_name,
|
||||
head->sysfs_name,
|
||||
sizeof(obj->fs_data.sysfs_name));
|
||||
snprintf(obj->fs_data.sysfs_name, sizeof(obj->fs_data.sysfs_name),
|
||||
"%s_err_count", head->name);
|
||||
|
||||
obj->sysfs_attr = (struct device_attribute){
|
||||
.attr = {
|
||||
@@ -1647,9 +1593,9 @@ int amdgpu_ras_interrupt_dispatch(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
int amdgpu_ras_interrupt_remove_handler(struct amdgpu_device *adev,
|
||||
struct ras_ih_if *info)
|
||||
struct ras_common_if *head)
|
||||
{
|
||||
struct ras_manager *obj = amdgpu_ras_find_obj(adev, &info->head);
|
||||
struct ras_manager *obj = amdgpu_ras_find_obj(adev, head);
|
||||
struct ras_ih_data *data;
|
||||
|
||||
if (!obj)
|
||||
@@ -1669,24 +1615,27 @@ int amdgpu_ras_interrupt_remove_handler(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
int amdgpu_ras_interrupt_add_handler(struct amdgpu_device *adev,
|
||||
struct ras_ih_if *info)
|
||||
struct ras_common_if *head)
|
||||
{
|
||||
struct ras_manager *obj = amdgpu_ras_find_obj(adev, &info->head);
|
||||
struct ras_manager *obj = amdgpu_ras_find_obj(adev, head);
|
||||
struct ras_ih_data *data;
|
||||
struct amdgpu_ras_block_object *ras_obj;
|
||||
|
||||
if (!obj) {
|
||||
/* in case we registe the IH before enable ras feature */
|
||||
obj = amdgpu_ras_create_obj(adev, &info->head);
|
||||
obj = amdgpu_ras_create_obj(adev, head);
|
||||
if (!obj)
|
||||
return -EINVAL;
|
||||
} else
|
||||
get_obj(obj);
|
||||
|
||||
ras_obj = container_of(head, struct amdgpu_ras_block_object, ras_comm);
|
||||
|
||||
data = &obj->ih_data;
|
||||
/* add the callback.etc */
|
||||
*data = (struct ras_ih_data) {
|
||||
.inuse = 0,
|
||||
.cb = info->cb,
|
||||
.cb = ras_obj->ras_cb,
|
||||
.element_size = sizeof(struct amdgpu_iv_entry),
|
||||
.rptr = 0,
|
||||
.wptr = 0,
|
||||
@@ -1715,10 +1664,7 @@ static int amdgpu_ras_interrupt_remove_all(struct amdgpu_device *adev)
|
||||
struct ras_manager *obj, *tmp;
|
||||
|
||||
list_for_each_entry_safe(obj, tmp, &con->head, node) {
|
||||
struct ras_ih_if info = {
|
||||
.head = obj->head,
|
||||
};
|
||||
amdgpu_ras_interrupt_remove_handler(adev, &info);
|
||||
amdgpu_ras_interrupt_remove_handler(adev, &obj->head);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1766,24 +1712,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 +2091,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 +2297,27 @@ 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);
|
||||
adev->nbio.ras_if = &adev->nbio.ras->ras_block.ras_comm;
|
||||
}
|
||||
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;
|
||||
@@ -2445,11 +2397,10 @@ bool amdgpu_ras_is_poison_mode_supported(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
/* helper function to handle common stuff in ip late init phase */
|
||||
int amdgpu_ras_late_init(struct amdgpu_device *adev,
|
||||
struct ras_common_if *ras_block,
|
||||
struct ras_fs_if *fs_info,
|
||||
struct ras_ih_if *ih_info)
|
||||
int amdgpu_ras_block_late_init(struct amdgpu_device *adev,
|
||||
struct ras_common_if *ras_block)
|
||||
{
|
||||
struct amdgpu_ras_block_object *ras_obj;
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
unsigned long ue_count, ce_count;
|
||||
int r;
|
||||
@@ -2477,15 +2428,16 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev,
|
||||
if (adev->in_suspend || amdgpu_in_reset(adev))
|
||||
return 0;
|
||||
|
||||
if (ih_info->cb) {
|
||||
r = amdgpu_ras_interrupt_add_handler(adev, ih_info);
|
||||
ras_obj = container_of(ras_block, struct amdgpu_ras_block_object, ras_comm);
|
||||
if (ras_obj->ras_cb) {
|
||||
r = amdgpu_ras_interrupt_add_handler(adev, ras_block);
|
||||
if (r)
|
||||
goto interrupt;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
r = amdgpu_ras_sysfs_create(adev, fs_info);
|
||||
r = amdgpu_ras_sysfs_create(adev, ras_block);
|
||||
if (r)
|
||||
goto sysfs;
|
||||
goto interrupt;
|
||||
|
||||
/* Those are the cached values at init.
|
||||
*/
|
||||
@@ -2495,27 +2447,34 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
return 0;
|
||||
cleanup:
|
||||
amdgpu_ras_sysfs_remove(adev, ras_block);
|
||||
sysfs:
|
||||
if (ih_info->cb)
|
||||
amdgpu_ras_interrupt_remove_handler(adev, ih_info);
|
||||
|
||||
interrupt:
|
||||
if (ras_obj->ras_cb)
|
||||
amdgpu_ras_interrupt_remove_handler(adev, ras_block);
|
||||
cleanup:
|
||||
amdgpu_ras_feature_enable(adev, ras_block, 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* helper function to remove ras fs node and interrupt handler */
|
||||
void amdgpu_ras_late_fini(struct amdgpu_device *adev,
|
||||
struct ras_common_if *ras_block,
|
||||
struct ras_ih_if *ih_info)
|
||||
int amdgpu_ras_block_late_init_default(struct amdgpu_device *adev,
|
||||
struct ras_common_if *ras_block)
|
||||
{
|
||||
if (!ras_block || !ih_info)
|
||||
return amdgpu_ras_block_late_init(adev, ras_block);
|
||||
}
|
||||
|
||||
/* helper function to remove ras fs node and interrupt handler */
|
||||
void amdgpu_ras_block_late_fini(struct amdgpu_device *adev,
|
||||
struct ras_common_if *ras_block)
|
||||
{
|
||||
struct amdgpu_ras_block_object *ras_obj;
|
||||
if (!ras_block)
|
||||
return;
|
||||
|
||||
amdgpu_ras_sysfs_remove(adev, ras_block);
|
||||
if (ih_info->cb)
|
||||
amdgpu_ras_interrupt_remove_handler(adev, ih_info);
|
||||
|
||||
ras_obj = container_of(ras_block, struct amdgpu_ras_block_object, ras_comm);
|
||||
if (ras_obj->ras_cb)
|
||||
amdgpu_ras_interrupt_remove_handler(adev, ras_block);
|
||||
}
|
||||
|
||||
/* do some init work after IP late init as dependence.
|
||||
@@ -2568,6 +2527,33 @@ void amdgpu_ras_suspend(struct amdgpu_device *adev)
|
||||
amdgpu_ras_disable_all_features(adev, 1);
|
||||
}
|
||||
|
||||
int amdgpu_ras_late_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras_block_list *node, *tmp;
|
||||
struct amdgpu_ras_block_object *obj;
|
||||
int r;
|
||||
|
||||
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_late_init) {
|
||||
r = obj->ras_late_init(adev, &obj->ras_comm);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "%s failed to execute ras_late_init! ret:%d\n",
|
||||
obj->ras_comm.name, r);
|
||||
return r;
|
||||
}
|
||||
} else
|
||||
amdgpu_ras_block_late_init_default(adev, &obj->ras_comm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* do some fini work before IP fini as dependence */
|
||||
int amdgpu_ras_pre_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
@@ -2585,6 +2571,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 +2590,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 +2710,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 +2721,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 +2762,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,27 @@ struct ras_debug_if {
|
||||
};
|
||||
int op;
|
||||
};
|
||||
|
||||
struct amdgpu_ras_block_object {
|
||||
struct ras_common_if ras_comm;
|
||||
|
||||
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, struct ras_common_if *ras_block);
|
||||
void (*ras_fini)(struct amdgpu_device *adev);
|
||||
ras_ih_cb ras_cb;
|
||||
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 +519,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 +535,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) {
|
||||
@@ -596,15 +595,15 @@ amdgpu_ras_error_to_ta(enum amdgpu_ras_error_type error) {
|
||||
|
||||
/* called in ip_init and ip_fini */
|
||||
int amdgpu_ras_init(struct amdgpu_device *adev);
|
||||
int amdgpu_ras_late_init(struct amdgpu_device *adev);
|
||||
int amdgpu_ras_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_ras_pre_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_ras_late_init(struct amdgpu_device *adev,
|
||||
struct ras_common_if *ras_block,
|
||||
struct ras_fs_if *fs_info,
|
||||
struct ras_ih_if *ih_info);
|
||||
void amdgpu_ras_late_fini(struct amdgpu_device *adev,
|
||||
struct ras_common_if *ras_block,
|
||||
struct ras_ih_if *ih_info);
|
||||
|
||||
int amdgpu_ras_block_late_init(struct amdgpu_device *adev,
|
||||
struct ras_common_if *ras_block);
|
||||
|
||||
void amdgpu_ras_block_late_fini(struct amdgpu_device *adev,
|
||||
struct ras_common_if *ras_block);
|
||||
|
||||
int amdgpu_ras_feature_enable(struct amdgpu_device *adev,
|
||||
struct ras_common_if *head, bool enable);
|
||||
@@ -613,7 +612,7 @@ int amdgpu_ras_feature_enable_on_boot(struct amdgpu_device *adev,
|
||||
struct ras_common_if *head, bool enable);
|
||||
|
||||
int amdgpu_ras_sysfs_create(struct amdgpu_device *adev,
|
||||
struct ras_fs_if *head);
|
||||
struct ras_common_if *head);
|
||||
|
||||
int amdgpu_ras_sysfs_remove(struct amdgpu_device *adev,
|
||||
struct ras_common_if *head);
|
||||
@@ -630,10 +629,10 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev,
|
||||
struct ras_inject_if *info);
|
||||
|
||||
int amdgpu_ras_interrupt_add_handler(struct amdgpu_device *adev,
|
||||
struct ras_ih_if *info);
|
||||
struct ras_common_if *head);
|
||||
|
||||
int amdgpu_ras_interrupt_remove_handler(struct amdgpu_device *adev,
|
||||
struct ras_ih_if *info);
|
||||
struct ras_common_if *head);
|
||||
|
||||
int amdgpu_ras_interrupt_dispatch(struct amdgpu_device *adev,
|
||||
struct ras_dispatch_if *info);
|
||||
@@ -667,4 +666,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
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include "amdgpu_reset.h"
|
||||
|
||||
#define EEPROM_I2C_MADDR_VEGA20 0x0
|
||||
#define EEPROM_I2C_MADDR_ARCTURUS 0x40000
|
||||
#define EEPROM_I2C_MADDR_ARCTURUS_D342 0x0
|
||||
@@ -193,12 +195,12 @@ static int __write_table_header(struct amdgpu_ras_eeprom_control *control)
|
||||
__encode_table_header_to_buf(&control->tbl_hdr, buf);
|
||||
|
||||
/* i2c may be unstable in gpu reset */
|
||||
down_read(&adev->reset_sem);
|
||||
res = amdgpu_eeprom_write(&adev->pm.smu_i2c,
|
||||
down_read(&adev->reset_domain->sem);
|
||||
res = amdgpu_eeprom_write(adev->pm.ras_eeprom_i2c_bus,
|
||||
control->i2c_address +
|
||||
control->ras_header_offset,
|
||||
buf, RAS_TABLE_HEADER_SIZE);
|
||||
up_read(&adev->reset_sem);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
|
||||
if (res < 0) {
|
||||
DRM_ERROR("Failed to write EEPROM table header:%d", res);
|
||||
@@ -263,6 +265,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 +285,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);
|
||||
@@ -387,13 +392,13 @@ static int __amdgpu_ras_eeprom_write(struct amdgpu_ras_eeprom_control *control,
|
||||
int res;
|
||||
|
||||
/* i2c may be unstable in gpu reset */
|
||||
down_read(&adev->reset_sem);
|
||||
down_read(&adev->reset_domain->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);
|
||||
up_read(&adev->reset_sem);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
if (res < 0) {
|
||||
DRM_ERROR("Writing %d EEPROM table records error:%d",
|
||||
num, res);
|
||||
@@ -547,12 +552,12 @@ amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control)
|
||||
goto Out;
|
||||
}
|
||||
|
||||
down_read(&adev->reset_sem);
|
||||
res = amdgpu_eeprom_read(&adev->pm.smu_i2c,
|
||||
down_read(&adev->reset_domain->sem);
|
||||
res = amdgpu_eeprom_read(adev->pm.ras_eeprom_i2c_bus,
|
||||
control->i2c_address +
|
||||
control->ras_record_offset,
|
||||
buf, buf_size);
|
||||
up_read(&adev->reset_sem);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
if (res < 0) {
|
||||
DRM_ERROR("EEPROM failed reading records:%d\n",
|
||||
res);
|
||||
@@ -642,13 +647,13 @@ static int __amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control,
|
||||
int res;
|
||||
|
||||
/* i2c may be unstable in gpu reset */
|
||||
down_read(&adev->reset_sem);
|
||||
down_read(&adev->reset_domain->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);
|
||||
up_read(&adev->reset_sem);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
if (res < 0) {
|
||||
DRM_ERROR("Reading %d EEPROM table records error:%d",
|
||||
num, res);
|
||||
@@ -1009,7 +1014,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 +1050,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 +1062,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) {
|
||||
|
||||
@@ -96,3 +96,59 @@ int amdgpu_reset_perform_reset(struct amdgpu_device *adev,
|
||||
return reset_handler->restore_hwcontext(adev->reset_cntl,
|
||||
reset_context);
|
||||
}
|
||||
|
||||
|
||||
void amdgpu_reset_destroy_reset_domain(struct kref *ref)
|
||||
{
|
||||
struct amdgpu_reset_domain *reset_domain = container_of(ref,
|
||||
struct amdgpu_reset_domain,
|
||||
refcount);
|
||||
if (reset_domain->wq)
|
||||
destroy_workqueue(reset_domain->wq);
|
||||
|
||||
kvfree(reset_domain);
|
||||
}
|
||||
|
||||
struct amdgpu_reset_domain *amdgpu_reset_create_reset_domain(enum amdgpu_reset_domain_type type,
|
||||
char *wq_name)
|
||||
{
|
||||
struct amdgpu_reset_domain *reset_domain;
|
||||
|
||||
reset_domain = kvzalloc(sizeof(struct amdgpu_reset_domain), GFP_KERNEL);
|
||||
if (!reset_domain) {
|
||||
DRM_ERROR("Failed to allocate amdgpu_reset_domain!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
reset_domain->type = type;
|
||||
kref_init(&reset_domain->refcount);
|
||||
|
||||
reset_domain->wq = create_singlethread_workqueue(wq_name);
|
||||
if (!reset_domain->wq) {
|
||||
DRM_ERROR("Failed to allocate wq for amdgpu_reset_domain!");
|
||||
amdgpu_reset_put_reset_domain(reset_domain);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
atomic_set(&reset_domain->in_gpu_reset, 0);
|
||||
init_rwsem(&reset_domain->sem);
|
||||
|
||||
return reset_domain;
|
||||
}
|
||||
|
||||
void amdgpu_device_lock_reset_domain(struct amdgpu_reset_domain *reset_domain)
|
||||
{
|
||||
atomic_set(&reset_domain->in_gpu_reset, 1);
|
||||
down_write(&reset_domain->sem);
|
||||
}
|
||||
|
||||
|
||||
void amdgpu_device_unlock_reset_domain(struct amdgpu_reset_domain *reset_domain)
|
||||
{
|
||||
atomic_set(&reset_domain->in_gpu_reset, 0);
|
||||
up_write(&reset_domain->sem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -70,6 +70,21 @@ struct amdgpu_reset_control {
|
||||
void (*async_reset)(struct work_struct *work);
|
||||
};
|
||||
|
||||
|
||||
enum amdgpu_reset_domain_type {
|
||||
SINGLE_DEVICE,
|
||||
XGMI_HIVE
|
||||
};
|
||||
|
||||
struct amdgpu_reset_domain {
|
||||
struct kref refcount;
|
||||
struct workqueue_struct *wq;
|
||||
enum amdgpu_reset_domain_type type;
|
||||
struct rw_semaphore sem;
|
||||
atomic_t in_gpu_reset;
|
||||
};
|
||||
|
||||
|
||||
int amdgpu_reset_init(struct amdgpu_device *adev);
|
||||
int amdgpu_reset_fini(struct amdgpu_device *adev);
|
||||
|
||||
@@ -82,4 +97,29 @@ int amdgpu_reset_perform_reset(struct amdgpu_device *adev,
|
||||
int amdgpu_reset_add_handler(struct amdgpu_reset_control *reset_ctl,
|
||||
struct amdgpu_reset_handler *handler);
|
||||
|
||||
struct amdgpu_reset_domain *amdgpu_reset_create_reset_domain(enum amdgpu_reset_domain_type type,
|
||||
char *wq_name);
|
||||
|
||||
void amdgpu_reset_destroy_reset_domain(struct kref *ref);
|
||||
|
||||
static inline bool amdgpu_reset_get_reset_domain(struct amdgpu_reset_domain *domain)
|
||||
{
|
||||
return kref_get_unless_zero(&domain->refcount) != 0;
|
||||
}
|
||||
|
||||
static inline void amdgpu_reset_put_reset_domain(struct amdgpu_reset_domain *domain)
|
||||
{
|
||||
kref_put(&domain->refcount, amdgpu_reset_destroy_reset_domain);
|
||||
}
|
||||
|
||||
static inline bool amdgpu_reset_domain_schedule(struct amdgpu_reset_domain *domain,
|
||||
struct work_struct *work)
|
||||
{
|
||||
return queue_work(domain->wq, work);
|
||||
}
|
||||
|
||||
void amdgpu_device_lock_reset_domain(struct amdgpu_reset_domain *reset_domain);
|
||||
|
||||
void amdgpu_device_unlock_reset_domain(struct amdgpu_reset_domain *reset_domain);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -191,8 +191,9 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
|
||||
ring->adev = adev;
|
||||
ring->idx = adev->num_rings++;
|
||||
adev->rings[ring->idx] = ring;
|
||||
r = amdgpu_fence_driver_init_ring(ring, sched_hw_submission,
|
||||
sched_score);
|
||||
ring->num_hw_submission = sched_hw_submission;
|
||||
ring->sched_score = sched_score;
|
||||
r = amdgpu_fence_driver_init_ring(ring);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -114,9 +114,7 @@ struct amdgpu_fence_driver {
|
||||
void amdgpu_fence_driver_clear_job_fences(struct amdgpu_ring *ring);
|
||||
void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring);
|
||||
|
||||
int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
|
||||
unsigned num_hw_submission,
|
||||
atomic_t *sched_score);
|
||||
int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring);
|
||||
int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
|
||||
struct amdgpu_irq_src *irq_src,
|
||||
unsigned irq_type);
|
||||
@@ -251,6 +249,8 @@ struct amdgpu_ring {
|
||||
bool has_compute_vm_bug;
|
||||
bool no_scheduler;
|
||||
int hw_prio;
|
||||
unsigned num_hw_submission;
|
||||
atomic_t *sched_score;
|
||||
};
|
||||
|
||||
#define amdgpu_ring_parse_cs(r, p, ib) ((r)->funcs->parse_cs((p), (ib)))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -87,71 +87,35 @@ uint64_t amdgpu_sdma_get_csa_mc_addr(struct amdgpu_ring *ring,
|
||||
}
|
||||
|
||||
int amdgpu_sdma_ras_late_init(struct amdgpu_device *adev,
|
||||
void *ras_ih_info)
|
||||
struct ras_common_if *ras_block)
|
||||
{
|
||||
int r, i;
|
||||
struct ras_ih_if *ih_info = (struct ras_ih_if *)ras_ih_info;
|
||||
struct ras_fs_if fs_info = {
|
||||
.sysfs_name = "sdma_err_count",
|
||||
};
|
||||
|
||||
if (!ih_info)
|
||||
return -EINVAL;
|
||||
|
||||
if (!adev->sdma.ras_if) {
|
||||
adev->sdma.ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
|
||||
if (!adev->sdma.ras_if)
|
||||
return -ENOMEM;
|
||||
adev->sdma.ras_if->block = AMDGPU_RAS_BLOCK__SDMA;
|
||||
adev->sdma.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
|
||||
adev->sdma.ras_if->sub_block_index = 0;
|
||||
}
|
||||
fs_info.head = ih_info->head = *adev->sdma.ras_if;
|
||||
|
||||
r = amdgpu_ras_late_init(adev, adev->sdma.ras_if,
|
||||
&fs_info, ih_info);
|
||||
r = amdgpu_ras_block_late_init(adev, ras_block);
|
||||
if (r)
|
||||
goto free;
|
||||
return r;
|
||||
|
||||
if (amdgpu_ras_is_supported(adev, adev->sdma.ras_if->block)) {
|
||||
if (amdgpu_ras_is_supported(adev, ras_block->block)) {
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
r = amdgpu_irq_get(adev, &adev->sdma.ecc_irq,
|
||||
AMDGPU_SDMA_IRQ_INSTANCE0 + i);
|
||||
if (r)
|
||||
goto late_fini;
|
||||
}
|
||||
} else {
|
||||
r = 0;
|
||||
goto free;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
late_fini:
|
||||
amdgpu_ras_late_fini(adev, adev->sdma.ras_if, ih_info);
|
||||
free:
|
||||
kfree(adev->sdma.ras_if);
|
||||
adev->sdma.ras_if = NULL;
|
||||
amdgpu_ras_block_late_fini(adev, ras_block);
|
||||
return r;
|
||||
}
|
||||
|
||||
void amdgpu_sdma_ras_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__SDMA) &&
|
||||
adev->sdma.ras_if) {
|
||||
struct ras_common_if *ras_if = adev->sdma.ras_if;
|
||||
struct ras_ih_if ih_info = {
|
||||
.head = *ras_if,
|
||||
/* the cb member will not be used by
|
||||
* amdgpu_ras_interrupt_remove_handler, init it only
|
||||
* to cheat the check in ras_late_fini
|
||||
*/
|
||||
.cb = amdgpu_sdma_process_ras_data_cb,
|
||||
};
|
||||
|
||||
amdgpu_ras_late_fini(adev, ras_if, &ih_info);
|
||||
kfree(ras_if);
|
||||
}
|
||||
adev->sdma.ras_if)
|
||||
amdgpu_ras_block_late_fini(adev, adev->sdma.ras_if);
|
||||
}
|
||||
|
||||
int amdgpu_sdma_process_ras_data_cb(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;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -121,7 +117,7 @@ amdgpu_sdma_get_instance_from_ring(struct amdgpu_ring *ring);
|
||||
int amdgpu_sdma_get_index_from_ring(struct amdgpu_ring *ring, uint32_t *index);
|
||||
uint64_t amdgpu_sdma_get_csa_mc_addr(struct amdgpu_ring *ring, unsigned vmid);
|
||||
int amdgpu_sdma_ras_late_init(struct amdgpu_device *adev,
|
||||
void *ras_ih_info);
|
||||
struct ras_common_if *ras_block);
|
||||
void amdgpu_sdma_ras_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_sdma_process_ras_data_cb(struct amdgpu_device *adev,
|
||||
void *err_data,
|
||||
|
||||
@@ -261,10 +261,9 @@ int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync,
|
||||
|
||||
dma_resv_for_each_fence(&cursor, resv, true, f) {
|
||||
dma_fence_chain_for_each(f, f) {
|
||||
struct dma_fence_chain *chain = to_dma_fence_chain(f);
|
||||
struct dma_fence *tmp = dma_fence_chain_contained(f);
|
||||
|
||||
if (amdgpu_sync_test_fence(adev, mode, owner, chain ?
|
||||
chain->fence : f)) {
|
||||
if (amdgpu_sync_test_fence(adev, mode, owner, tmp)) {
|
||||
r = amdgpu_sync_fence(sync, f);
|
||||
dma_fence_put(f);
|
||||
if (r)
|
||||
|
||||
@@ -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)) {
|
||||
@@ -1884,27 +1941,59 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
|
||||
size = adev->gmc.real_vram_size;
|
||||
else
|
||||
size = adev->gmc.visible_vram_size;
|
||||
man->size = size >> PAGE_SHIFT;
|
||||
man->size = size;
|
||||
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
|
||||
|
||||
@@ -44,7 +44,6 @@ struct amdgpu_vram_mgr {
|
||||
spinlock_t lock;
|
||||
struct list_head reservations_pending;
|
||||
struct list_head reserved_pages;
|
||||
atomic64_t usage;
|
||||
atomic64_t vis_usage;
|
||||
};
|
||||
|
||||
@@ -52,12 +51,6 @@ struct amdgpu_gtt_mgr {
|
||||
struct ttm_resource_manager manager;
|
||||
struct drm_mm mm;
|
||||
spinlock_t lock;
|
||||
atomic64_t used;
|
||||
};
|
||||
|
||||
struct amdgpu_preempt_mgr {
|
||||
struct ttm_resource_manager manager;
|
||||
atomic64_t used;
|
||||
};
|
||||
|
||||
struct amdgpu_mman {
|
||||
@@ -76,7 +69,7 @@ struct amdgpu_mman {
|
||||
|
||||
struct amdgpu_vram_mgr vram_mgr;
|
||||
struct amdgpu_gtt_mgr gtt_mgr;
|
||||
struct amdgpu_preempt_mgr preempt_mgr;
|
||||
struct ttm_resource_manager preempt_mgr;
|
||||
|
||||
uint64_t stolen_vga_size;
|
||||
struct amdgpu_bo *stolen_vga_memory;
|
||||
@@ -98,6 +91,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 {
|
||||
@@ -114,8 +111,7 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev);
|
||||
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);
|
||||
|
||||
@@ -129,7 +125,6 @@ int amdgpu_vram_mgr_alloc_sgt(struct amdgpu_device *adev,
|
||||
void amdgpu_vram_mgr_free_sgt(struct device *dev,
|
||||
enum dma_data_direction dir,
|
||||
struct sg_table *sgt);
|
||||
uint64_t amdgpu_vram_mgr_usage(struct amdgpu_vram_mgr *mgr);
|
||||
uint64_t amdgpu_vram_mgr_vis_usage(struct amdgpu_vram_mgr *mgr);
|
||||
int amdgpu_vram_mgr_reserve_range(struct amdgpu_vram_mgr *mgr,
|
||||
uint64_t start, uint64_t size);
|
||||
@@ -158,7 +153,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 +172,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)
|
||||
@@ -130,76 +129,44 @@ int amdgpu_umc_poison_handler(struct amdgpu_device *adev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev,
|
||||
int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev,
|
||||
void *ras_error_status,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
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, struct ras_common_if *ras_block)
|
||||
{
|
||||
int r;
|
||||
struct ras_fs_if fs_info = {
|
||||
.sysfs_name = "umc_err_count",
|
||||
};
|
||||
struct ras_ih_if ih_info = {
|
||||
.cb = amdgpu_umc_process_ras_data_cb,
|
||||
};
|
||||
|
||||
if (!adev->umc.ras_if) {
|
||||
adev->umc.ras_if =
|
||||
kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
|
||||
if (!adev->umc.ras_if)
|
||||
return -ENOMEM;
|
||||
adev->umc.ras_if->block = AMDGPU_RAS_BLOCK__UMC;
|
||||
adev->umc.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
|
||||
adev->umc.ras_if->sub_block_index = 0;
|
||||
}
|
||||
ih_info.head = fs_info.head = *adev->umc.ras_if;
|
||||
|
||||
r = amdgpu_ras_late_init(adev, adev->umc.ras_if,
|
||||
&fs_info, &ih_info);
|
||||
r = amdgpu_ras_block_late_init(adev, ras_block);
|
||||
if (r)
|
||||
goto free;
|
||||
return r;
|
||||
|
||||
if (amdgpu_ras_is_supported(adev, adev->umc.ras_if->block)) {
|
||||
if (amdgpu_ras_is_supported(adev, ras_block->block)) {
|
||||
r = amdgpu_irq_get(adev, &adev->gmc.ecc_irq, 0);
|
||||
if (r)
|
||||
goto late_fini;
|
||||
} else {
|
||||
r = 0;
|
||||
goto free;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
late_fini:
|
||||
amdgpu_ras_late_fini(adev, adev->umc.ras_if, &ih_info);
|
||||
free:
|
||||
kfree(adev->umc.ras_if);
|
||||
adev->umc.ras_if = NULL;
|
||||
amdgpu_ras_block_late_fini(adev, ras_block);
|
||||
return r;
|
||||
}
|
||||
|
||||
void amdgpu_umc_ras_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC) &&
|
||||
adev->umc.ras_if) {
|
||||
struct ras_common_if *ras_if = adev->umc.ras_if;
|
||||
struct ras_ih_if ih_info = {
|
||||
.head = *ras_if,
|
||||
.cb = amdgpu_umc_process_ras_data_cb,
|
||||
};
|
||||
|
||||
amdgpu_ras_late_fini(adev, ras_if, &ih_info);
|
||||
kfree(ras_if);
|
||||
}
|
||||
adev->umc.ras_if)
|
||||
amdgpu_ras_block_late_fini(adev, adev->umc.ras_if);
|
||||
}
|
||||
|
||||
int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev,
|
||||
@@ -219,3 +186,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, struct ras_common_if *ras_block);
|
||||
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,13 @@ 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);
|
||||
|
||||
int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev,
|
||||
void *ras_error_status,
|
||||
struct amdgpu_iv_entry *entry);
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
@@ -575,8 +575,10 @@ static int amdgpu_virt_write_vf2pf_data(struct amdgpu_device *adev)
|
||||
vf2pf_info->driver_cert = 0;
|
||||
vf2pf_info->os_info.all = 0;
|
||||
|
||||
vf2pf_info->fb_usage = amdgpu_vram_mgr_usage(&adev->mman.vram_mgr) >> 20;
|
||||
vf2pf_info->fb_vis_usage = amdgpu_vram_mgr_vis_usage(&adev->mman.vram_mgr) >> 20;
|
||||
vf2pf_info->fb_usage =
|
||||
ttm_resource_manager_usage(&adev->mman.vram_mgr.manager) >> 20;
|
||||
vf2pf_info->fb_vis_usage =
|
||||
amdgpu_vram_mgr_vis_usage(&adev->mman.vram_mgr) >> 20;
|
||||
vf2pf_info->fb_size = adev->gmc.real_vram_size >> 20;
|
||||
vf2pf_info->fb_vis_size = adev->gmc.visible_vram_size >> 20;
|
||||
|
||||
@@ -820,3 +822,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) && write) {
|
||||
*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 & AMDGPU_RLCG_SCRATCH1_ADDRESS_MASK))
|
||||
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,19 @@
|
||||
#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
|
||||
|
||||
#define AMDGPU_RLCG_SCRATCH1_ADDRESS_MASK 0xFFFFF
|
||||
|
||||
/* all asic after AI use this offset */
|
||||
#define mmRCC_IOV_FUNC_IDENTIFIER 0xDE5
|
||||
/* tonga/fiji use this offset */
|
||||
@@ -275,13 +288,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 +311,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 +338,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,
|
||||
|
||||
@@ -96,9 +96,9 @@ static ssize_t amdgpu_mem_info_vram_used_show(struct device *dev,
|
||||
{
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
struct ttm_resource_manager *man = &adev->mman.vram_mgr.manager;
|
||||
|
||||
return sysfs_emit(buf, "%llu\n",
|
||||
amdgpu_vram_mgr_usage(&adev->mman.vram_mgr));
|
||||
return sysfs_emit(buf, "%llu\n", ttm_resource_manager_usage(man));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -253,7 +253,9 @@ static void amdgpu_vram_mgr_do_reserve(struct ttm_resource_manager *man)
|
||||
|
||||
vis_usage = amdgpu_vram_mgr_vis_size(adev, &rsv->mm_node);
|
||||
atomic64_add(vis_usage, &mgr->vis_usage);
|
||||
atomic64_add(rsv->mm_node.size << PAGE_SHIFT, &mgr->usage);
|
||||
spin_lock(&man->bdev->lru_lock);
|
||||
man->usage += rsv->mm_node.size << PAGE_SHIFT;
|
||||
spin_unlock(&man->bdev->lru_lock);
|
||||
list_move(&rsv->node, &mgr->reserved_pages);
|
||||
}
|
||||
}
|
||||
@@ -281,7 +283,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);
|
||||
|
||||
@@ -378,19 +380,13 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
|
||||
|
||||
lpfn = place->lpfn;
|
||||
if (!lpfn)
|
||||
lpfn = man->size;
|
||||
lpfn = man->size >> PAGE_SHIFT;
|
||||
|
||||
max_bytes = adev->gmc.mc_vram_size;
|
||||
if (tbo->type != ttm_bo_type_kernel)
|
||||
max_bytes -= AMDGPU_VM_RESERVED_VRAM;
|
||||
|
||||
/* bail out quickly if there's likely not enough VRAM for this BO */
|
||||
mem_bytes = tbo->base.size;
|
||||
if (atomic64_add_return(mem_bytes, &mgr->usage) > max_bytes) {
|
||||
r = -ENOSPC;
|
||||
goto error_sub;
|
||||
}
|
||||
|
||||
if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
|
||||
pages_per_node = ~0ul;
|
||||
num_nodes = 1;
|
||||
@@ -408,13 +404,17 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
|
||||
|
||||
node = kvmalloc(struct_size(node, mm_nodes, num_nodes),
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!node) {
|
||||
r = -ENOMEM;
|
||||
goto error_sub;
|
||||
}
|
||||
if (!node)
|
||||
return -ENOMEM;
|
||||
|
||||
ttm_resource_init(tbo, place, &node->base);
|
||||
|
||||
/* bail out quickly if there's likely not enough VRAM for this BO */
|
||||
if (ttm_resource_manager_usage(man) > max_bytes) {
|
||||
r = -ENOSPC;
|
||||
goto error_fini;
|
||||
}
|
||||
|
||||
mode = DRM_MM_INSERT_BEST;
|
||||
if (place->flags & TTM_PL_FLAG_TOPDOWN)
|
||||
mode = DRM_MM_INSERT_HIGH;
|
||||
@@ -472,11 +472,10 @@ error_free:
|
||||
while (i--)
|
||||
drm_mm_remove_node(&node->mm_nodes[i]);
|
||||
spin_unlock(&mgr->lock);
|
||||
error_fini:
|
||||
ttm_resource_fini(man, &node->base);
|
||||
kvfree(node);
|
||||
|
||||
error_sub:
|
||||
atomic64_sub(mem_bytes, &mgr->usage);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -494,7 +493,7 @@ static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man,
|
||||
struct ttm_range_mgr_node *node = to_ttm_range_mgr_node(res);
|
||||
struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
|
||||
struct amdgpu_device *adev = to_amdgpu_device(mgr);
|
||||
uint64_t usage = 0, vis_usage = 0;
|
||||
uint64_t vis_usage = 0;
|
||||
unsigned i, pages;
|
||||
|
||||
spin_lock(&mgr->lock);
|
||||
@@ -503,13 +502,11 @@ static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man,
|
||||
struct drm_mm_node *mm = &node->mm_nodes[i];
|
||||
|
||||
drm_mm_remove_node(mm);
|
||||
usage += mm->size << PAGE_SHIFT;
|
||||
vis_usage += amdgpu_vram_mgr_vis_size(adev, mm);
|
||||
}
|
||||
amdgpu_vram_mgr_do_reserve(man);
|
||||
spin_unlock(&mgr->lock);
|
||||
|
||||
atomic64_sub(usage, &mgr->usage);
|
||||
atomic64_sub(vis_usage, &mgr->vis_usage);
|
||||
|
||||
ttm_resource_fini(man, res);
|
||||
@@ -627,18 +624,6 @@ void amdgpu_vram_mgr_free_sgt(struct device *dev,
|
||||
kfree(sgt);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_vram_mgr_usage - how many bytes are used in this domain
|
||||
*
|
||||
* @mgr: amdgpu_vram_mgr pointer
|
||||
*
|
||||
* Returns how many bytes are used in this domain.
|
||||
*/
|
||||
uint64_t amdgpu_vram_mgr_usage(struct amdgpu_vram_mgr *mgr)
|
||||
{
|
||||
return atomic64_read(&mgr->usage);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_vram_mgr_vis_usage - how many bytes are used in the visible part
|
||||
*
|
||||
@@ -664,13 +649,12 @@ static void amdgpu_vram_mgr_debug(struct ttm_resource_manager *man,
|
||||
{
|
||||
struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
|
||||
|
||||
drm_printf(printer, " vis usage:%llu\n",
|
||||
amdgpu_vram_mgr_vis_usage(mgr));
|
||||
|
||||
spin_lock(&mgr->lock);
|
||||
drm_mm_print(&mgr->mm, printer);
|
||||
spin_unlock(&mgr->lock);
|
||||
|
||||
drm_printf(printer, "man size:%llu pages, ram usage:%lluMB, vis usage:%lluMB\n",
|
||||
man->size, amdgpu_vram_mgr_usage(mgr) >> 20,
|
||||
amdgpu_vram_mgr_vis_usage(mgr) >> 20);
|
||||
}
|
||||
|
||||
static const struct ttm_resource_manager_func amdgpu_vram_mgr_func = {
|
||||
@@ -692,11 +676,11 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev)
|
||||
struct ttm_resource_manager *man = &mgr->manager;
|
||||
|
||||
ttm_resource_manager_init(man, &adev->mman.bdev,
|
||||
adev->gmc.real_vram_size >> PAGE_SHIFT);
|
||||
adev->gmc.real_vram_size);
|
||||
|
||||
man->func = &amdgpu_vram_mgr_func;
|
||||
|
||||
drm_mm_init(&mgr->mm, 0, man->size);
|
||||
drm_mm_init(&mgr->mm, 0, man->size >> PAGE_SHIFT);
|
||||
spin_lock_init(&mgr->lock);
|
||||
INIT_LIST_HEAD(&mgr->reservations_pending);
|
||||
INIT_LIST_HEAD(&mgr->reserved_pages);
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include "wafl/wafl2_4_0_0_smn.h"
|
||||
#include "wafl/wafl2_4_0_0_sh_mask.h"
|
||||
|
||||
#include "amdgpu_reset.h"
|
||||
|
||||
#define smnPCS_XGMI23_PCS_ERROR_STATUS 0x11a01210
|
||||
#define smnPCS_XGMI3X16_PCS_ERROR_STATUS 0x11a0020c
|
||||
#define smnPCS_GOPX1_PCS_ERROR_STATUS 0x12200210
|
||||
@@ -227,6 +229,9 @@ static void amdgpu_xgmi_hive_release(struct kobject *kobj)
|
||||
struct amdgpu_hive_info *hive = container_of(
|
||||
kobj, struct amdgpu_hive_info, kobj);
|
||||
|
||||
amdgpu_reset_put_reset_domain(hive->reset_domain);
|
||||
hive->reset_domain = NULL;
|
||||
|
||||
mutex_destroy(&hive->hive_lock);
|
||||
kfree(hive);
|
||||
}
|
||||
@@ -398,15 +403,35 @@ struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev)
|
||||
goto pro_end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Avoid recreating reset domain when hive is reconstructed for the case
|
||||
* of reset the devices in the XGMI hive during probe for SRIOV
|
||||
* See https://www.spinics.net/lists/amd-gfx/msg58836.html
|
||||
*/
|
||||
if (adev->reset_domain->type != XGMI_HIVE) {
|
||||
hive->reset_domain = amdgpu_reset_create_reset_domain(XGMI_HIVE, "amdgpu-reset-hive");
|
||||
if (!hive->reset_domain) {
|
||||
dev_err(adev->dev, "XGMI: failed initializing reset domain for xgmi hive\n");
|
||||
ret = -ENOMEM;
|
||||
kobject_put(&hive->kobj);
|
||||
kfree(hive);
|
||||
hive = NULL;
|
||||
goto pro_end;
|
||||
}
|
||||
} else {
|
||||
amdgpu_reset_get_reset_domain(adev->reset_domain);
|
||||
hive->reset_domain = adev->reset_domain;
|
||||
}
|
||||
|
||||
hive->hive_id = adev->gmc.xgmi.hive_id;
|
||||
INIT_LIST_HEAD(&hive->device_list);
|
||||
INIT_LIST_HEAD(&hive->node);
|
||||
mutex_init(&hive->hive_lock);
|
||||
atomic_set(&hive->in_reset, 0);
|
||||
atomic_set(&hive->number_devices, 0);
|
||||
task_barrier_init(&hive->tb);
|
||||
hive->pstate = AMDGPU_XGMI_PSTATE_UNKNOWN;
|
||||
hive->hi_req_gpu = NULL;
|
||||
|
||||
/*
|
||||
* hive pstate on boot is high in vega20 so we have to go to low
|
||||
* pstate on after boot.
|
||||
@@ -732,53 +757,22 @@ 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, struct ras_common_if *ras_block)
|
||||
{
|
||||
int r;
|
||||
struct ras_ih_if ih_info = {
|
||||
.cb = NULL,
|
||||
};
|
||||
struct ras_fs_if fs_info = {
|
||||
.sysfs_name = "xgmi_wafl_err_count",
|
||||
};
|
||||
|
||||
if (!adev->gmc.xgmi.supported ||
|
||||
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);
|
||||
if (!adev->gmc.xgmi.ras_if)
|
||||
return -ENOMEM;
|
||||
adev->gmc.xgmi.ras_if->block = AMDGPU_RAS_BLOCK__XGMI_WAFL;
|
||||
adev->gmc.xgmi.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
|
||||
adev->gmc.xgmi.ras_if->sub_block_index = 0;
|
||||
}
|
||||
ih_info.head = fs_info.head = *adev->gmc.xgmi.ras_if;
|
||||
r = amdgpu_ras_late_init(adev, adev->gmc.xgmi.ras_if,
|
||||
&fs_info, &ih_info);
|
||||
if (r || !amdgpu_ras_is_supported(adev, adev->gmc.xgmi.ras_if->block)) {
|
||||
kfree(adev->gmc.xgmi.ras_if);
|
||||
adev->gmc.xgmi.ras_if = NULL;
|
||||
}
|
||||
|
||||
return r;
|
||||
return amdgpu_ras_block_late_init(adev, ras_block);
|
||||
}
|
||||
|
||||
static void amdgpu_xgmi_ras_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__XGMI_WAFL) &&
|
||||
adev->gmc.xgmi.ras_if) {
|
||||
struct ras_common_if *ras_if = adev->gmc.xgmi.ras_if;
|
||||
struct ras_ih_if ih_info = {
|
||||
.cb = NULL,
|
||||
};
|
||||
|
||||
amdgpu_ras_late_fini(adev, ras_if, &ih_info);
|
||||
kfree(ras_if);
|
||||
}
|
||||
adev->gmc.xgmi.ras_if)
|
||||
amdgpu_ras_block_late_fini(adev, adev->gmc.xgmi.ras_if);
|
||||
}
|
||||
|
||||
uint64_t amdgpu_xgmi_get_relative_phy_addr(struct amdgpu_device *adev,
|
||||
@@ -865,7 +859,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 +868,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 +934,54 @@ 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 = {
|
||||
.ras_comm = {
|
||||
.name = "xgmi_wafl",
|
||||
.block = AMDGPU_RAS_BLOCK__XGMI_WAFL,
|
||||
.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
|
||||
},
|
||||
.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;
|
||||
@@ -33,7 +33,6 @@ struct amdgpu_hive_info {
|
||||
struct list_head node;
|
||||
atomic_t number_devices;
|
||||
struct mutex hive_lock;
|
||||
atomic_t in_reset;
|
||||
int hi_req_count;
|
||||
struct amdgpu_device *hi_req_gpu;
|
||||
struct task_barrier tb;
|
||||
@@ -42,6 +41,8 @@ struct amdgpu_hive_info {
|
||||
AMDGPU_XGMI_PSTATE_MAX_VEGA20,
|
||||
AMDGPU_XGMI_PSTATE_UNKNOWN
|
||||
} pstate;
|
||||
|
||||
struct amdgpu_reset_domain *reset_domain;
|
||||
};
|
||||
|
||||
struct amdgpu_pcs_ras_field {
|
||||
@@ -50,7 +51,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;
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <drm/drm_util.h>
|
||||
@@ -740,7 +742,7 @@ static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg)
|
||||
break;
|
||||
}
|
||||
if (arg != ATOM_COND_ALWAYS)
|
||||
SDEBUG(" taken: %s\n", execute ? "yes" : "no");
|
||||
SDEBUG(" taken: %s\n", str_yes_no(execute));
|
||||
SDEBUG(" target: 0x%04X\n", target);
|
||||
if (execute) {
|
||||
if (ctx->last_jump == (ctx->start + target)) {
|
||||
|
||||
@@ -1719,7 +1719,7 @@ static void cik_program_aspm(struct amdgpu_device *adev)
|
||||
bool disable_l0s = false, disable_l1 = false, disable_plloff_in_l1 = false;
|
||||
bool disable_clkreq = false;
|
||||
|
||||
if (amdgpu_aspm == 0)
|
||||
if (!amdgpu_device_should_use_aspm(adev))
|
||||
return;
|
||||
|
||||
if (pci_is_root_bus(adev->pdev->bus))
|
||||
|
||||
@@ -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)
|
||||
@@ -2798,6 +2798,8 @@ static int dce_v10_0_sw_init(void *handle)
|
||||
adev_to_drm(adev)->mode_config.preferred_depth = 24;
|
||||
adev_to_drm(adev)->mode_config.prefer_shadow = 1;
|
||||
|
||||
adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
|
||||
|
||||
adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
|
||||
|
||||
r = amdgpu_display_modeset_create_props(adev);
|
||||
|
||||
@@ -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)
|
||||
@@ -2916,6 +2916,8 @@ static int dce_v11_0_sw_init(void *handle)
|
||||
adev_to_drm(adev)->mode_config.preferred_depth = 24;
|
||||
adev_to_drm(adev)->mode_config.prefer_shadow = 1;
|
||||
|
||||
adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
|
||||
|
||||
adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
|
||||
|
||||
r = amdgpu_display_modeset_create_props(adev);
|
||||
|
||||
@@ -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)
|
||||
@@ -2674,6 +2674,7 @@ static int dce_v6_0_sw_init(void *handle)
|
||||
adev_to_drm(adev)->mode_config.max_height = 16384;
|
||||
adev_to_drm(adev)->mode_config.preferred_depth = 24;
|
||||
adev_to_drm(adev)->mode_config.prefer_shadow = 1;
|
||||
adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
|
||||
adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
|
||||
|
||||
r = amdgpu_display_modeset_create_props(adev);
|
||||
|
||||
@@ -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)
|
||||
@@ -2695,6 +2695,8 @@ static int dce_v8_0_sw_init(void *handle)
|
||||
adev_to_drm(adev)->mode_config.preferred_depth = 24;
|
||||
adev_to_drm(adev)->mode_config.prefer_shadow = 1;
|
||||
|
||||
adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
|
||||
|
||||
adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
|
||||
|
||||
r = amdgpu_display_modeset_create_props(adev);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -110,6 +106,12 @@
|
||||
#define mmGOLDEN_TSC_COUNT_UPPER_Vangogh_BASE_IDX 1
|
||||
#define mmGOLDEN_TSC_COUNT_LOWER_Vangogh 0x0026
|
||||
#define mmGOLDEN_TSC_COUNT_LOWER_Vangogh_BASE_IDX 1
|
||||
|
||||
#define mmGOLDEN_TSC_COUNT_UPPER_GC_10_3_6 0x002d
|
||||
#define mmGOLDEN_TSC_COUNT_UPPER_GC_10_3_6_BASE_IDX 1
|
||||
#define mmGOLDEN_TSC_COUNT_LOWER_GC_10_3_6 0x002e
|
||||
#define mmGOLDEN_TSC_COUNT_LOWER_GC_10_3_6_BASE_IDX 1
|
||||
|
||||
#define mmSPI_CONFIG_CNTL_1_Vangogh 0x2441
|
||||
#define mmSPI_CONFIG_CNTL_1_Vangogh_BASE_IDX 1
|
||||
#define mmVGT_TF_MEMORY_BASE_HI_Vangogh 0x2261
|
||||
@@ -180,14 +182,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");
|
||||
@@ -270,6 +264,20 @@ MODULE_FIRMWARE("amdgpu/cyan_skillfish2_mec.bin");
|
||||
MODULE_FIRMWARE("amdgpu/cyan_skillfish2_mec2.bin");
|
||||
MODULE_FIRMWARE("amdgpu/cyan_skillfish2_rlc.bin");
|
||||
|
||||
MODULE_FIRMWARE("amdgpu/gc_10_3_6_ce.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_10_3_6_pfp.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_10_3_6_me.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_10_3_6_mec.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_10_3_6_mec2.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_10_3_6_rlc.bin");
|
||||
|
||||
MODULE_FIRMWARE("amdgpu/gc_10_3_7_ce.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_10_3_7_pfp.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_10_3_7_me.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_10_3_7_mec.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_10_3_7_mec2.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_10_3_7_rlc.bin");
|
||||
|
||||
static const struct soc15_reg_golden golden_settings_gc_10_1[] =
|
||||
{
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_4, 0xffffffff, 0x00400014),
|
||||
@@ -1463,143 +1471,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 */
|
||||
@@ -3557,6 +3428,57 @@ static const struct soc15_reg_golden golden_settings_gc_10_0_cyan_skillfish[] =
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0x00800000, 0x00800000)
|
||||
};
|
||||
|
||||
static const struct soc15_reg_golden golden_settings_gc_10_3_6[] =
|
||||
{
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_CS_CLK_CTRL, 0xff7f0fff, 0x78000100),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCH_PIPE_STEER, 0x000000ff, 0x00000044),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCPF_GCR_CNTL, 0x0007ffff, 0x0000c200),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG3, 0xffffffff, 0x00000280),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG4, 0xffffffff, 0x00800000),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGB_ADDR_CONFIG, 0x0c1807ff, 0x00000042),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCR_GENERAL_CNTL, 0x1ff1ffff, 0x00000500),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL1_PIPE_STEER, 0x000000ff, 0x00000044),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2_PIPE_STEER_0, 0x77777777, 0x32103210),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2_PIPE_STEER_1, 0x77777777, 0x32103210),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2A_ADDR_MATCH_MASK, 0xffffffff, 0xfffffff3),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_ADDR_MATCH_MASK, 0xffffffff, 0xfffffff3),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CM_CTRL1, 0xff8fff0f, 0x580f1008),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL3, 0xf7ffffff, 0x00f80988),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmLDS_CONFIG, 0x000001ff, 0x00000020),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_CL_ENHANCE, 0xf17fffff, 0x01200007),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_BINNER_TIMEOUT_COUNTER, 0xffffffff, 0x00000800),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_2, 0xffffffbf, 0x00000820),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQG_CONFIG, 0x000017ff, 0x00001000),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSX_DEBUG_1, 0xffffff7f, 0x00010020),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmTA_CNTL_AUX, 0xfff7ffff, 0x01030000),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffffffff, 0x00100000)
|
||||
};
|
||||
|
||||
static const struct soc15_reg_golden golden_settings_gc_10_3_7[] = {
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_CS_CLK_CTRL, 0xff7f0fff, 0x78000100),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCH_PIPE_STEER, 0x000000ff, 0x000000e4),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCPF_GCR_CNTL, 0x0007ffff, 0x0000c200),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG3, 0xffffffff, 0x00000280),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG4, 0xffffffff, 0x00800000),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGB_ADDR_CONFIG, 0x0c1807ff, 0x00000041),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCR_GENERAL_CNTL, 0x1ff1ffff, 0x00000500),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL1_PIPE_STEER, 0x000000ff, 0x000000e4),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2_PIPE_STEER_0, 0x77777777, 0x32103210),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2_PIPE_STEER_1, 0x77777777, 0x32103210),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2A_ADDR_MATCH_MASK, 0xffffffff, 0xffffffff),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_ADDR_MATCH_MASK, 0xffffffff, 0xffffffff),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CM_CTRL1, 0xff8fff0f, 0x580f1008),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL3, 0xf7ffffff, 0x00f80988),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmLDS_CONFIG, 0x000001ff, 0x00000020),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_CL_ENHANCE, 0xf000003f, 0x01200007),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_BINNER_TIMEOUT_COUNTER, 0xffffffff, 0x00000800),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_2, 0xffffffbf, 0x00000820),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQG_CONFIG, 0x000017ff, 0x00001000),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSX_DEBUG_1, 0xffffff7f, 0x00010020),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmTA_CNTL_AUX, 0xfff7ffff, 0x01030000),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffffffff, 0x00100000)
|
||||
};
|
||||
|
||||
#define DEFAULT_SH_MEM_CONFIG \
|
||||
((SH_MEM_ADDRESS_MODE_64 << SH_MEM_CONFIG__ADDRESS_MODE__SHIFT) | \
|
||||
(SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | \
|
||||
@@ -3790,10 +3712,21 @@ 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));
|
||||
break;
|
||||
case IP_VERSION(10, 3, 6):
|
||||
soc15_program_register_sequence(adev,
|
||||
golden_settings_gc_10_3_6,
|
||||
(const u32)ARRAY_SIZE(golden_settings_gc_10_3_6));
|
||||
break;
|
||||
case IP_VERSION(10, 3, 7):
|
||||
soc15_program_register_sequence(adev,
|
||||
golden_settings_gc_10_3_7,
|
||||
(const u32)ARRAY_SIZE(golden_settings_gc_10_3_7));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -3968,6 +3901,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) &&
|
||||
@@ -3981,7 +3915,9 @@ static void gfx_v10_0_check_fw_write_wait(struct amdgpu_device *adev)
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
adev->gfx.cp_fw_write_wait = true;
|
||||
break;
|
||||
default:
|
||||
@@ -4102,12 +4038,19 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
|
||||
case IP_VERSION(10, 3, 3):
|
||||
chip_name = "yellow_carp";
|
||||
break;
|
||||
case IP_VERSION(10, 3, 6):
|
||||
chip_name = "gc_10_3_6";
|
||||
break;
|
||||
case IP_VERSION(10, 1, 3):
|
||||
case IP_VERSION(10, 1, 4):
|
||||
if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2)
|
||||
chip_name = "cyan_skillfish2";
|
||||
else
|
||||
chip_name = "cyan_skillfish";
|
||||
break;
|
||||
case IP_VERSION(10, 3, 7):
|
||||
chip_name = "gc_10_3_7";
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
@@ -4448,6 +4391,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 +4435,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;
|
||||
}
|
||||
|
||||
@@ -4678,7 +4646,9 @@ static void gfx_v10_0_gpu_early_init(struct amdgpu_device *adev)
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
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;
|
||||
@@ -4689,6 +4659,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 +4772,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;
|
||||
@@ -4813,7 +4785,9 @@ static int gfx_v10_0_sw_init(void *handle)
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
adev->gfx.me.num_me = 1;
|
||||
adev->gfx.me.num_pipe_per_me = 1;
|
||||
adev->gfx.me.num_queue_per_pipe = 1;
|
||||
@@ -4865,10 +4839,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);
|
||||
@@ -5047,7 +5025,8 @@ static void gfx_v10_0_setup_rb(struct amdgpu_device *adev)
|
||||
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
|
||||
bitmap = i * adev->gfx.config.max_sh_per_se + j;
|
||||
if (((adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0)) ||
|
||||
(adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 3))) &&
|
||||
(adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 3)) ||
|
||||
(adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 6))) &&
|
||||
((gfx_v10_3_get_disabled_sa(adev) >> bitmap) & 1))
|
||||
continue;
|
||||
gfx_v10_0_select_se_sh(adev, i, j, 0xffffffff);
|
||||
@@ -6321,7 +6300,9 @@ static void gfx_v10_0_cp_gfx_set_doorbell(struct amdgpu_device *adev,
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
tmp = REG_SET_FIELD(0, CP_RB_DOORBELL_RANGE_LOWER,
|
||||
DOORBELL_RANGE_LOWER_Sienna_Cichlid, ring->doorbell_index);
|
||||
WREG32_SOC15(GC, 0, mmCP_RB_DOORBELL_RANGE_LOWER, tmp);
|
||||
@@ -6458,7 +6439,9 @@ static void gfx_v10_0_cp_compute_enable(struct amdgpu_device *adev, bool enable)
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
WREG32_SOC15(GC, 0, mmCP_MEC_CNTL_Sienna_Cichlid, 0);
|
||||
break;
|
||||
default:
|
||||
@@ -6472,7 +6455,9 @@ static void gfx_v10_0_cp_compute_enable(struct amdgpu_device *adev, bool enable)
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
WREG32_SOC15(GC, 0, mmCP_MEC_CNTL_Sienna_Cichlid,
|
||||
(CP_MEC_CNTL__MEC_ME1_HALT_MASK |
|
||||
CP_MEC_CNTL__MEC_ME2_HALT_MASK));
|
||||
@@ -6570,6 +6555,7 @@ static void gfx_v10_0_kiq_setting(struct amdgpu_ring *ring)
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
tmp = RREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS_Sienna_Cichlid);
|
||||
tmp &= 0xffffff00;
|
||||
@@ -7300,6 +7286,8 @@ static bool gfx_v10_0_check_grbm_cam_remapping(struct amdgpu_device *adev)
|
||||
break;
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
return true;
|
||||
default:
|
||||
data = RREG32_SOC15(GC, 0, mmVGT_ESGS_RING_SIZE);
|
||||
@@ -7334,7 +7322,9 @@ static void gfx_v10_0_setup_grbm_cam_remapping(struct amdgpu_device *adev)
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
/* mmVGT_TF_RING_SIZE_UMD -> mmVGT_TF_RING_SIZE */
|
||||
data = (SOC15_REG_OFFSET(GC, 0, mmVGT_TF_RING_SIZE_UMD) <<
|
||||
GRBM_CAM_DATA__CAM_ADDR__SHIFT) |
|
||||
@@ -7654,6 +7644,7 @@ static int gfx_v10_0_soft_reset(void *handle)
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
if (REG_GET_FIELD(tmp, GRBM_STATUS2, RLC_BUSY_Sienna_Cichlid))
|
||||
grbm_soft_reset = REG_SET_FIELD(grbm_soft_reset,
|
||||
@@ -7721,6 +7712,21 @@ static uint64_t gfx_v10_0_get_gpu_clock_counter(struct amdgpu_device *adev)
|
||||
preempt_enable();
|
||||
clock = clock_lo | (clock_hi << 32ULL);
|
||||
break;
|
||||
case IP_VERSION(10, 3, 6):
|
||||
preempt_disable();
|
||||
clock_hi = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_GC_10_3_6);
|
||||
clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_GC_10_3_6);
|
||||
hi_check = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_GC_10_3_6);
|
||||
/* The SMUIO TSC clock frequency is 100MHz, which sets 32-bit carry over
|
||||
* roughly every 42 seconds.
|
||||
*/
|
||||
if (hi_check != clock_hi) {
|
||||
clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_GC_10_3_6);
|
||||
clock_hi = hi_check;
|
||||
}
|
||||
preempt_enable();
|
||||
clock = clock_lo | (clock_hi << 32ULL);
|
||||
break;
|
||||
default:
|
||||
preempt_disable();
|
||||
clock_hi = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER);
|
||||
@@ -7778,6 +7784,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):
|
||||
@@ -7785,7 +7792,9 @@ static int gfx_v10_0_early_init(void *handle)
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
adev->gfx.num_gfx_rings = GFX10_NUM_GFX_RINGS_Sienna_Cichlid;
|
||||
break;
|
||||
default:
|
||||
@@ -7801,6 +7810,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;
|
||||
}
|
||||
|
||||
@@ -7843,6 +7855,7 @@ static void gfx_v10_0_set_safe_mode(struct amdgpu_device *adev)
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
WREG32_SOC15(GC, 0, mmRLC_SAFE_MODE_Sienna_Cichlid, data);
|
||||
|
||||
@@ -7879,6 +7892,7 @@ static void gfx_v10_0_unset_safe_mode(struct amdgpu_device *adev)
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
WREG32_SOC15(GC, 0, mmRLC_SAFE_MODE_Sienna_Cichlid, data);
|
||||
break;
|
||||
@@ -8333,6 +8347,7 @@ static void gfx_v10_cntl_power_gating(struct amdgpu_device *adev, bool enable)
|
||||
switch (adev->ip_versions[GC_HWIP][0]) {
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
data = 0x4E20 & RLC_PG_DELAY_3__CGCG_ACTIVE_BEFORE_CGPG_MASK_Vangogh;
|
||||
WREG32_SOC15(GC, 0, mmRLC_PG_DELAY_3, data);
|
||||
break;
|
||||
@@ -8377,8 +8392,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,
|
||||
};
|
||||
|
||||
@@ -8403,6 +8416,7 @@ static int gfx_v10_0_set_powergating_state(void *handle,
|
||||
break;
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
gfx_v10_cntl_pg(adev, enable);
|
||||
amdgpu_gfx_off_ctrl(adev, enable);
|
||||
break;
|
||||
@@ -8429,6 +8443,7 @@ static int gfx_v10_0_set_clockgating_state(void *handle,
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
gfx_v10_0_update_gfx_clock_gating(adev,
|
||||
state == AMD_CG_STATE_GATE);
|
||||
@@ -9537,11 +9552,14 @@ 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):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
adev->gfx.rlc.funcs = &gfx_v10_0_rlc_funcs;
|
||||
break;
|
||||
case IP_VERSION(10, 1, 2):
|
||||
@@ -9634,7 +9652,9 @@ static int gfx_v10_0_get_cu_info(struct amdgpu_device *adev,
|
||||
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
|
||||
bitmap = i * adev->gfx.config.max_sh_per_se + j;
|
||||
if (((adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0)) ||
|
||||
(adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 3))) &&
|
||||
(adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 3)) ||
|
||||
(adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 6)) ||
|
||||
(adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 7))) &&
|
||||
((gfx_v10_3_get_disabled_sa(adev) >> bitmap) & 1))
|
||||
continue;
|
||||
mask = 1;
|
||||
|
||||
@@ -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,31 @@ 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.ras_comm.name, "gfx");
|
||||
adev->gfx.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__GFX;
|
||||
adev->gfx.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
|
||||
adev->gfx.ras_if = &adev->gfx.ras->ras_block.ras_comm;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* If not defined special ras_cb function, use default ras_cb */
|
||||
if (!adev->gfx.ras->ras_block.ras_cb)
|
||||
adev->gfx.ras->ras_block.ras_cb = amdgpu_gfx_process_ras_data_cb;
|
||||
}
|
||||
|
||||
adev->gfx.config.gb_addr_config = gb_addr_config;
|
||||
|
||||
adev->gfx.config.gb_addr_config_fields.num_pipes = 1 <<
|
||||
@@ -2434,10 +2349,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 +2432,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 +4758,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 +4791,9 @@ 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 (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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,8 @@
|
||||
#include "athub_v2_0.h"
|
||||
#include "athub_v2_1.h"
|
||||
|
||||
#include "amdgpu_reset.h"
|
||||
|
||||
#if 0
|
||||
static const struct soc15_reg_golden golden_settings_navi10_hdp[] =
|
||||
{
|
||||
@@ -328,7 +330,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
||||
*/
|
||||
if (adev->gfx.kiq.ring.sched.ready &&
|
||||
(amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) &&
|
||||
down_read_trylock(&adev->reset_sem)) {
|
||||
down_read_trylock(&adev->reset_domain->sem)) {
|
||||
struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
|
||||
const unsigned eng = 17;
|
||||
u32 inv_req = hub->vmhub_funcs->get_invalidate_req(vmid, flush_type);
|
||||
@@ -338,7 +340,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
||||
amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req,
|
||||
1 << vmid);
|
||||
|
||||
up_read(&adev->reset_sem);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -664,11 +666,31 @@ 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.ras_comm.name, "umc");
|
||||
adev->umc.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__UMC;
|
||||
adev->umc.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
|
||||
adev->umc.ras_if = &adev->umc.ras->ras_block.ras_comm;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* If not defined special ras_cb function, use default ras_cb */
|
||||
if (!adev->umc.ras->ras_block.ras_cb)
|
||||
adev->umc.ras->ras_block.ras_cb = amdgpu_umc_process_ras_data_cb;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -677,6 +699,7 @@ static void gmc_v10_0_set_mmhub_funcs(struct amdgpu_device *adev)
|
||||
switch (adev->ip_versions[MMHUB_HWIP][0]) {
|
||||
case IP_VERSION(2, 3, 0):
|
||||
case IP_VERSION(2, 4, 0):
|
||||
case IP_VERSION(2, 4, 1):
|
||||
adev->mmhub.funcs = &mmhub_v2_3_funcs;
|
||||
break;
|
||||
default:
|
||||
@@ -693,7 +716,9 @@ static void gmc_v10_0_set_gfxhub_funcs(struct amdgpu_device *adev)
|
||||
case IP_VERSION(10, 3, 1):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
adev->gfxhub.funcs = &gfxhub_v2_1_funcs;
|
||||
break;
|
||||
default:
|
||||
@@ -705,6 +730,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 +746,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,12 +892,15 @@ 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):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
adev->num_vmhubs = 2;
|
||||
/*
|
||||
* To fulfill 4-level page support,
|
||||
@@ -986,14 +1019,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 +1045,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 +1067,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 +1170,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)
|
||||
|
||||
@@ -62,6 +62,8 @@
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_xgmi.h"
|
||||
|
||||
#include "amdgpu_reset.h"
|
||||
|
||||
/* add these here since we already include dce12 headers and these are for DCN */
|
||||
#define mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION 0x055d
|
||||
#define mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_BASE_IDX 2
|
||||
@@ -787,13 +789,13 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
||||
*/
|
||||
if (adev->gfx.kiq.ring.sched.ready &&
|
||||
(amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) &&
|
||||
down_read_trylock(&adev->reset_sem)) {
|
||||
down_read_trylock(&adev->reset_domain->sem)) {
|
||||
uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
|
||||
uint32_t ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
|
||||
|
||||
amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req,
|
||||
1 << vmid);
|
||||
up_read(&adev->reset_sem);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -900,7 +902,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
|
||||
if (amdgpu_in_reset(adev))
|
||||
return -EIO;
|
||||
|
||||
if (ring->sched.ready && down_read_trylock(&adev->reset_sem)) {
|
||||
if (ring->sched.ready && down_read_trylock(&adev->reset_domain->sem)) {
|
||||
/* Vega20+XGMI caches PTEs in TC and TLB. Add a
|
||||
* heavy-weight TLB flush (type 2), which flushes
|
||||
* both. Due to a race condition with concurrent
|
||||
@@ -927,7 +929,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
|
||||
if (r) {
|
||||
amdgpu_ring_undo(ring);
|
||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||
up_read(&adev->reset_sem);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
@@ -936,10 +938,10 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
|
||||
r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout);
|
||||
if (r < 1) {
|
||||
dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r);
|
||||
up_read(&adev->reset_sem);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
return -ETIME;
|
||||
}
|
||||
up_read(&adev->reset_sem);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1202,7 +1204,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 +1212,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 +1230,27 @@ 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.ras_comm.name, "umc");
|
||||
adev->umc.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__UMC;
|
||||
adev->umc.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
|
||||
adev->umc.ras_if = &adev->umc.ras->ras_block.ras_comm;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* If not defined special ras_cb function, use default ras_cb */
|
||||
if (!adev->umc.ras->ras_block.ras_cb)
|
||||
adev->umc.ras->ras_block.ras_cb = amdgpu_umc_process_ras_data_cb;
|
||||
}
|
||||
}
|
||||
|
||||
static void gmc_v9_0_set_mmhub_funcs(struct amdgpu_device *adev)
|
||||
@@ -1248,18 +1272,31 @@ 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.ras_comm.name, "mmhub");
|
||||
adev->mmhub.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__MMHUB;
|
||||
adev->mmhub.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
|
||||
adev->mmhub.ras_if = &adev->mmhub.ras->ras_block.ras_comm;
|
||||
|
||||
/* 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 +1306,9 @@ 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);
|
||||
adev->hdp.ras_if = &adev->hdp.ras->ras_block.ras_comm;
|
||||
}
|
||||
|
||||
static void gmc_v9_0_set_mca_funcs(struct amdgpu_device *adev)
|
||||
@@ -1287,6 +1326,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 +1356,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 +1386,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 +1796,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 +1813,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 +1820,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 +1855,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,23 @@ 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 = {
|
||||
.ras_comm = {
|
||||
.name = "hdp",
|
||||
.block = AMDGPU_RAS_BLOCK__HDP,
|
||||
.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
|
||||
},
|
||||
.hw_ops = &hdp_v4_0_ras_hw_ops,
|
||||
.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,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user