mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
amd-drm-next-6.12-2024-08-26:
amdgpu: - SDMA devcoredump support - DCN 4.0.1 updates - DC SUBVP fixes - Refactor OPP in DC - Refactor MMHUBBUB in DC - DC DML 2.1 updates - DC FAMS2 updates - RAS updates - GFX12 updates - VCN 4.0.3 updates - JPEG 4.0.3 updates - Enable wave kill (soft recovery) for compute queues - Clean up CP error interrupt handling - Enable CP bad opcode interrupts - VCN 4.x fixes - VCN 5.x fixes - GPU reset fixes - Fix vbios embedded EDID size handling - SMU 14.x updates - Misc code cleanups and spelling fixes - VCN devcoredump support - ISP MFD i2c support - DC vblank fixes - GFX 12 fixes - PSR fixes - Convert vbios embedded EDID to drm_edid - DCN 3.5 updates - DMCUB updates - Cursor fixes - Overdrive support for SMU 14.x - GFX CP padding optimizations - DCC fixes - DSC fixes - Preliminary per queue reset infrastructure - Initial per queue reset support for GFX 9 - Initial per queue reset support for GFX 7, 8 - DCN 3.2 fixes - DP MST fixes - SR-IOV fixes - GFX 9.4.3/4 devcoredump support - Add process isolation framework - Enable process isolation support for GFX 9.4.3/4 - Take IOMMU remapping into account for P2P DMA checks amdkfd: - CRIU fixes - Improved input validation for user queues - HMM fix - Enable process isolation support for GFX 9.4.3/4 - Initial per queue reset support for GFX 9 - Allow users to target recommended SDMA engines radeon: - remove .load and drm_dev_alloc - Fix vbios embedded EDID size handling - Convert vbios embedded EDID to drm_edid - Use GEM references instead of TTM - r100 cp init cleanup - Fix potential overflows in evergreen CS offset tracking UAPI: - KFD support for targetting queues on recommended SDMA engines Proposed userspace:2f588a2406
eb30a5bbc7
drm/buddy: - Add start address support for trim function -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCZszhcQAKCRC93/aFa7yZ 2M4ZAQD+xgIJkQ9HISQeqER5GblnfrorARd32yP/BH0c+JbGUAD9H/BIB41teZ80 vw2WTx+4TyB39awgvtpDH8iEQdkcSAE= =717w -----END PGP SIGNATURE----- Merge tag 'amd-drm-next-6.12-2024-08-26' of https://gitlab.freedesktop.org/agd5f/linux into drm-next amd-drm-next-6.12-2024-08-26: amdgpu: - SDMA devcoredump support - DCN 4.0.1 updates - DC SUBVP fixes - Refactor OPP in DC - Refactor MMHUBBUB in DC - DC DML 2.1 updates - DC FAMS2 updates - RAS updates - GFX12 updates - VCN 4.0.3 updates - JPEG 4.0.3 updates - Enable wave kill (soft recovery) for compute queues - Clean up CP error interrupt handling - Enable CP bad opcode interrupts - VCN 4.x fixes - VCN 5.x fixes - GPU reset fixes - Fix vbios embedded EDID size handling - SMU 14.x updates - Misc code cleanups and spelling fixes - VCN devcoredump support - ISP MFD i2c support - DC vblank fixes - GFX 12 fixes - PSR fixes - Convert vbios embedded EDID to drm_edid - DCN 3.5 updates - DMCUB updates - Cursor fixes - Overdrive support for SMU 14.x - GFX CP padding optimizations - DCC fixes - DSC fixes - Preliminary per queue reset infrastructure - Initial per queue reset support for GFX 9 - Initial per queue reset support for GFX 7, 8 - DCN 3.2 fixes - DP MST fixes - SR-IOV fixes - GFX 9.4.3/4 devcoredump support - Add process isolation framework - Enable process isolation support for GFX 9.4.3/4 - Take IOMMU remapping into account for P2P DMA checks amdkfd: - CRIU fixes - Improved input validation for user queues - HMM fix - Enable process isolation support for GFX 9.4.3/4 - Initial per queue reset support for GFX 9 - Allow users to target recommended SDMA engines radeon: - remove .load and drm_dev_alloc - Fix vbios embedded EDID size handling - Convert vbios embedded EDID to drm_edid - Use GEM references instead of TTM - r100 cp init cleanup - Fix potential overflows in evergreen CS offset tracking UAPI: - KFD support for targetting queues on recommended SDMA engines Proposed userspace:2f588a2406
eb30a5bbc7
drm/buddy: - Add start address support for trim function From: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240826201528.55307-1-alexander.deucher@amd.com
This commit is contained in:
commit
e55ef65510
@ -118,6 +118,8 @@
|
||||
|
||||
#define MAX_GPU_INSTANCE 64
|
||||
|
||||
#define GFX_SLICE_PERIOD msecs_to_jiffies(250)
|
||||
|
||||
struct amdgpu_gpu_instance {
|
||||
struct amdgpu_device *adev;
|
||||
int mgpu_fan_enabled;
|
||||
@ -347,9 +349,9 @@ enum amdgpu_kiq_irq {
|
||||
AMDGPU_CP_KIQ_IRQ_DRIVER0 = 0,
|
||||
AMDGPU_CP_KIQ_IRQ_LAST
|
||||
};
|
||||
#define SRIOV_USEC_TIMEOUT 1200000 /* wait 12 * 100ms for SRIOV */
|
||||
#define MAX_KIQ_REG_WAIT (amdgpu_sriov_vf(adev) ? 50000 : 5000) /* in usecs, extend for VF */
|
||||
#define MAX_KIQ_REG_BAILOUT_INTERVAL 5 /* in msecs, 5ms */
|
||||
#define SRIOV_USEC_TIMEOUT 1200000 /* wait 12 * 100ms for SRIOV */
|
||||
#define MAX_KIQ_REG_WAIT 5000 /* in usecs, 5ms */
|
||||
#define MAX_KIQ_REG_BAILOUT_INTERVAL 5 /* in msecs, 5ms */
|
||||
#define MAX_KIQ_REG_TRY 1000
|
||||
|
||||
int amdgpu_device_ip_set_clockgating_state(void *dev,
|
||||
@ -823,17 +825,6 @@ struct amdgpu_mqd {
|
||||
struct amdgpu_reset_domain;
|
||||
struct amdgpu_fru_info;
|
||||
|
||||
struct amdgpu_reset_info {
|
||||
/* reset dump register */
|
||||
u32 *reset_dump_reg_list;
|
||||
u32 *reset_dump_reg_value;
|
||||
int num_regs;
|
||||
|
||||
#ifdef CONFIG_DEV_COREDUMP
|
||||
struct amdgpu_coredump_info *coredump_info;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Non-zero (true) if the GPU has VRAM. Zero (false) otherwise.
|
||||
*/
|
||||
@ -1157,8 +1148,6 @@ struct amdgpu_device {
|
||||
|
||||
struct mutex benchmark_mutex;
|
||||
|
||||
struct amdgpu_reset_info reset_info;
|
||||
|
||||
bool scpm_enabled;
|
||||
uint32_t scpm_status;
|
||||
|
||||
@ -1175,6 +1164,10 @@ struct amdgpu_device {
|
||||
bool debug_disable_soft_recovery;
|
||||
bool debug_use_vram_fw_buf;
|
||||
bool debug_enable_ras_aca;
|
||||
|
||||
bool enforce_isolation[MAX_XCP];
|
||||
/* Added this mutex for cleaner shader isolation between GFX and compute processes */
|
||||
struct mutex enforce_isolation_mutex;
|
||||
};
|
||||
|
||||
static inline uint32_t amdgpu_ip_version(const struct amdgpu_device *adev,
|
||||
@ -1587,13 +1580,6 @@ static inline bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) { return
|
||||
static inline void amdgpu_choose_low_power_state(struct amdgpu_device *adev) { }
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC)
|
||||
int amdgpu_dm_display_resume(struct amdgpu_device *adev );
|
||||
#else
|
||||
static inline int amdgpu_dm_display_resume(struct amdgpu_device *adev) { return 0; }
|
||||
#endif
|
||||
|
||||
|
||||
void amdgpu_register_gpu_instance(struct amdgpu_device *adev);
|
||||
void amdgpu_unregister_gpu_instance(struct amdgpu_device *adev);
|
||||
|
||||
|
@ -80,6 +80,9 @@ static void aca_banks_release(struct aca_banks *banks)
|
||||
{
|
||||
struct aca_bank_node *node, *tmp;
|
||||
|
||||
if (list_empty(&banks->list))
|
||||
return;
|
||||
|
||||
list_for_each_entry_safe(node, tmp, &banks->list, node) {
|
||||
list_del(&node->node);
|
||||
kvfree(node);
|
||||
@ -453,13 +456,13 @@ static int aca_log_aca_error_data(struct aca_bank_error *bank_error, enum aca_er
|
||||
|
||||
switch (type) {
|
||||
case ACA_ERROR_TYPE_UE:
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, NULL, count);
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, count);
|
||||
break;
|
||||
case ACA_ERROR_TYPE_CE:
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, NULL, count);
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, count);
|
||||
break;
|
||||
case ACA_ERROR_TYPE_DEFERRED:
|
||||
amdgpu_ras_error_statistic_de_count(err_data, &mcm_info, NULL, count);
|
||||
amdgpu_ras_error_statistic_de_count(err_data, &mcm_info, count);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -562,9 +565,13 @@ static void aca_error_fini(struct aca_error *aerr)
|
||||
struct aca_bank_error *bank_error, *tmp;
|
||||
|
||||
mutex_lock(&aerr->lock);
|
||||
if (list_empty(&aerr->list))
|
||||
goto out_unlock;
|
||||
|
||||
list_for_each_entry_safe(bank_error, tmp, &aerr->list, node)
|
||||
aca_bank_error_remove(aerr, bank_error);
|
||||
|
||||
out_unlock:
|
||||
mutex_destroy(&aerr->lock);
|
||||
}
|
||||
|
||||
@ -680,6 +687,9 @@ static void aca_manager_fini(struct aca_handle_manager *mgr)
|
||||
{
|
||||
struct aca_handle *handle, *tmp;
|
||||
|
||||
if (list_empty(&mgr->list))
|
||||
return;
|
||||
|
||||
list_for_each_entry_safe(handle, tmp, &mgr->list, node)
|
||||
amdgpu_aca_remove_handle(handle);
|
||||
}
|
||||
|
@ -364,15 +364,15 @@ allocate_mem_reserve_bo_failed:
|
||||
return r;
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_free_gtt_mem(struct amdgpu_device *adev, void *mem_obj)
|
||||
void amdgpu_amdkfd_free_gtt_mem(struct amdgpu_device *adev, void **mem_obj)
|
||||
{
|
||||
struct amdgpu_bo *bo = (struct amdgpu_bo *) mem_obj;
|
||||
struct amdgpu_bo **bo = (struct amdgpu_bo **) mem_obj;
|
||||
|
||||
amdgpu_bo_reserve(bo, true);
|
||||
amdgpu_bo_kunmap(bo);
|
||||
amdgpu_bo_unpin(bo);
|
||||
amdgpu_bo_unreserve(bo);
|
||||
amdgpu_bo_unref(&(bo));
|
||||
amdgpu_bo_reserve(*bo, true);
|
||||
amdgpu_bo_kunmap(*bo);
|
||||
amdgpu_bo_unpin(*bo);
|
||||
amdgpu_bo_unreserve(*bo);
|
||||
amdgpu_bo_unref(bo);
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_alloc_gws(struct amdgpu_device *adev, size_t size,
|
||||
@ -783,22 +783,6 @@ int amdgpu_amdkfd_send_close_event_drain_irq(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev,
|
||||
int hub_inst, int hub_type)
|
||||
{
|
||||
if (!hub_type) {
|
||||
if (adev->gfxhub.funcs->query_utcl2_poison_status)
|
||||
return adev->gfxhub.funcs->query_utcl2_poison_status(adev, hub_inst);
|
||||
else
|
||||
return false;
|
||||
} else {
|
||||
if (adev->mmhub.funcs->query_utcl2_poison_status)
|
||||
return adev->mmhub.funcs->query_utcl2_poison_status(adev, hub_inst);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_check_and_lock_kfd(struct amdgpu_device *adev)
|
||||
{
|
||||
return kgd2kfd_check_and_lock_kfd();
|
||||
@ -887,3 +871,21 @@ free_ring_funcs:
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Stop scheduling on KFD */
|
||||
int amdgpu_amdkfd_stop_sched(struct amdgpu_device *adev, uint32_t node_id)
|
||||
{
|
||||
if (!adev->kfd.init_complete)
|
||||
return 0;
|
||||
|
||||
return kgd2kfd_stop_sched(adev->kfd.dev, node_id);
|
||||
}
|
||||
|
||||
/* Start scheduling on KFD */
|
||||
int amdgpu_amdkfd_start_sched(struct amdgpu_device *adev, uint32_t node_id)
|
||||
{
|
||||
if (!adev->kfd.init_complete)
|
||||
return 0;
|
||||
|
||||
return kgd2kfd_start_sched(adev->kfd.dev, node_id);
|
||||
}
|
||||
|
@ -235,7 +235,7 @@ int amdgpu_amdkfd_bo_validate_and_fence(struct amdgpu_bo *bo,
|
||||
int amdgpu_amdkfd_alloc_gtt_mem(struct amdgpu_device *adev, size_t size,
|
||||
void **mem_obj, uint64_t *gpu_addr,
|
||||
void **cpu_ptr, bool mqd_gfx9);
|
||||
void amdgpu_amdkfd_free_gtt_mem(struct amdgpu_device *adev, void *mem_obj);
|
||||
void amdgpu_amdkfd_free_gtt_mem(struct amdgpu_device *adev, void **mem_obj);
|
||||
int amdgpu_amdkfd_alloc_gws(struct amdgpu_device *adev, size_t size,
|
||||
void **mem_obj);
|
||||
void amdgpu_amdkfd_free_gws(struct amdgpu_device *adev, void *mem_obj);
|
||||
@ -264,6 +264,8 @@ int amdgpu_amdkfd_send_close_event_drain_irq(struct amdgpu_device *adev,
|
||||
uint32_t *payload);
|
||||
int amdgpu_amdkfd_unmap_hiq(struct amdgpu_device *adev, u32 doorbell_off,
|
||||
u32 inst);
|
||||
int amdgpu_amdkfd_start_sched(struct amdgpu_device *adev, uint32_t node_id);
|
||||
int amdgpu_amdkfd_stop_sched(struct amdgpu_device *adev, uint32_t node_id);
|
||||
|
||||
/* Read user wptr from a specified user address space with page fault
|
||||
* disabled. The memory must be pinned and mapped to the hardware when
|
||||
@ -322,7 +324,7 @@ int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_mem *mem,
|
||||
void **kptr, uint64_t *size);
|
||||
void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct kgd_mem *mem);
|
||||
|
||||
int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_bo *bo);
|
||||
int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_bo *bo, struct amdgpu_bo **bo_gart);
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info,
|
||||
struct dma_fence __rcu **ef);
|
||||
@ -345,11 +347,9 @@ void amdgpu_amdkfd_ras_pasid_poison_consumption_handler(struct amdgpu_device *ad
|
||||
pasid_notify pasid_fn, void *data, uint32_t reset);
|
||||
|
||||
bool amdgpu_amdkfd_is_fed(struct amdgpu_device *adev);
|
||||
bool amdgpu_amdkfd_bo_mapped_to_dev(struct amdgpu_device *adev, struct kgd_mem *mem);
|
||||
bool amdgpu_amdkfd_bo_mapped_to_dev(void *drm_priv, struct kgd_mem *mem);
|
||||
void amdgpu_amdkfd_block_mmu_notifications(void *p);
|
||||
int amdgpu_amdkfd_criu_resume(void *p);
|
||||
bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev,
|
||||
int hub_inst, int hub_type);
|
||||
int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
|
||||
uint64_t size, u32 alloc_flag, int8_t xcp_id);
|
||||
void amdgpu_amdkfd_unreserve_mem_limit(struct amdgpu_device *adev,
|
||||
@ -426,6 +426,8 @@ void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd);
|
||||
void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask);
|
||||
int kgd2kfd_check_and_lock_kfd(void);
|
||||
void kgd2kfd_unlock_kfd(void);
|
||||
int kgd2kfd_start_sched(struct kfd_dev *kfd, uint32_t node_id);
|
||||
int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id);
|
||||
#else
|
||||
static inline int kgd2kfd_init(void)
|
||||
{
|
||||
@ -496,5 +498,15 @@ static inline int kgd2kfd_check_and_lock_kfd(void)
|
||||
static inline void kgd2kfd_unlock_kfd(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int kgd2kfd_start_sched(struct kfd_dev *kfd, uint32_t node_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif /* AMDGPU_AMDKFD_H_INCLUDED */
|
||||
|
@ -191,4 +191,6 @@ const struct kfd2kgd_calls aldebaran_kfd2kgd = {
|
||||
.get_iq_wait_times = kgd_gfx_v9_get_iq_wait_times,
|
||||
.build_grace_period_packet_info = kgd_gfx_v9_build_grace_period_packet_info,
|
||||
.program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings,
|
||||
.hqd_get_pq_addr = kgd_gfx_v9_hqd_get_pq_addr,
|
||||
.hqd_reset = kgd_gfx_v9_hqd_reset,
|
||||
};
|
||||
|
@ -418,5 +418,7 @@ const struct kfd2kgd_calls arcturus_kfd2kgd = {
|
||||
.get_iq_wait_times = kgd_gfx_v9_get_iq_wait_times,
|
||||
.build_grace_period_packet_info = kgd_gfx_v9_build_grace_period_packet_info,
|
||||
.get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy,
|
||||
.program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings
|
||||
.program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings,
|
||||
.hqd_get_pq_addr = kgd_gfx_v9_hqd_get_pq_addr,
|
||||
.hqd_reset = kgd_gfx_v9_hqd_reset
|
||||
};
|
||||
|
@ -541,5 +541,7 @@ const struct kfd2kgd_calls gc_9_4_3_kfd2kgd = {
|
||||
kgd_gfx_v9_4_3_set_wave_launch_trap_override,
|
||||
.set_wave_launch_mode = kgd_aldebaran_set_wave_launch_mode,
|
||||
.set_address_watch = kgd_gfx_v9_4_3_set_address_watch,
|
||||
.clear_address_watch = kgd_gfx_v9_4_3_clear_address_watch
|
||||
.clear_address_watch = kgd_gfx_v9_4_3_clear_address_watch,
|
||||
.hqd_get_pq_addr = kgd_gfx_v9_hqd_get_pq_addr,
|
||||
.hqd_reset = kgd_gfx_v9_hqd_reset
|
||||
};
|
||||
|
@ -1070,6 +1070,20 @@ static void program_trap_handler_settings(struct amdgpu_device *adev,
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
uint64_t kgd_gfx_v10_hqd_get_pq_addr(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t inst)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t kgd_gfx_v10_hqd_reset(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t inst, unsigned int utimeout)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct kfd2kgd_calls gfx_v10_kfd2kgd = {
|
||||
.program_sh_mem_settings = kgd_program_sh_mem_settings,
|
||||
.set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping,
|
||||
@ -1097,4 +1111,6 @@ const struct kfd2kgd_calls gfx_v10_kfd2kgd = {
|
||||
.get_iq_wait_times = kgd_gfx_v10_get_iq_wait_times,
|
||||
.build_grace_period_packet_info = kgd_gfx_v10_build_grace_period_packet_info,
|
||||
.program_trap_handler_settings = program_trap_handler_settings,
|
||||
.hqd_get_pq_addr = kgd_gfx_v10_hqd_get_pq_addr,
|
||||
.hqd_reset = kgd_gfx_v10_hqd_reset
|
||||
};
|
||||
|
@ -56,3 +56,12 @@ void kgd_gfx_v10_build_grace_period_packet_info(struct amdgpu_device *adev,
|
||||
uint32_t grace_period,
|
||||
uint32_t *reg_offset,
|
||||
uint32_t *reg_data);
|
||||
uint64_t kgd_gfx_v10_hqd_get_pq_addr(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id,
|
||||
uint32_t queue_id,
|
||||
uint32_t inst);
|
||||
uint64_t kgd_gfx_v10_hqd_reset(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id,
|
||||
uint32_t queue_id,
|
||||
uint32_t inst,
|
||||
unsigned int utimeout);
|
||||
|
@ -680,5 +680,7 @@ const struct kfd2kgd_calls gfx_v10_3_kfd2kgd = {
|
||||
.set_wave_launch_trap_override = kgd_gfx_v10_set_wave_launch_trap_override,
|
||||
.set_wave_launch_mode = kgd_gfx_v10_set_wave_launch_mode,
|
||||
.set_address_watch = kgd_gfx_v10_set_address_watch,
|
||||
.clear_address_watch = kgd_gfx_v10_clear_address_watch
|
||||
.clear_address_watch = kgd_gfx_v10_clear_address_watch,
|
||||
.hqd_get_pq_addr = kgd_gfx_v10_hqd_get_pq_addr,
|
||||
.hqd_reset = kgd_gfx_v10_hqd_reset
|
||||
};
|
||||
|
@ -786,6 +786,20 @@ static uint32_t kgd_gfx_v11_clear_address_watch(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t kgd_gfx_v11_hqd_get_pq_addr(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t inst)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t kgd_gfx_v11_hqd_reset(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t inst, unsigned int utimeout)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct kfd2kgd_calls gfx_v11_kfd2kgd = {
|
||||
.program_sh_mem_settings = program_sh_mem_settings_v11,
|
||||
.set_pasid_vmid_mapping = set_pasid_vmid_mapping_v11,
|
||||
@ -808,5 +822,7 @@ const struct kfd2kgd_calls gfx_v11_kfd2kgd = {
|
||||
.set_wave_launch_trap_override = kgd_gfx_v11_set_wave_launch_trap_override,
|
||||
.set_wave_launch_mode = kgd_gfx_v11_set_wave_launch_mode,
|
||||
.set_address_watch = kgd_gfx_v11_set_address_watch,
|
||||
.clear_address_watch = kgd_gfx_v11_clear_address_watch
|
||||
.clear_address_watch = kgd_gfx_v11_clear_address_watch,
|
||||
.hqd_get_pq_addr = kgd_gfx_v11_hqd_get_pq_addr,
|
||||
.hqd_reset = kgd_gfx_v11_hqd_reset
|
||||
};
|
||||
|
@ -1144,6 +1144,105 @@ void kgd_gfx_v9_program_trap_handler_settings(struct amdgpu_device *adev,
|
||||
kgd_gfx_v9_unlock_srbm(adev, inst);
|
||||
}
|
||||
|
||||
uint64_t kgd_gfx_v9_hqd_get_pq_addr(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t inst)
|
||||
{
|
||||
uint32_t low, high;
|
||||
uint64_t queue_addr = 0;
|
||||
|
||||
kgd_gfx_v9_acquire_queue(adev, pipe_id, queue_id, inst);
|
||||
amdgpu_gfx_rlc_enter_safe_mode(adev, inst);
|
||||
|
||||
if (!RREG32_SOC15(GC, GET_INST(GC, inst), mmCP_HQD_ACTIVE))
|
||||
goto unlock_out;
|
||||
|
||||
low = RREG32_SOC15(GC, GET_INST(GC, inst), mmCP_HQD_PQ_BASE);
|
||||
high = RREG32_SOC15(GC, GET_INST(GC, inst), mmCP_HQD_PQ_BASE_HI);
|
||||
|
||||
/* only concerned with user queues. */
|
||||
if (!high)
|
||||
goto unlock_out;
|
||||
|
||||
queue_addr = (((queue_addr | high) << 32) | low) << 8;
|
||||
|
||||
unlock_out:
|
||||
amdgpu_gfx_rlc_exit_safe_mode(adev, inst);
|
||||
kgd_gfx_v9_release_queue(adev, inst);
|
||||
|
||||
return queue_addr;
|
||||
}
|
||||
|
||||
/* assume queue acquired */
|
||||
static int kgd_gfx_v9_hqd_dequeue_wait(struct amdgpu_device *adev, uint32_t inst,
|
||||
unsigned int utimeout)
|
||||
{
|
||||
unsigned long end_jiffies = (utimeout * HZ / 1000) + jiffies;
|
||||
|
||||
while (true) {
|
||||
uint32_t temp = RREG32_SOC15(GC, GET_INST(GC, inst), mmCP_HQD_ACTIVE);
|
||||
|
||||
if (!(temp & CP_HQD_ACTIVE__ACTIVE_MASK))
|
||||
return 0;
|
||||
|
||||
if (time_after(jiffies, end_jiffies))
|
||||
return -ETIME;
|
||||
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t kgd_gfx_v9_hqd_reset(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t inst, unsigned int utimeout)
|
||||
{
|
||||
uint32_t low, high, pipe_reset_data = 0;
|
||||
uint64_t queue_addr = 0;
|
||||
|
||||
kgd_gfx_v9_acquire_queue(adev, pipe_id, queue_id, inst);
|
||||
amdgpu_gfx_rlc_enter_safe_mode(adev, inst);
|
||||
|
||||
if (!RREG32_SOC15(GC, GET_INST(GC, inst), mmCP_HQD_ACTIVE))
|
||||
goto unlock_out;
|
||||
|
||||
low = RREG32_SOC15(GC, GET_INST(GC, inst), mmCP_HQD_PQ_BASE);
|
||||
high = RREG32_SOC15(GC, GET_INST(GC, inst), mmCP_HQD_PQ_BASE_HI);
|
||||
|
||||
/* only concerned with user queues. */
|
||||
if (!high)
|
||||
goto unlock_out;
|
||||
|
||||
queue_addr = (((queue_addr | high) << 32) | low) << 8;
|
||||
|
||||
pr_debug("Attempting queue reset on XCC %i pipe id %i queue id %i\n",
|
||||
inst, pipe_id, queue_id);
|
||||
|
||||
/* assume previous dequeue request issued will take affect after reset */
|
||||
WREG32_SOC15(GC, GET_INST(GC, inst), mmSPI_COMPUTE_QUEUE_RESET, 0x1);
|
||||
|
||||
if (!kgd_gfx_v9_hqd_dequeue_wait(adev, inst, utimeout))
|
||||
goto unlock_out;
|
||||
|
||||
pr_debug("Attempting pipe reset on XCC %i pipe id %i\n", inst, pipe_id);
|
||||
|
||||
pipe_reset_data = REG_SET_FIELD(pipe_reset_data, CP_MEC_CNTL, MEC_ME1_PIPE0_RESET, 1);
|
||||
pipe_reset_data = pipe_reset_data << pipe_id;
|
||||
|
||||
WREG32_SOC15(GC, GET_INST(GC, inst), mmCP_MEC_CNTL, pipe_reset_data);
|
||||
WREG32_SOC15(GC, GET_INST(GC, inst), mmCP_MEC_CNTL, 0);
|
||||
|
||||
if (kgd_gfx_v9_hqd_dequeue_wait(adev, inst, utimeout))
|
||||
queue_addr = 0;
|
||||
|
||||
unlock_out:
|
||||
pr_debug("queue reset on XCC %i pipe id %i queue id %i %s\n",
|
||||
inst, pipe_id, queue_id, !!queue_addr ? "succeeded!" : "failed!");
|
||||
amdgpu_gfx_rlc_exit_safe_mode(adev, inst);
|
||||
kgd_gfx_v9_release_queue(adev, inst);
|
||||
|
||||
return queue_addr;
|
||||
}
|
||||
|
||||
const struct kfd2kgd_calls gfx_v9_kfd2kgd = {
|
||||
.program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings,
|
||||
.set_pasid_vmid_mapping = kgd_gfx_v9_set_pasid_vmid_mapping,
|
||||
@ -1172,4 +1271,6 @@ const struct kfd2kgd_calls gfx_v9_kfd2kgd = {
|
||||
.build_grace_period_packet_info = kgd_gfx_v9_build_grace_period_packet_info,
|
||||
.get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy,
|
||||
.program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings,
|
||||
.hqd_get_pq_addr = kgd_gfx_v9_hqd_get_pq_addr,
|
||||
.hqd_reset = kgd_gfx_v9_hqd_reset
|
||||
};
|
||||
|
@ -101,3 +101,12 @@ void kgd_gfx_v9_build_grace_period_packet_info(struct amdgpu_device *adev,
|
||||
uint32_t grace_period,
|
||||
uint32_t *reg_offset,
|
||||
uint32_t *reg_data);
|
||||
uint64_t kgd_gfx_v9_hqd_get_pq_addr(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id,
|
||||
uint32_t queue_id,
|
||||
uint32_t inst);
|
||||
uint64_t kgd_gfx_v9_hqd_reset(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id,
|
||||
uint32_t queue_id,
|
||||
uint32_t inst,
|
||||
unsigned int utimeout);
|
||||
|
@ -1252,7 +1252,7 @@ static int unreserve_bo_and_vms(struct bo_vm_reservation_context *ctx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void unmap_bo_from_gpuvm(struct kgd_mem *mem,
|
||||
static int unmap_bo_from_gpuvm(struct kgd_mem *mem,
|
||||
struct kfd_mem_attachment *entry,
|
||||
struct amdgpu_sync *sync)
|
||||
{
|
||||
@ -1260,11 +1260,18 @@ static void unmap_bo_from_gpuvm(struct kgd_mem *mem,
|
||||
struct amdgpu_device *adev = entry->adev;
|
||||
struct amdgpu_vm *vm = bo_va->base.vm;
|
||||
|
||||
if (bo_va->queue_refcount) {
|
||||
pr_debug("bo_va->queue_refcount %d\n", bo_va->queue_refcount);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
amdgpu_vm_bo_unmap(adev, bo_va, entry->va);
|
||||
|
||||
amdgpu_vm_clear_freed(adev, vm, &bo_va->last_pt_update);
|
||||
|
||||
amdgpu_sync_fence(sync, bo_va->last_pt_update);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int update_gpuvm_pte(struct kgd_mem *mem,
|
||||
@ -2191,7 +2198,10 @@ int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
|
||||
pr_debug("\t unmap VA 0x%llx - 0x%llx from entry %p\n",
|
||||
entry->va, entry->va + bo_size, entry);
|
||||
|
||||
unmap_bo_from_gpuvm(mem, entry, ctx.sync);
|
||||
ret = unmap_bo_from_gpuvm(mem, entry, ctx.sync);
|
||||
if (ret)
|
||||
goto unreserve_out;
|
||||
|
||||
entry->is_mapped = false;
|
||||
|
||||
mem->mapped_to_gpu_memory--;
|
||||
@ -2226,11 +2236,12 @@ int amdgpu_amdkfd_gpuvm_sync_memory(
|
||||
/**
|
||||
* amdgpu_amdkfd_map_gtt_bo_to_gart - Map BO to GART and increment reference count
|
||||
* @bo: Buffer object to be mapped
|
||||
* @bo_gart: Return bo reference
|
||||
*
|
||||
* Before return, bo reference count is incremented. To release the reference and unpin/
|
||||
* unmap the BO, call amdgpu_amdkfd_free_gtt_mem.
|
||||
*/
|
||||
int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_bo *bo)
|
||||
int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_bo *bo, struct amdgpu_bo **bo_gart)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -2257,7 +2268,7 @@ int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_bo *bo)
|
||||
|
||||
amdgpu_bo_unreserve(bo);
|
||||
|
||||
bo = amdgpu_bo_ref(bo);
|
||||
*bo_gart = amdgpu_bo_ref(bo);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -3200,12 +3211,13 @@ 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)
|
||||
bool amdgpu_amdkfd_bo_mapped_to_dev(void *drm_priv, struct kgd_mem *mem)
|
||||
{
|
||||
struct amdgpu_vm *vm = drm_priv_to_vm(drm_priv);
|
||||
struct kfd_mem_attachment *entry;
|
||||
|
||||
list_for_each_entry(entry, &mem->attachments, list) {
|
||||
if (entry->is_mapped && entry->adev == adev)
|
||||
if (entry->is_mapped && entry->bo_va->base.vm == vm)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1018,8 +1018,9 @@ int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev,
|
||||
if (clock_type == COMPUTE_ENGINE_PLL_PARAM) {
|
||||
args.v3.ulClockParams = cpu_to_le32((clock_type << 24) | clock);
|
||||
|
||||
amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args,
|
||||
sizeof(args));
|
||||
if (amdgpu_atom_execute_table(adev->mode_info.atom_context,
|
||||
index, (uint32_t *)&args, sizeof(args)))
|
||||
return -EINVAL;
|
||||
|
||||
dividers->post_div = args.v3.ucPostDiv;
|
||||
dividers->enable_post_div = (args.v3.ucCntlFlag &
|
||||
@ -1039,8 +1040,9 @@ int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev,
|
||||
if (strobe_mode)
|
||||
args.v5.ucInputFlag = ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN;
|
||||
|
||||
amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args,
|
||||
sizeof(args));
|
||||
if (amdgpu_atom_execute_table(adev->mode_info.atom_context,
|
||||
index, (uint32_t *)&args, sizeof(args)))
|
||||
return -EINVAL;
|
||||
|
||||
dividers->post_div = args.v5.ucPostDiv;
|
||||
dividers->enable_post_div = (args.v5.ucCntlFlag &
|
||||
@ -1058,8 +1060,9 @@ int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev,
|
||||
/* fusion */
|
||||
args.v4.ulClock = cpu_to_le32(clock); /* 10 khz */
|
||||
|
||||
amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args,
|
||||
sizeof(args));
|
||||
if (amdgpu_atom_execute_table(adev->mode_info.atom_context,
|
||||
index, (uint32_t *)&args, sizeof(args)))
|
||||
return -EINVAL;
|
||||
|
||||
dividers->post_divider = dividers->post_div = args.v4.ucPostDiv;
|
||||
dividers->real_clock = le32_to_cpu(args.v4.ulClock);
|
||||
@ -1070,8 +1073,9 @@ int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev,
|
||||
args.v6_in.ulClock.ulComputeClockFlag = clock_type;
|
||||
args.v6_in.ulClock.ulClockFreq = cpu_to_le32(clock); /* 10 khz */
|
||||
|
||||
amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args,
|
||||
sizeof(args));
|
||||
if (amdgpu_atom_execute_table(adev->mode_info.atom_context,
|
||||
index, (uint32_t *)&args, sizeof(args)))
|
||||
return -EINVAL;
|
||||
|
||||
dividers->whole_fb_div = le16_to_cpu(args.v6_out.ulFbDiv.usFbDiv);
|
||||
dividers->frac_fb_div = le16_to_cpu(args.v6_out.ulFbDiv.usFbDivFrac);
|
||||
@ -1113,8 +1117,9 @@ int amdgpu_atombios_get_memory_pll_dividers(struct amdgpu_device *adev,
|
||||
if (strobe_mode)
|
||||
args.ucInputFlag |= MPLL_INPUT_FLAG_STROBE_MODE_EN;
|
||||
|
||||
amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args,
|
||||
sizeof(args));
|
||||
if (amdgpu_atom_execute_table(adev->mode_info.atom_context,
|
||||
index, (uint32_t *)&args, sizeof(args)))
|
||||
return -EINVAL;
|
||||
|
||||
mpll_param->clkfrac = le16_to_cpu(args.ulFbDiv.usFbDivFrac);
|
||||
mpll_param->clkf = le16_to_cpu(args.ulFbDiv.usFbDiv);
|
||||
@ -1211,8 +1216,9 @@ int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type,
|
||||
args.v2.ucVoltageMode = 0;
|
||||
args.v2.usVoltageLevel = 0;
|
||||
|
||||
amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args,
|
||||
sizeof(args));
|
||||
if (amdgpu_atom_execute_table(adev->mode_info.atom_context,
|
||||
index, (uint32_t *)&args, sizeof(args)))
|
||||
return -EINVAL;
|
||||
|
||||
*voltage = le16_to_cpu(args.v2.usVoltageLevel);
|
||||
break;
|
||||
@ -1221,8 +1227,9 @@ int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type,
|
||||
args.v3.ucVoltageMode = ATOM_GET_VOLTAGE_LEVEL;
|
||||
args.v3.usVoltageLevel = cpu_to_le16(voltage_id);
|
||||
|
||||
amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args,
|
||||
sizeof(args));
|
||||
if (amdgpu_atom_execute_table(adev->mode_info.atom_context,
|
||||
index, (uint32_t *)&args, sizeof(args)))
|
||||
return -EINVAL;
|
||||
|
||||
*voltage = le16_to_cpu(args.v3.usVoltageLevel);
|
||||
break;
|
||||
|
@ -431,6 +431,11 @@ bool amdgpu_get_bios(struct amdgpu_device *adev)
|
||||
goto success;
|
||||
}
|
||||
|
||||
if (amdgpu_read_platform_bios(adev)) {
|
||||
dev_info(adev->dev, "Fetched VBIOS from platform\n");
|
||||
goto success;
|
||||
}
|
||||
|
||||
if (amdgpu_read_bios(adev)) {
|
||||
dev_info(adev->dev, "Fetched VBIOS from ROM BAR\n");
|
||||
goto success;
|
||||
@ -446,11 +451,6 @@ bool amdgpu_get_bios(struct amdgpu_device *adev)
|
||||
goto success;
|
||||
}
|
||||
|
||||
if (amdgpu_read_platform_bios(adev)) {
|
||||
dev_info(adev->dev, "Fetched VBIOS from platform\n");
|
||||
goto success;
|
||||
}
|
||||
|
||||
dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
|
||||
return false;
|
||||
|
||||
|
@ -414,7 +414,7 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = amdgpu_ucode_request(adev, &adev->pm.fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->pm.fw, "%s", fw_name);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to load firmware \"%s\"", fw_name);
|
||||
amdgpu_ucode_release(&adev->pm.fw);
|
||||
|
@ -249,11 +249,7 @@ amdgpu_connector_find_encoder(struct drm_connector *connector,
|
||||
static struct edid *
|
||||
amdgpu_connector_get_hardcoded_edid(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->mode_info.bios_hardcoded_edid) {
|
||||
return kmemdup((unsigned char *)adev->mode_info.bios_hardcoded_edid,
|
||||
adev->mode_info.bios_hardcoded_edid_size, GFP_KERNEL);
|
||||
}
|
||||
return NULL;
|
||||
return drm_edid_duplicate(drm_edid_raw(adev->mode_info.bios_hardcoded_edid));
|
||||
}
|
||||
|
||||
static void amdgpu_connector_get_edid(struct drm_connector *connector)
|
||||
@ -442,6 +438,9 @@ static void amdgpu_connector_add_common_modes(struct drm_encoder *encoder,
|
||||
continue;
|
||||
|
||||
mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
|
||||
if (!mode)
|
||||
return;
|
||||
|
||||
drm_mode_probed_add(connector, mode);
|
||||
}
|
||||
}
|
||||
|
@ -263,6 +263,10 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
|
||||
if (size < sizeof(struct drm_amdgpu_bo_list_in))
|
||||
goto free_partial_kdata;
|
||||
|
||||
/* Only a single BO list is allowed to simplify handling. */
|
||||
if (p->bo_list)
|
||||
ret = -EINVAL;
|
||||
|
||||
ret = amdgpu_cs_p1_bo_handles(p, p->chunks[i].kdata);
|
||||
if (ret)
|
||||
goto free_partial_kdata;
|
||||
@ -292,6 +296,7 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
|
||||
num_ibs[i], &p->jobs[i]);
|
||||
if (ret)
|
||||
goto free_all_kdata;
|
||||
p->jobs[i]->enforce_isolation = p->adev->enforce_isolation[fpriv->xcp_id];
|
||||
}
|
||||
p->gang_leader = p->jobs[p->gang_leader_idx];
|
||||
|
||||
@ -1106,7 +1111,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
|
||||
struct drm_gpu_scheduler *sched = entity->rq->sched;
|
||||
struct amdgpu_ring *ring = to_amdgpu_ring(sched);
|
||||
|
||||
if (amdgpu_vmid_uses_reserved(vm, ring->vm_hub))
|
||||
if (amdgpu_vmid_uses_reserved(adev, vm, ring->vm_hub))
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -2026,100 +2026,6 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_ib_preempt, NULL,
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_sclk_set, NULL,
|
||||
amdgpu_debugfs_sclk_set, "%llu\n");
|
||||
|
||||
static ssize_t amdgpu_reset_dump_register_list_read(struct file *f,
|
||||
char __user *buf, size_t size, loff_t *pos)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
|
||||
char reg_offset[12];
|
||||
int i, ret, len = 0;
|
||||
|
||||
if (*pos)
|
||||
return 0;
|
||||
|
||||
memset(reg_offset, 0, 12);
|
||||
ret = down_read_killable(&adev->reset_domain->sem);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < adev->reset_info.num_regs; i++) {
|
||||
sprintf(reg_offset, "0x%x\n", adev->reset_info.reset_dump_reg_list[i]);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
if (copy_to_user(buf + len, reg_offset, strlen(reg_offset)))
|
||||
return -EFAULT;
|
||||
|
||||
len += strlen(reg_offset);
|
||||
ret = down_read_killable(&adev->reset_domain->sem);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
up_read(&adev->reset_domain->sem);
|
||||
*pos += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_reset_dump_register_list_write(struct file *f,
|
||||
const char __user *buf, size_t size, loff_t *pos)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
|
||||
char reg_offset[11];
|
||||
uint32_t *new = NULL, *tmp = NULL;
|
||||
unsigned int len = 0;
|
||||
int ret, i = 0;
|
||||
|
||||
do {
|
||||
memset(reg_offset, 0, 11);
|
||||
if (copy_from_user(reg_offset, buf + len,
|
||||
min(10, (size-len)))) {
|
||||
ret = -EFAULT;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
new = krealloc_array(tmp, i + 1, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (!new) {
|
||||
ret = -ENOMEM;
|
||||
goto error_free;
|
||||
}
|
||||
tmp = new;
|
||||
if (sscanf(reg_offset, "%X %n", &tmp[i], &ret) != 1) {
|
||||
ret = -EINVAL;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
len += ret;
|
||||
i++;
|
||||
} while (len < size);
|
||||
|
||||
new = kmalloc_array(i, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (!new) {
|
||||
ret = -ENOMEM;
|
||||
goto error_free;
|
||||
}
|
||||
ret = down_write_killable(&adev->reset_domain->sem);
|
||||
if (ret)
|
||||
goto error_free;
|
||||
|
||||
swap(adev->reset_info.reset_dump_reg_list, tmp);
|
||||
swap(adev->reset_info.reset_dump_reg_value, new);
|
||||
adev->reset_info.num_regs = i;
|
||||
up_write(&adev->reset_domain->sem);
|
||||
ret = size;
|
||||
|
||||
error_free:
|
||||
if (tmp != new)
|
||||
kfree(tmp);
|
||||
kfree(new);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations amdgpu_reset_dump_register_list = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = amdgpu_reset_dump_register_list_read,
|
||||
.write = amdgpu_reset_dump_register_list_write,
|
||||
.llseek = default_llseek
|
||||
};
|
||||
|
||||
int amdgpu_debugfs_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct dentry *root = adev_to_drm(adev)->primary->debugfs_root;
|
||||
@ -2204,8 +2110,6 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
|
||||
&amdgpu_debugfs_vm_info_fops);
|
||||
debugfs_create_file("amdgpu_benchmark", 0200, root, adev,
|
||||
&amdgpu_benchmark_fops);
|
||||
debugfs_create_file("amdgpu_reset_dump_register_list", 0644, root, adev,
|
||||
&amdgpu_reset_dump_register_list);
|
||||
|
||||
adev->debugfs_vbios_blob.data = adev->bios;
|
||||
adev->debugfs_vbios_blob.size = adev->bios_size;
|
||||
|
@ -203,7 +203,7 @@ amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count,
|
||||
struct amdgpu_coredump_info *coredump = data;
|
||||
struct drm_print_iterator iter;
|
||||
struct amdgpu_vm_fault_info *fault_info;
|
||||
int i, ver;
|
||||
int ver;
|
||||
|
||||
iter.data = buffer;
|
||||
iter.offset = 0;
|
||||
@ -236,7 +236,7 @@ amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count,
|
||||
drm_printf(&p, "\nSOC Memory Information\n");
|
||||
drm_printf(&p, "real vram size: %llu\n", coredump->adev->gmc.real_vram_size);
|
||||
drm_printf(&p, "visible vram size: %llu\n", coredump->adev->gmc.visible_vram_size);
|
||||
drm_printf(&p, "visible vram size: %llu\n", coredump->adev->mman.gtt_mgr.manager.size);
|
||||
drm_printf(&p, "gtt size: %llu\n", coredump->adev->mman.gtt_mgr.manager.size);
|
||||
|
||||
/* GDS Config */
|
||||
drm_printf(&p, "\nGDS Config\n");
|
||||
@ -317,14 +317,6 @@ amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count,
|
||||
|
||||
if (coredump->reset_vram_lost)
|
||||
drm_printf(&p, "VRAM is lost due to GPU reset!\n");
|
||||
if (coredump->adev->reset_info.num_regs) {
|
||||
drm_printf(&p, "AMDGPU register dumps:\nOffset: Value:\n");
|
||||
|
||||
for (i = 0; i < coredump->adev->reset_info.num_regs; i++)
|
||||
drm_printf(&p, "0x%08x: 0x%08x\n",
|
||||
coredump->adev->reset_info.reset_dump_reg_list[i],
|
||||
coredump->adev->reset_info.reset_dump_reg_value[i]);
|
||||
}
|
||||
|
||||
return count - iter.remain;
|
||||
}
|
||||
|
@ -1916,6 +1916,8 @@ static int amdgpu_device_init_apu_flags(struct amdgpu_device *adev)
|
||||
*/
|
||||
static int amdgpu_device_check_arguments(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (amdgpu_sched_jobs < 4) {
|
||||
dev_warn(adev->dev, "sched jobs (%d) must be at least 4\n",
|
||||
amdgpu_sched_jobs);
|
||||
@ -1970,6 +1972,9 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev)
|
||||
|
||||
adev->firmware.load_type = amdgpu_ucode_get_load_type(adev, amdgpu_fw_load_type);
|
||||
|
||||
for (i = 0; i < MAX_XCP; i++)
|
||||
adev->enforce_isolation[i] = !!enforce_isolation;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2471,6 +2476,7 @@ out:
|
||||
*/
|
||||
static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ip_block *ip_block;
|
||||
struct pci_dev *parent;
|
||||
int i, r;
|
||||
bool total;
|
||||
@ -2608,7 +2614,10 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
||||
if (!total)
|
||||
return -ENODEV;
|
||||
|
||||
amdgpu_amdkfd_device_probe(adev);
|
||||
ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_GFX);
|
||||
if (ip_block->status.valid != false)
|
||||
amdgpu_amdkfd_device_probe(adev);
|
||||
|
||||
adev->cg_flags &= amdgpu_cg_mask;
|
||||
adev->pg_flags &= amdgpu_pg_mask;
|
||||
|
||||
@ -3948,6 +3957,27 @@ static void amdgpu_device_check_iommu_direct_map(struct amdgpu_device *adev)
|
||||
adev->ram_is_direct_mapped = true;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_HSA_AMD_P2P)
|
||||
/**
|
||||
* amdgpu_device_check_iommu_remap - Check if DMA remapping is enabled.
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* return if IOMMU remapping bar address
|
||||
*/
|
||||
static bool amdgpu_device_check_iommu_remap(struct amdgpu_device *adev)
|
||||
{
|
||||
struct iommu_domain *domain;
|
||||
|
||||
domain = iommu_get_domain_for_dev(adev->dev);
|
||||
if (domain && (domain->type == IOMMU_DOMAIN_DMA ||
|
||||
domain->type == IOMMU_DOMAIN_DMA_FQ))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct attribute *amdgpu_dev_attributes[] = {
|
||||
&dev_attr_pcie_replay_count.attr,
|
||||
NULL
|
||||
@ -4055,6 +4085,10 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
mutex_init(&adev->notifier_lock);
|
||||
mutex_init(&adev->pm.stable_pstate_ctx_lock);
|
||||
mutex_init(&adev->benchmark_mutex);
|
||||
mutex_init(&adev->gfx.reset_sem_mutex);
|
||||
/* Initialize the mutex for cleaner shader isolation between GFX and compute processes */
|
||||
mutex_init(&adev->enforce_isolation_mutex);
|
||||
mutex_init(&adev->gfx.kfd_sch_mutex);
|
||||
|
||||
amdgpu_device_init_apu_flags(adev);
|
||||
|
||||
@ -4086,6 +4120,21 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
amdgpu_device_delayed_init_work_handler);
|
||||
INIT_DELAYED_WORK(&adev->gfx.gfx_off_delay_work,
|
||||
amdgpu_device_delay_enable_gfx_off);
|
||||
/*
|
||||
* Initialize the enforce_isolation work structures for each XCP
|
||||
* partition. This work handler is responsible for enforcing shader
|
||||
* isolation on AMD GPUs. It counts the number of emitted fences for
|
||||
* each GFX and compute ring. If there are any fences, it schedules
|
||||
* the `enforce_isolation_work` to be run after a delay. If there are
|
||||
* no fences, it signals the Kernel Fusion Driver (KFD) to resume the
|
||||
* runqueue.
|
||||
*/
|
||||
for (i = 0; i < MAX_XCP; i++) {
|
||||
INIT_DELAYED_WORK(&adev->gfx.enforce_isolation[i].work,
|
||||
amdgpu_gfx_enforce_isolation_handler);
|
||||
adev->gfx.enforce_isolation[i].adev = adev;
|
||||
adev->gfx.enforce_isolation[i].xcp_id = i;
|
||||
}
|
||||
|
||||
INIT_WORK(&adev->xgmi_reset_work, amdgpu_device_xgmi_reset_func);
|
||||
|
||||
@ -5278,16 +5327,15 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
|
||||
{
|
||||
int i, r = 0;
|
||||
struct amdgpu_job *job = NULL;
|
||||
struct amdgpu_device *tmp_adev = reset_context->reset_req_dev;
|
||||
bool need_full_reset =
|
||||
test_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
|
||||
|
||||
if (reset_context->reset_req_dev == adev)
|
||||
job = reset_context->job;
|
||||
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
/* stop the data exchange thread */
|
||||
amdgpu_virt_fini_data_exchange(adev);
|
||||
}
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
amdgpu_virt_pre_reset(adev);
|
||||
|
||||
amdgpu_fence_driver_isr_toggle(adev, true);
|
||||
|
||||
@ -5336,6 +5384,16 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
|
||||
}
|
||||
}
|
||||
|
||||
if (!test_bit(AMDGPU_SKIP_COREDUMP, &reset_context->flags)) {
|
||||
dev_info(tmp_adev->dev, "Dumping IP State\n");
|
||||
/* Trigger ip dump before we reset the asic */
|
||||
for (i = 0; i < tmp_adev->num_ip_blocks; i++)
|
||||
if (tmp_adev->ip_blocks[i].version->funcs->dump_ip_state)
|
||||
tmp_adev->ip_blocks[i].version->funcs
|
||||
->dump_ip_state((void *)tmp_adev);
|
||||
dev_info(tmp_adev->dev, "Dumping IP State Completed\n");
|
||||
}
|
||||
|
||||
if (need_full_reset)
|
||||
r = amdgpu_device_ip_suspend(adev);
|
||||
if (need_full_reset)
|
||||
@ -5348,47 +5406,17 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
|
||||
return r;
|
||||
}
|
||||
|
||||
static int amdgpu_reset_reg_dumps(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&adev->reset_domain->sem);
|
||||
|
||||
for (i = 0; i < adev->reset_info.num_regs; i++) {
|
||||
adev->reset_info.reset_dump_reg_value[i] =
|
||||
RREG32(adev->reset_info.reset_dump_reg_list[i]);
|
||||
|
||||
trace_amdgpu_reset_reg_dumps(adev->reset_info.reset_dump_reg_list[i],
|
||||
adev->reset_info.reset_dump_reg_value[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_do_asic_reset(struct list_head *device_list_handle,
|
||||
struct amdgpu_reset_context *reset_context)
|
||||
{
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
bool need_full_reset, skip_hw_reset, vram_lost = false;
|
||||
int r = 0;
|
||||
uint32_t i;
|
||||
|
||||
/* Try reset handler method first */
|
||||
tmp_adev = list_first_entry(device_list_handle, struct amdgpu_device,
|
||||
reset_list);
|
||||
|
||||
if (!test_bit(AMDGPU_SKIP_COREDUMP, &reset_context->flags)) {
|
||||
amdgpu_reset_reg_dumps(tmp_adev);
|
||||
|
||||
dev_info(tmp_adev->dev, "Dumping IP State\n");
|
||||
/* Trigger ip dump before we reset the asic */
|
||||
for (i = 0; i < tmp_adev->num_ip_blocks; i++)
|
||||
if (tmp_adev->ip_blocks[i].version->funcs->dump_ip_state)
|
||||
tmp_adev->ip_blocks[i].version->funcs
|
||||
->dump_ip_state((void *)tmp_adev);
|
||||
dev_info(tmp_adev->dev, "Dumping IP State Completed\n");
|
||||
}
|
||||
|
||||
reset_context->reset_device_list = device_list_handle;
|
||||
r = amdgpu_reset_perform_reset(tmp_adev, reset_context);
|
||||
/* If reset handler not implemented, continue; otherwise return */
|
||||
@ -5513,7 +5541,7 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle,
|
||||
* bad_page_threshold value to fix this once
|
||||
* probing driver again.
|
||||
*/
|
||||
if (!amdgpu_ras_eeprom_check_err_threshold(tmp_adev)) {
|
||||
if (!amdgpu_ras_is_rma(tmp_adev)) {
|
||||
/* must succeed. */
|
||||
amdgpu_ras_resume(tmp_adev);
|
||||
} else {
|
||||
@ -5891,8 +5919,14 @@ skip_hw_reset:
|
||||
tmp_adev->asic_reset_res = 0;
|
||||
|
||||
if (r) {
|
||||
/* bad news, how to tell it to userspace ? */
|
||||
dev_info(tmp_adev->dev, "GPU reset(%d) failed\n", atomic_read(&tmp_adev->gpu_reset_counter));
|
||||
/* bad news, how to tell it to userspace ?
|
||||
* for ras error, we should report GPU bad status instead of
|
||||
* reset failure
|
||||
*/
|
||||
if (reset_context->src != AMDGPU_RESET_SRC_RAS ||
|
||||
!amdgpu_ras_eeprom_check_err_threshold(tmp_adev))
|
||||
dev_info(tmp_adev->dev, "GPU reset(%d) failed\n",
|
||||
atomic_read(&tmp_adev->gpu_reset_counter));
|
||||
amdgpu_vf_error_put(tmp_adev, AMDGIM_ERROR_VF_GPU_RESET_FAIL, 0, r);
|
||||
} else {
|
||||
dev_info(tmp_adev->dev, "GPU reset(%d) succeeded!\n", atomic_read(&tmp_adev->gpu_reset_counter));
|
||||
@ -6138,18 +6172,24 @@ bool amdgpu_device_is_peer_accessible(struct amdgpu_device *adev,
|
||||
struct amdgpu_device *peer_adev)
|
||||
{
|
||||
#ifdef CONFIG_HSA_AMD_P2P
|
||||
uint64_t address_mask = peer_adev->dev->dma_mask ?
|
||||
~*peer_adev->dev->dma_mask : ~((1ULL << 32) - 1);
|
||||
resource_size_t aper_limit =
|
||||
adev->gmc.aper_base + adev->gmc.aper_size - 1;
|
||||
bool p2p_access =
|
||||
!adev->gmc.xgmi.connected_to_cpu &&
|
||||
!(pci_p2pdma_distance(adev->pdev, peer_adev->dev, false) < 0);
|
||||
|
||||
return pcie_p2p && p2p_access && (adev->gmc.visible_vram_size &&
|
||||
adev->gmc.real_vram_size == adev->gmc.visible_vram_size &&
|
||||
!(adev->gmc.aper_base & address_mask ||
|
||||
aper_limit & address_mask));
|
||||
bool is_large_bar = adev->gmc.visible_vram_size &&
|
||||
adev->gmc.real_vram_size == adev->gmc.visible_vram_size;
|
||||
bool p2p_addressable = amdgpu_device_check_iommu_remap(peer_adev);
|
||||
|
||||
if (!p2p_addressable) {
|
||||
uint64_t address_mask = peer_adev->dev->dma_mask ?
|
||||
~*peer_adev->dev->dma_mask : ~((1ULL << 32) - 1);
|
||||
resource_size_t aper_limit =
|
||||
adev->gmc.aper_base + adev->gmc.aper_size - 1;
|
||||
|
||||
p2p_addressable = !(adev->gmc.aper_base & address_mask ||
|
||||
aper_limit & address_mask);
|
||||
}
|
||||
return is_large_bar && p2p_access && p2p_addressable;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
@ -1500,6 +1500,7 @@ union gc_info {
|
||||
struct gc_info_v1_0 v1;
|
||||
struct gc_info_v1_1 v1_1;
|
||||
struct gc_info_v1_2 v1_2;
|
||||
struct gc_info_v1_3 v1_3;
|
||||
struct gc_info_v2_0 v2;
|
||||
struct gc_info_v2_1 v2_1;
|
||||
};
|
||||
@ -1558,6 +1559,16 @@ static int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev)
|
||||
adev->gfx.config.gc_gl1c_size_per_instance = le32_to_cpu(gc_info->v1_2.gc_gl1c_size_per_instance);
|
||||
adev->gfx.config.gc_gl2c_per_gpu = le32_to_cpu(gc_info->v1_2.gc_gl2c_per_gpu);
|
||||
}
|
||||
if (le16_to_cpu(gc_info->v1.header.version_minor) >= 3) {
|
||||
adev->gfx.config.gc_tcp_size_per_cu = le32_to_cpu(gc_info->v1_3.gc_tcp_size_per_cu);
|
||||
adev->gfx.config.gc_tcp_cache_line_size = le32_to_cpu(gc_info->v1_3.gc_tcp_cache_line_size);
|
||||
adev->gfx.config.gc_instruction_cache_size_per_sqc = le32_to_cpu(gc_info->v1_3.gc_instruction_cache_size_per_sqc);
|
||||
adev->gfx.config.gc_instruction_cache_line_size = le32_to_cpu(gc_info->v1_3.gc_instruction_cache_line_size);
|
||||
adev->gfx.config.gc_scalar_data_cache_size_per_sqc = le32_to_cpu(gc_info->v1_3.gc_scalar_data_cache_size_per_sqc);
|
||||
adev->gfx.config.gc_scalar_data_cache_line_size = le32_to_cpu(gc_info->v1_3.gc_scalar_data_cache_line_size);
|
||||
adev->gfx.config.gc_tcc_size = le32_to_cpu(gc_info->v1_3.gc_tcc_size);
|
||||
adev->gfx.config.gc_tcc_cache_line_size = le32_to_cpu(gc_info->v1_3.gc_tcc_cache_line_size);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
adev->gfx.config.max_shader_engines = le32_to_cpu(gc_info->v2.gc_num_se);
|
||||
|
@ -55,8 +55,6 @@ int amdgpu_gart_table_ram_alloc(struct amdgpu_device *adev);
|
||||
void amdgpu_gart_table_ram_free(struct amdgpu_device *adev);
|
||||
int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev);
|
||||
void amdgpu_gart_table_vram_free(struct amdgpu_device *adev);
|
||||
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);
|
||||
void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
|
||||
|
@ -24,10 +24,13 @@
|
||||
*/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_gfx.h"
|
||||
#include "amdgpu_rlc.h"
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_reset.h"
|
||||
#include "amdgpu_xcp.h"
|
||||
#include "amdgpu_xgmi.h"
|
||||
|
||||
@ -882,8 +885,11 @@ int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *r
|
||||
int r;
|
||||
|
||||
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);
|
||||
if (!amdgpu_persistent_edc_harvesting_supported(adev)) {
|
||||
r = amdgpu_ras_reset_error_status(adev, AMDGPU_RAS_BLOCK__GFX);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_ras_block_late_init(adev, ras_block);
|
||||
if (r)
|
||||
@ -1027,7 +1033,10 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg, uint32_t xcc_
|
||||
pr_err("critical bug! too many kiq readers\n");
|
||||
goto failed_unlock;
|
||||
}
|
||||
amdgpu_ring_alloc(ring, 32);
|
||||
r = amdgpu_ring_alloc(ring, 32);
|
||||
if (r)
|
||||
goto failed_unlock;
|
||||
|
||||
amdgpu_ring_emit_rreg(ring, reg, reg_val_offs);
|
||||
r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
|
||||
if (r)
|
||||
@ -1093,7 +1102,10 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint3
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&kiq->ring_lock, flags);
|
||||
amdgpu_ring_alloc(ring, 32);
|
||||
r = amdgpu_ring_alloc(ring, 32);
|
||||
if (r)
|
||||
goto failed_unlock;
|
||||
|
||||
amdgpu_ring_emit_wreg(ring, reg, v);
|
||||
r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
|
||||
if (r)
|
||||
@ -1129,6 +1141,7 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint3
|
||||
|
||||
failed_undo:
|
||||
amdgpu_ring_undo(ring);
|
||||
failed_unlock:
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
failed_kiq_write:
|
||||
dev_err(adev->dev, "failed to write reg:%x\n", reg);
|
||||
@ -1381,6 +1394,214 @@ static ssize_t amdgpu_gfx_get_available_compute_partition(struct device *dev,
|
||||
return sysfs_emit(buf, "%s\n", supported_partition);
|
||||
}
|
||||
|
||||
static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
long timeout = msecs_to_jiffies(1000);
|
||||
struct dma_fence *f = NULL;
|
||||
struct amdgpu_job *job;
|
||||
struct amdgpu_ib *ib;
|
||||
int i, r;
|
||||
|
||||
r = amdgpu_job_alloc_with_ib(adev, NULL, NULL,
|
||||
64, AMDGPU_IB_POOL_DIRECT,
|
||||
&job);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
job->enforce_isolation = true;
|
||||
|
||||
ib = &job->ibs[0];
|
||||
for (i = 0; i <= ring->funcs->align_mask; ++i)
|
||||
ib->ptr[i] = ring->funcs->nop;
|
||||
ib->length_dw = ring->funcs->align_mask + 1;
|
||||
|
||||
r = amdgpu_job_submit_direct(job, ring, &f);
|
||||
if (r)
|
||||
goto err_free;
|
||||
|
||||
r = dma_fence_wait_timeout(f, false, timeout);
|
||||
if (r == 0)
|
||||
r = -ETIMEDOUT;
|
||||
else if (r > 0)
|
||||
r = 0;
|
||||
|
||||
amdgpu_ib_free(adev, ib, f);
|
||||
dma_fence_put(f);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
amdgpu_job_free(job);
|
||||
amdgpu_ib_free(adev, ib, f);
|
||||
err:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int amdgpu_gfx_run_cleaner_shader(struct amdgpu_device *adev, int xcp_id)
|
||||
{
|
||||
int num_xcc = NUM_XCC(adev->gfx.xcc_mask);
|
||||
struct amdgpu_ring *ring;
|
||||
int num_xcc_to_clear;
|
||||
int i, r, xcc_id;
|
||||
|
||||
if (adev->gfx.num_xcc_per_xcp)
|
||||
num_xcc_to_clear = adev->gfx.num_xcc_per_xcp;
|
||||
else
|
||||
num_xcc_to_clear = 1;
|
||||
|
||||
for (xcc_id = 0; xcc_id < num_xcc; xcc_id++) {
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
|
||||
ring = &adev->gfx.compute_ring[i + xcc_id * adev->gfx.num_compute_rings];
|
||||
if ((ring->xcp_id == xcp_id) && ring->sched.ready) {
|
||||
r = amdgpu_gfx_run_cleaner_shader_job(ring);
|
||||
if (r)
|
||||
return r;
|
||||
num_xcc_to_clear--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (num_xcc_to_clear)
|
||||
return -ENOENT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_gfx_set_run_cleaner_shader(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
int ret;
|
||||
long value;
|
||||
|
||||
if (amdgpu_in_reset(adev))
|
||||
return -EPERM;
|
||||
if (adev->in_suspend && !adev->in_runpm)
|
||||
return -EPERM;
|
||||
|
||||
ret = kstrtol(buf, 0, &value);
|
||||
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
if (value < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (adev->xcp_mgr) {
|
||||
if (value >= adev->xcp_mgr->num_xcps)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (value > 1)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = pm_runtime_get_sync(ddev->dev);
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_autosuspend(ddev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = amdgpu_gfx_run_cleaner_shader(adev, value);
|
||||
|
||||
pm_runtime_mark_last_busy(ddev->dev);
|
||||
pm_runtime_put_autosuspend(ddev->dev);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_gfx_get_enforce_isolation(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
int i;
|
||||
ssize_t size = 0;
|
||||
|
||||
if (adev->xcp_mgr) {
|
||||
for (i = 0; i < adev->xcp_mgr->num_xcps; i++) {
|
||||
size += sysfs_emit_at(buf, size, "%u", adev->enforce_isolation[i]);
|
||||
if (i < (adev->xcp_mgr->num_xcps - 1))
|
||||
size += sysfs_emit_at(buf, size, " ");
|
||||
}
|
||||
buf[size++] = '\n';
|
||||
} else {
|
||||
size = sysfs_emit_at(buf, 0, "%u\n", adev->enforce_isolation[0]);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_gfx_set_enforce_isolation(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
long partition_values[MAX_XCP] = {0};
|
||||
int ret, i, num_partitions;
|
||||
const char *input_buf = buf;
|
||||
|
||||
for (i = 0; i < (adev->xcp_mgr ? adev->xcp_mgr->num_xcps : 1); i++) {
|
||||
ret = sscanf(input_buf, "%ld", &partition_values[i]);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
|
||||
/* Move the pointer to the next value in the string */
|
||||
input_buf = strchr(input_buf, ' ');
|
||||
if (input_buf) {
|
||||
input_buf++;
|
||||
} else {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
num_partitions = i;
|
||||
|
||||
if (adev->xcp_mgr && num_partitions != adev->xcp_mgr->num_xcps)
|
||||
return -EINVAL;
|
||||
|
||||
if (!adev->xcp_mgr && num_partitions != 1)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < num_partitions; i++) {
|
||||
if (partition_values[i] != 0 && partition_values[i] != 1)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&adev->enforce_isolation_mutex);
|
||||
|
||||
for (i = 0; i < num_partitions; i++) {
|
||||
if (adev->enforce_isolation[i] && !partition_values[i]) {
|
||||
/* Going from enabled to disabled */
|
||||
amdgpu_vmid_free_reserved(adev, AMDGPU_GFXHUB(i));
|
||||
} else if (!adev->enforce_isolation[i] && partition_values[i]) {
|
||||
/* Going from disabled to enabled */
|
||||
amdgpu_vmid_alloc_reserved(adev, AMDGPU_GFXHUB(i));
|
||||
}
|
||||
adev->enforce_isolation[i] = partition_values[i];
|
||||
}
|
||||
|
||||
mutex_unlock(&adev->enforce_isolation_mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(run_cleaner_shader, 0200,
|
||||
NULL, amdgpu_gfx_set_run_cleaner_shader);
|
||||
|
||||
static DEVICE_ATTR(enforce_isolation, 0644,
|
||||
amdgpu_gfx_get_enforce_isolation,
|
||||
amdgpu_gfx_set_enforce_isolation);
|
||||
|
||||
static DEVICE_ATTR(current_compute_partition, 0644,
|
||||
amdgpu_gfx_get_current_compute_partition,
|
||||
amdgpu_gfx_set_compute_partition);
|
||||
@ -1406,3 +1627,229 @@ void amdgpu_gfx_sysfs_fini(struct amdgpu_device *adev)
|
||||
device_remove_file(adev->dev, &dev_attr_current_compute_partition);
|
||||
device_remove_file(adev->dev, &dev_attr_available_compute_partition);
|
||||
}
|
||||
|
||||
int amdgpu_gfx_sysfs_isolation_shader_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
r = device_create_file(adev->dev, &dev_attr_enforce_isolation);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = device_create_file(adev->dev, &dev_attr_run_cleaner_shader);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_gfx_sysfs_isolation_shader_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
device_remove_file(adev->dev, &dev_attr_enforce_isolation);
|
||||
device_remove_file(adev->dev, &dev_attr_run_cleaner_shader);
|
||||
}
|
||||
|
||||
int amdgpu_gfx_cleaner_shader_sw_init(struct amdgpu_device *adev,
|
||||
unsigned int cleaner_shader_size)
|
||||
{
|
||||
if (!adev->gfx.enable_cleaner_shader)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return amdgpu_bo_create_kernel(adev, cleaner_shader_size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->gfx.cleaner_shader_obj,
|
||||
&adev->gfx.cleaner_shader_gpu_addr,
|
||||
(void **)&adev->gfx.cleaner_shader_cpu_ptr);
|
||||
}
|
||||
|
||||
void amdgpu_gfx_cleaner_shader_sw_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
if (!adev->gfx.enable_cleaner_shader)
|
||||
return;
|
||||
|
||||
amdgpu_bo_free_kernel(&adev->gfx.cleaner_shader_obj,
|
||||
&adev->gfx.cleaner_shader_gpu_addr,
|
||||
(void **)&adev->gfx.cleaner_shader_cpu_ptr);
|
||||
}
|
||||
|
||||
void amdgpu_gfx_cleaner_shader_init(struct amdgpu_device *adev,
|
||||
unsigned int cleaner_shader_size,
|
||||
const void *cleaner_shader_ptr)
|
||||
{
|
||||
if (!adev->gfx.enable_cleaner_shader)
|
||||
return;
|
||||
|
||||
if (adev->gfx.cleaner_shader_cpu_ptr && cleaner_shader_ptr)
|
||||
memcpy_toio(adev->gfx.cleaner_shader_cpu_ptr, cleaner_shader_ptr,
|
||||
cleaner_shader_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_gfx_kfd_sch_ctrl - Control the KFD scheduler from the KGD (Graphics Driver)
|
||||
* @adev: amdgpu_device pointer
|
||||
* @idx: Index of the scheduler to control
|
||||
* @enable: Whether to enable or disable the KFD scheduler
|
||||
*
|
||||
* This function is used to control the KFD (Kernel Fusion Driver) scheduler
|
||||
* from the KGD. It is part of the cleaner shader feature. This function plays
|
||||
* a key role in enforcing process isolation on the GPU.
|
||||
*
|
||||
* The function uses a reference count mechanism (kfd_sch_req_count) to keep
|
||||
* track of the number of requests to enable the KFD scheduler. When a request
|
||||
* to enable the KFD scheduler is made, the reference count is decremented.
|
||||
* When the reference count reaches zero, a delayed work is scheduled to
|
||||
* enforce isolation after a delay of GFX_SLICE_PERIOD.
|
||||
*
|
||||
* When a request to disable the KFD scheduler is made, the function first
|
||||
* checks if the reference count is zero. If it is, it cancels the delayed work
|
||||
* for enforcing isolation and checks if the KFD scheduler is active. If the
|
||||
* KFD scheduler is active, it sends a request to stop the KFD scheduler and
|
||||
* sets the KFD scheduler state to inactive. Then, it increments the reference
|
||||
* count.
|
||||
*
|
||||
* The function is synchronized using the kfd_sch_mutex to ensure that the KFD
|
||||
* scheduler state and reference count are updated atomically.
|
||||
*
|
||||
* Note: If the reference count is already zero when a request to enable the
|
||||
* KFD scheduler is made, it means there's an imbalance bug somewhere. The
|
||||
* function triggers a warning in this case.
|
||||
*/
|
||||
static void amdgpu_gfx_kfd_sch_ctrl(struct amdgpu_device *adev, u32 idx,
|
||||
bool enable)
|
||||
{
|
||||
mutex_lock(&adev->gfx.kfd_sch_mutex);
|
||||
|
||||
if (enable) {
|
||||
/* If the count is already 0, it means there's an imbalance bug somewhere.
|
||||
* Note that the bug may be in a different caller than the one which triggers the
|
||||
* WARN_ON_ONCE.
|
||||
*/
|
||||
if (WARN_ON_ONCE(adev->gfx.kfd_sch_req_count[idx] == 0)) {
|
||||
dev_err(adev->dev, "Attempted to enable KFD scheduler when reference count is already zero\n");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
adev->gfx.kfd_sch_req_count[idx]--;
|
||||
|
||||
if (adev->gfx.kfd_sch_req_count[idx] == 0 &&
|
||||
adev->gfx.kfd_sch_inactive[idx]) {
|
||||
schedule_delayed_work(&adev->gfx.enforce_isolation[idx].work,
|
||||
GFX_SLICE_PERIOD);
|
||||
}
|
||||
} else {
|
||||
if (adev->gfx.kfd_sch_req_count[idx] == 0) {
|
||||
cancel_delayed_work_sync(&adev->gfx.enforce_isolation[idx].work);
|
||||
if (!adev->gfx.kfd_sch_inactive[idx]) {
|
||||
amdgpu_amdkfd_stop_sched(adev, idx);
|
||||
adev->gfx.kfd_sch_inactive[idx] = true;
|
||||
}
|
||||
}
|
||||
|
||||
adev->gfx.kfd_sch_req_count[idx]++;
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&adev->gfx.kfd_sch_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_gfx_enforce_isolation_handler - work handler for enforcing shader isolation
|
||||
*
|
||||
* @work: work_struct.
|
||||
*
|
||||
* This function is the work handler for enforcing shader isolation on AMD GPUs.
|
||||
* It counts the number of emitted fences for each GFX and compute ring. If there
|
||||
* are any fences, it schedules the `enforce_isolation_work` to be run after a
|
||||
* delay of `GFX_SLICE_PERIOD`. If there are no fences, it signals the Kernel Fusion
|
||||
* Driver (KFD) to resume the runqueue. The function is synchronized using the
|
||||
* `enforce_isolation_mutex`.
|
||||
*/
|
||||
void amdgpu_gfx_enforce_isolation_handler(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_isolation_work *isolation_work =
|
||||
container_of(work, struct amdgpu_isolation_work, work.work);
|
||||
struct amdgpu_device *adev = isolation_work->adev;
|
||||
u32 i, idx, fences = 0;
|
||||
|
||||
if (isolation_work->xcp_id == AMDGPU_XCP_NO_PARTITION)
|
||||
idx = 0;
|
||||
else
|
||||
idx = isolation_work->xcp_id;
|
||||
|
||||
if (idx >= MAX_XCP)
|
||||
return;
|
||||
|
||||
mutex_lock(&adev->enforce_isolation_mutex);
|
||||
for (i = 0; i < AMDGPU_MAX_GFX_RINGS; ++i) {
|
||||
if (isolation_work->xcp_id == adev->gfx.gfx_ring[i].xcp_id)
|
||||
fences += amdgpu_fence_count_emitted(&adev->gfx.gfx_ring[i]);
|
||||
}
|
||||
for (i = 0; i < (AMDGPU_MAX_COMPUTE_RINGS * AMDGPU_MAX_GC_INSTANCES); ++i) {
|
||||
if (isolation_work->xcp_id == adev->gfx.compute_ring[i].xcp_id)
|
||||
fences += amdgpu_fence_count_emitted(&adev->gfx.compute_ring[i]);
|
||||
}
|
||||
if (fences) {
|
||||
schedule_delayed_work(&adev->gfx.enforce_isolation[idx].work,
|
||||
GFX_SLICE_PERIOD);
|
||||
} else {
|
||||
/* Tell KFD to resume the runqueue */
|
||||
if (adev->kfd.init_complete) {
|
||||
WARN_ON_ONCE(!adev->gfx.kfd_sch_inactive[idx]);
|
||||
WARN_ON_ONCE(adev->gfx.kfd_sch_req_count[idx]);
|
||||
amdgpu_amdkfd_start_sched(adev, idx);
|
||||
adev->gfx.kfd_sch_inactive[idx] = false;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&adev->enforce_isolation_mutex);
|
||||
}
|
||||
|
||||
void amdgpu_gfx_enforce_isolation_ring_begin_use(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
u32 idx;
|
||||
|
||||
if (!adev->gfx.enable_cleaner_shader)
|
||||
return;
|
||||
|
||||
if (ring->xcp_id == AMDGPU_XCP_NO_PARTITION)
|
||||
idx = 0;
|
||||
else
|
||||
idx = ring->xcp_id;
|
||||
|
||||
if (idx >= MAX_XCP)
|
||||
return;
|
||||
|
||||
mutex_lock(&adev->enforce_isolation_mutex);
|
||||
if (adev->enforce_isolation[idx]) {
|
||||
if (adev->kfd.init_complete)
|
||||
amdgpu_gfx_kfd_sch_ctrl(adev, idx, false);
|
||||
}
|
||||
mutex_unlock(&adev->enforce_isolation_mutex);
|
||||
}
|
||||
|
||||
void amdgpu_gfx_enforce_isolation_ring_end_use(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
u32 idx;
|
||||
|
||||
if (!adev->gfx.enable_cleaner_shader)
|
||||
return;
|
||||
|
||||
if (ring->xcp_id == AMDGPU_XCP_NO_PARTITION)
|
||||
idx = 0;
|
||||
else
|
||||
idx = ring->xcp_id;
|
||||
|
||||
if (idx >= MAX_XCP)
|
||||
return;
|
||||
|
||||
mutex_lock(&adev->enforce_isolation_mutex);
|
||||
if (adev->enforce_isolation[idx]) {
|
||||
if (adev->kfd.init_complete)
|
||||
amdgpu_gfx_kfd_sch_ctrl(adev, idx, true);
|
||||
}
|
||||
mutex_unlock(&adev->enforce_isolation_mutex);
|
||||
}
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "soc15.h"
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_ring_mux.h"
|
||||
#include "amdgpu_xcp.h"
|
||||
|
||||
/* GFX current status */
|
||||
#define AMDGPU_GFX_NORMAL_MODE 0x00000000L
|
||||
@ -138,6 +139,10 @@ struct kiq_pm4_funcs {
|
||||
void (*kiq_invalidate_tlbs)(struct amdgpu_ring *kiq_ring,
|
||||
uint16_t pasid, uint32_t flush_type,
|
||||
bool all_hub);
|
||||
void (*kiq_reset_hw_queue)(struct amdgpu_ring *kiq_ring,
|
||||
uint32_t queue_type, uint32_t me_id,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t xcc_id, uint32_t vmid);
|
||||
/* Packet sizes */
|
||||
int set_resources_size;
|
||||
int map_queues_size;
|
||||
@ -240,6 +245,12 @@ struct amdgpu_gfx_config {
|
||||
uint32_t gc_tcp_size_per_cu;
|
||||
uint32_t gc_num_cu_per_sqc;
|
||||
uint32_t gc_tcc_size;
|
||||
uint32_t gc_tcp_cache_line_size;
|
||||
uint32_t gc_instruction_cache_size_per_sqc;
|
||||
uint32_t gc_instruction_cache_line_size;
|
||||
uint32_t gc_scalar_data_cache_size_per_sqc;
|
||||
uint32_t gc_scalar_data_cache_line_size;
|
||||
uint32_t gc_tcc_cache_line_size;
|
||||
};
|
||||
|
||||
struct amdgpu_cu_info {
|
||||
@ -339,6 +350,12 @@ struct amdgpu_me {
|
||||
DECLARE_BITMAP(queue_bitmap, AMDGPU_MAX_GFX_QUEUES);
|
||||
};
|
||||
|
||||
struct amdgpu_isolation_work {
|
||||
struct amdgpu_device *adev;
|
||||
u32 xcp_id;
|
||||
struct delayed_work work;
|
||||
};
|
||||
|
||||
struct amdgpu_gfx {
|
||||
struct mutex gpu_clock_mutex;
|
||||
struct amdgpu_gfx_config config;
|
||||
@ -391,6 +408,7 @@ struct amdgpu_gfx {
|
||||
struct amdgpu_irq_src eop_irq;
|
||||
struct amdgpu_irq_src priv_reg_irq;
|
||||
struct amdgpu_irq_src priv_inst_irq;
|
||||
struct amdgpu_irq_src bad_op_irq;
|
||||
struct amdgpu_irq_src cp_ecc_error_irq;
|
||||
struct amdgpu_irq_src sq_irq;
|
||||
struct amdgpu_irq_src rlc_gc_fed_irq;
|
||||
@ -439,6 +457,21 @@ struct amdgpu_gfx {
|
||||
uint32_t *ip_dump_core;
|
||||
uint32_t *ip_dump_compute_queues;
|
||||
uint32_t *ip_dump_gfx_queues;
|
||||
|
||||
struct mutex reset_sem_mutex;
|
||||
|
||||
/* cleaner shader */
|
||||
struct amdgpu_bo *cleaner_shader_obj;
|
||||
unsigned int cleaner_shader_size;
|
||||
u64 cleaner_shader_gpu_addr;
|
||||
void *cleaner_shader_cpu_ptr;
|
||||
const void *cleaner_shader_ptr;
|
||||
bool enable_cleaner_shader;
|
||||
struct amdgpu_isolation_work enforce_isolation[MAX_XCP];
|
||||
/* Mutex for synchronizing KFD scheduler operations */
|
||||
struct mutex kfd_sch_mutex;
|
||||
u64 kfd_sch_req_count[MAX_XCP];
|
||||
bool kfd_sch_inactive[MAX_XCP];
|
||||
};
|
||||
|
||||
struct amdgpu_gfx_ras_reg_entry {
|
||||
@ -540,6 +573,17 @@ void amdgpu_gfx_ras_error_func(struct amdgpu_device *adev,
|
||||
void *ras_error_status,
|
||||
void (*func)(struct amdgpu_device *adev, void *ras_error_status,
|
||||
int xcc_id));
|
||||
int amdgpu_gfx_cleaner_shader_sw_init(struct amdgpu_device *adev,
|
||||
unsigned int cleaner_shader_size);
|
||||
void amdgpu_gfx_cleaner_shader_sw_fini(struct amdgpu_device *adev);
|
||||
void amdgpu_gfx_cleaner_shader_init(struct amdgpu_device *adev,
|
||||
unsigned int cleaner_shader_size,
|
||||
const void *cleaner_shader_ptr);
|
||||
int amdgpu_gfx_sysfs_isolation_shader_init(struct amdgpu_device *adev);
|
||||
void amdgpu_gfx_sysfs_isolation_shader_fini(struct amdgpu_device *adev);
|
||||
void amdgpu_gfx_enforce_isolation_handler(struct work_struct *work);
|
||||
void amdgpu_gfx_enforce_isolation_ring_begin_use(struct amdgpu_ring *ring);
|
||||
void amdgpu_gfx_enforce_isolation_ring_end_use(struct amdgpu_ring *ring);
|
||||
|
||||
static inline const char *amdgpu_gfx_compute_mode_desc(int mode)
|
||||
{
|
||||
|
@ -38,8 +38,6 @@ struct amdgpu_gfxhub_funcs {
|
||||
void (*mode2_save_regs)(struct amdgpu_device *adev);
|
||||
void (*mode2_restore_regs)(struct amdgpu_device *adev);
|
||||
void (*halt)(struct amdgpu_device *adev);
|
||||
bool (*query_utcl2_poison_status)(struct amdgpu_device *adev,
|
||||
int xcc_id);
|
||||
};
|
||||
|
||||
struct amdgpu_gfxhub {
|
||||
|
@ -786,7 +786,8 @@ void amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev,
|
||||
goto failed_kiq;
|
||||
|
||||
might_sleep();
|
||||
while (r < 1 && cnt++ < MAX_KIQ_REG_TRY) {
|
||||
while (r < 1 && cnt++ < MAX_KIQ_REG_TRY &&
|
||||
!amdgpu_reset_pending(adev->reset_domain)) {
|
||||
|
||||
msleep(MAX_KIQ_REG_BAILOUT_INTERVAL);
|
||||
r = amdgpu_fence_wait_polling(ring, seq, MAX_KIQ_REG_WAIT);
|
||||
|
@ -424,7 +424,7 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
|
||||
if (r || !idle)
|
||||
goto error;
|
||||
|
||||
if (amdgpu_vmid_uses_reserved(vm, vmhub)) {
|
||||
if (amdgpu_vmid_uses_reserved(adev, vm, vmhub)) {
|
||||
r = amdgpu_vmid_grab_reserved(vm, ring, job, &id, fence);
|
||||
if (r || !id)
|
||||
goto error;
|
||||
@ -476,15 +476,19 @@ error:
|
||||
|
||||
/*
|
||||
* amdgpu_vmid_uses_reserved - check if a VM will use a reserved VMID
|
||||
* @adev: amdgpu_device pointer
|
||||
* @vm: the VM to check
|
||||
* @vmhub: the VMHUB which will be used
|
||||
*
|
||||
* Returns: True if the VM will use a reserved VMID.
|
||||
*/
|
||||
bool amdgpu_vmid_uses_reserved(struct amdgpu_vm *vm, unsigned int vmhub)
|
||||
bool amdgpu_vmid_uses_reserved(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm, unsigned int vmhub)
|
||||
{
|
||||
return vm->reserved_vmid[vmhub] ||
|
||||
(enforce_isolation && (vmhub == AMDGPU_GFXHUB(0)));
|
||||
(adev->enforce_isolation[(vm->root.bo->xcp_id != AMDGPU_XCP_NO_PARTITION) ?
|
||||
vm->root.bo->xcp_id : 0] &&
|
||||
AMDGPU_IS_GFXHUB(vmhub));
|
||||
}
|
||||
|
||||
int amdgpu_vmid_alloc_reserved(struct amdgpu_device *adev,
|
||||
@ -600,9 +604,10 @@ void amdgpu_vmid_mgr_init(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
/* alloc a default reserved vmid to enforce isolation */
|
||||
if (enforce_isolation)
|
||||
amdgpu_vmid_alloc_reserved(adev, AMDGPU_GFXHUB(0));
|
||||
|
||||
for (i = 0; i < (adev->xcp_mgr ? adev->xcp_mgr->num_xcps : 1); i++) {
|
||||
if (adev->enforce_isolation[i])
|
||||
amdgpu_vmid_alloc_reserved(adev, AMDGPU_GFXHUB(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,7 +78,8 @@ void amdgpu_pasid_free_delayed(struct dma_resv *resv,
|
||||
|
||||
bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev,
|
||||
struct amdgpu_vmid *id);
|
||||
bool amdgpu_vmid_uses_reserved(struct amdgpu_vm *vm, unsigned int vmhub);
|
||||
bool amdgpu_vmid_uses_reserved(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm, unsigned int vmhub);
|
||||
int amdgpu_vmid_alloc_reserved(struct amdgpu_device *adev,
|
||||
unsigned vmhub);
|
||||
void amdgpu_vmid_free_reserved(struct amdgpu_device *adev,
|
||||
|
@ -49,6 +49,7 @@ struct amdgpu_isp {
|
||||
const struct isp_funcs *funcs;
|
||||
struct mfd_cell *isp_cell;
|
||||
struct resource *isp_res;
|
||||
struct resource *isp_i2c_res;
|
||||
struct isp_platform_data *isp_pdata;
|
||||
unsigned int harvest_config;
|
||||
const struct firmware *fw;
|
||||
|
@ -72,6 +72,26 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
|
||||
|
||||
dma_fence_set_error(&s_job->s_fence->finished, -ETIME);
|
||||
|
||||
/* attempt a per ring reset */
|
||||
if (amdgpu_gpu_recovery &&
|
||||
ring->funcs->reset) {
|
||||
/* stop the scheduler, but don't mess with the
|
||||
* bad job yet because if ring reset fails
|
||||
* we'll fall back to full GPU reset.
|
||||
*/
|
||||
drm_sched_wqueue_stop(&ring->sched);
|
||||
r = amdgpu_ring_reset(ring, job->vmid);
|
||||
if (!r) {
|
||||
if (amdgpu_ring_sched_ready(ring))
|
||||
drm_sched_stop(&ring->sched, s_job);
|
||||
atomic_inc(&ring->adev->gpu_reset_counter);
|
||||
amdgpu_fence_driver_force_completion(ring);
|
||||
if (amdgpu_ring_sched_ready(ring))
|
||||
drm_sched_start(&ring->sched);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (amdgpu_device_should_recover_gpu(ring->adev)) {
|
||||
struct amdgpu_reset_context reset_context;
|
||||
memset(&reset_context, 0, sizeof(reset_context));
|
||||
|
@ -76,6 +76,9 @@ struct amdgpu_job {
|
||||
/* job_run_counter >= 1 means a resubmit job */
|
||||
uint32_t job_run_counter;
|
||||
|
||||
/* enforce isolation */
|
||||
bool enforce_isolation;
|
||||
|
||||
uint32_t num_ibs;
|
||||
struct amdgpu_ib ibs[];
|
||||
};
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "amdgpu_gem.h"
|
||||
#include "amdgpu_display.h"
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_reset.h"
|
||||
#include "amd_pcie.h"
|
||||
|
||||
void amdgpu_unregister_gpu_instance(struct amdgpu_device *adev)
|
||||
@ -778,6 +779,7 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
? -EFAULT : 0;
|
||||
}
|
||||
case AMDGPU_INFO_READ_MMR_REG: {
|
||||
int ret = 0;
|
||||
unsigned int n, alloc_size;
|
||||
uint32_t *regs;
|
||||
unsigned int se_num = (info->read_mmr_reg.instance >>
|
||||
@ -787,24 +789,37 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
AMDGPU_INFO_MMR_SH_INDEX_SHIFT) &
|
||||
AMDGPU_INFO_MMR_SH_INDEX_MASK;
|
||||
|
||||
if (!down_read_trylock(&adev->reset_domain->sem))
|
||||
return -ENOENT;
|
||||
|
||||
/* set full masks if the userspace set all bits
|
||||
* in the bitfields
|
||||
*/
|
||||
if (se_num == AMDGPU_INFO_MMR_SE_INDEX_MASK)
|
||||
if (se_num == AMDGPU_INFO_MMR_SE_INDEX_MASK) {
|
||||
se_num = 0xffffffff;
|
||||
else if (se_num >= AMDGPU_GFX_MAX_SE)
|
||||
return -EINVAL;
|
||||
if (sh_num == AMDGPU_INFO_MMR_SH_INDEX_MASK)
|
||||
sh_num = 0xffffffff;
|
||||
else if (sh_num >= AMDGPU_GFX_MAX_SH_PER_SE)
|
||||
return -EINVAL;
|
||||
} else if (se_num >= AMDGPU_GFX_MAX_SE) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (info->read_mmr_reg.count > 128)
|
||||
return -EINVAL;
|
||||
if (sh_num == AMDGPU_INFO_MMR_SH_INDEX_MASK) {
|
||||
sh_num = 0xffffffff;
|
||||
} else if (sh_num >= AMDGPU_GFX_MAX_SH_PER_SE) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (info->read_mmr_reg.count > 128) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
regs = kmalloc_array(info->read_mmr_reg.count, sizeof(*regs), GFP_KERNEL);
|
||||
if (!regs)
|
||||
return -ENOMEM;
|
||||
if (!regs) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
alloc_size = info->read_mmr_reg.count * sizeof(*regs);
|
||||
|
||||
amdgpu_gfx_off_ctrl(adev, false);
|
||||
@ -816,13 +831,17 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
info->read_mmr_reg.dword_offset + i);
|
||||
kfree(regs);
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
n = copy_to_user(out, regs, min(size, alloc_size));
|
||||
kfree(regs);
|
||||
return n ? -EFAULT : 0;
|
||||
ret = (n ? -EFAULT : 0);
|
||||
out:
|
||||
up_read(&adev->reset_domain->sem);
|
||||
return ret;
|
||||
}
|
||||
case AMDGPU_INFO_DEV_INFO: {
|
||||
struct drm_amdgpu_info_device *dev_info;
|
||||
|
@ -396,7 +396,6 @@ static int amdgpu_mca_smu_parse_mca_error_count(struct amdgpu_device *adev, enum
|
||||
static int amdgpu_mca_dispatch_mca_set(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type,
|
||||
struct mca_bank_set *mca_set, struct ras_err_data *err_data)
|
||||
{
|
||||
struct ras_err_addr err_addr;
|
||||
struct amdgpu_smuio_mcm_config_info mcm_info;
|
||||
struct mca_bank_node *node, *tmp;
|
||||
struct mca_bank_entry *entry;
|
||||
@ -421,27 +420,20 @@ static int amdgpu_mca_dispatch_mca_set(struct amdgpu_device *adev, enum amdgpu_r
|
||||
continue;
|
||||
|
||||
memset(&mcm_info, 0, sizeof(mcm_info));
|
||||
memset(&err_addr, 0, sizeof(err_addr));
|
||||
|
||||
mcm_info.socket_id = entry->info.socket_id;
|
||||
mcm_info.die_id = entry->info.aid;
|
||||
|
||||
if (blk == AMDGPU_RAS_BLOCK__UMC) {
|
||||
err_addr.err_status = entry->regs[MCA_REG_IDX_STATUS];
|
||||
err_addr.err_ipid = entry->regs[MCA_REG_IDX_IPID];
|
||||
err_addr.err_addr = entry->regs[MCA_REG_IDX_ADDR];
|
||||
}
|
||||
|
||||
if (type == AMDGPU_MCA_ERROR_TYPE_UE) {
|
||||
amdgpu_ras_error_statistic_ue_count(err_data,
|
||||
&mcm_info, &err_addr, (uint64_t)count);
|
||||
&mcm_info, (uint64_t)count);
|
||||
} else {
|
||||
if (amdgpu_mca_is_deferred_error(adev, entry->regs[MCA_REG_IDX_STATUS]))
|
||||
amdgpu_ras_error_statistic_de_count(err_data,
|
||||
&mcm_info, &err_addr, (uint64_t)count);
|
||||
&mcm_info, (uint64_t)count);
|
||||
else
|
||||
amdgpu_ras_error_statistic_ce_count(err_data,
|
||||
&mcm_info, &err_addr, (uint64_t)count);
|
||||
&mcm_info, (uint64_t)count);
|
||||
}
|
||||
|
||||
amdgpu_mca_bank_set_remove_node(mca_set, node);
|
||||
|
@ -501,60 +501,50 @@ int amdgpu_mes_remove_gang(struct amdgpu_device *adev, int gang_id)
|
||||
|
||||
int amdgpu_mes_suspend(struct amdgpu_device *adev)
|
||||
{
|
||||
struct idr *idp;
|
||||
struct amdgpu_mes_process *process;
|
||||
struct amdgpu_mes_gang *gang;
|
||||
struct mes_suspend_gang_input input;
|
||||
int r, pasid;
|
||||
int r;
|
||||
|
||||
if (!amdgpu_mes_suspend_resume_all_supported(adev))
|
||||
return 0;
|
||||
|
||||
memset(&input, 0x0, sizeof(struct mes_suspend_gang_input));
|
||||
input.suspend_all_gangs = 1;
|
||||
|
||||
/*
|
||||
* Avoid taking any other locks under MES lock to avoid circular
|
||||
* lock dependencies.
|
||||
*/
|
||||
amdgpu_mes_lock(&adev->mes);
|
||||
|
||||
idp = &adev->mes.pasid_idr;
|
||||
|
||||
idr_for_each_entry(idp, process, pasid) {
|
||||
list_for_each_entry(gang, &process->gang_list, list) {
|
||||
r = adev->mes.funcs->suspend_gang(&adev->mes, &input);
|
||||
if (r)
|
||||
DRM_ERROR("failed to suspend pasid %d gangid %d",
|
||||
pasid, gang->gang_id);
|
||||
}
|
||||
}
|
||||
|
||||
r = adev->mes.funcs->suspend_gang(&adev->mes, &input);
|
||||
amdgpu_mes_unlock(&adev->mes);
|
||||
return 0;
|
||||
if (r)
|
||||
DRM_ERROR("failed to suspend all gangs");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_mes_resume(struct amdgpu_device *adev)
|
||||
{
|
||||
struct idr *idp;
|
||||
struct amdgpu_mes_process *process;
|
||||
struct amdgpu_mes_gang *gang;
|
||||
struct mes_resume_gang_input input;
|
||||
int r, pasid;
|
||||
int r;
|
||||
|
||||
if (!amdgpu_mes_suspend_resume_all_supported(adev))
|
||||
return 0;
|
||||
|
||||
memset(&input, 0x0, sizeof(struct mes_resume_gang_input));
|
||||
input.resume_all_gangs = 1;
|
||||
|
||||
/*
|
||||
* Avoid taking any other locks under MES lock to avoid circular
|
||||
* lock dependencies.
|
||||
*/
|
||||
amdgpu_mes_lock(&adev->mes);
|
||||
|
||||
idp = &adev->mes.pasid_idr;
|
||||
|
||||
idr_for_each_entry(idp, process, pasid) {
|
||||
list_for_each_entry(gang, &process->gang_list, list) {
|
||||
r = adev->mes.funcs->resume_gang(&adev->mes, &input);
|
||||
if (r)
|
||||
DRM_ERROR("failed to resume pasid %d gangid %d",
|
||||
pasid, gang->gang_id);
|
||||
}
|
||||
}
|
||||
|
||||
r = adev->mes.funcs->resume_gang(&adev->mes, &input);
|
||||
amdgpu_mes_unlock(&adev->mes);
|
||||
return 0;
|
||||
if (r)
|
||||
DRM_ERROR("failed to resume all gangs");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int amdgpu_mes_queue_alloc_mqd(struct amdgpu_device *adev,
|
||||
@ -793,6 +783,49 @@ int amdgpu_mes_remove_hw_queue(struct amdgpu_device *adev, int queue_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_mes_reset_hw_queue(struct amdgpu_device *adev, int queue_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct amdgpu_mes_queue *queue;
|
||||
struct amdgpu_mes_gang *gang;
|
||||
struct mes_reset_queue_input queue_input;
|
||||
int r;
|
||||
|
||||
/*
|
||||
* Avoid taking any other locks under MES lock to avoid circular
|
||||
* lock dependencies.
|
||||
*/
|
||||
amdgpu_mes_lock(&adev->mes);
|
||||
|
||||
/* remove the mes gang from idr list */
|
||||
spin_lock_irqsave(&adev->mes.queue_id_lock, flags);
|
||||
|
||||
queue = idr_find(&adev->mes.queue_id_idr, queue_id);
|
||||
if (!queue) {
|
||||
spin_unlock_irqrestore(&adev->mes.queue_id_lock, flags);
|
||||
amdgpu_mes_unlock(&adev->mes);
|
||||
DRM_ERROR("queue id %d doesn't exist\n", queue_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
spin_unlock_irqrestore(&adev->mes.queue_id_lock, flags);
|
||||
|
||||
DRM_DEBUG("try to reset queue, doorbell off = 0x%llx\n",
|
||||
queue->doorbell_off);
|
||||
|
||||
gang = queue->gang;
|
||||
queue_input.doorbell_offset = queue->doorbell_off;
|
||||
queue_input.gang_context_addr = gang->gang_ctx_gpu_addr;
|
||||
|
||||
r = adev->mes.funcs->reset_hw_queue(&adev->mes, &queue_input);
|
||||
if (r)
|
||||
DRM_ERROR("failed to reset hardware queue, queue id = %d\n",
|
||||
queue_id);
|
||||
|
||||
amdgpu_mes_unlock(&adev->mes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_mes_map_legacy_queue(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring)
|
||||
{
|
||||
@ -838,6 +871,30 @@ int amdgpu_mes_unmap_legacy_queue(struct amdgpu_device *adev,
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_mes_reset_legacy_queue(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring,
|
||||
unsigned int vmid)
|
||||
{
|
||||
struct mes_reset_legacy_queue_input queue_input;
|
||||
int r;
|
||||
|
||||
memset(&queue_input, 0, sizeof(queue_input));
|
||||
|
||||
queue_input.queue_type = ring->funcs->type;
|
||||
queue_input.doorbell_offset = ring->doorbell_index;
|
||||
queue_input.pipe_id = ring->pipe;
|
||||
queue_input.queue_id = ring->queue;
|
||||
queue_input.mqd_addr = amdgpu_bo_gpu_offset(ring->mqd_obj);
|
||||
queue_input.wptr_addr = ring->wptr_gpu_addr;
|
||||
queue_input.vmid = vmid;
|
||||
|
||||
r = adev->mes.funcs->reset_legacy_queue(&adev->mes, &queue_input);
|
||||
if (r)
|
||||
DRM_ERROR("failed to reset legacy queue\n");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
uint32_t amdgpu_mes_rreg(struct amdgpu_device *adev, uint32_t reg)
|
||||
{
|
||||
struct mes_misc_op_input op_input;
|
||||
@ -1533,7 +1590,7 @@ int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe)
|
||||
pipe == AMDGPU_MES_SCHED_PIPE ? "" : "1");
|
||||
}
|
||||
|
||||
r = amdgpu_ucode_request(adev, &adev->mes.fw[pipe], fw_name);
|
||||
r = amdgpu_ucode_request(adev, &adev->mes.fw[pipe], "%s", fw_name);
|
||||
if (r && need_retry && pipe == AMDGPU_MES_SCHED_PIPE) {
|
||||
dev_info(adev->dev, "try to fall back to %s_mes.bin\n", ucode_prefix);
|
||||
r = amdgpu_ucode_request(adev, &adev->mes.fw[pipe],
|
||||
@ -1584,6 +1641,19 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
bool amdgpu_mes_suspend_resume_all_supported(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t mes_rev = adev->mes.sched_version & AMDGPU_MES_VERSION_MASK;
|
||||
bool is_supported = false;
|
||||
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(11, 0, 0) &&
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(12, 0, 0) &&
|
||||
mes_rev >= 0x63)
|
||||
is_supported = true;
|
||||
|
||||
return is_supported;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
||||
static int amdgpu_debugfs_mes_event_log_show(struct seq_file *m, void *unused)
|
||||
|
@ -248,6 +248,11 @@ struct mes_remove_queue_input {
|
||||
uint64_t gang_context_addr;
|
||||
};
|
||||
|
||||
struct mes_reset_queue_input {
|
||||
uint32_t doorbell_offset;
|
||||
uint64_t gang_context_addr;
|
||||
};
|
||||
|
||||
struct mes_map_legacy_queue_input {
|
||||
uint32_t queue_type;
|
||||
uint32_t doorbell_offset;
|
||||
@ -279,6 +284,16 @@ struct mes_resume_gang_input {
|
||||
uint64_t gang_context_addr;
|
||||
};
|
||||
|
||||
struct mes_reset_legacy_queue_input {
|
||||
uint32_t queue_type;
|
||||
uint32_t doorbell_offset;
|
||||
uint32_t pipe_id;
|
||||
uint32_t queue_id;
|
||||
uint64_t mqd_addr;
|
||||
uint64_t wptr_addr;
|
||||
uint32_t vmid;
|
||||
};
|
||||
|
||||
enum mes_misc_opcode {
|
||||
MES_MISC_OP_WRITE_REG,
|
||||
MES_MISC_OP_READ_REG,
|
||||
@ -347,6 +362,12 @@ struct amdgpu_mes_funcs {
|
||||
|
||||
int (*misc_op)(struct amdgpu_mes *mes,
|
||||
struct mes_misc_op_input *input);
|
||||
|
||||
int (*reset_legacy_queue)(struct amdgpu_mes *mes,
|
||||
struct mes_reset_legacy_queue_input *input);
|
||||
|
||||
int (*reset_hw_queue)(struct amdgpu_mes *mes,
|
||||
struct mes_reset_queue_input *input);
|
||||
};
|
||||
|
||||
#define amdgpu_mes_kiq_hw_init(adev) (adev)->mes.kiq_hw_init((adev))
|
||||
@ -374,6 +395,7 @@ int amdgpu_mes_add_hw_queue(struct amdgpu_device *adev, int gang_id,
|
||||
struct amdgpu_mes_queue_properties *qprops,
|
||||
int *queue_id);
|
||||
int amdgpu_mes_remove_hw_queue(struct amdgpu_device *adev, int queue_id);
|
||||
int amdgpu_mes_reset_hw_queue(struct amdgpu_device *adev, int queue_id);
|
||||
|
||||
int amdgpu_mes_map_legacy_queue(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring);
|
||||
@ -381,6 +403,9 @@ int amdgpu_mes_unmap_legacy_queue(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring,
|
||||
enum amdgpu_unmap_queues_action action,
|
||||
u64 gpu_addr, u64 seq);
|
||||
int amdgpu_mes_reset_legacy_queue(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring,
|
||||
unsigned int vmid);
|
||||
|
||||
uint32_t amdgpu_mes_rreg(struct amdgpu_device *adev, uint32_t reg);
|
||||
int amdgpu_mes_wreg(struct amdgpu_device *adev,
|
||||
@ -478,4 +503,6 @@ static inline void amdgpu_mes_unlock(struct amdgpu_mes *mes)
|
||||
memalloc_noreclaim_restore(mes->saved_flags);
|
||||
mutex_unlock(&mes->mutex_hidden);
|
||||
}
|
||||
|
||||
bool amdgpu_mes_suspend_resume_all_supported(struct amdgpu_device *adev);
|
||||
#endif /* __AMDGPU_MES_H__ */
|
||||
|
@ -63,8 +63,6 @@ struct amdgpu_mmhub_funcs {
|
||||
uint64_t page_table_base);
|
||||
void (*update_power_gating)(struct amdgpu_device *adev,
|
||||
bool enable);
|
||||
bool (*query_utcl2_poison_status)(struct amdgpu_device *adev,
|
||||
int hub_inst);
|
||||
};
|
||||
|
||||
struct amdgpu_mmhub {
|
||||
|
@ -51,6 +51,7 @@ struct amdgpu_encoder;
|
||||
struct amdgpu_router;
|
||||
struct amdgpu_hpd;
|
||||
struct edid;
|
||||
struct drm_edid;
|
||||
|
||||
#define to_amdgpu_crtc(x) container_of(x, struct amdgpu_crtc, base)
|
||||
#define to_amdgpu_connector(x) container_of(x, struct amdgpu_connector, base)
|
||||
@ -326,8 +327,7 @@ struct amdgpu_mode_info {
|
||||
/* FMT dithering */
|
||||
struct drm_property *dither_property;
|
||||
/* hardcoded DFP edid from BIOS */
|
||||
struct edid *bios_hardcoded_edid;
|
||||
int bios_hardcoded_edid_size;
|
||||
const struct drm_edid *bios_hardcoded_edid;
|
||||
|
||||
/* firmware flags */
|
||||
u32 firmware_flags;
|
||||
|
@ -90,6 +90,12 @@ struct amdgpu_bo_va {
|
||||
bool cleared;
|
||||
|
||||
bool is_xgmi;
|
||||
|
||||
/*
|
||||
* protected by vm reservation lock
|
||||
* if non-zero, cannot unmap from GPU because user queues may still access it
|
||||
*/
|
||||
unsigned int queue_refcount;
|
||||
};
|
||||
|
||||
struct amdgpu_bo {
|
||||
|
@ -1223,11 +1223,11 @@ static void amdgpu_rasmgr_error_data_statistic_update(struct ras_manager *obj, s
|
||||
for_each_ras_error(err_node, err_data) {
|
||||
err_info = &err_node->err_info;
|
||||
amdgpu_ras_error_statistic_de_count(&obj->err_data,
|
||||
&err_info->mcm_info, NULL, err_info->de_count);
|
||||
&err_info->mcm_info, err_info->de_count);
|
||||
amdgpu_ras_error_statistic_ce_count(&obj->err_data,
|
||||
&err_info->mcm_info, NULL, err_info->ce_count);
|
||||
&err_info->mcm_info, err_info->ce_count);
|
||||
amdgpu_ras_error_statistic_ue_count(&obj->err_data,
|
||||
&err_info->mcm_info, NULL, err_info->ue_count);
|
||||
&err_info->mcm_info, err_info->ue_count);
|
||||
}
|
||||
} else {
|
||||
/* for legacy asic path which doesn't has error source info */
|
||||
@ -2153,7 +2153,7 @@ static void amdgpu_ras_interrupt_poison_consumption_handler(struct ras_manager *
|
||||
/* gpu reset is fallback for failed and default cases.
|
||||
* For RMA case, amdgpu_umc_poison_handler will handle gpu reset.
|
||||
*/
|
||||
if (poison_stat && !con->is_rma) {
|
||||
if (poison_stat && !amdgpu_ras_is_rma(adev)) {
|
||||
event_id = amdgpu_ras_acquire_event_id(adev, type);
|
||||
RAS_EVENT_LOG(adev, event_id,
|
||||
"GPU reset for %s RAS poison consumption is issued!\n",
|
||||
@ -2881,9 +2881,6 @@ static void amdgpu_ras_ecc_log_init(struct ras_ecc_log_info *ecc_log)
|
||||
{
|
||||
mutex_init(&ecc_log->lock);
|
||||
|
||||
/* Set any value as siphash key */
|
||||
memset(&ecc_log->ecc_key, 0xad, sizeof(ecc_log->ecc_key));
|
||||
|
||||
INIT_RADIX_TREE(&ecc_log->de_page_tree, GFP_KERNEL);
|
||||
ecc_log->de_queried_count = 0;
|
||||
ecc_log->prev_de_queried_count = 0;
|
||||
@ -2948,7 +2945,7 @@ static void amdgpu_ras_do_page_retirement(struct work_struct *work)
|
||||
|
||||
amdgpu_ras_error_data_fini(&err_data);
|
||||
|
||||
if (err_cnt && con->is_rma)
|
||||
if (err_cnt && amdgpu_ras_is_rma(adev))
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
|
||||
amdgpu_ras_schedule_retirement_dwork(con,
|
||||
@ -3049,7 +3046,7 @@ static int amdgpu_ras_poison_consumption_handler(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
/* for RMA, amdgpu_ras_poison_creation_handler will trigger gpu reset */
|
||||
if (reset_flags && !con->is_rma) {
|
||||
if (reset_flags && !amdgpu_ras_is_rma(adev)) {
|
||||
if (reset_flags & AMDGPU_RAS_GPU_RESET_MODE1_RESET)
|
||||
reset = AMDGPU_RAS_GPU_RESET_MODE1_RESET;
|
||||
else if (reset_flags & AMDGPU_RAS_GPU_RESET_MODE2_RESET)
|
||||
@ -3195,7 +3192,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
|
||||
* This calling fails when is_rma is true or
|
||||
* ret != 0.
|
||||
*/
|
||||
if (con->is_rma || ret)
|
||||
if (amdgpu_ras_is_rma(adev) || ret)
|
||||
goto free;
|
||||
|
||||
if (con->eeprom_control.ras_num_recs) {
|
||||
@ -3244,7 +3241,7 @@ out:
|
||||
* Except error threshold exceeding case, other failure cases in this
|
||||
* function would not fail amdgpu driver init.
|
||||
*/
|
||||
if (!con->is_rma)
|
||||
if (!amdgpu_ras_is_rma(adev))
|
||||
ret = 0;
|
||||
else
|
||||
ret = -EINVAL;
|
||||
@ -4287,7 +4284,7 @@ int amdgpu_ras_reset_gpu(struct amdgpu_device *adev)
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
|
||||
/* mode1 is the only selection for RMA status */
|
||||
if (ras->is_rma) {
|
||||
if (amdgpu_ras_is_rma(adev)) {
|
||||
ras->gpu_reset_flags = 0;
|
||||
ras->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE1_RESET;
|
||||
}
|
||||
@ -4611,8 +4608,6 @@ static struct ras_err_info *amdgpu_ras_error_get_info(struct ras_err_data *err_d
|
||||
if (!err_node)
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&err_node->err_info.err_addr_list);
|
||||
|
||||
memcpy(&err_node->err_info.mcm_info, mcm_info, sizeof(*mcm_info));
|
||||
|
||||
err_data->err_list_count++;
|
||||
@ -4622,21 +4617,9 @@ static struct ras_err_info *amdgpu_ras_error_get_info(struct ras_err_data *err_d
|
||||
return &err_node->err_info;
|
||||
}
|
||||
|
||||
void amdgpu_ras_add_mca_err_addr(struct ras_err_info *err_info, struct ras_err_addr *err_addr)
|
||||
{
|
||||
/* This function will be retired. */
|
||||
return;
|
||||
}
|
||||
|
||||
void amdgpu_ras_del_mca_err_addr(struct ras_err_info *err_info, struct ras_err_addr *mca_err_addr)
|
||||
{
|
||||
list_del(&mca_err_addr->node);
|
||||
kfree(mca_err_addr);
|
||||
}
|
||||
|
||||
int amdgpu_ras_error_statistic_ue_count(struct ras_err_data *err_data,
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
struct ras_err_addr *err_addr, u64 count)
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
u64 count)
|
||||
{
|
||||
struct ras_err_info *err_info;
|
||||
|
||||
@ -4650,9 +4633,6 @@ int amdgpu_ras_error_statistic_ue_count(struct ras_err_data *err_data,
|
||||
if (!err_info)
|
||||
return -EINVAL;
|
||||
|
||||
if (err_addr && err_addr->err_status)
|
||||
amdgpu_ras_add_mca_err_addr(err_info, err_addr);
|
||||
|
||||
err_info->ue_count += count;
|
||||
err_data->ue_count += count;
|
||||
|
||||
@ -4660,8 +4640,8 @@ int amdgpu_ras_error_statistic_ue_count(struct ras_err_data *err_data,
|
||||
}
|
||||
|
||||
int amdgpu_ras_error_statistic_ce_count(struct ras_err_data *err_data,
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
struct ras_err_addr *err_addr, u64 count)
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
u64 count)
|
||||
{
|
||||
struct ras_err_info *err_info;
|
||||
|
||||
@ -4682,8 +4662,8 @@ int amdgpu_ras_error_statistic_ce_count(struct ras_err_data *err_data,
|
||||
}
|
||||
|
||||
int amdgpu_ras_error_statistic_de_count(struct ras_err_data *err_data,
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
struct ras_err_addr *err_addr, u64 count)
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
u64 count)
|
||||
{
|
||||
struct ras_err_info *err_info;
|
||||
|
||||
@ -4697,9 +4677,6 @@ int amdgpu_ras_error_statistic_de_count(struct ras_err_data *err_data,
|
||||
if (!err_info)
|
||||
return -EINVAL;
|
||||
|
||||
if (err_addr && err_addr->err_status)
|
||||
amdgpu_ras_add_mca_err_addr(err_info, err_addr);
|
||||
|
||||
err_info->de_count += count;
|
||||
err_data->de_count += count;
|
||||
|
||||
@ -4771,6 +4748,16 @@ static void amdgpu_ras_boot_time_error_reporting(struct amdgpu_device *adev,
|
||||
dev_info(adev->dev,
|
||||
"socket: %d, aid: %d, hbm: %d, fw_status: 0x%x, hbm bist test failed\n",
|
||||
socket_id, aid_id, hbm_id, fw_status);
|
||||
|
||||
if (AMDGPU_RAS_GPU_ERR_DATA_ABORT(boot_error))
|
||||
dev_info(adev->dev,
|
||||
"socket: %d, aid: %d, fw_status: 0x%x, data abort exception\n",
|
||||
socket_id, aid_id, fw_status);
|
||||
|
||||
if (AMDGPU_RAS_GPU_ERR_UNKNOWN(boot_error))
|
||||
dev_info(adev->dev,
|
||||
"socket: %d, aid: %d, fw_status: 0x%x, unknown boot time errors\n",
|
||||
socket_id, aid_id, fw_status);
|
||||
}
|
||||
|
||||
static bool amdgpu_ras_boot_error_detected(struct amdgpu_device *adev,
|
||||
@ -4837,3 +4824,13 @@ void amdgpu_ras_event_log_print(struct amdgpu_device *adev, u64 event_id,
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
bool amdgpu_ras_is_rma(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
|
||||
if (!con)
|
||||
return false;
|
||||
|
||||
return con->is_rma;
|
||||
}
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/radix-tree.h>
|
||||
#include <linux/siphash.h>
|
||||
#include "ta_ras_if.h"
|
||||
#include "amdgpu_ras_eeprom.h"
|
||||
#include "amdgpu_smuio.h"
|
||||
@ -47,6 +46,8 @@ struct amdgpu_iv_entry;
|
||||
#define AMDGPU_RAS_GPU_ERR_SOCKET_ID(x) AMDGPU_GET_REG_FIELD(x, 10, 8)
|
||||
#define AMDGPU_RAS_GPU_ERR_AID_ID(x) AMDGPU_GET_REG_FIELD(x, 12, 11)
|
||||
#define AMDGPU_RAS_GPU_ERR_HBM_ID(x) AMDGPU_GET_REG_FIELD(x, 14, 13)
|
||||
#define AMDGPU_RAS_GPU_ERR_DATA_ABORT(x) AMDGPU_GET_REG_FIELD(x, 29, 29)
|
||||
#define AMDGPU_RAS_GPU_ERR_UNKNOWN(x) AMDGPU_GET_REG_FIELD(x, 30, 30)
|
||||
|
||||
#define AMDGPU_RAS_BOOT_STATUS_POLLING_LIMIT 100
|
||||
#define AMDGPU_RAS_BOOT_STEADY_STATUS 0xBA
|
||||
@ -476,16 +477,15 @@ struct ras_err_pages {
|
||||
};
|
||||
|
||||
struct ras_ecc_err {
|
||||
u64 hash_index;
|
||||
uint64_t status;
|
||||
uint64_t ipid;
|
||||
uint64_t addr;
|
||||
uint64_t pa_pfn;
|
||||
struct ras_err_pages err_pages;
|
||||
};
|
||||
|
||||
struct ras_ecc_log_info {
|
||||
struct mutex lock;
|
||||
siphash_key_t ecc_key;
|
||||
struct radix_tree_root de_page_tree;
|
||||
uint64_t de_queried_count;
|
||||
uint64_t prev_de_queried_count;
|
||||
@ -572,19 +572,11 @@ struct ras_fs_data {
|
||||
char debugfs_name[32];
|
||||
};
|
||||
|
||||
struct ras_err_addr {
|
||||
struct list_head node;
|
||||
uint64_t err_status;
|
||||
uint64_t err_ipid;
|
||||
uint64_t err_addr;
|
||||
};
|
||||
|
||||
struct ras_err_info {
|
||||
struct amdgpu_smuio_mcm_config_info mcm_info;
|
||||
u64 ce_count;
|
||||
u64 ue_count;
|
||||
u64 de_count;
|
||||
struct list_head err_addr_list;
|
||||
};
|
||||
|
||||
struct ras_err_node {
|
||||
@ -941,14 +933,14 @@ void amdgpu_ras_inst_reset_ras_error_count(struct amdgpu_device *adev,
|
||||
int amdgpu_ras_error_data_init(struct ras_err_data *err_data);
|
||||
void amdgpu_ras_error_data_fini(struct ras_err_data *err_data);
|
||||
int amdgpu_ras_error_statistic_ce_count(struct ras_err_data *err_data,
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
struct ras_err_addr *err_addr, u64 count);
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
u64 count);
|
||||
int amdgpu_ras_error_statistic_ue_count(struct ras_err_data *err_data,
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
struct ras_err_addr *err_addr, u64 count);
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
u64 count);
|
||||
int amdgpu_ras_error_statistic_de_count(struct ras_err_data *err_data,
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
struct ras_err_addr *err_addr, u64 count);
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
u64 count);
|
||||
void amdgpu_ras_query_boot_status(struct amdgpu_device *adev, u32 num_instances);
|
||||
int amdgpu_ras_bind_aca(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
|
||||
const struct aca_info *aca_info, void *data);
|
||||
@ -957,12 +949,6 @@ int amdgpu_ras_unbind_aca(struct amdgpu_device *adev, enum amdgpu_ras_block blk)
|
||||
ssize_t amdgpu_ras_aca_sysfs_read(struct device *dev, struct device_attribute *attr,
|
||||
struct aca_handle *handle, char *buf, void *data);
|
||||
|
||||
void amdgpu_ras_add_mca_err_addr(struct ras_err_info *err_info,
|
||||
struct ras_err_addr *err_addr);
|
||||
|
||||
void amdgpu_ras_del_mca_err_addr(struct ras_err_info *err_info,
|
||||
struct ras_err_addr *mca_err_addr);
|
||||
|
||||
void amdgpu_ras_set_fed(struct amdgpu_device *adev, bool status);
|
||||
bool amdgpu_ras_get_fed_status(struct amdgpu_device *adev);
|
||||
|
||||
@ -982,4 +968,5 @@ __printf(3, 4)
|
||||
void amdgpu_ras_event_log_print(struct amdgpu_device *adev, u64 event_id,
|
||||
const char *fmt, ...);
|
||||
|
||||
bool amdgpu_ras_is_rma(struct amdgpu_device *adev);
|
||||
#endif
|
||||
|
@ -136,6 +136,12 @@ static inline bool amdgpu_reset_domain_schedule(struct amdgpu_reset_domain *doma
|
||||
return queue_work(domain->wq, work);
|
||||
}
|
||||
|
||||
static inline bool amdgpu_reset_pending(struct amdgpu_reset_domain *domain)
|
||||
{
|
||||
lockdep_assert_held(&domain->sem);
|
||||
return rwsem_is_contended(&domain->sem);
|
||||
}
|
||||
|
||||
void amdgpu_device_lock_reset_domain(struct amdgpu_reset_domain *reset_domain);
|
||||
|
||||
void amdgpu_device_unlock_reset_domain(struct amdgpu_reset_domain *reset_domain);
|
||||
|
@ -144,8 +144,10 @@ void amdgpu_ring_commit(struct amdgpu_ring *ring)
|
||||
/* We pad to match fetch size */
|
||||
count = ring->funcs->align_mask + 1 -
|
||||
(ring->wptr & ring->funcs->align_mask);
|
||||
count %= ring->funcs->align_mask + 1;
|
||||
ring->funcs->insert_nop(ring, count);
|
||||
count &= ring->funcs->align_mask;
|
||||
|
||||
if (count != 0)
|
||||
ring->funcs->insert_nop(ring, count);
|
||||
|
||||
mb();
|
||||
amdgpu_ring_set_wptr(ring);
|
||||
|
@ -235,6 +235,8 @@ struct amdgpu_ring_funcs {
|
||||
void (*patch_cntl)(struct amdgpu_ring *ring, unsigned offset);
|
||||
void (*patch_ce)(struct amdgpu_ring *ring, unsigned offset);
|
||||
void (*patch_de)(struct amdgpu_ring *ring, unsigned offset);
|
||||
int (*reset)(struct amdgpu_ring *ring, unsigned int vmid);
|
||||
void (*emit_cleaner_shader)(struct amdgpu_ring *ring);
|
||||
};
|
||||
|
||||
struct amdgpu_ring {
|
||||
@ -334,6 +336,7 @@ struct amdgpu_ring {
|
||||
#define amdgpu_ring_patch_cntl(r, o) ((r)->funcs->patch_cntl((r), (o)))
|
||||
#define amdgpu_ring_patch_ce(r, o) ((r)->funcs->patch_ce((r), (o)))
|
||||
#define amdgpu_ring_patch_de(r, o) ((r)->funcs->patch_de((r), (o)))
|
||||
#define amdgpu_ring_reset(r, v) (r)->funcs->reset((r), (v))
|
||||
|
||||
unsigned int amdgpu_ring_max_ibs(enum amdgpu_ring_type type);
|
||||
int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned ndw);
|
||||
|
@ -410,7 +410,7 @@ void amdgpu_sw_ring_ib_end(struct amdgpu_ring *ring)
|
||||
struct amdgpu_ring_mux *mux = &adev->gfx.muxer;
|
||||
|
||||
WARN_ON(!ring->is_sw_ring);
|
||||
if (ring->hw_prio > AMDGPU_RING_PRIO_DEFAULT)
|
||||
if (adev->gfx.mcbp && ring->hw_prio > AMDGPU_RING_PRIO_DEFAULT)
|
||||
return;
|
||||
amdgpu_ring_mux_end_ib(mux, ring);
|
||||
}
|
||||
|
@ -115,6 +115,7 @@ struct amdgpu_sdma {
|
||||
bool has_page_queue;
|
||||
struct ras_common_if *ras_if;
|
||||
struct amdgpu_sdma_ras *ras;
|
||||
uint32_t *ip_dump;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -196,7 +196,7 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
|
||||
amdgpu_umc_handle_bad_pages(adev, ras_error_status);
|
||||
|
||||
if ((err_data->ue_count || err_data->de_count) &&
|
||||
(reset || (con && con->is_rma))) {
|
||||
(reset || amdgpu_ras_is_rma(adev))) {
|
||||
con->gpu_reset_flags |= reset;
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
}
|
||||
@ -204,55 +204,6 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
|
||||
return AMDGPU_RAS_SUCCESS;
|
||||
}
|
||||
|
||||
int amdgpu_umc_bad_page_polling_timeout(struct amdgpu_device *adev,
|
||||
uint32_t reset, uint32_t timeout_ms)
|
||||
{
|
||||
struct ras_err_data err_data;
|
||||
struct ras_common_if head = {
|
||||
.block = AMDGPU_RAS_BLOCK__UMC,
|
||||
};
|
||||
struct ras_manager *obj = amdgpu_ras_find_obj(adev, &head);
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
uint32_t timeout = timeout_ms;
|
||||
|
||||
memset(&err_data, 0, sizeof(err_data));
|
||||
amdgpu_ras_error_data_init(&err_data);
|
||||
|
||||
do {
|
||||
|
||||
amdgpu_umc_handle_bad_pages(adev, &err_data);
|
||||
|
||||
if (timeout && !err_data.de_count) {
|
||||
msleep(1);
|
||||
timeout--;
|
||||
}
|
||||
|
||||
} while (timeout && !err_data.de_count);
|
||||
|
||||
if (!timeout)
|
||||
dev_warn(adev->dev, "Can't find bad pages\n");
|
||||
|
||||
if (err_data.de_count)
|
||||
dev_info(adev->dev, "%ld new deferred hardware errors detected\n", err_data.de_count);
|
||||
|
||||
if (obj) {
|
||||
obj->err_data.ue_count += err_data.ue_count;
|
||||
obj->err_data.ce_count += err_data.ce_count;
|
||||
obj->err_data.de_count += err_data.de_count;
|
||||
}
|
||||
|
||||
amdgpu_ras_error_data_fini(&err_data);
|
||||
|
||||
kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
|
||||
|
||||
if (reset || (err_data.err_addr_cnt && con && con->is_rma)) {
|
||||
con->gpu_reset_flags |= reset;
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_umc_pasid_poison_handler(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block, uint16_t pasid,
|
||||
pasid_notify pasid_fn, void *data, uint32_t reset)
|
||||
@ -472,43 +423,6 @@ int amdgpu_umc_update_ecc_status(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_umc_uint64_cmp(const void *a, const void *b)
|
||||
{
|
||||
uint64_t *addr_a = (uint64_t *)a;
|
||||
uint64_t *addr_b = (uint64_t *)b;
|
||||
|
||||
if (*addr_a > *addr_b)
|
||||
return 1;
|
||||
else if (*addr_a < *addr_b)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use string hash to avoid logging the same bad pages repeatedly */
|
||||
int amdgpu_umc_build_pages_hash(struct amdgpu_device *adev,
|
||||
uint64_t *pfns, int len, uint64_t *val)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
char buf[MAX_UMC_HASH_STRING_SIZE] = {0};
|
||||
int offset = 0, i = 0;
|
||||
uint64_t hash_val;
|
||||
|
||||
if (!pfns || !len)
|
||||
return -EINVAL;
|
||||
|
||||
sort(pfns, len, sizeof(uint64_t), amdgpu_umc_uint64_cmp, NULL);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
offset += snprintf(&buf[offset], sizeof(buf) - offset, "%llx", pfns[i]);
|
||||
|
||||
hash_val = siphash(buf, offset, &con->umc_ecc_log.ecc_key);
|
||||
|
||||
*val = hash_val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_umc_logs_ecc_err(struct amdgpu_device *adev,
|
||||
struct radix_tree_root *ecc_tree, struct ras_ecc_err *ecc_err)
|
||||
{
|
||||
@ -519,18 +433,10 @@ int amdgpu_umc_logs_ecc_err(struct amdgpu_device *adev,
|
||||
ecc_log = &con->umc_ecc_log;
|
||||
|
||||
mutex_lock(&ecc_log->lock);
|
||||
ret = radix_tree_insert(ecc_tree, ecc_err->hash_index, ecc_err);
|
||||
if (!ret) {
|
||||
struct ras_err_pages *err_pages = &ecc_err->err_pages;
|
||||
int i;
|
||||
|
||||
/* Reserve memory */
|
||||
for (i = 0; i < err_pages->count; i++)
|
||||
amdgpu_ras_reserve_page(adev, err_pages->pfn[i]);
|
||||
|
||||
ret = radix_tree_insert(ecc_tree, ecc_err->pa_pfn, ecc_err);
|
||||
if (!ret)
|
||||
radix_tree_tag_set(ecc_tree,
|
||||
ecc_err->hash_index, UMC_ECC_NEW_DETECTED_TAG);
|
||||
}
|
||||
ecc_err->pa_pfn, UMC_ECC_NEW_DETECTED_TAG);
|
||||
mutex_unlock(&ecc_log->lock);
|
||||
|
||||
return ret;
|
||||
|
@ -127,13 +127,8 @@ int amdgpu_umc_page_retirement_mca(struct amdgpu_device *adev,
|
||||
int amdgpu_umc_loop_channels(struct amdgpu_device *adev,
|
||||
umc_func func, void *data);
|
||||
|
||||
int amdgpu_umc_bad_page_polling_timeout(struct amdgpu_device *adev,
|
||||
uint32_t reset, uint32_t timeout_ms);
|
||||
|
||||
int amdgpu_umc_update_ecc_status(struct amdgpu_device *adev,
|
||||
uint64_t status, uint64_t ipid, uint64_t addr);
|
||||
int amdgpu_umc_build_pages_hash(struct amdgpu_device *adev,
|
||||
uint64_t *pfns, int len, uint64_t *val);
|
||||
int amdgpu_umc_logs_ecc_err(struct amdgpu_device *adev,
|
||||
struct radix_tree_root *ecc_tree, struct ras_ecc_err *ecc_err);
|
||||
|
||||
|
@ -587,7 +587,7 @@ int amdgpu_umsch_mm_init_microcode(struct amdgpu_umsch_mm *umsch)
|
||||
break;
|
||||
}
|
||||
|
||||
r = amdgpu_ucode_request(adev, &adev->umsch_mm.fw, fw_name);
|
||||
r = amdgpu_ucode_request(adev, &adev->umsch_mm.fw, "%s", fw_name);
|
||||
if (r) {
|
||||
release_firmware(adev->umsch_mm.fw);
|
||||
adev->umsch_mm.fw = NULL;
|
||||
|
@ -260,7 +260,7 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = amdgpu_ucode_request(adev, &adev->uvd.fw, fw_name);
|
||||
r = amdgpu_ucode_request(adev, &adev->uvd.fw, "%s", fw_name);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "amdgpu_uvd: Can't validate firmware \"%s\"\n",
|
||||
fw_name);
|
||||
@ -1088,7 +1088,6 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser,
|
||||
int r;
|
||||
|
||||
job->vm = NULL;
|
||||
ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo);
|
||||
|
||||
if (ib->length_dw % 16) {
|
||||
DRM_ERROR("UVD IB length (%d) not 16 dwords aligned!\n",
|
||||
|
@ -158,7 +158,7 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = amdgpu_ucode_request(adev, &adev->vce.fw, fw_name);
|
||||
r = amdgpu_ucode_request(adev, &adev->vce.fw, "%s", fw_name);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "amdgpu_vce: Can't validate firmware \"%s\"\n",
|
||||
fw_name);
|
||||
@ -749,7 +749,6 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p,
|
||||
int i, r = 0;
|
||||
|
||||
job->vm = NULL;
|
||||
ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo);
|
||||
|
||||
for (idx = 0; idx < ib->length_dw;) {
|
||||
uint32_t len = amdgpu_ib_get_value(ib, idx);
|
||||
@ -1044,7 +1043,6 @@ out:
|
||||
if (!r) {
|
||||
/* No error, free all destroyed handle slots */
|
||||
tmp = destroyed;
|
||||
amdgpu_ib_free(p->adev, ib, NULL);
|
||||
} else {
|
||||
/* Error during parsing, free all allocated handle slots */
|
||||
tmp = allocated;
|
||||
|
@ -330,6 +330,9 @@ struct amdgpu_vcn {
|
||||
uint16_t inst_mask;
|
||||
uint8_t num_inst_per_aid;
|
||||
bool using_unified_queue;
|
||||
|
||||
/* IP reg dump */
|
||||
uint32_t *ip_dump;
|
||||
};
|
||||
|
||||
struct amdgpu_fw_shared_rb_ptrs_struct {
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_reset.h"
|
||||
#include "amdgpu_dpm.h"
|
||||
#include "vi.h"
|
||||
#include "soc15.h"
|
||||
#include "nv.h"
|
||||
@ -849,6 +850,13 @@ enum amdgpu_sriov_vf_mode amdgpu_virt_get_sriov_vf_mode(struct amdgpu_device *ad
|
||||
return mode;
|
||||
}
|
||||
|
||||
void amdgpu_virt_pre_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
/* stop the data exchange thread */
|
||||
amdgpu_virt_fini_data_exchange(adev);
|
||||
amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_FLR);
|
||||
}
|
||||
|
||||
void amdgpu_virt_post_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 0, 3)) {
|
||||
|
@ -376,6 +376,7 @@ u32 amdgpu_sriov_rreg(struct amdgpu_device *adev,
|
||||
u32 offset, u32 acc_flags, u32 hwip, u32 xcc_id);
|
||||
bool amdgpu_virt_fw_load_skip_check(struct amdgpu_device *adev,
|
||||
uint32_t ucode_id);
|
||||
void amdgpu_virt_pre_reset(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_post_reset(struct amdgpu_device *adev);
|
||||
bool amdgpu_sriov_xnack_support(struct amdgpu_device *adev);
|
||||
bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev,
|
||||
|
@ -549,7 +549,7 @@ static int amdgpu_vkms_sw_fini(void *handle)
|
||||
|
||||
adev->mode_info.mode_config_initialized = false;
|
||||
|
||||
kfree(adev->mode_info.bios_hardcoded_edid);
|
||||
drm_edid_free(adev->mode_info.bios_hardcoded_edid);
|
||||
kfree(adev->amdgpu_vkms_output);
|
||||
return 0;
|
||||
}
|
||||
|
@ -681,6 +681,11 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
|
||||
pasid_mapping_needed &= adev->gmc.gmc_funcs->emit_pasid_mapping &&
|
||||
ring->funcs->emit_wreg;
|
||||
|
||||
if (adev->gfx.enable_cleaner_shader &&
|
||||
ring->funcs->emit_cleaner_shader &&
|
||||
job->enforce_isolation)
|
||||
ring->funcs->emit_cleaner_shader(ring);
|
||||
|
||||
if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync)
|
||||
return 0;
|
||||
|
||||
@ -742,6 +747,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
|
||||
amdgpu_ring_emit_switch_buffer(ring);
|
||||
amdgpu_ring_emit_switch_buffer(ring);
|
||||
}
|
||||
|
||||
amdgpu_ring_ib_end(ring);
|
||||
return 0;
|
||||
}
|
||||
@ -2397,6 +2403,7 @@ void amdgpu_vm_set_task_info(struct amdgpu_vm *vm)
|
||||
int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
int32_t xcp_id)
|
||||
{
|
||||
struct amdgpu_ip_block *ip_block;
|
||||
struct amdgpu_bo *root_bo;
|
||||
struct amdgpu_bo_vm *root;
|
||||
int r, i;
|
||||
@ -2428,6 +2435,11 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
vm->use_cpu_for_update = !!(adev->vm_manager.vm_update_mode &
|
||||
AMDGPU_VM_USE_CPU_FOR_GFX);
|
||||
|
||||
/* use CPU for page table update if SDMA is unavailable */
|
||||
ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_SDMA);
|
||||
if (!ip_block || ip_block->status.valid == false)
|
||||
vm->use_cpu_for_update = true;
|
||||
|
||||
DRM_DEBUG_DRIVER("VM update mode is %s\n",
|
||||
vm->use_cpu_for_update ? "CPU" : "SDMA");
|
||||
WARN_ONCE((vm->use_cpu_for_update &&
|
||||
@ -2768,7 +2780,7 @@ int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
* shouldn't be reported any more.
|
||||
*/
|
||||
bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
|
||||
u32 vmid, u32 node_id, uint64_t addr,
|
||||
u32 vmid, u32 node_id, uint64_t addr, uint64_t ts,
|
||||
bool write_fault)
|
||||
{
|
||||
bool is_compute_context = false;
|
||||
@ -2794,7 +2806,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
|
||||
addr /= AMDGPU_GPU_PAGE_SIZE;
|
||||
|
||||
if (is_compute_context && !svm_range_restore_pages(adev, pasid, vmid,
|
||||
node_id, addr, write_fault)) {
|
||||
node_id, addr, ts, write_fault)) {
|
||||
amdgpu_bo_unref(&root);
|
||||
return true;
|
||||
}
|
||||
|
@ -558,7 +558,7 @@ amdgpu_vm_get_task_info_vm(struct amdgpu_vm *vm);
|
||||
void amdgpu_vm_put_task_info(struct amdgpu_task_info *task_info);
|
||||
|
||||
bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
|
||||
u32 vmid, u32 node_id, uint64_t addr,
|
||||
u32 vmid, u32 node_id, uint64_t addr, uint64_t ts,
|
||||
bool write_fault);
|
||||
|
||||
void amdgpu_vm_set_task_info(struct amdgpu_vm *vm);
|
||||
|
@ -1389,10 +1389,10 @@ static void __xgmi_v6_4_0_query_error_count(struct amdgpu_device *adev, struct a
|
||||
|
||||
switch (xgmi_v6_4_0_pcs_mca_get_error_type(adev, status)) {
|
||||
case ACA_ERROR_TYPE_UE:
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, mcm_info, NULL, 1ULL);
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, mcm_info, 1ULL);
|
||||
break;
|
||||
case ACA_ERROR_TYPE_CE:
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, mcm_info, NULL, 1ULL);
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, mcm_info, 1ULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -213,7 +213,7 @@ struct amd_sriov_msg_pf2vf_info {
|
||||
uint32_t gpu_capacity;
|
||||
/* reserved */
|
||||
uint32_t reserved[256 - AMD_SRIOV_MSG_PF2VF_INFO_FILLED_SIZE];
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct amd_sriov_msg_vf2pf_info_header {
|
||||
/* the total structure size in byte */
|
||||
@ -273,7 +273,7 @@ struct amd_sriov_msg_vf2pf_info {
|
||||
uint32_t mes_info_size;
|
||||
/* reserved */
|
||||
uint32_t reserved[256 - AMD_SRIOV_MSG_VF2PF_INFO_FILLED_SIZE];
|
||||
};
|
||||
} __packed;
|
||||
|
||||
/* mailbox message send from guest to host */
|
||||
enum amd_sriov_mailbox_request_message {
|
||||
|
@ -75,6 +75,8 @@ static void aqua_vanjaram_set_xcp_id(struct amdgpu_device *adev,
|
||||
uint32_t inst_mask;
|
||||
|
||||
ring->xcp_id = AMDGPU_XCP_NO_PARTITION;
|
||||
if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE)
|
||||
adev->gfx.enforce_isolation[0].xcp_id = ring->xcp_id;
|
||||
if (adev->xcp_mgr->mode == AMDGPU_XCP_MODE_NONE)
|
||||
return;
|
||||
|
||||
@ -103,6 +105,8 @@ static void aqua_vanjaram_set_xcp_id(struct amdgpu_device *adev,
|
||||
for (xcp_id = 0; xcp_id < adev->xcp_mgr->num_xcps; xcp_id++) {
|
||||
if (adev->xcp_mgr->xcp[xcp_id].ip[ip_blk].inst_mask & inst_mask) {
|
||||
ring->xcp_id = xcp_id;
|
||||
if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE)
|
||||
adev->gfx.enforce_isolation[xcp_id].xcp_id = xcp_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2064,27 +2064,25 @@ amdgpu_atombios_encoder_get_lcd_info(struct amdgpu_encoder *encoder)
|
||||
case LCD_FAKE_EDID_PATCH_RECORD_TYPE:
|
||||
fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record;
|
||||
if (fake_edid_record->ucFakeEDIDLength) {
|
||||
struct edid *edid;
|
||||
int edid_size =
|
||||
max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength);
|
||||
edid = kmalloc(edid_size, GFP_KERNEL);
|
||||
if (edid) {
|
||||
memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0],
|
||||
fake_edid_record->ucFakeEDIDLength);
|
||||
const struct drm_edid *edid;
|
||||
int edid_size;
|
||||
|
||||
if (drm_edid_is_valid(edid)) {
|
||||
adev->mode_info.bios_hardcoded_edid = edid;
|
||||
adev->mode_info.bios_hardcoded_edid_size = edid_size;
|
||||
} else
|
||||
kfree(edid);
|
||||
}
|
||||
if (fake_edid_record->ucFakeEDIDLength == 128)
|
||||
edid_size = fake_edid_record->ucFakeEDIDLength;
|
||||
else
|
||||
edid_size = fake_edid_record->ucFakeEDIDLength * 128;
|
||||
edid = drm_edid_alloc(fake_edid_record->ucFakeEDIDString, edid_size);
|
||||
if (drm_edid_valid(edid))
|
||||
adev->mode_info.bios_hardcoded_edid = edid;
|
||||
else
|
||||
drm_edid_free(edid);
|
||||
record += struct_size(fake_edid_record,
|
||||
ucFakeEDIDString,
|
||||
edid_size);
|
||||
} else {
|
||||
/* empty fake edid record must be 3 bytes long */
|
||||
record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1;
|
||||
}
|
||||
record += fake_edid_record->ucFakeEDIDLength ?
|
||||
struct_size(fake_edid_record,
|
||||
ucFakeEDIDString,
|
||||
fake_edid_record->ucFakeEDIDLength) :
|
||||
/* empty fake edid record must be 3 bytes long */
|
||||
sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1;
|
||||
break;
|
||||
case LCD_PANEL_RESOLUTION_RECORD_TYPE:
|
||||
panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;
|
||||
|
@ -364,6 +364,7 @@
|
||||
* 1 - Stream
|
||||
* 2 - Bypass
|
||||
*/
|
||||
#define EOP_EXEC (1 << 28) /* For Trailing Fence */
|
||||
#define DATA_SEL(x) ((x) << 29)
|
||||
/* 0 - discard
|
||||
* 1 - send low 32bit data
|
||||
|
@ -2846,7 +2846,7 @@ static int dce_v10_0_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
kfree(adev->mode_info.bios_hardcoded_edid);
|
||||
drm_edid_free(adev->mode_info.bios_hardcoded_edid);
|
||||
|
||||
drm_kms_helper_poll_fini(adev_to_drm(adev));
|
||||
|
||||
|
@ -2973,7 +2973,7 @@ static int dce_v11_0_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
kfree(adev->mode_info.bios_hardcoded_edid);
|
||||
drm_edid_free(adev->mode_info.bios_hardcoded_edid);
|
||||
|
||||
drm_kms_helper_poll_fini(adev_to_drm(adev));
|
||||
|
||||
|
@ -2745,7 +2745,7 @@ static int dce_v6_0_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
kfree(adev->mode_info.bios_hardcoded_edid);
|
||||
drm_edid_free(adev->mode_info.bios_hardcoded_edid);
|
||||
|
||||
drm_kms_helper_poll_fini(adev_to_drm(adev));
|
||||
|
||||
|
@ -2766,7 +2766,7 @@ static int dce_v8_0_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
kfree(adev->mode_info.bios_hardcoded_edid);
|
||||
drm_edid_free(adev->mode_info.bios_hardcoded_edid);
|
||||
|
||||
drm_kms_helper_poll_fini(adev_to_drm(adev));
|
||||
|
||||
|
@ -4649,7 +4649,7 @@ static void gfx_v10_0_alloc_ip_dump(struct amdgpu_device *adev)
|
||||
uint32_t inst;
|
||||
|
||||
ptr = kcalloc(reg_count, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (ptr == NULL) {
|
||||
if (!ptr) {
|
||||
DRM_ERROR("Failed to allocate memory for GFX IP Dump\n");
|
||||
adev->gfx.ip_dump_core = NULL;
|
||||
} else {
|
||||
@ -4662,7 +4662,7 @@ static void gfx_v10_0_alloc_ip_dump(struct amdgpu_device *adev)
|
||||
adev->gfx.mec.num_queue_per_pipe;
|
||||
|
||||
ptr = kcalloc(reg_count * inst, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (ptr == NULL) {
|
||||
if (!ptr) {
|
||||
DRM_ERROR("Failed to allocate memory for Compute Queues IP Dump\n");
|
||||
adev->gfx.ip_dump_compute_queues = NULL;
|
||||
} else {
|
||||
@ -4675,7 +4675,7 @@ static void gfx_v10_0_alloc_ip_dump(struct amdgpu_device *adev)
|
||||
adev->gfx.me.num_queue_per_pipe;
|
||||
|
||||
ptr = kcalloc(reg_count * inst, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (ptr == NULL) {
|
||||
if (!ptr) {
|
||||
DRM_ERROR("Failed to allocate memory for GFX Queues IP Dump\n");
|
||||
adev->gfx.ip_dump_gfx_queues = NULL;
|
||||
} else {
|
||||
@ -4741,6 +4741,13 @@ static int gfx_v10_0_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Bad opcode Event */
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_GRBM_CP,
|
||||
GFX_10_1__SRCID__CP_BAD_OPCODE_ERROR,
|
||||
&adev->gfx.bad_op_irq);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Privileged reg */
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_GRBM_CP, GFX_10_1__SRCID__CP_PRIV_REG_FAULT,
|
||||
&adev->gfx.priv_reg_irq);
|
||||
@ -5213,26 +5220,74 @@ static void gfx_v10_0_constants_init(struct amdgpu_device *adev)
|
||||
|
||||
}
|
||||
|
||||
static u32 gfx_v10_0_get_cpg_int_cntl(struct amdgpu_device *adev,
|
||||
int me, int pipe)
|
||||
{
|
||||
if (me != 0)
|
||||
return 0;
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
return SOC15_REG_OFFSET(GC, 0, mmCP_INT_CNTL_RING0);
|
||||
case 1:
|
||||
return SOC15_REG_OFFSET(GC, 0, mmCP_INT_CNTL_RING1);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 gfx_v10_0_get_cpc_int_cntl(struct amdgpu_device *adev,
|
||||
int me, int pipe)
|
||||
{
|
||||
/*
|
||||
* amdgpu controls only the first MEC. That's why this function only
|
||||
* handles the setting of interrupts for this specific MEC. All other
|
||||
* pipes' interrupts are set by amdkfd.
|
||||
*/
|
||||
if (me != 1)
|
||||
return 0;
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
return SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE0_INT_CNTL);
|
||||
case 1:
|
||||
return SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE1_INT_CNTL);
|
||||
case 2:
|
||||
return SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE2_INT_CNTL);
|
||||
case 3:
|
||||
return SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE3_INT_CNTL);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_v10_0_enable_gui_idle_interrupt(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
u32 tmp;
|
||||
u32 tmp, cp_int_cntl_reg;
|
||||
int i, j;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return;
|
||||
|
||||
tmp = RREG32_SOC15(GC, 0, mmCP_INT_CNTL_RING0);
|
||||
for (i = 0; i < adev->gfx.me.num_me; i++) {
|
||||
for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
|
||||
cp_int_cntl_reg = gfx_v10_0_get_cpg_int_cntl(adev, i, j);
|
||||
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
|
||||
WREG32_SOC15(GC, 0, mmCP_INT_CNTL_RING0, tmp);
|
||||
if (cp_int_cntl_reg) {
|
||||
tmp = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int gfx_v10_0_init_csb(struct amdgpu_device *adev)
|
||||
@ -7369,6 +7424,7 @@ static int gfx_v10_0_hw_fini(void *handle)
|
||||
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.bad_op_irq, 0);
|
||||
|
||||
/* WA added for Vangogh asic fixing the SMU suspend failure
|
||||
* It needs to set power gating again during gfxoff control
|
||||
@ -7679,6 +7735,10 @@ static int gfx_v10_0_late_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_irq_get(adev, &adev->gfx.bad_op_irq, 0);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -9074,12 +9134,39 @@ static int gfx_v10_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
|
||||
unsigned int type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
u32 cp_int_cntl_reg, cp_int_cntl;
|
||||
int i, j;
|
||||
|
||||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
WREG32_FIELD15(GC, 0, CP_INT_CNTL_RING0,
|
||||
PRIV_REG_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
for (i = 0; i < adev->gfx.me.num_me; i++) {
|
||||
for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
|
||||
cp_int_cntl_reg = gfx_v10_0_get_cpg_int_cntl(adev, i, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
|
||||
PRIV_REG_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < adev->gfx.mec.num_mec; i++) {
|
||||
for (j = 0; j < adev->gfx.mec.num_pipe_per_mec; j++) {
|
||||
/* MECs start at 1 */
|
||||
cp_int_cntl_reg = gfx_v10_0_get_cpc_int_cntl(adev, i + 1, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_ME1_PIPE0_INT_CNTL,
|
||||
PRIV_REG_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -9088,17 +9175,75 @@ static int gfx_v10_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v10_0_set_bad_op_fault_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
u32 cp_int_cntl_reg, cp_int_cntl;
|
||||
int i, j;
|
||||
|
||||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
for (i = 0; i < adev->gfx.me.num_me; i++) {
|
||||
for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
|
||||
cp_int_cntl_reg = gfx_v10_0_get_cpg_int_cntl(adev, i, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
|
||||
OPCODE_ERROR_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < adev->gfx.mec.num_mec; i++) {
|
||||
for (j = 0; j < adev->gfx.mec.num_pipe_per_mec; j++) {
|
||||
/* MECs start at 1 */
|
||||
cp_int_cntl_reg = gfx_v10_0_get_cpc_int_cntl(adev, i + 1, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_ME1_PIPE0_INT_CNTL,
|
||||
OPCODE_ERROR_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v10_0_set_priv_inst_fault_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned int type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
u32 cp_int_cntl_reg, cp_int_cntl;
|
||||
int i, j;
|
||||
|
||||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
WREG32_FIELD15(GC, 0, CP_INT_CNTL_RING0,
|
||||
PRIV_INSTR_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
for (i = 0; i < adev->gfx.me.num_me; i++) {
|
||||
for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
|
||||
cp_int_cntl_reg = gfx_v10_0_get_cpg_int_cntl(adev, i, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
|
||||
PRIV_INSTR_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -9122,8 +9267,8 @@ static void gfx_v10_0_handle_priv_fault(struct amdgpu_device *adev,
|
||||
case 0:
|
||||
for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
|
||||
ring = &adev->gfx.gfx_ring[i];
|
||||
/* we only enabled 1 gfx queue per pipe for now */
|
||||
if (ring->me == me_id && ring->pipe == pipe_id)
|
||||
if (ring->me == me_id && ring->pipe == pipe_id &&
|
||||
ring->queue == queue_id)
|
||||
drm_sched_fault(&ring->sched);
|
||||
}
|
||||
break;
|
||||
@ -9150,6 +9295,15 @@ static int gfx_v10_0_priv_reg_irq(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v10_0_bad_op_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
DRM_ERROR("Illegal opcode in command stream \n");
|
||||
gfx_v10_0_handle_priv_fault(adev, entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v10_0_priv_inst_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
@ -9244,6 +9398,24 @@ static void gfx_v10_0_emit_mem_sync(struct amdgpu_ring *ring)
|
||||
amdgpu_ring_write(ring, gcr_cntl); /* GCR_CNTL */
|
||||
}
|
||||
|
||||
static void gfx_v10_ring_insert_nop(struct amdgpu_ring *ring, uint32_t num_nop)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Header itself is a NOP packet */
|
||||
if (num_nop == 1) {
|
||||
amdgpu_ring_write(ring, ring->funcs->nop);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max HW optimization till 0x3ffe, followed by remaining one NOP at a time*/
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_NOP, min(num_nop - 2, 0x3ffe)));
|
||||
|
||||
/* Header is at index 0, followed by num_nops - 1 NOP packet's */
|
||||
for (i = 1; i < num_nop; i++)
|
||||
amdgpu_ring_write(ring, ring->funcs->nop);
|
||||
}
|
||||
|
||||
static void gfx_v10_ip_print(void *handle, struct drm_printer *p)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
@ -9435,7 +9607,7 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_gfx = {
|
||||
.emit_hdp_flush = gfx_v10_0_ring_emit_hdp_flush,
|
||||
.test_ring = gfx_v10_0_ring_test_ring,
|
||||
.test_ib = gfx_v10_0_ring_test_ib,
|
||||
.insert_nop = amdgpu_ring_insert_nop,
|
||||
.insert_nop = gfx_v10_ring_insert_nop,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.emit_switch_buffer = gfx_v10_0_ring_emit_sb,
|
||||
.emit_cntxcntl = gfx_v10_0_ring_emit_cntxcntl,
|
||||
@ -9476,11 +9648,12 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_compute = {
|
||||
.emit_hdp_flush = gfx_v10_0_ring_emit_hdp_flush,
|
||||
.test_ring = gfx_v10_0_ring_test_ring,
|
||||
.test_ib = gfx_v10_0_ring_test_ib,
|
||||
.insert_nop = amdgpu_ring_insert_nop,
|
||||
.insert_nop = gfx_v10_ring_insert_nop,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.emit_wreg = gfx_v10_0_ring_emit_wreg,
|
||||
.emit_reg_wait = gfx_v10_0_ring_emit_reg_wait,
|
||||
.emit_reg_write_reg_wait = gfx_v10_0_ring_emit_reg_write_reg_wait,
|
||||
.soft_recovery = gfx_v10_0_ring_soft_recovery,
|
||||
.emit_mem_sync = gfx_v10_0_emit_mem_sync,
|
||||
};
|
||||
|
||||
@ -9536,6 +9709,11 @@ static const struct amdgpu_irq_src_funcs gfx_v10_0_priv_reg_irq_funcs = {
|
||||
.process = gfx_v10_0_priv_reg_irq,
|
||||
};
|
||||
|
||||
static const struct amdgpu_irq_src_funcs gfx_v10_0_bad_op_irq_funcs = {
|
||||
.set = gfx_v10_0_set_bad_op_fault_state,
|
||||
.process = gfx_v10_0_bad_op_irq,
|
||||
};
|
||||
|
||||
static const struct amdgpu_irq_src_funcs gfx_v10_0_priv_inst_irq_funcs = {
|
||||
.set = gfx_v10_0_set_priv_inst_fault_state,
|
||||
.process = gfx_v10_0_priv_inst_irq,
|
||||
@ -9557,6 +9735,9 @@ static void gfx_v10_0_set_irq_funcs(struct amdgpu_device *adev)
|
||||
adev->gfx.priv_reg_irq.num_types = 1;
|
||||
adev->gfx.priv_reg_irq.funcs = &gfx_v10_0_priv_reg_irq_funcs;
|
||||
|
||||
adev->gfx.bad_op_irq.num_types = 1;
|
||||
adev->gfx.bad_op_irq.funcs = &gfx_v10_0_bad_op_irq_funcs;
|
||||
|
||||
adev->gfx.priv_inst_irq.num_types = 1;
|
||||
adev->gfx.priv_inst_irq.funcs = &gfx_v10_0_priv_inst_irq_funcs;
|
||||
}
|
||||
|
@ -481,6 +481,24 @@ static void gfx_v11_0_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
|
||||
amdgpu_ring_write(ring, inv); /* poll interval */
|
||||
}
|
||||
|
||||
static void gfx_v11_ring_insert_nop(struct amdgpu_ring *ring, uint32_t num_nop)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Header itself is a NOP packet */
|
||||
if (num_nop == 1) {
|
||||
amdgpu_ring_write(ring, ring->funcs->nop);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max HW optimization till 0x3ffe, followed by remaining one NOP at a time*/
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_NOP, min(num_nop - 2, 0x3ffe)));
|
||||
|
||||
/* Header is at index 0, followed by num_nops - 1 NOP packet's */
|
||||
for (i = 1; i < num_nop; i++)
|
||||
amdgpu_ring_write(ring, ring->funcs->nop);
|
||||
}
|
||||
|
||||
static int gfx_v11_0_ring_test_ring(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
@ -1484,7 +1502,7 @@ static void gfx_v11_0_alloc_ip_dump(struct amdgpu_device *adev)
|
||||
uint32_t inst;
|
||||
|
||||
ptr = kcalloc(reg_count, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (ptr == NULL) {
|
||||
if (!ptr) {
|
||||
DRM_ERROR("Failed to allocate memory for GFX IP Dump\n");
|
||||
adev->gfx.ip_dump_core = NULL;
|
||||
} else {
|
||||
@ -1497,7 +1515,7 @@ static void gfx_v11_0_alloc_ip_dump(struct amdgpu_device *adev)
|
||||
adev->gfx.mec.num_queue_per_pipe;
|
||||
|
||||
ptr = kcalloc(reg_count * inst, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (ptr == NULL) {
|
||||
if (!ptr) {
|
||||
DRM_ERROR("Failed to allocate memory for Compute Queues IP Dump\n");
|
||||
adev->gfx.ip_dump_compute_queues = NULL;
|
||||
} else {
|
||||
@ -1510,7 +1528,7 @@ static void gfx_v11_0_alloc_ip_dump(struct amdgpu_device *adev)
|
||||
adev->gfx.me.num_queue_per_pipe;
|
||||
|
||||
ptr = kcalloc(reg_count * inst, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (ptr == NULL) {
|
||||
if (!ptr) {
|
||||
DRM_ERROR("Failed to allocate memory for GFX Queues IP Dump\n");
|
||||
adev->gfx.ip_dump_gfx_queues = NULL;
|
||||
} else {
|
||||
@ -1569,6 +1587,13 @@ static int gfx_v11_0_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Bad opcode Event */
|
||||
r = amdgpu_irq_add_id(adev, SOC21_IH_CLIENTID_GRBM_CP,
|
||||
GFX_11_0_0__SRCID__CP_BAD_OPCODE_ERROR,
|
||||
&adev->gfx.bad_op_irq);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Privileged reg */
|
||||
r = amdgpu_irq_add_id(adev, SOC21_IH_CLIENTID_GRBM_CP,
|
||||
GFX_11_0_0__SRCID__CP_PRIV_REG_FAULT,
|
||||
@ -1953,26 +1978,74 @@ static void gfx_v11_0_constants_init(struct amdgpu_device *adev)
|
||||
gfx_v11_0_init_gds_vmid(adev);
|
||||
}
|
||||
|
||||
static u32 gfx_v11_0_get_cpg_int_cntl(struct amdgpu_device *adev,
|
||||
int me, int pipe)
|
||||
{
|
||||
if (me != 0)
|
||||
return 0;
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
return SOC15_REG_OFFSET(GC, 0, regCP_INT_CNTL_RING0);
|
||||
case 1:
|
||||
return SOC15_REG_OFFSET(GC, 0, regCP_INT_CNTL_RING1);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 gfx_v11_0_get_cpc_int_cntl(struct amdgpu_device *adev,
|
||||
int me, int pipe)
|
||||
{
|
||||
/*
|
||||
* amdgpu controls only the first MEC. That's why this function only
|
||||
* handles the setting of interrupts for this specific MEC. All other
|
||||
* pipes' interrupts are set by amdkfd.
|
||||
*/
|
||||
if (me != 1)
|
||||
return 0;
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
return SOC15_REG_OFFSET(GC, 0, regCP_ME1_PIPE0_INT_CNTL);
|
||||
case 1:
|
||||
return SOC15_REG_OFFSET(GC, 0, regCP_ME1_PIPE1_INT_CNTL);
|
||||
case 2:
|
||||
return SOC15_REG_OFFSET(GC, 0, regCP_ME1_PIPE2_INT_CNTL);
|
||||
case 3:
|
||||
return SOC15_REG_OFFSET(GC, 0, regCP_ME1_PIPE3_INT_CNTL);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_v11_0_enable_gui_idle_interrupt(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
u32 tmp;
|
||||
u32 tmp, cp_int_cntl_reg;
|
||||
int i, j;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return;
|
||||
|
||||
tmp = RREG32_SOC15(GC, 0, regCP_INT_CNTL_RING0);
|
||||
for (i = 0; i < adev->gfx.me.num_me; i++) {
|
||||
for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
|
||||
cp_int_cntl_reg = gfx_v11_0_get_cpg_int_cntl(adev, i, j);
|
||||
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
|
||||
WREG32_SOC15(GC, 0, regCP_INT_CNTL_RING0, tmp);
|
||||
if (cp_int_cntl_reg) {
|
||||
tmp = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int gfx_v11_0_init_csb(struct amdgpu_device *adev)
|
||||
@ -4598,6 +4671,7 @@ static int gfx_v11_0_hw_fini(void *handle)
|
||||
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.bad_op_irq, 0);
|
||||
|
||||
if (!adev->no_hw_access) {
|
||||
if (amdgpu_async_gfx_ring) {
|
||||
@ -4668,8 +4742,8 @@ static int gfx_v11_0_wait_for_idle(void *handle)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int gfx_v11_0_request_gfx_index_mutex(struct amdgpu_device *adev,
|
||||
int req)
|
||||
int gfx_v11_0_request_gfx_index_mutex(struct amdgpu_device *adev,
|
||||
bool req)
|
||||
{
|
||||
u32 i, tmp, val;
|
||||
|
||||
@ -4707,6 +4781,8 @@ static int gfx_v11_0_soft_reset(void *handle)
|
||||
int r, i, j, k;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
gfx_v11_0_set_safe_mode(adev, 0);
|
||||
|
||||
tmp = RREG32_SOC15(GC, 0, regCP_INT_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL, CMP_BUSY_INT_ENABLE, 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL, CNTX_BUSY_INT_ENABLE, 0);
|
||||
@ -4714,8 +4790,6 @@ static int gfx_v11_0_soft_reset(void *handle)
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL, GFX_IDLE_INT_ENABLE, 0);
|
||||
WREG32_SOC15(GC, 0, regCP_INT_CNTL, tmp);
|
||||
|
||||
gfx_v11_0_set_safe_mode(adev, 0);
|
||||
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
for (i = 0; i < adev->gfx.mec.num_mec; ++i) {
|
||||
for (j = 0; j < adev->gfx.mec.num_queue_per_pipe; j++) {
|
||||
@ -4740,8 +4814,10 @@ static int gfx_v11_0_soft_reset(void *handle)
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
|
||||
/* Try to acquire the gfx mutex before access to CP_VMID_RESET */
|
||||
r = gfx_v11_0_request_gfx_index_mutex(adev, 1);
|
||||
mutex_lock(&adev->gfx.reset_sem_mutex);
|
||||
r = gfx_v11_0_request_gfx_index_mutex(adev, true);
|
||||
if (r) {
|
||||
mutex_unlock(&adev->gfx.reset_sem_mutex);
|
||||
DRM_ERROR("Failed to acquire the gfx mutex during soft reset\n");
|
||||
return r;
|
||||
}
|
||||
@ -4755,7 +4831,8 @@ static int gfx_v11_0_soft_reset(void *handle)
|
||||
RREG32_SOC15(GC, 0, regCP_VMID_RESET);
|
||||
|
||||
/* release the gfx mutex */
|
||||
r = gfx_v11_0_request_gfx_index_mutex(adev, 0);
|
||||
r = gfx_v11_0_request_gfx_index_mutex(adev, false);
|
||||
mutex_unlock(&adev->gfx.reset_sem_mutex);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to release the gfx mutex during soft reset\n");
|
||||
return r;
|
||||
@ -4954,6 +5031,9 @@ static int gfx_v11_0_late_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_irq_get(adev, &adev->gfx.bad_op_irq, 0);
|
||||
if (r)
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -6201,15 +6281,42 @@ static int gfx_v11_0_eop_irq(struct amdgpu_device *adev,
|
||||
|
||||
static int gfx_v11_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
unsigned int type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
u32 cp_int_cntl_reg, cp_int_cntl;
|
||||
int i, j;
|
||||
|
||||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
WREG32_FIELD15_PREREG(GC, 0, CP_INT_CNTL_RING0,
|
||||
PRIV_REG_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
for (i = 0; i < adev->gfx.me.num_me; i++) {
|
||||
for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
|
||||
cp_int_cntl_reg = gfx_v11_0_get_cpg_int_cntl(adev, i, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
|
||||
PRIV_REG_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < adev->gfx.mec.num_mec; i++) {
|
||||
for (j = 0; j < adev->gfx.mec.num_pipe_per_mec; j++) {
|
||||
/* MECs start at 1 */
|
||||
cp_int_cntl_reg = gfx_v11_0_get_cpc_int_cntl(adev, i + 1, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_ME1_PIPE0_INT_CNTL,
|
||||
PRIV_REG_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -6218,17 +6325,75 @@ static int gfx_v11_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v11_0_set_priv_inst_fault_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
static int gfx_v11_0_set_bad_op_fault_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
u32 cp_int_cntl_reg, cp_int_cntl;
|
||||
int i, j;
|
||||
|
||||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
WREG32_FIELD15_PREREG(GC, 0, CP_INT_CNTL_RING0,
|
||||
PRIV_INSTR_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
for (i = 0; i < adev->gfx.me.num_me; i++) {
|
||||
for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
|
||||
cp_int_cntl_reg = gfx_v11_0_get_cpg_int_cntl(adev, i, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
|
||||
OPCODE_ERROR_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < adev->gfx.mec.num_mec; i++) {
|
||||
for (j = 0; j < adev->gfx.mec.num_pipe_per_mec; j++) {
|
||||
/* MECs start at 1 */
|
||||
cp_int_cntl_reg = gfx_v11_0_get_cpc_int_cntl(adev, i + 1, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_ME1_PIPE0_INT_CNTL,
|
||||
OPCODE_ERROR_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v11_0_set_priv_inst_fault_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned int type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
u32 cp_int_cntl_reg, cp_int_cntl;
|
||||
int i, j;
|
||||
|
||||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
for (i = 0; i < adev->gfx.me.num_me; i++) {
|
||||
for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
|
||||
cp_int_cntl_reg = gfx_v11_0_get_cpg_int_cntl(adev, i, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
|
||||
PRIV_INSTR_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -6252,8 +6417,8 @@ static void gfx_v11_0_handle_priv_fault(struct amdgpu_device *adev,
|
||||
case 0:
|
||||
for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
|
||||
ring = &adev->gfx.gfx_ring[i];
|
||||
/* we only enabled 1 gfx queue per pipe for now */
|
||||
if (ring->me == me_id && ring->pipe == pipe_id)
|
||||
if (ring->me == me_id && ring->pipe == pipe_id &&
|
||||
ring->queue == queue_id)
|
||||
drm_sched_fault(&ring->sched);
|
||||
}
|
||||
break;
|
||||
@ -6281,6 +6446,15 @@ static int gfx_v11_0_priv_reg_irq(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v11_0_bad_op_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
DRM_ERROR("Illegal opcode in command stream \n");
|
||||
gfx_v11_0_handle_priv_fault(adev, entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v11_0_priv_inst_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
@ -6556,7 +6730,7 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_gfx = {
|
||||
.emit_hdp_flush = gfx_v11_0_ring_emit_hdp_flush,
|
||||
.test_ring = gfx_v11_0_ring_test_ring,
|
||||
.test_ib = gfx_v11_0_ring_test_ib,
|
||||
.insert_nop = amdgpu_ring_insert_nop,
|
||||
.insert_nop = gfx_v11_ring_insert_nop,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.emit_cntxcntl = gfx_v11_0_ring_emit_cntxcntl,
|
||||
.emit_gfx_shadow = gfx_v11_0_ring_emit_gfx_shadow,
|
||||
@ -6598,11 +6772,12 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_compute = {
|
||||
.emit_hdp_flush = gfx_v11_0_ring_emit_hdp_flush,
|
||||
.test_ring = gfx_v11_0_ring_test_ring,
|
||||
.test_ib = gfx_v11_0_ring_test_ib,
|
||||
.insert_nop = amdgpu_ring_insert_nop,
|
||||
.insert_nop = gfx_v11_ring_insert_nop,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.emit_wreg = gfx_v11_0_ring_emit_wreg,
|
||||
.emit_reg_wait = gfx_v11_0_ring_emit_reg_wait,
|
||||
.emit_reg_write_reg_wait = gfx_v11_0_ring_emit_reg_write_reg_wait,
|
||||
.soft_recovery = gfx_v11_0_ring_soft_recovery,
|
||||
.emit_mem_sync = gfx_v11_0_emit_mem_sync,
|
||||
};
|
||||
|
||||
@ -6658,6 +6833,11 @@ static const struct amdgpu_irq_src_funcs gfx_v11_0_priv_reg_irq_funcs = {
|
||||
.process = gfx_v11_0_priv_reg_irq,
|
||||
};
|
||||
|
||||
static const struct amdgpu_irq_src_funcs gfx_v11_0_bad_op_irq_funcs = {
|
||||
.set = gfx_v11_0_set_bad_op_fault_state,
|
||||
.process = gfx_v11_0_bad_op_irq,
|
||||
};
|
||||
|
||||
static const struct amdgpu_irq_src_funcs gfx_v11_0_priv_inst_irq_funcs = {
|
||||
.set = gfx_v11_0_set_priv_inst_fault_state,
|
||||
.process = gfx_v11_0_priv_inst_irq,
|
||||
@ -6675,6 +6855,9 @@ static void gfx_v11_0_set_irq_funcs(struct amdgpu_device *adev)
|
||||
adev->gfx.priv_reg_irq.num_types = 1;
|
||||
adev->gfx.priv_reg_irq.funcs = &gfx_v11_0_priv_reg_irq_funcs;
|
||||
|
||||
adev->gfx.bad_op_irq.num_types = 1;
|
||||
adev->gfx.bad_op_irq.funcs = &gfx_v11_0_bad_op_irq_funcs;
|
||||
|
||||
adev->gfx.priv_inst_irq.num_types = 1;
|
||||
adev->gfx.priv_inst_irq.funcs = &gfx_v11_0_priv_inst_irq_funcs;
|
||||
|
||||
|
@ -26,4 +26,7 @@
|
||||
|
||||
extern const struct amdgpu_ip_block_version gfx_v11_0_ip_block;
|
||||
|
||||
int gfx_v11_0_request_gfx_index_mutex(struct amdgpu_device *adev,
|
||||
bool req);
|
||||
|
||||
#endif
|
||||
|
@ -97,7 +97,7 @@ static int gfx_v11_0_3_poison_consumption_handler(struct amdgpu_device *adev,
|
||||
ras->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE2_RESET;
|
||||
}
|
||||
|
||||
if (con && !con->is_rma)
|
||||
if (con && !amdgpu_ras_is_rma(adev))
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
}
|
||||
|
||||
|
@ -1281,7 +1281,7 @@ static void gfx_v12_0_alloc_ip_dump(struct amdgpu_device *adev)
|
||||
uint32_t inst;
|
||||
|
||||
ptr = kcalloc(reg_count, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (ptr == NULL) {
|
||||
if (!ptr) {
|
||||
DRM_ERROR("Failed to allocate memory for GFX IP Dump\n");
|
||||
adev->gfx.ip_dump_core = NULL;
|
||||
} else {
|
||||
@ -1294,7 +1294,7 @@ static void gfx_v12_0_alloc_ip_dump(struct amdgpu_device *adev)
|
||||
adev->gfx.mec.num_queue_per_pipe;
|
||||
|
||||
ptr = kcalloc(reg_count * inst, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (ptr == NULL) {
|
||||
if (!ptr) {
|
||||
DRM_ERROR("Failed to allocate memory for Compute Queues IP Dump\n");
|
||||
adev->gfx.ip_dump_compute_queues = NULL;
|
||||
} else {
|
||||
@ -1307,7 +1307,7 @@ static void gfx_v12_0_alloc_ip_dump(struct amdgpu_device *adev)
|
||||
adev->gfx.me.num_queue_per_pipe;
|
||||
|
||||
ptr = kcalloc(reg_count * inst, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (ptr == NULL) {
|
||||
if (!ptr) {
|
||||
DRM_ERROR("Failed to allocate memory for GFX Queues IP Dump\n");
|
||||
adev->gfx.ip_dump_gfx_queues = NULL;
|
||||
} else {
|
||||
@ -1355,6 +1355,13 @@ static int gfx_v12_0_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Bad opcode Event */
|
||||
r = amdgpu_irq_add_id(adev, SOC21_IH_CLIENTID_GRBM_CP,
|
||||
GFX_11_0_0__SRCID__CP_BAD_OPCODE_ERROR,
|
||||
&adev->gfx.bad_op_irq);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Privileged reg */
|
||||
r = amdgpu_irq_add_id(adev, SOC21_IH_CLIENTID_GRBM_CP,
|
||||
GFX_11_0_0__SRCID__CP_PRIV_REG_FAULT,
|
||||
@ -1686,26 +1693,68 @@ static void gfx_v12_0_constants_init(struct amdgpu_device *adev)
|
||||
gfx_v12_0_init_compute_vmid(adev);
|
||||
}
|
||||
|
||||
static void gfx_v12_0_enable_gui_idle_interrupt(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
static u32 gfx_v12_0_get_cpg_int_cntl(struct amdgpu_device *adev,
|
||||
int me, int pipe)
|
||||
{
|
||||
u32 tmp;
|
||||
if (me != 0)
|
||||
return 0;
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
return SOC15_REG_OFFSET(GC, 0, regCP_INT_CNTL_RING0);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 gfx_v12_0_get_cpc_int_cntl(struct amdgpu_device *adev,
|
||||
int me, int pipe)
|
||||
{
|
||||
/*
|
||||
* amdgpu controls only the first MEC. That's why this function only
|
||||
* handles the setting of interrupts for this specific MEC. All other
|
||||
* pipes' interrupts are set by amdkfd.
|
||||
*/
|
||||
if (me != 1)
|
||||
return 0;
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
return SOC15_REG_OFFSET(GC, 0, regCP_ME1_PIPE0_INT_CNTL);
|
||||
case 1:
|
||||
return SOC15_REG_OFFSET(GC, 0, regCP_ME1_PIPE1_INT_CNTL);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_v12_0_enable_gui_idle_interrupt(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
u32 tmp, cp_int_cntl_reg;
|
||||
int i, j;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return;
|
||||
|
||||
tmp = RREG32_SOC15(GC, 0, regCP_INT_CNTL_RING0);
|
||||
for (i = 0; i < adev->gfx.me.num_me; i++) {
|
||||
for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
|
||||
cp_int_cntl_reg = gfx_v12_0_get_cpg_int_cntl(adev, i, j);
|
||||
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
|
||||
WREG32_SOC15(GC, 0, regCP_INT_CNTL_RING0, tmp);
|
||||
if (cp_int_cntl_reg) {
|
||||
tmp = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE,
|
||||
enable ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int gfx_v12_0_init_csb(struct amdgpu_device *adev)
|
||||
@ -3005,7 +3054,7 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
|
||||
(order_base_2(prop->queue_size / 4) - 1));
|
||||
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE,
|
||||
(order_base_2(AMDGPU_GPU_PAGE_SIZE / 4) - 1));
|
||||
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 1);
|
||||
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1);
|
||||
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1);
|
||||
@ -3553,6 +3602,7 @@ static int gfx_v12_0_hw_fini(void *handle)
|
||||
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.bad_op_irq, 0);
|
||||
|
||||
if (!adev->no_hw_access) {
|
||||
if (amdgpu_async_gfx_ring) {
|
||||
@ -3672,6 +3722,10 @@ static int gfx_v12_0_late_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_irq_get(adev, &adev->gfx.bad_op_irq, 0);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4747,15 +4801,42 @@ static int gfx_v12_0_eop_irq(struct amdgpu_device *adev,
|
||||
|
||||
static int gfx_v12_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
unsigned int type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
u32 cp_int_cntl_reg, cp_int_cntl;
|
||||
int i, j;
|
||||
|
||||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
WREG32_FIELD15_PREREG(GC, 0, CP_INT_CNTL_RING0,
|
||||
PRIV_REG_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
for (i = 0; i < adev->gfx.me.num_me; i++) {
|
||||
for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
|
||||
cp_int_cntl_reg = gfx_v12_0_get_cpg_int_cntl(adev, i, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
|
||||
PRIV_REG_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < adev->gfx.mec.num_mec; i++) {
|
||||
for (j = 0; j < adev->gfx.mec.num_pipe_per_mec; j++) {
|
||||
/* MECs start at 1 */
|
||||
cp_int_cntl_reg = gfx_v12_0_get_cpc_int_cntl(adev, i + 1, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_ME1_PIPE0_INT_CNTL,
|
||||
PRIV_REG_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -4764,17 +4845,75 @@ static int gfx_v12_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v12_0_set_priv_inst_fault_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
static int gfx_v12_0_set_bad_op_fault_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
u32 cp_int_cntl_reg, cp_int_cntl;
|
||||
int i, j;
|
||||
|
||||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
WREG32_FIELD15_PREREG(GC, 0, CP_INT_CNTL_RING0,
|
||||
PRIV_INSTR_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
for (i = 0; i < adev->gfx.me.num_me; i++) {
|
||||
for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
|
||||
cp_int_cntl_reg = gfx_v12_0_get_cpg_int_cntl(adev, i, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
|
||||
OPCODE_ERROR_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < adev->gfx.mec.num_mec; i++) {
|
||||
for (j = 0; j < adev->gfx.mec.num_pipe_per_mec; j++) {
|
||||
/* MECs start at 1 */
|
||||
cp_int_cntl_reg = gfx_v12_0_get_cpc_int_cntl(adev, i + 1, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_ME1_PIPE0_INT_CNTL,
|
||||
OPCODE_ERROR_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v12_0_set_priv_inst_fault_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned int type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
u32 cp_int_cntl_reg, cp_int_cntl;
|
||||
int i, j;
|
||||
|
||||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
for (i = 0; i < adev->gfx.me.num_me; i++) {
|
||||
for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
|
||||
cp_int_cntl_reg = gfx_v12_0_get_cpg_int_cntl(adev, i, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
|
||||
PRIV_INSTR_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -4798,8 +4937,8 @@ static void gfx_v12_0_handle_priv_fault(struct amdgpu_device *adev,
|
||||
case 0:
|
||||
for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
|
||||
ring = &adev->gfx.gfx_ring[i];
|
||||
/* we only enabled 1 gfx queue per pipe for now */
|
||||
if (ring->me == me_id && ring->pipe == pipe_id)
|
||||
if (ring->me == me_id && ring->pipe == pipe_id &&
|
||||
ring->queue == queue_id)
|
||||
drm_sched_fault(&ring->sched);
|
||||
}
|
||||
break;
|
||||
@ -4827,6 +4966,15 @@ static int gfx_v12_0_priv_reg_irq(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v12_0_bad_op_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
DRM_ERROR("Illegal opcode in command stream \n");
|
||||
gfx_v12_0_handle_priv_fault(adev, entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v12_0_priv_inst_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
@ -4859,6 +5007,24 @@ static void gfx_v12_0_emit_mem_sync(struct amdgpu_ring *ring)
|
||||
amdgpu_ring_write(ring, gcr_cntl); /* GCR_CNTL */
|
||||
}
|
||||
|
||||
static void gfx_v12_ring_insert_nop(struct amdgpu_ring *ring, uint32_t num_nop)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Header itself is a NOP packet */
|
||||
if (num_nop == 1) {
|
||||
amdgpu_ring_write(ring, ring->funcs->nop);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max HW optimization till 0x3ffe, followed by remaining one NOP at a time*/
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_NOP, min(num_nop - 2, 0x3ffe)));
|
||||
|
||||
/* Header is at index 0, followed by num_nops - 1 NOP packet's */
|
||||
for (i = 1; i < num_nop; i++)
|
||||
amdgpu_ring_write(ring, ring->funcs->nop);
|
||||
}
|
||||
|
||||
static void gfx_v12_ip_print(void *handle, struct drm_printer *p)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
@ -5040,7 +5206,7 @@ static const struct amdgpu_ring_funcs gfx_v12_0_ring_funcs_gfx = {
|
||||
.emit_hdp_flush = gfx_v12_0_ring_emit_hdp_flush,
|
||||
.test_ring = gfx_v12_0_ring_test_ring,
|
||||
.test_ib = gfx_v12_0_ring_test_ib,
|
||||
.insert_nop = amdgpu_ring_insert_nop,
|
||||
.insert_nop = gfx_v12_ring_insert_nop,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.emit_cntxcntl = gfx_v12_0_ring_emit_cntxcntl,
|
||||
.init_cond_exec = gfx_v12_0_ring_emit_init_cond_exec,
|
||||
@ -5078,11 +5244,12 @@ static const struct amdgpu_ring_funcs gfx_v12_0_ring_funcs_compute = {
|
||||
.emit_hdp_flush = gfx_v12_0_ring_emit_hdp_flush,
|
||||
.test_ring = gfx_v12_0_ring_test_ring,
|
||||
.test_ib = gfx_v12_0_ring_test_ib,
|
||||
.insert_nop = amdgpu_ring_insert_nop,
|
||||
.insert_nop = gfx_v12_ring_insert_nop,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.emit_wreg = gfx_v12_0_ring_emit_wreg,
|
||||
.emit_reg_wait = gfx_v12_0_ring_emit_reg_wait,
|
||||
.emit_reg_write_reg_wait = gfx_v12_0_ring_emit_reg_write_reg_wait,
|
||||
.soft_recovery = gfx_v12_0_ring_soft_recovery,
|
||||
.emit_mem_sync = gfx_v12_0_emit_mem_sync,
|
||||
};
|
||||
|
||||
@ -5138,6 +5305,11 @@ static const struct amdgpu_irq_src_funcs gfx_v12_0_priv_reg_irq_funcs = {
|
||||
.process = gfx_v12_0_priv_reg_irq,
|
||||
};
|
||||
|
||||
static const struct amdgpu_irq_src_funcs gfx_v12_0_bad_op_irq_funcs = {
|
||||
.set = gfx_v12_0_set_bad_op_fault_state,
|
||||
.process = gfx_v12_0_bad_op_irq,
|
||||
};
|
||||
|
||||
static const struct amdgpu_irq_src_funcs gfx_v12_0_priv_inst_irq_funcs = {
|
||||
.set = gfx_v12_0_set_priv_inst_fault_state,
|
||||
.process = gfx_v12_0_priv_inst_irq,
|
||||
@ -5151,6 +5323,9 @@ static void gfx_v12_0_set_irq_funcs(struct amdgpu_device *adev)
|
||||
adev->gfx.priv_reg_irq.num_types = 1;
|
||||
adev->gfx.priv_reg_irq.funcs = &gfx_v12_0_priv_reg_irq_funcs;
|
||||
|
||||
adev->gfx.bad_op_irq.num_types = 1;
|
||||
adev->gfx.bad_op_irq.funcs = &gfx_v12_0_bad_op_irq_funcs;
|
||||
|
||||
adev->gfx.priv_inst_irq.num_types = 1;
|
||||
adev->gfx.priv_inst_irq.funcs = &gfx_v12_0_priv_inst_irq_funcs;
|
||||
}
|
||||
|
@ -2114,6 +2114,8 @@ static void gfx_v7_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr,
|
||||
{
|
||||
bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT;
|
||||
bool int_sel = flags & AMDGPU_FENCE_FLAG_INT;
|
||||
bool exec = flags & AMDGPU_FENCE_FLAG_EXEC;
|
||||
|
||||
/* Workaround for cache flush problems. First send a dummy EOP
|
||||
* event down the pipe with seq one below.
|
||||
*/
|
||||
@ -2133,7 +2135,8 @@ static void gfx_v7_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr,
|
||||
amdgpu_ring_write(ring, (EOP_TCL1_ACTION_EN |
|
||||
EOP_TC_ACTION_EN |
|
||||
EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) |
|
||||
EVENT_INDEX(5)));
|
||||
EVENT_INDEX(5) |
|
||||
(exec ? EOP_EXEC : 0)));
|
||||
amdgpu_ring_write(ring, addr & 0xfffffffc);
|
||||
amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xffff) |
|
||||
DATA_SEL(write64bit ? 2 : 1) | INT_SEL(int_sel ? 2 : 0));
|
||||
@ -4921,6 +4924,76 @@ static void gfx_v7_0_emit_mem_sync_compute(struct amdgpu_ring *ring)
|
||||
amdgpu_ring_write(ring, 0x0000000A); /* poll interval */
|
||||
}
|
||||
|
||||
static void gfx_v7_0_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
|
||||
int mem_space, int opt, uint32_t addr0,
|
||||
uint32_t addr1, uint32_t ref, uint32_t mask,
|
||||
uint32_t inv)
|
||||
{
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
|
||||
amdgpu_ring_write(ring,
|
||||
/* memory (1) or register (0) */
|
||||
(WAIT_REG_MEM_MEM_SPACE(mem_space) |
|
||||
WAIT_REG_MEM_OPERATION(opt) | /* wait */
|
||||
WAIT_REG_MEM_FUNCTION(3) | /* equal */
|
||||
WAIT_REG_MEM_ENGINE(eng_sel)));
|
||||
|
||||
if (mem_space)
|
||||
BUG_ON(addr0 & 0x3); /* Dword align */
|
||||
amdgpu_ring_write(ring, addr0);
|
||||
amdgpu_ring_write(ring, addr1);
|
||||
amdgpu_ring_write(ring, ref);
|
||||
amdgpu_ring_write(ring, mask);
|
||||
amdgpu_ring_write(ring, inv); /* poll interval */
|
||||
}
|
||||
|
||||
static void gfx_v7_0_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
|
||||
uint32_t val, uint32_t mask)
|
||||
{
|
||||
gfx_v7_0_wait_reg_mem(ring, 0, 0, 0, reg, 0, val, mask, 0x20);
|
||||
}
|
||||
|
||||
static int gfx_v7_0_reset_kgq(struct amdgpu_ring *ring, unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
|
||||
struct amdgpu_ring *kiq_ring = &kiq->ring;
|
||||
unsigned long flags;
|
||||
u32 tmp;
|
||||
int r;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&kiq->ring_lock, flags);
|
||||
|
||||
if (amdgpu_ring_alloc(kiq_ring, 5)) {
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tmp = REG_SET_FIELD(0, CP_VMID_RESET, RESET_REQUEST, 1 << vmid);
|
||||
gfx_v7_0_ring_emit_wreg(kiq_ring, mmCP_VMID_RESET, tmp);
|
||||
amdgpu_ring_commit(kiq_ring);
|
||||
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
|
||||
r = amdgpu_ring_test_ring(kiq_ring);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (amdgpu_ring_alloc(ring, 7 + 12 + 5))
|
||||
return -ENOMEM;
|
||||
gfx_v7_0_ring_emit_fence_gfx(ring, ring->fence_drv.gpu_addr,
|
||||
ring->fence_drv.sync_seq, AMDGPU_FENCE_FLAG_EXEC);
|
||||
gfx_v7_0_ring_emit_reg_wait(ring, mmCP_VMID_RESET, 0, 0xffff);
|
||||
gfx_v7_0_ring_emit_wreg(ring, mmCP_VMID_RESET, 0);
|
||||
|
||||
return amdgpu_ring_test_ring(ring);
|
||||
}
|
||||
|
||||
static const struct amd_ip_funcs gfx_v7_0_ip_funcs = {
|
||||
.name = "gfx_v7_0",
|
||||
.early_init = gfx_v7_0_early_init,
|
||||
@ -4972,6 +5045,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = {
|
||||
.emit_wreg = gfx_v7_0_ring_emit_wreg,
|
||||
.soft_recovery = gfx_v7_0_ring_soft_recovery,
|
||||
.emit_mem_sync = gfx_v7_0_emit_mem_sync,
|
||||
.reset = gfx_v7_0_reset_kgq,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = {
|
||||
@ -5002,6 +5076,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = {
|
||||
.insert_nop = amdgpu_ring_insert_nop,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.emit_wreg = gfx_v7_0_ring_emit_wreg,
|
||||
.soft_recovery = gfx_v7_0_ring_soft_recovery,
|
||||
.emit_mem_sync = gfx_v7_0_emit_mem_sync_compute,
|
||||
};
|
||||
|
||||
|
@ -6149,6 +6149,7 @@ static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr,
|
||||
{
|
||||
bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT;
|
||||
bool int_sel = flags & AMDGPU_FENCE_FLAG_INT;
|
||||
bool exec = flags & AMDGPU_FENCE_FLAG_EXEC;
|
||||
|
||||
/* Workaround for cache flush problems. First send a dummy EOP
|
||||
* event down the pipe with seq one below.
|
||||
@ -6172,7 +6173,8 @@ static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr,
|
||||
EOP_TC_ACTION_EN |
|
||||
EOP_TC_WB_ACTION_EN |
|
||||
EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) |
|
||||
EVENT_INDEX(5)));
|
||||
EVENT_INDEX(5) |
|
||||
(exec ? EOP_EXEC : 0)));
|
||||
amdgpu_ring_write(ring, addr & 0xfffffffc);
|
||||
amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xffff) |
|
||||
DATA_SEL(write64bit ? 2 : 1) | INT_SEL(int_sel ? 2 : 0));
|
||||
@ -6380,6 +6382,34 @@ static void gfx_v8_0_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg,
|
||||
amdgpu_ring_write(ring, val);
|
||||
}
|
||||
|
||||
static void gfx_v8_0_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
|
||||
int mem_space, int opt, uint32_t addr0,
|
||||
uint32_t addr1, uint32_t ref, uint32_t mask,
|
||||
uint32_t inv)
|
||||
{
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
|
||||
amdgpu_ring_write(ring,
|
||||
/* memory (1) or register (0) */
|
||||
(WAIT_REG_MEM_MEM_SPACE(mem_space) |
|
||||
WAIT_REG_MEM_OPERATION(opt) | /* wait */
|
||||
WAIT_REG_MEM_FUNCTION(3) | /* equal */
|
||||
WAIT_REG_MEM_ENGINE(eng_sel)));
|
||||
|
||||
if (mem_space)
|
||||
BUG_ON(addr0 & 0x3); /* Dword align */
|
||||
amdgpu_ring_write(ring, addr0);
|
||||
amdgpu_ring_write(ring, addr1);
|
||||
amdgpu_ring_write(ring, ref);
|
||||
amdgpu_ring_write(ring, mask);
|
||||
amdgpu_ring_write(ring, inv); /* poll interval */
|
||||
}
|
||||
|
||||
static void gfx_v8_0_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
|
||||
uint32_t val, uint32_t mask)
|
||||
{
|
||||
gfx_v8_0_wait_reg_mem(ring, 0, 0, 0, reg, 0, val, mask, 0x20);
|
||||
}
|
||||
|
||||
static void gfx_v8_0_ring_soft_recovery(struct amdgpu_ring *ring, unsigned vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
@ -6856,6 +6886,48 @@ static void gfx_v8_0_emit_wave_limit(struct amdgpu_ring *ring, bool enable)
|
||||
|
||||
}
|
||||
|
||||
static int gfx_v8_0_reset_kgq(struct amdgpu_ring *ring, unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
|
||||
struct amdgpu_ring *kiq_ring = &kiq->ring;
|
||||
unsigned long flags;
|
||||
u32 tmp;
|
||||
int r;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&kiq->ring_lock, flags);
|
||||
|
||||
if (amdgpu_ring_alloc(kiq_ring, 5)) {
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tmp = REG_SET_FIELD(0, CP_VMID_RESET, RESET_REQUEST, 1 << vmid);
|
||||
gfx_v8_0_ring_emit_wreg(kiq_ring, mmCP_VMID_RESET, tmp);
|
||||
amdgpu_ring_commit(kiq_ring);
|
||||
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
|
||||
r = amdgpu_ring_test_ring(kiq_ring);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (amdgpu_ring_alloc(ring, 7 + 12 + 5))
|
||||
return -ENOMEM;
|
||||
gfx_v8_0_ring_emit_fence_gfx(ring, ring->fence_drv.gpu_addr,
|
||||
ring->fence_drv.sync_seq, AMDGPU_FENCE_FLAG_EXEC);
|
||||
gfx_v8_0_ring_emit_reg_wait(ring, mmCP_VMID_RESET, 0, 0xffff);
|
||||
gfx_v8_0_ring_emit_wreg(ring, mmCP_VMID_RESET, 0);
|
||||
|
||||
return amdgpu_ring_test_ring(ring);
|
||||
}
|
||||
|
||||
static const struct amd_ip_funcs gfx_v8_0_ip_funcs = {
|
||||
.name = "gfx_v8_0",
|
||||
.early_init = gfx_v8_0_early_init,
|
||||
@ -6923,6 +6995,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
|
||||
.emit_wreg = gfx_v8_0_ring_emit_wreg,
|
||||
.soft_recovery = gfx_v8_0_ring_soft_recovery,
|
||||
.emit_mem_sync = gfx_v8_0_emit_mem_sync,
|
||||
.reset = gfx_v8_0_reset_kgq,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = {
|
||||
@ -6955,6 +7028,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = {
|
||||
.insert_nop = amdgpu_ring_insert_nop,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.emit_wreg = gfx_v8_0_ring_emit_wreg,
|
||||
.soft_recovery = gfx_v8_0_ring_soft_recovery,
|
||||
.emit_mem_sync = gfx_v8_0_emit_mem_sync_compute,
|
||||
.emit_wave_limit = gfx_v8_0_emit_wave_limit,
|
||||
};
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "amdgpu_ring_mux.h"
|
||||
#include "gfx_v9_4.h"
|
||||
#include "gfx_v9_0.h"
|
||||
#include "gfx_v9_0_cleaner_shader.h"
|
||||
#include "gfx_v9_4_2.h"
|
||||
|
||||
#include "asic_reg/pwr/pwr_10_0_offset.h"
|
||||
@ -893,10 +894,18 @@ static int gfx_v9_0_ras_error_inject(struct amdgpu_device *adev,
|
||||
static void gfx_v9_0_reset_ras_error_count(struct amdgpu_device *adev);
|
||||
static void gfx_v9_0_update_spm_vmid_internal(struct amdgpu_device *adev,
|
||||
unsigned int vmid);
|
||||
static void gfx_v9_0_set_safe_mode(struct amdgpu_device *adev, int xcc_id);
|
||||
static void gfx_v9_0_unset_safe_mode(struct amdgpu_device *adev, int xcc_id);
|
||||
|
||||
static void gfx_v9_0_kiq_set_resources(struct amdgpu_ring *kiq_ring,
|
||||
uint64_t queue_mask)
|
||||
{
|
||||
struct amdgpu_device *adev = kiq_ring->adev;
|
||||
u64 shader_mc_addr;
|
||||
|
||||
/* Cleaner shader MC address */
|
||||
shader_mc_addr = adev->gfx.cleaner_shader_gpu_addr >> 8;
|
||||
|
||||
amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_SET_RESOURCES, 6));
|
||||
amdgpu_ring_write(kiq_ring,
|
||||
PACKET3_SET_RESOURCES_VMID_MASK(0) |
|
||||
@ -906,8 +915,8 @@ static void gfx_v9_0_kiq_set_resources(struct amdgpu_ring *kiq_ring,
|
||||
lower_32_bits(queue_mask)); /* queue mask lo */
|
||||
amdgpu_ring_write(kiq_ring,
|
||||
upper_32_bits(queue_mask)); /* queue mask hi */
|
||||
amdgpu_ring_write(kiq_ring, 0); /* gws mask lo */
|
||||
amdgpu_ring_write(kiq_ring, 0); /* gws mask hi */
|
||||
amdgpu_ring_write(kiq_ring, lower_32_bits(shader_mc_addr)); /* cleaner shader addr lo */
|
||||
amdgpu_ring_write(kiq_ring, upper_32_bits(shader_mc_addr)); /* cleaner shader addr hi */
|
||||
amdgpu_ring_write(kiq_ring, 0); /* oac mask */
|
||||
amdgpu_ring_write(kiq_ring, 0); /* gds heap base:0, gds heap size:0 */
|
||||
}
|
||||
@ -1004,12 +1013,47 @@ static void gfx_v9_0_kiq_invalidate_tlbs(struct amdgpu_ring *kiq_ring,
|
||||
PACKET3_INVALIDATE_TLBS_FLUSH_TYPE(flush_type));
|
||||
}
|
||||
|
||||
|
||||
static void gfx_v9_0_kiq_reset_hw_queue(struct amdgpu_ring *kiq_ring, uint32_t queue_type,
|
||||
uint32_t me_id, uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t xcc_id, uint32_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = kiq_ring->adev;
|
||||
unsigned i;
|
||||
|
||||
/* enter save mode */
|
||||
amdgpu_gfx_rlc_enter_safe_mode(adev, xcc_id);
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
soc15_grbm_select(adev, me_id, pipe_id, queue_id, 0, 0);
|
||||
|
||||
if (queue_type == AMDGPU_RING_TYPE_COMPUTE) {
|
||||
WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST, 0x2);
|
||||
WREG32_SOC15(GC, 0, mmSPI_COMPUTE_QUEUE_RESET, 0x1);
|
||||
/* wait till dequeue take effects */
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
if (!(RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE) & 1))
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
if (i >= adev->usec_timeout)
|
||||
dev_err(adev->dev, "fail to wait on hqd deactive\n");
|
||||
} else {
|
||||
dev_err(adev->dev, "reset queue_type(%d) not supported\n", queue_type);
|
||||
}
|
||||
|
||||
soc15_grbm_select(adev, 0, 0, 0, 0, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
/* exit safe mode */
|
||||
amdgpu_gfx_rlc_exit_safe_mode(adev, xcc_id);
|
||||
}
|
||||
|
||||
static const struct kiq_pm4_funcs gfx_v9_0_kiq_pm4_funcs = {
|
||||
.kiq_set_resources = gfx_v9_0_kiq_set_resources,
|
||||
.kiq_map_queues = gfx_v9_0_kiq_map_queues,
|
||||
.kiq_unmap_queues = gfx_v9_0_kiq_unmap_queues,
|
||||
.kiq_query_status = gfx_v9_0_kiq_query_status,
|
||||
.kiq_invalidate_tlbs = gfx_v9_0_kiq_invalidate_tlbs,
|
||||
.kiq_reset_hw_queue = gfx_v9_0_kiq_reset_hw_queue,
|
||||
.set_resources_size = 8,
|
||||
.map_queues_size = 7,
|
||||
.unmap_queues_size = 6,
|
||||
@ -2129,7 +2173,7 @@ static void gfx_v9_0_alloc_ip_dump(struct amdgpu_device *adev)
|
||||
uint32_t inst;
|
||||
|
||||
ptr = kcalloc(reg_count, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (ptr == NULL) {
|
||||
if (!ptr) {
|
||||
DRM_ERROR("Failed to allocate memory for GFX IP Dump\n");
|
||||
adev->gfx.ip_dump_core = NULL;
|
||||
} else {
|
||||
@ -2142,7 +2186,7 @@ static void gfx_v9_0_alloc_ip_dump(struct amdgpu_device *adev)
|
||||
adev->gfx.mec.num_queue_per_pipe;
|
||||
|
||||
ptr = kcalloc(reg_count * inst, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (ptr == NULL) {
|
||||
if (!ptr) {
|
||||
DRM_ERROR("Failed to allocate memory for Compute Queues IP Dump\n");
|
||||
adev->gfx.ip_dump_compute_queues = NULL;
|
||||
} else {
|
||||
@ -2174,6 +2218,12 @@ static int gfx_v9_0_sw_init(void *handle)
|
||||
break;
|
||||
}
|
||||
|
||||
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
|
||||
default:
|
||||
adev->gfx.enable_cleaner_shader = false;
|
||||
break;
|
||||
}
|
||||
|
||||
adev->gfx.mec.num_pipe_per_mec = 4;
|
||||
adev->gfx.mec.num_queue_per_pipe = 8;
|
||||
|
||||
@ -2182,6 +2232,13 @@ static int gfx_v9_0_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Bad opcode Event */
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_GRBM_CP,
|
||||
GFX_9_0__SRCID__CP_BAD_OPCODE_ERROR,
|
||||
&adev->gfx.bad_op_irq);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Privileged reg */
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_GRBM_CP, GFX_9_0__SRCID__CP_PRIV_REG_FAULT,
|
||||
&adev->gfx.priv_reg_irq);
|
||||
@ -2329,6 +2386,10 @@ static int gfx_v9_0_sw_init(void *handle)
|
||||
|
||||
gfx_v9_0_alloc_ip_dump(adev);
|
||||
|
||||
r = amdgpu_gfx_sysfs_isolation_shader_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2364,6 +2425,8 @@ static int gfx_v9_0_sw_fini(void *handle)
|
||||
}
|
||||
gfx_v9_0_free_microcode(adev);
|
||||
|
||||
amdgpu_gfx_sysfs_isolation_shader_fini(adev);
|
||||
|
||||
kfree(adev->gfx.ip_dump_core);
|
||||
kfree(adev->gfx.ip_dump_compute_queues);
|
||||
|
||||
@ -2634,7 +2697,7 @@ static void gfx_v9_0_enable_gui_idle_interrupt(struct amdgpu_device *adev,
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE, enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE, enable ? 1 : 0);
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE, enable ? 1 : 0);
|
||||
if(adev->gfx.num_gfx_rings)
|
||||
if (adev->gfx.num_gfx_rings)
|
||||
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE, enable ? 1 : 0);
|
||||
|
||||
WREG32_SOC15(GC, 0, mmCP_INT_CNTL_RING0, tmp);
|
||||
@ -3735,7 +3798,7 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring)
|
||||
static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring, bool restore)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct v9_mqd *mqd = ring->mqd_ptr;
|
||||
@ -3747,8 +3810,8 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring)
|
||||
*/
|
||||
tmp_mqd = (struct v9_mqd *)adev->gfx.mec.mqd_backup[mqd_idx];
|
||||
|
||||
if (!tmp_mqd->cp_hqd_pq_control ||
|
||||
(!amdgpu_in_reset(adev) && !adev->in_suspend)) {
|
||||
if (!restore && (!tmp_mqd->cp_hqd_pq_control ||
|
||||
(!amdgpu_in_reset(adev) && !adev->in_suspend))) {
|
||||
memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation));
|
||||
((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF;
|
||||
((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF;
|
||||
@ -3812,7 +3875,7 @@ static int gfx_v9_0_kcq_resume(struct amdgpu_device *adev)
|
||||
goto done;
|
||||
r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
|
||||
if (!r) {
|
||||
r = gfx_v9_0_kcq_init_queue(ring);
|
||||
r = gfx_v9_0_kcq_init_queue(ring, false);
|
||||
amdgpu_bo_kunmap(ring->mqd_obj);
|
||||
ring->mqd_ptr = NULL;
|
||||
}
|
||||
@ -3908,6 +3971,9 @@ static int gfx_v9_0_hw_init(void *handle)
|
||||
int r;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_gfx_cleaner_shader_init(adev, adev->gfx.cleaner_shader_size,
|
||||
adev->gfx.cleaner_shader_ptr);
|
||||
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
gfx_v9_0_init_golden_registers(adev);
|
||||
|
||||
@ -3937,6 +4003,7 @@ static int gfx_v9_0_hw_fini(void *handle)
|
||||
amdgpu_irq_put(adev, &adev->gfx.cp_ecc_error_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.bad_op_irq, 0);
|
||||
|
||||
/* DF freeze and kcq disable will fail */
|
||||
if (!amdgpu_ras_intr_triggered())
|
||||
@ -4747,6 +4814,10 @@ static int gfx_v9_0_late_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_irq_get(adev, &adev->gfx.bad_op_irq, 0);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = gfx_v9_0_ecc_late_init(handle);
|
||||
if (r)
|
||||
return r;
|
||||
@ -5858,7 +5929,9 @@ static void gfx_v9_0_ring_soft_recovery(struct amdgpu_ring *ring, unsigned vmid)
|
||||
value = REG_SET_FIELD(value, SQ_CMD, MODE, 0x01);
|
||||
value = REG_SET_FIELD(value, SQ_CMD, CHECK_VMID, 1);
|
||||
value = REG_SET_FIELD(value, SQ_CMD, VM_ID, vmid);
|
||||
amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
|
||||
WREG32_SOC15(GC, 0, mmSQ_CMD, value);
|
||||
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
|
||||
}
|
||||
|
||||
static void gfx_v9_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
|
||||
@ -5929,17 +6002,95 @@ static void gfx_v9_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev,
|
||||
}
|
||||
}
|
||||
|
||||
static u32 gfx_v9_0_get_cpc_int_cntl(struct amdgpu_device *adev,
|
||||
int me, int pipe)
|
||||
{
|
||||
/*
|
||||
* amdgpu controls only the first MEC. That's why this function only
|
||||
* handles the setting of interrupts for this specific MEC. All other
|
||||
* pipes' interrupts are set by amdkfd.
|
||||
*/
|
||||
if (me != 1)
|
||||
return 0;
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
return SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE0_INT_CNTL);
|
||||
case 1:
|
||||
return SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE1_INT_CNTL);
|
||||
case 2:
|
||||
return SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE2_INT_CNTL);
|
||||
case 3:
|
||||
return SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE3_INT_CNTL);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int gfx_v9_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
u32 cp_int_cntl_reg, cp_int_cntl;
|
||||
int i, j;
|
||||
|
||||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
WREG32_FIELD15(GC, 0, CP_INT_CNTL_RING0,
|
||||
PRIV_REG_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
for (i = 0; i < adev->gfx.mec.num_mec; i++) {
|
||||
for (j = 0; j < adev->gfx.mec.num_pipe_per_mec; j++) {
|
||||
/* MECs start at 1 */
|
||||
cp_int_cntl_reg = gfx_v9_0_get_cpc_int_cntl(adev, i + 1, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_ME1_PIPE0_INT_CNTL,
|
||||
PRIV_REG_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v9_0_set_bad_op_fault_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
u32 cp_int_cntl_reg, cp_int_cntl;
|
||||
int i, j;
|
||||
|
||||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
WREG32_FIELD15(GC, 0, CP_INT_CNTL_RING0,
|
||||
OPCODE_ERROR_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
for (i = 0; i < adev->gfx.mec.num_mec; i++) {
|
||||
for (j = 0; j < adev->gfx.mec.num_pipe_per_mec; j++) {
|
||||
/* MECs start at 1 */
|
||||
cp_int_cntl_reg = gfx_v9_0_get_cpc_int_cntl(adev, i + 1, j);
|
||||
|
||||
if (cp_int_cntl_reg) {
|
||||
cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_ME1_PIPE0_INT_CNTL,
|
||||
OPCODE_ERROR_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -6121,6 +6272,15 @@ static int gfx_v9_0_priv_reg_irq(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v9_0_bad_op_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
DRM_ERROR("Illegal opcode in command stream\n");
|
||||
gfx_v9_0_fault(adev, entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v9_0_priv_inst_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
@ -7001,6 +7161,153 @@ static void gfx_v9_0_emit_wave_limit(struct amdgpu_ring *ring, bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_v9_ring_insert_nop(struct amdgpu_ring *ring, uint32_t num_nop)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Header itself is a NOP packet */
|
||||
if (num_nop == 1) {
|
||||
amdgpu_ring_write(ring, ring->funcs->nop);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max HW optimization till 0x3ffe, followed by remaining one NOP at a time*/
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_NOP, min(num_nop - 2, 0x3ffe)));
|
||||
|
||||
/* Header is at index 0, followed by num_nops - 1 NOP packet's */
|
||||
for (i = 1; i < num_nop; i++)
|
||||
amdgpu_ring_write(ring, ring->funcs->nop);
|
||||
}
|
||||
|
||||
static int gfx_v9_0_reset_kgq(struct amdgpu_ring *ring, unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
|
||||
struct amdgpu_ring *kiq_ring = &kiq->ring;
|
||||
unsigned long flags;
|
||||
u32 tmp;
|
||||
int r;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&kiq->ring_lock, flags);
|
||||
|
||||
if (amdgpu_ring_alloc(kiq_ring, 5)) {
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tmp = REG_SET_FIELD(0, CP_VMID_RESET, RESET_REQUEST, 1 << vmid);
|
||||
gfx_v9_0_ring_emit_wreg(kiq_ring,
|
||||
SOC15_REG_OFFSET(GC, 0, mmCP_VMID_RESET), tmp);
|
||||
amdgpu_ring_commit(kiq_ring);
|
||||
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
|
||||
r = amdgpu_ring_test_ring(kiq_ring);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (amdgpu_ring_alloc(ring, 7 + 7 + 5))
|
||||
return -ENOMEM;
|
||||
gfx_v9_0_ring_emit_fence(ring, ring->fence_drv.gpu_addr,
|
||||
ring->fence_drv.sync_seq, AMDGPU_FENCE_FLAG_EXEC);
|
||||
gfx_v9_0_ring_emit_reg_wait(ring,
|
||||
SOC15_REG_OFFSET(GC, 0, mmCP_VMID_RESET), 0, 0xffff);
|
||||
gfx_v9_0_ring_emit_wreg(ring,
|
||||
SOC15_REG_OFFSET(GC, 0, mmCP_VMID_RESET), 0);
|
||||
|
||||
return amdgpu_ring_test_ring(ring);
|
||||
}
|
||||
|
||||
static int gfx_v9_0_reset_kcq(struct amdgpu_ring *ring,
|
||||
unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
|
||||
struct amdgpu_ring *kiq_ring = &kiq->ring;
|
||||
unsigned long flags;
|
||||
int i, r;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&kiq->ring_lock, flags);
|
||||
|
||||
if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size)) {
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
kiq->pmf->kiq_unmap_queues(kiq_ring, ring, RESET_QUEUES,
|
||||
0, 0);
|
||||
amdgpu_ring_commit(kiq_ring);
|
||||
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
|
||||
r = amdgpu_ring_test_ring(kiq_ring);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* make sure dequeue is complete*/
|
||||
amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0, 0);
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
if (!(RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE) & 1))
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
if (i >= adev->usec_timeout)
|
||||
r = -ETIMEDOUT;
|
||||
soc15_grbm_select(adev, 0, 0, 0, 0, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "fail to wait on hqd deactive\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_bo_reserve(ring->mqd_obj, false);
|
||||
if (unlikely(r != 0)){
|
||||
dev_err(adev->dev, "fail to resv mqd_obj\n");
|
||||
return r;
|
||||
}
|
||||
r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
|
||||
if (!r) {
|
||||
r = gfx_v9_0_kcq_init_queue(ring, true);
|
||||
amdgpu_bo_kunmap(ring->mqd_obj);
|
||||
ring->mqd_ptr = NULL;
|
||||
}
|
||||
amdgpu_bo_unreserve(ring->mqd_obj);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "fail to unresv mqd_obj\n");
|
||||
return r;
|
||||
}
|
||||
spin_lock_irqsave(&kiq->ring_lock, flags);
|
||||
r = amdgpu_ring_alloc(kiq_ring, kiq->pmf->map_queues_size);
|
||||
if (r) {
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
kiq->pmf->kiq_map_queues(kiq_ring, ring);
|
||||
amdgpu_ring_commit(kiq_ring);
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
r = amdgpu_ring_test_ring(kiq_ring);
|
||||
if (r) {
|
||||
DRM_ERROR("fail to remap queue\n");
|
||||
return r;
|
||||
}
|
||||
return amdgpu_ring_test_ring(ring);
|
||||
}
|
||||
|
||||
static void gfx_v9_ip_print(void *handle, struct drm_printer *p)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
@ -7083,6 +7390,13 @@ static void gfx_v9_ip_dump(void *handle)
|
||||
|
||||
}
|
||||
|
||||
static void gfx_v9_0_ring_emit_cleaner_shader(struct amdgpu_ring *ring)
|
||||
{
|
||||
/* Emit the cleaner shader */
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_RUN_CLEANER_SHADER, 0));
|
||||
amdgpu_ring_write(ring, 0); /* RESERVED field, programmed to zero */
|
||||
}
|
||||
|
||||
static const struct amd_ip_funcs gfx_v9_0_ip_funcs = {
|
||||
.name = "gfx_v9_0",
|
||||
.early_init = gfx_v9_0_early_init,
|
||||
@ -7132,7 +7446,8 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_gfx = {
|
||||
5 + /* HDP_INVL */
|
||||
8 + 8 + /* FENCE x2 */
|
||||
2 + /* SWITCH_BUFFER */
|
||||
7, /* gfx_v9_0_emit_mem_sync */
|
||||
7 + /* gfx_v9_0_emit_mem_sync */
|
||||
2, /* gfx_v9_0_ring_emit_cleaner_shader */
|
||||
.emit_ib_size = 4, /* gfx_v9_0_ring_emit_ib_gfx */
|
||||
.emit_ib = gfx_v9_0_ring_emit_ib_gfx,
|
||||
.emit_fence = gfx_v9_0_ring_emit_fence,
|
||||
@ -7141,7 +7456,7 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_gfx = {
|
||||
.emit_gds_switch = gfx_v9_0_ring_emit_gds_switch,
|
||||
.emit_hdp_flush = gfx_v9_0_ring_emit_hdp_flush,
|
||||
.test_ring = gfx_v9_0_ring_test_ring,
|
||||
.insert_nop = amdgpu_ring_insert_nop,
|
||||
.insert_nop = gfx_v9_ring_insert_nop,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.emit_switch_buffer = gfx_v9_ring_emit_sb,
|
||||
.emit_cntxcntl = gfx_v9_ring_emit_cntxcntl,
|
||||
@ -7153,6 +7468,10 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_gfx = {
|
||||
.emit_reg_write_reg_wait = gfx_v9_0_ring_emit_reg_write_reg_wait,
|
||||
.soft_recovery = gfx_v9_0_ring_soft_recovery,
|
||||
.emit_mem_sync = gfx_v9_0_emit_mem_sync,
|
||||
.reset = gfx_v9_0_reset_kgq,
|
||||
.emit_cleaner_shader = gfx_v9_0_ring_emit_cleaner_shader,
|
||||
.begin_use = amdgpu_gfx_enforce_isolation_ring_begin_use,
|
||||
.end_use = amdgpu_gfx_enforce_isolation_ring_end_use,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ring_funcs gfx_v9_0_sw_ring_funcs_gfx = {
|
||||
@ -7185,7 +7504,8 @@ static const struct amdgpu_ring_funcs gfx_v9_0_sw_ring_funcs_gfx = {
|
||||
5 + /* HDP_INVL */
|
||||
8 + 8 + /* FENCE x2 */
|
||||
2 + /* SWITCH_BUFFER */
|
||||
7, /* gfx_v9_0_emit_mem_sync */
|
||||
7 + /* gfx_v9_0_emit_mem_sync */
|
||||
2, /* gfx_v9_0_ring_emit_cleaner_shader */
|
||||
.emit_ib_size = 4, /* gfx_v9_0_ring_emit_ib_gfx */
|
||||
.emit_ib = gfx_v9_0_ring_emit_ib_gfx,
|
||||
.emit_fence = gfx_v9_0_ring_emit_fence,
|
||||
@ -7195,7 +7515,7 @@ static const struct amdgpu_ring_funcs gfx_v9_0_sw_ring_funcs_gfx = {
|
||||
.emit_hdp_flush = gfx_v9_0_ring_emit_hdp_flush,
|
||||
.test_ring = gfx_v9_0_ring_test_ring,
|
||||
.test_ib = gfx_v9_0_ring_test_ib,
|
||||
.insert_nop = amdgpu_sw_ring_insert_nop,
|
||||
.insert_nop = gfx_v9_ring_insert_nop,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.emit_switch_buffer = gfx_v9_ring_emit_sb,
|
||||
.emit_cntxcntl = gfx_v9_ring_emit_cntxcntl,
|
||||
@ -7209,6 +7529,9 @@ static const struct amdgpu_ring_funcs gfx_v9_0_sw_ring_funcs_gfx = {
|
||||
.patch_cntl = gfx_v9_0_ring_patch_cntl,
|
||||
.patch_de = gfx_v9_0_ring_patch_de_meta,
|
||||
.patch_ce = gfx_v9_0_ring_patch_ce_meta,
|
||||
.emit_cleaner_shader = gfx_v9_0_ring_emit_cleaner_shader,
|
||||
.begin_use = amdgpu_gfx_enforce_isolation_ring_begin_use,
|
||||
.end_use = amdgpu_gfx_enforce_isolation_ring_end_use,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_compute = {
|
||||
@ -7229,7 +7552,8 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_compute = {
|
||||
8 + 8 + 8 + /* gfx_v9_0_ring_emit_fence x3 for user fence, vm fence */
|
||||
7 + /* gfx_v9_0_emit_mem_sync */
|
||||
5 + /* gfx_v9_0_emit_wave_limit for updating mmSPI_WCL_PIPE_PERCENT_GFX register */
|
||||
15, /* for updating 3 mmSPI_WCL_PIPE_PERCENT_CS registers */
|
||||
15 + /* for updating 3 mmSPI_WCL_PIPE_PERCENT_CS registers */
|
||||
2, /* gfx_v9_0_ring_emit_cleaner_shader */
|
||||
.emit_ib_size = 7, /* gfx_v9_0_ring_emit_ib_compute */
|
||||
.emit_ib = gfx_v9_0_ring_emit_ib_compute,
|
||||
.emit_fence = gfx_v9_0_ring_emit_fence,
|
||||
@ -7239,13 +7563,18 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_compute = {
|
||||
.emit_hdp_flush = gfx_v9_0_ring_emit_hdp_flush,
|
||||
.test_ring = gfx_v9_0_ring_test_ring,
|
||||
.test_ib = gfx_v9_0_ring_test_ib,
|
||||
.insert_nop = amdgpu_ring_insert_nop,
|
||||
.insert_nop = gfx_v9_ring_insert_nop,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.emit_wreg = gfx_v9_0_ring_emit_wreg,
|
||||
.emit_reg_wait = gfx_v9_0_ring_emit_reg_wait,
|
||||
.emit_reg_write_reg_wait = gfx_v9_0_ring_emit_reg_write_reg_wait,
|
||||
.soft_recovery = gfx_v9_0_ring_soft_recovery,
|
||||
.emit_mem_sync = gfx_v9_0_emit_mem_sync,
|
||||
.emit_wave_limit = gfx_v9_0_emit_wave_limit,
|
||||
.reset = gfx_v9_0_reset_kcq,
|
||||
.emit_cleaner_shader = gfx_v9_0_ring_emit_cleaner_shader,
|
||||
.begin_use = amdgpu_gfx_enforce_isolation_ring_begin_use,
|
||||
.end_use = amdgpu_gfx_enforce_isolation_ring_end_use,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_kiq = {
|
||||
@ -7303,6 +7632,11 @@ static const struct amdgpu_irq_src_funcs gfx_v9_0_priv_reg_irq_funcs = {
|
||||
.process = gfx_v9_0_priv_reg_irq,
|
||||
};
|
||||
|
||||
static const struct amdgpu_irq_src_funcs gfx_v9_0_bad_op_irq_funcs = {
|
||||
.set = gfx_v9_0_set_bad_op_fault_state,
|
||||
.process = gfx_v9_0_bad_op_irq,
|
||||
};
|
||||
|
||||
static const struct amdgpu_irq_src_funcs gfx_v9_0_priv_inst_irq_funcs = {
|
||||
.set = gfx_v9_0_set_priv_inst_fault_state,
|
||||
.process = gfx_v9_0_priv_inst_irq,
|
||||
@ -7322,6 +7656,9 @@ static void gfx_v9_0_set_irq_funcs(struct amdgpu_device *adev)
|
||||
adev->gfx.priv_reg_irq.num_types = 1;
|
||||
adev->gfx.priv_reg_irq.funcs = &gfx_v9_0_priv_reg_irq_funcs;
|
||||
|
||||
adev->gfx.bad_op_irq.num_types = 1;
|
||||
adev->gfx.bad_op_irq.funcs = &gfx_v9_0_bad_op_irq_funcs;
|
||||
|
||||
adev->gfx.priv_inst_irq.num_types = 1;
|
||||
adev->gfx.priv_inst_irq.funcs = &gfx_v9_0_priv_inst_irq_funcs;
|
||||
|
||||
|
26
drivers/gpu/drm/amd/amdgpu/gfx_v9_0_cleaner_shader.h
Normal file
26
drivers/gpu/drm/amd/amdgpu/gfx_v9_0_cleaner_shader.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright 2018 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/* Define the cleaner shader gfx_9_0 */
|
||||
static const u32 __maybe_unused gfx_9_0_cleaner_shader_hex[] = {
|
||||
/* Add the cleaner shader code here */
|
||||
};
|
@ -37,6 +37,7 @@
|
||||
#include "gc/gc_9_4_3_sh_mask.h"
|
||||
|
||||
#include "gfx_v9_4_3.h"
|
||||
#include "gfx_v9_4_3_cleaner_shader.h"
|
||||
#include "amdgpu_xcp.h"
|
||||
#include "amdgpu_aca.h"
|
||||
|
||||
@ -63,6 +64,98 @@ MODULE_FIRMWARE("amdgpu/gc_9_4_4_rlc.bin");
|
||||
#define NORMALIZE_XCC_REG_OFFSET(offset) \
|
||||
(offset & 0xFFFF)
|
||||
|
||||
static const struct amdgpu_hwip_reg_entry gc_reg_list_9_4_3[] = {
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS2),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_STALLED_STAT1),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_STALLED_STAT2),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_CPC_STALLED_STAT1),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_CPF_STALLED_STAT1),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_BUSY_STAT),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_CPC_BUSY_STAT),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_CPF_BUSY_STAT),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_CPF_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_GFX_ERROR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCPF_UTCL1_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCPC_UTCL1_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCPG_UTCL1_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regGDS_PROTECTION_FAULT),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regGDS_VM_PROTECTION_FAULT),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regRLC_UTCL1_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regRMI_UTCL1_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSQC_DCACHE_UTCL1_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSQC_ICACHE_UTCL1_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSQ_UTCL1_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regTCP_UTCL1_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regWD_UTCL1_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regVM_L2_PROTECTION_FAULT_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regVM_L2_PROTECTION_FAULT_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_DEBUG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_MEC_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_MEC1_INSTR_PNTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_MEC2_INSTR_PNTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_CPC_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regRLC_STAT),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regRLC_SMU_COMMAND),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regRLC_SMU_MESSAGE),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regRLC_SMU_ARGUMENT_1),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regRLC_SMU_ARGUMENT_2),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSMU_RLC_RESPONSE),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regRLC_SAFE_MODE),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regRLC_SMU_SAFE_MODE),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regRLC_INT_STAT),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regRLC_GPM_GENERAL_6),
|
||||
/* cp header registers */
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_MEC_ME1_HEADER_DUMP),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_MEC_ME2_HEADER_DUMP),
|
||||
/* SE status registers */
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS_SE0),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS_SE1),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS_SE2),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS_SE3)
|
||||
};
|
||||
|
||||
static const struct amdgpu_hwip_reg_entry gc_cp_reg_list_9_4_3[] = {
|
||||
/* compute queue registers */
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_VMID),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_ACTIVE),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PERSISTENT_STATE),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PIPE_PRIORITY),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_QUEUE_PRIORITY),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_QUANTUM),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_BASE),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_BASE_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_WPTR_POLL_ADDR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_WPTR_POLL_ADDR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_CONTROL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_IB_BASE_ADDR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_IB_BASE_ADDR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_IB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_IB_CONTROL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_DEQUEUE_REQUEST),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_EOP_BASE_ADDR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_EOP_BASE_ADDR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_EOP_CONTROL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_EOP_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_EOP_WPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_EOP_EVENTS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_CTX_SAVE_BASE_ADDR_LO),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_CTX_SAVE_BASE_ADDR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_CTX_SAVE_CONTROL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_CNTL_STACK_OFFSET),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_CNTL_STACK_SIZE),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_WG_STATE_OFFSET),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_CTX_SAVE_SIZE),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_GDS_RESOURCE_STATE),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_ERROR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_EOP_WPTR_MEM),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_WPTR_LO),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_PQ_WPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regCP_HQD_GFX_STATUS),
|
||||
};
|
||||
|
||||
struct amdgpu_gfx_ras gfx_v9_4_3_ras;
|
||||
|
||||
static void gfx_v9_4_3_set_ring_funcs(struct amdgpu_device *adev);
|
||||
@ -71,10 +164,18 @@ static void gfx_v9_4_3_set_gds_init(struct amdgpu_device *adev);
|
||||
static void gfx_v9_4_3_set_rlc_funcs(struct amdgpu_device *adev);
|
||||
static int gfx_v9_4_3_get_cu_info(struct amdgpu_device *adev,
|
||||
struct amdgpu_cu_info *cu_info);
|
||||
static void gfx_v9_4_3_xcc_set_safe_mode(struct amdgpu_device *adev, int xcc_id);
|
||||
static void gfx_v9_4_3_xcc_unset_safe_mode(struct amdgpu_device *adev, int xcc_id);
|
||||
|
||||
static void gfx_v9_4_3_kiq_set_resources(struct amdgpu_ring *kiq_ring,
|
||||
uint64_t queue_mask)
|
||||
{
|
||||
struct amdgpu_device *adev = kiq_ring->adev;
|
||||
u64 shader_mc_addr;
|
||||
|
||||
/* Cleaner shader MC address */
|
||||
shader_mc_addr = adev->gfx.cleaner_shader_gpu_addr >> 8;
|
||||
|
||||
amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_SET_RESOURCES, 6));
|
||||
amdgpu_ring_write(kiq_ring,
|
||||
PACKET3_SET_RESOURCES_VMID_MASK(0) |
|
||||
@ -84,8 +185,8 @@ static void gfx_v9_4_3_kiq_set_resources(struct amdgpu_ring *kiq_ring,
|
||||
lower_32_bits(queue_mask)); /* queue mask lo */
|
||||
amdgpu_ring_write(kiq_ring,
|
||||
upper_32_bits(queue_mask)); /* queue mask hi */
|
||||
amdgpu_ring_write(kiq_ring, 0); /* gws mask lo */
|
||||
amdgpu_ring_write(kiq_ring, 0); /* gws mask hi */
|
||||
amdgpu_ring_write(kiq_ring, lower_32_bits(shader_mc_addr)); /* cleaner shader addr lo */
|
||||
amdgpu_ring_write(kiq_ring, upper_32_bits(shader_mc_addr)); /* cleaner shader addr hi */
|
||||
amdgpu_ring_write(kiq_ring, 0); /* oac mask */
|
||||
amdgpu_ring_write(kiq_ring, 0); /* gds heap base:0, gds heap size:0 */
|
||||
}
|
||||
@ -182,12 +283,46 @@ static void gfx_v9_4_3_kiq_invalidate_tlbs(struct amdgpu_ring *kiq_ring,
|
||||
PACKET3_INVALIDATE_TLBS_FLUSH_TYPE(flush_type));
|
||||
}
|
||||
|
||||
static void gfx_v9_4_3_kiq_reset_hw_queue(struct amdgpu_ring *kiq_ring, uint32_t queue_type,
|
||||
uint32_t me_id, uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t xcc_id, uint32_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = kiq_ring->adev;
|
||||
unsigned i;
|
||||
|
||||
/* enter save mode */
|
||||
amdgpu_gfx_rlc_enter_safe_mode(adev, xcc_id);
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
soc15_grbm_select(adev, me_id, pipe_id, queue_id, 0, xcc_id);
|
||||
|
||||
if (queue_type == AMDGPU_RING_TYPE_COMPUTE) {
|
||||
WREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_HQD_DEQUEUE_REQUEST, 0x2);
|
||||
WREG32_SOC15(GC, GET_INST(GC, xcc_id), regSPI_COMPUTE_QUEUE_RESET, 0x1);
|
||||
/* wait till dequeue take effects */
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
if (!(RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_HQD_ACTIVE) & 1))
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
if (i >= adev->usec_timeout)
|
||||
dev_err(adev->dev, "fail to wait on hqd deactive\n");
|
||||
} else {
|
||||
dev_err(adev->dev, "reset queue_type(%d) not supported\n\n", queue_type);
|
||||
}
|
||||
|
||||
soc15_grbm_select(adev, 0, 0, 0, 0, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
/* exit safe mode */
|
||||
amdgpu_gfx_rlc_exit_safe_mode(adev, xcc_id);
|
||||
}
|
||||
|
||||
static const struct kiq_pm4_funcs gfx_v9_4_3_kiq_pm4_funcs = {
|
||||
.kiq_set_resources = gfx_v9_4_3_kiq_set_resources,
|
||||
.kiq_map_queues = gfx_v9_4_3_kiq_map_queues,
|
||||
.kiq_unmap_queues = gfx_v9_4_3_kiq_unmap_queues,
|
||||
.kiq_query_status = gfx_v9_4_3_kiq_query_status,
|
||||
.kiq_invalidate_tlbs = gfx_v9_4_3_kiq_invalidate_tlbs,
|
||||
.kiq_reset_hw_queue = gfx_v9_4_3_kiq_reset_hw_queue,
|
||||
.set_resources_size = 8,
|
||||
.map_queues_size = 7,
|
||||
.unmap_queues_size = 6,
|
||||
@ -885,11 +1020,59 @@ static int gfx_v9_4_3_compute_ring_init(struct amdgpu_device *adev, int ring_id,
|
||||
hw_prio, NULL);
|
||||
}
|
||||
|
||||
static void gfx_v9_4_3_alloc_ip_dump(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t reg_count = ARRAY_SIZE(gc_reg_list_9_4_3);
|
||||
uint32_t *ptr, num_xcc, inst;
|
||||
|
||||
num_xcc = NUM_XCC(adev->gfx.xcc_mask);
|
||||
|
||||
ptr = kcalloc(reg_count * num_xcc, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (!ptr) {
|
||||
DRM_ERROR("Failed to allocate memory for GFX IP Dump\n");
|
||||
adev->gfx.ip_dump_core = NULL;
|
||||
} else {
|
||||
adev->gfx.ip_dump_core = ptr;
|
||||
}
|
||||
|
||||
/* Allocate memory for compute queue registers for all the instances */
|
||||
reg_count = ARRAY_SIZE(gc_cp_reg_list_9_4_3);
|
||||
inst = adev->gfx.mec.num_mec * adev->gfx.mec.num_pipe_per_mec *
|
||||
adev->gfx.mec.num_queue_per_pipe;
|
||||
|
||||
ptr = kcalloc(reg_count * inst * num_xcc, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (!ptr) {
|
||||
DRM_ERROR("Failed to allocate memory for Compute Queues IP Dump\n");
|
||||
adev->gfx.ip_dump_compute_queues = NULL;
|
||||
} else {
|
||||
adev->gfx.ip_dump_compute_queues = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
static int gfx_v9_4_3_sw_init(void *handle)
|
||||
{
|
||||
int i, j, k, r, ring_id, xcc_id, num_xcc;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
|
||||
case IP_VERSION(9, 4, 3):
|
||||
case IP_VERSION(9, 4, 4):
|
||||
adev->gfx.cleaner_shader_ptr = gfx_9_4_3_cleaner_shader_hex;
|
||||
adev->gfx.cleaner_shader_size = sizeof(gfx_9_4_3_cleaner_shader_hex);
|
||||
if (adev->gfx.mec_fw_version >= 153) {
|
||||
adev->gfx.enable_cleaner_shader = true;
|
||||
r = amdgpu_gfx_cleaner_shader_sw_init(adev, adev->gfx.cleaner_shader_size);
|
||||
if (r) {
|
||||
adev->gfx.enable_cleaner_shader = false;
|
||||
dev_err(adev->dev, "Failed to initialize cleaner shader\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
adev->gfx.enable_cleaner_shader = false;
|
||||
break;
|
||||
}
|
||||
|
||||
adev->gfx.mec.num_mec = 2;
|
||||
adev->gfx.mec.num_pipe_per_mec = 4;
|
||||
adev->gfx.mec.num_queue_per_pipe = 8;
|
||||
@ -901,6 +1084,13 @@ static int gfx_v9_4_3_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Bad opcode Event */
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_GRBM_CP,
|
||||
GFX_9_0__SRCID__CP_BAD_OPCODE_ERROR,
|
||||
&adev->gfx.bad_op_irq);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Privileged reg */
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_GRBM_CP, GFX_9_0__SRCID__CP_PRIV_REG_FAULT,
|
||||
&adev->gfx.priv_reg_irq);
|
||||
@ -976,10 +1166,19 @@ static int gfx_v9_4_3_sw_init(void *handle)
|
||||
return r;
|
||||
|
||||
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
r = amdgpu_gfx_sysfs_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return r;
|
||||
gfx_v9_4_3_alloc_ip_dump(adev);
|
||||
|
||||
r = amdgpu_gfx_sysfs_isolation_shader_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v9_4_3_sw_fini(void *handle)
|
||||
@ -997,11 +1196,17 @@ static int gfx_v9_4_3_sw_fini(void *handle)
|
||||
amdgpu_gfx_kiq_fini(adev, i);
|
||||
}
|
||||
|
||||
amdgpu_gfx_cleaner_shader_sw_fini(adev);
|
||||
|
||||
gfx_v9_4_3_mec_fini(adev);
|
||||
amdgpu_bo_unref(&adev->gfx.rlc.clear_state_obj);
|
||||
gfx_v9_4_3_free_microcode(adev);
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
amdgpu_gfx_sysfs_fini(adev);
|
||||
amdgpu_gfx_sysfs_isolation_shader_fini(adev);
|
||||
|
||||
kfree(adev->gfx.ip_dump_core);
|
||||
kfree(adev->gfx.ip_dump_compute_queues);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1910,7 +2115,7 @@ static int gfx_v9_4_3_xcc_kiq_init_queue(struct amdgpu_ring *ring, int xcc_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v9_4_3_xcc_kcq_init_queue(struct amdgpu_ring *ring, int xcc_id)
|
||||
static int gfx_v9_4_3_xcc_kcq_init_queue(struct amdgpu_ring *ring, int xcc_id, bool restore)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct v9_mqd *mqd = ring->mqd_ptr;
|
||||
@ -1922,8 +2127,8 @@ static int gfx_v9_4_3_xcc_kcq_init_queue(struct amdgpu_ring *ring, int xcc_id)
|
||||
*/
|
||||
tmp_mqd = (struct v9_mqd *)adev->gfx.mec.mqd_backup[mqd_idx];
|
||||
|
||||
if (!tmp_mqd->cp_hqd_pq_control ||
|
||||
(!amdgpu_in_reset(adev) && !adev->in_suspend)) {
|
||||
if (!restore && (!tmp_mqd->cp_hqd_pq_control ||
|
||||
(!amdgpu_in_reset(adev) && !adev->in_suspend))) {
|
||||
memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation));
|
||||
((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF;
|
||||
((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF;
|
||||
@ -2008,7 +2213,7 @@ static int gfx_v9_4_3_xcc_kcq_resume(struct amdgpu_device *adev, int xcc_id)
|
||||
goto done;
|
||||
r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
|
||||
if (!r) {
|
||||
r = gfx_v9_4_3_xcc_kcq_init_queue(ring, xcc_id);
|
||||
r = gfx_v9_4_3_xcc_kcq_init_queue(ring, xcc_id, false);
|
||||
amdgpu_bo_kunmap(ring->mqd_obj);
|
||||
ring->mqd_ptr = NULL;
|
||||
}
|
||||
@ -2139,6 +2344,9 @@ static int gfx_v9_4_3_hw_init(void *handle)
|
||||
int r;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_gfx_cleaner_shader_init(adev, adev->gfx.cleaner_shader_size,
|
||||
adev->gfx.cleaner_shader_ptr);
|
||||
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
gfx_v9_4_3_init_golden_registers(adev);
|
||||
|
||||
@ -2162,6 +2370,7 @@ static int gfx_v9_4_3_hw_fini(void *handle)
|
||||
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.bad_op_irq, 0);
|
||||
|
||||
num_xcc = NUM_XCC(adev->gfx.xcc_mask);
|
||||
for (i = 0; i < num_xcc; i++) {
|
||||
@ -2327,6 +2536,10 @@ static int gfx_v9_4_3_late_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_irq_get(adev, &adev->gfx.bad_op_irq, 0);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (adev->gfx.ras &&
|
||||
adev->gfx.ras->enable_watchdog_timer)
|
||||
adev->gfx.ras->enable_watchdog_timer(adev);
|
||||
@ -2833,6 +3046,21 @@ static void gfx_v9_4_3_ring_emit_reg_write_reg_wait(struct amdgpu_ring *ring,
|
||||
ref, mask);
|
||||
}
|
||||
|
||||
static void gfx_v9_4_3_ring_soft_recovery(struct amdgpu_ring *ring,
|
||||
unsigned vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
uint32_t value = 0;
|
||||
|
||||
value = REG_SET_FIELD(value, SQ_CMD, CMD, 0x03);
|
||||
value = REG_SET_FIELD(value, SQ_CMD, MODE, 0x01);
|
||||
value = REG_SET_FIELD(value, SQ_CMD, CHECK_VMID, 1);
|
||||
value = REG_SET_FIELD(value, SQ_CMD, VM_ID, vmid);
|
||||
amdgpu_gfx_rlc_enter_safe_mode(adev, ring->xcc_id);
|
||||
WREG32_SOC15(GC, GET_INST(GC, ring->xcc_id), regSQ_CMD, value);
|
||||
amdgpu_gfx_rlc_exit_safe_mode(adev, ring->xcc_id);
|
||||
}
|
||||
|
||||
static void gfx_v9_4_3_xcc_set_compute_eop_interrupt_state(
|
||||
struct amdgpu_device *adev, int me, int pipe,
|
||||
enum amdgpu_interrupt_state state, int xcc_id)
|
||||
@ -2886,21 +3114,103 @@ static void gfx_v9_4_3_xcc_set_compute_eop_interrupt_state(
|
||||
}
|
||||
}
|
||||
|
||||
static u32 gfx_v9_4_3_get_cpc_int_cntl(struct amdgpu_device *adev,
|
||||
int xcc_id, int me, int pipe)
|
||||
{
|
||||
/*
|
||||
* amdgpu controls only the first MEC. That's why this function only
|
||||
* handles the setting of interrupts for this specific MEC. All other
|
||||
* pipes' interrupts are set by amdkfd.
|
||||
*/
|
||||
if (me != 1)
|
||||
return 0;
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
return SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regCP_ME1_PIPE0_INT_CNTL);
|
||||
case 1:
|
||||
return SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regCP_ME1_PIPE1_INT_CNTL);
|
||||
case 2:
|
||||
return SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regCP_ME1_PIPE2_INT_CNTL);
|
||||
case 3:
|
||||
return SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regCP_ME1_PIPE3_INT_CNTL);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int gfx_v9_4_3_set_priv_reg_fault_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
int i, num_xcc;
|
||||
u32 mec_int_cntl_reg, mec_int_cntl;
|
||||
int i, j, k, num_xcc;
|
||||
|
||||
num_xcc = NUM_XCC(adev->gfx.xcc_mask);
|
||||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
for (i = 0; i < num_xcc; i++)
|
||||
for (i = 0; i < num_xcc; i++) {
|
||||
WREG32_FIELD15_PREREG(GC, GET_INST(GC, i), CP_INT_CNTL_RING0,
|
||||
PRIV_REG_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
PRIV_REG_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
for (j = 0; j < adev->gfx.mec.num_mec; j++) {
|
||||
for (k = 0; k < adev->gfx.mec.num_pipe_per_mec; k++) {
|
||||
/* MECs start at 1 */
|
||||
mec_int_cntl_reg = gfx_v9_4_3_get_cpc_int_cntl(adev, i, j + 1, k);
|
||||
|
||||
if (mec_int_cntl_reg) {
|
||||
mec_int_cntl = RREG32_XCC(mec_int_cntl_reg, i);
|
||||
mec_int_cntl = REG_SET_FIELD(mec_int_cntl, CP_ME1_PIPE0_INT_CNTL,
|
||||
PRIV_REG_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ?
|
||||
1 : 0);
|
||||
WREG32_XCC(mec_int_cntl_reg, mec_int_cntl, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v9_4_3_set_bad_op_fault_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
u32 mec_int_cntl_reg, mec_int_cntl;
|
||||
int i, j, k, num_xcc;
|
||||
|
||||
num_xcc = NUM_XCC(adev->gfx.xcc_mask);
|
||||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
for (i = 0; i < num_xcc; i++) {
|
||||
WREG32_FIELD15_PREREG(GC, GET_INST(GC, i), CP_INT_CNTL_RING0,
|
||||
OPCODE_ERROR_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
for (j = 0; j < adev->gfx.mec.num_mec; j++) {
|
||||
for (k = 0; k < adev->gfx.mec.num_pipe_per_mec; k++) {
|
||||
/* MECs start at 1 */
|
||||
mec_int_cntl_reg = gfx_v9_4_3_get_cpc_int_cntl(adev, i, j + 1, k);
|
||||
|
||||
if (mec_int_cntl_reg) {
|
||||
mec_int_cntl = RREG32_XCC(mec_int_cntl_reg, i);
|
||||
mec_int_cntl = REG_SET_FIELD(mec_int_cntl, CP_ME1_PIPE0_INT_CNTL,
|
||||
OPCODE_ERROR_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ?
|
||||
1 : 0);
|
||||
WREG32_XCC(mec_int_cntl_reg, mec_int_cntl, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -3061,6 +3371,15 @@ static int gfx_v9_4_3_priv_reg_irq(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v9_4_3_bad_op_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
DRM_ERROR("Illegal opcode in command stream\n");
|
||||
gfx_v9_4_3_fault(adev, entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v9_4_3_priv_inst_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
@ -3147,6 +3466,91 @@ static void gfx_v9_4_3_emit_wave_limit(struct amdgpu_ring *ring, bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
static int gfx_v9_4_3_reset_kcq(struct amdgpu_ring *ring,
|
||||
unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq[ring->xcc_id];
|
||||
struct amdgpu_ring *kiq_ring = &kiq->ring;
|
||||
unsigned long flags;
|
||||
int r, i;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&kiq->ring_lock, flags);
|
||||
|
||||
if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size)) {
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
kiq->pmf->kiq_unmap_queues(kiq_ring, ring, RESET_QUEUES,
|
||||
0, 0);
|
||||
amdgpu_ring_commit(kiq_ring);
|
||||
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
|
||||
r = amdgpu_ring_test_ring(kiq_ring);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* make sure dequeue is complete*/
|
||||
amdgpu_gfx_rlc_enter_safe_mode(adev, ring->xcc_id);
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0, GET_INST(GC, ring->xcc_id));
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
if (!(RREG32_SOC15(GC, 0, regCP_HQD_ACTIVE) & 1))
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
if (i >= adev->usec_timeout)
|
||||
r = -ETIMEDOUT;
|
||||
soc15_grbm_select(adev, 0, 0, 0, 0, GET_INST(GC, ring->xcc_id));
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
amdgpu_gfx_rlc_exit_safe_mode(adev, ring->xcc_id);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "fail to wait on hqd deactive\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_bo_reserve(ring->mqd_obj, false);
|
||||
if (unlikely(r != 0)){
|
||||
dev_err(adev->dev, "fail to resv mqd_obj\n");
|
||||
return r;
|
||||
}
|
||||
r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
|
||||
if (!r) {
|
||||
r = gfx_v9_4_3_xcc_kcq_init_queue(ring, ring->xcc_id, true);
|
||||
amdgpu_bo_kunmap(ring->mqd_obj);
|
||||
ring->mqd_ptr = NULL;
|
||||
}
|
||||
amdgpu_bo_unreserve(ring->mqd_obj);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "fail to unresv mqd_obj\n");
|
||||
return r;
|
||||
}
|
||||
spin_lock_irqsave(&kiq->ring_lock, flags);
|
||||
r = amdgpu_ring_alloc(kiq_ring, kiq->pmf->map_queues_size);
|
||||
if (r) {
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
kiq->pmf->kiq_map_queues(kiq_ring, ring);
|
||||
amdgpu_ring_commit(kiq_ring);
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
|
||||
r = amdgpu_ring_test_ring(kiq_ring);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "fail to remap queue\n");
|
||||
return r;
|
||||
}
|
||||
return amdgpu_ring_test_ring(ring);
|
||||
}
|
||||
|
||||
enum amdgpu_gfx_cp_ras_mem_id {
|
||||
AMDGPU_GFX_CP_MEM1 = 1,
|
||||
AMDGPU_GFX_CP_MEM2,
|
||||
@ -3959,8 +4363,8 @@ static void gfx_v9_4_3_inst_query_ras_err_count(struct amdgpu_device *adev,
|
||||
/* the caller should make sure initialize value of
|
||||
* err_data->ue_count and err_data->ce_count
|
||||
*/
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, NULL, ue_count);
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, NULL, ce_count);
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, ue_count);
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, ce_count);
|
||||
}
|
||||
|
||||
static void gfx_v9_4_3_inst_reset_ras_err_count(struct amdgpu_device *adev,
|
||||
@ -4062,6 +4466,151 @@ static void gfx_v9_4_3_enable_watchdog_timer(struct amdgpu_device *adev)
|
||||
amdgpu_gfx_ras_error_func(adev, NULL, gfx_v9_4_3_inst_enable_watchdog_timer);
|
||||
}
|
||||
|
||||
static void gfx_v9_4_3_ring_insert_nop(struct amdgpu_ring *ring, uint32_t num_nop)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Header itself is a NOP packet */
|
||||
if (num_nop == 1) {
|
||||
amdgpu_ring_write(ring, ring->funcs->nop);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max HW optimization till 0x3ffe, followed by remaining one NOP at a time*/
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_NOP, min(num_nop - 2, 0x3ffe)));
|
||||
|
||||
/* Header is at index 0, followed by num_nops - 1 NOP packet's */
|
||||
for (i = 1; i < num_nop; i++)
|
||||
amdgpu_ring_write(ring, ring->funcs->nop);
|
||||
}
|
||||
|
||||
static void gfx_v9_4_3_ip_print(void *handle, struct drm_printer *p)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
uint32_t i, j, k;
|
||||
uint32_t xcc_id, xcc_offset, inst_offset;
|
||||
uint32_t num_xcc, reg, num_inst;
|
||||
uint32_t reg_count = ARRAY_SIZE(gc_reg_list_9_4_3);
|
||||
|
||||
if (!adev->gfx.ip_dump_core)
|
||||
return;
|
||||
|
||||
num_xcc = NUM_XCC(adev->gfx.xcc_mask);
|
||||
drm_printf(p, "Number of Instances:%d\n", num_xcc);
|
||||
for (xcc_id = 0; xcc_id < num_xcc; xcc_id++) {
|
||||
xcc_offset = xcc_id * reg_count;
|
||||
drm_printf(p, "\nInstance id:%d\n", xcc_id);
|
||||
for (i = 0; i < reg_count; i++)
|
||||
drm_printf(p, "%-50s \t 0x%08x\n",
|
||||
gc_reg_list_9_4_3[i].reg_name,
|
||||
adev->gfx.ip_dump_core[xcc_offset + i]);
|
||||
}
|
||||
|
||||
/* print compute queue registers for all instances */
|
||||
if (!adev->gfx.ip_dump_compute_queues)
|
||||
return;
|
||||
|
||||
num_inst = adev->gfx.mec.num_mec * adev->gfx.mec.num_pipe_per_mec *
|
||||
adev->gfx.mec.num_queue_per_pipe;
|
||||
|
||||
reg_count = ARRAY_SIZE(gc_cp_reg_list_9_4_3);
|
||||
drm_printf(p, "\nnum_xcc: %d num_mec: %d num_pipe: %d num_queue: %d\n",
|
||||
num_xcc,
|
||||
adev->gfx.mec.num_mec,
|
||||
adev->gfx.mec.num_pipe_per_mec,
|
||||
adev->gfx.mec.num_queue_per_pipe);
|
||||
|
||||
for (xcc_id = 0; xcc_id < num_xcc; xcc_id++) {
|
||||
xcc_offset = xcc_id * reg_count * num_inst;
|
||||
inst_offset = 0;
|
||||
for (i = 0; i < adev->gfx.mec.num_mec; i++) {
|
||||
for (j = 0; j < adev->gfx.mec.num_pipe_per_mec; j++) {
|
||||
for (k = 0; k < adev->gfx.mec.num_queue_per_pipe; k++) {
|
||||
drm_printf(p,
|
||||
"\nxcc:%d mec:%d, pipe:%d, queue:%d\n",
|
||||
xcc_id, i, j, k);
|
||||
for (reg = 0; reg < reg_count; reg++) {
|
||||
drm_printf(p,
|
||||
"%-50s \t 0x%08x\n",
|
||||
gc_cp_reg_list_9_4_3[reg].reg_name,
|
||||
adev->gfx.ip_dump_compute_queues
|
||||
[xcc_offset + inst_offset +
|
||||
reg]);
|
||||
}
|
||||
inst_offset += reg_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_v9_4_3_ip_dump(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
uint32_t i, j, k;
|
||||
uint32_t num_xcc, reg, num_inst;
|
||||
uint32_t xcc_id, xcc_offset, inst_offset;
|
||||
uint32_t reg_count = ARRAY_SIZE(gc_reg_list_9_4_3);
|
||||
|
||||
if (!adev->gfx.ip_dump_core)
|
||||
return;
|
||||
|
||||
num_xcc = NUM_XCC(adev->gfx.xcc_mask);
|
||||
|
||||
amdgpu_gfx_off_ctrl(adev, false);
|
||||
for (xcc_id = 0; xcc_id < num_xcc; xcc_id++) {
|
||||
xcc_offset = xcc_id * reg_count;
|
||||
for (i = 0; i < reg_count; i++)
|
||||
adev->gfx.ip_dump_core[xcc_offset + i] =
|
||||
RREG32(SOC15_REG_ENTRY_OFFSET_INST(gc_reg_list_9_4_3[i],
|
||||
GET_INST(GC, xcc_id)));
|
||||
}
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
|
||||
/* dump compute queue registers for all instances */
|
||||
if (!adev->gfx.ip_dump_compute_queues)
|
||||
return;
|
||||
|
||||
num_inst = adev->gfx.mec.num_mec * adev->gfx.mec.num_pipe_per_mec *
|
||||
adev->gfx.mec.num_queue_per_pipe;
|
||||
reg_count = ARRAY_SIZE(gc_cp_reg_list_9_4_3);
|
||||
amdgpu_gfx_off_ctrl(adev, false);
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
for (xcc_id = 0; xcc_id < num_xcc; xcc_id++) {
|
||||
xcc_offset = xcc_id * reg_count * num_inst;
|
||||
inst_offset = 0;
|
||||
for (i = 0; i < adev->gfx.mec.num_mec; i++) {
|
||||
for (j = 0; j < adev->gfx.mec.num_pipe_per_mec; j++) {
|
||||
for (k = 0; k < adev->gfx.mec.num_queue_per_pipe; k++) {
|
||||
/* ME0 is for GFX so start from 1 for CP */
|
||||
soc15_grbm_select(adev, 1 + i, j, k, 0,
|
||||
GET_INST(GC, xcc_id));
|
||||
|
||||
for (reg = 0; reg < reg_count; reg++) {
|
||||
adev->gfx.ip_dump_compute_queues
|
||||
[xcc_offset +
|
||||
inst_offset + reg] =
|
||||
RREG32(SOC15_REG_ENTRY_OFFSET_INST(
|
||||
gc_cp_reg_list_9_4_3[reg],
|
||||
GET_INST(GC, xcc_id)));
|
||||
}
|
||||
inst_offset += reg_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
soc15_grbm_select(adev, 0, 0, 0, 0, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
}
|
||||
|
||||
static void gfx_v9_4_3_ring_emit_cleaner_shader(struct amdgpu_ring *ring)
|
||||
{
|
||||
/* Emit the cleaner shader */
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_RUN_CLEANER_SHADER, 0));
|
||||
amdgpu_ring_write(ring, 0); /* RESERVED field, programmed to zero */
|
||||
}
|
||||
|
||||
static const struct amd_ip_funcs gfx_v9_4_3_ip_funcs = {
|
||||
.name = "gfx_v9_4_3",
|
||||
.early_init = gfx_v9_4_3_early_init,
|
||||
@ -4078,8 +4627,8 @@ static const struct amd_ip_funcs gfx_v9_4_3_ip_funcs = {
|
||||
.set_clockgating_state = gfx_v9_4_3_set_clockgating_state,
|
||||
.set_powergating_state = gfx_v9_4_3_set_powergating_state,
|
||||
.get_clockgating_state = gfx_v9_4_3_get_clockgating_state,
|
||||
.dump_ip_state = NULL,
|
||||
.print_ip_state = NULL,
|
||||
.dump_ip_state = gfx_v9_4_3_ip_dump,
|
||||
.print_ip_state = gfx_v9_4_3_ip_print,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ring_funcs gfx_v9_4_3_ring_funcs_compute = {
|
||||
@ -4101,7 +4650,8 @@ static const struct amdgpu_ring_funcs gfx_v9_4_3_ring_funcs_compute = {
|
||||
8 + 8 + 8 + /* gfx_v9_4_3_ring_emit_fence x3 for user fence, vm fence */
|
||||
7 + /* gfx_v9_4_3_emit_mem_sync */
|
||||
5 + /* gfx_v9_4_3_emit_wave_limit for updating regSPI_WCL_PIPE_PERCENT_GFX register */
|
||||
15, /* for updating 3 regSPI_WCL_PIPE_PERCENT_CS registers */
|
||||
15 + /* for updating 3 regSPI_WCL_PIPE_PERCENT_CS registers */
|
||||
2, /* gfx_v9_4_3_ring_emit_cleaner_shader */
|
||||
.emit_ib_size = 7, /* gfx_v9_4_3_ring_emit_ib_compute */
|
||||
.emit_ib = gfx_v9_4_3_ring_emit_ib_compute,
|
||||
.emit_fence = gfx_v9_4_3_ring_emit_fence,
|
||||
@ -4111,13 +4661,18 @@ static const struct amdgpu_ring_funcs gfx_v9_4_3_ring_funcs_compute = {
|
||||
.emit_hdp_flush = gfx_v9_4_3_ring_emit_hdp_flush,
|
||||
.test_ring = gfx_v9_4_3_ring_test_ring,
|
||||
.test_ib = gfx_v9_4_3_ring_test_ib,
|
||||
.insert_nop = amdgpu_ring_insert_nop,
|
||||
.insert_nop = gfx_v9_4_3_ring_insert_nop,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.emit_wreg = gfx_v9_4_3_ring_emit_wreg,
|
||||
.emit_reg_wait = gfx_v9_4_3_ring_emit_reg_wait,
|
||||
.emit_reg_write_reg_wait = gfx_v9_4_3_ring_emit_reg_write_reg_wait,
|
||||
.soft_recovery = gfx_v9_4_3_ring_soft_recovery,
|
||||
.emit_mem_sync = gfx_v9_4_3_emit_mem_sync,
|
||||
.emit_wave_limit = gfx_v9_4_3_emit_wave_limit,
|
||||
.reset = gfx_v9_4_3_reset_kcq,
|
||||
.emit_cleaner_shader = gfx_v9_4_3_ring_emit_cleaner_shader,
|
||||
.begin_use = amdgpu_gfx_enforce_isolation_ring_begin_use,
|
||||
.end_use = amdgpu_gfx_enforce_isolation_ring_end_use,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ring_funcs gfx_v9_4_3_ring_funcs_kiq = {
|
||||
@ -4172,6 +4727,11 @@ static const struct amdgpu_irq_src_funcs gfx_v9_4_3_priv_reg_irq_funcs = {
|
||||
.process = gfx_v9_4_3_priv_reg_irq,
|
||||
};
|
||||
|
||||
static const struct amdgpu_irq_src_funcs gfx_v9_4_3_bad_op_irq_funcs = {
|
||||
.set = gfx_v9_4_3_set_bad_op_fault_state,
|
||||
.process = gfx_v9_4_3_bad_op_irq,
|
||||
};
|
||||
|
||||
static const struct amdgpu_irq_src_funcs gfx_v9_4_3_priv_inst_irq_funcs = {
|
||||
.set = gfx_v9_4_3_set_priv_inst_fault_state,
|
||||
.process = gfx_v9_4_3_priv_inst_irq,
|
||||
@ -4185,6 +4745,9 @@ static void gfx_v9_4_3_set_irq_funcs(struct amdgpu_device *adev)
|
||||
adev->gfx.priv_reg_irq.num_types = 1;
|
||||
adev->gfx.priv_reg_irq.funcs = &gfx_v9_4_3_priv_reg_irq_funcs;
|
||||
|
||||
adev->gfx.bad_op_irq.num_types = 1;
|
||||
adev->gfx.bad_op_irq.funcs = &gfx_v9_4_3_bad_op_irq_funcs;
|
||||
|
||||
adev->gfx.priv_inst_irq.num_types = 1;
|
||||
adev->gfx.priv_inst_irq.funcs = &gfx_v9_4_3_priv_inst_irq_funcs;
|
||||
}
|
||||
|
153
drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3_cleaner_shader.asm
Normal file
153
drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3_cleaner_shader.asm
Normal file
@ -0,0 +1,153 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright 2024 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// This shader is to clean LDS, SGPRs and VGPRs. It is first 64 Dwords or 256 bytes of 192 Dwords cleaner shader.
|
||||
//To turn this shader program on for complitaion change this to main and lower shader main to main_1
|
||||
|
||||
// MI300 : Clear SGPRs, VGPRs and LDS
|
||||
// Uses two kernels launched separately:
|
||||
// 1. Clean VGPRs, LDS, and lower SGPRs
|
||||
// Launches one workgroup per CU, each workgroup with 4x wave64 per SIMD in the CU
|
||||
// Waves are "wave64" and have 128 VGPRs each, which uses all 512 VGPRs per SIMD
|
||||
// Waves in the workgroup share the 64KB of LDS
|
||||
// Each wave clears SGPRs 0 - 95. Because there are 4 waves/SIMD, this is physical SGPRs 0-383
|
||||
// Each wave clears 128 VGPRs, so all 512 in the SIMD
|
||||
// The first wave of the workgroup clears its 64KB of LDS
|
||||
// The shader starts with "S_BARRIER" to ensure SPI has launched all waves of the workgroup
|
||||
// before any wave in the workgroup could end. Without this, it is possible not all SGPRs get cleared.
|
||||
// 2. Clean remaining SGPRs
|
||||
// Launches a workgroup with 24 waves per workgroup, yielding 6 waves per SIMD in each CU
|
||||
// Waves are allocating 96 SGPRs
|
||||
// CP sets up SPI_RESOURCE_RESERVE_* registers to prevent these waves from allocating SGPRs 0-223.
|
||||
// As such, these 6 waves per SIMD are allocated physical SGPRs 224-799
|
||||
// Barriers do not work for >16 waves per workgroup, so we cannot start with S_BARRIER
|
||||
// Instead, the shader starts with an S_SETHALT 1. Once all waves are launched CP will send unhalt command
|
||||
// The shader then clears all SGPRs allocated to it, cleaning out physical SGPRs 224-799
|
||||
|
||||
shader main
|
||||
asic(MI300)
|
||||
type(CS)
|
||||
wave_size(64)
|
||||
// Note: original source code from SQ team
|
||||
|
||||
// (theorhetical fastest = ~512clks vgpr + 1536 lds + ~128 sgpr = 2176 clks)
|
||||
|
||||
s_cmp_eq_u32 s0, 1 // Bit0 is set, sgpr0 is set then clear VGPRS and LDS as FW set COMPUTE_USER_DATA_3
|
||||
s_cbranch_scc0 label_0023 // Clean VGPRs and LDS if sgpr0 of wave is set, scc = (s3 == 1)
|
||||
S_BARRIER
|
||||
|
||||
s_movk_i32 m0, 0x0000
|
||||
s_mov_b32 s2, 0x00000078 // Loop 128/8=16 times (loop unrolled for performance)
|
||||
//
|
||||
// CLEAR VGPRs
|
||||
//
|
||||
s_set_gpr_idx_on s2, 0x8 // enable Dest VGPR indexing
|
||||
label_0005:
|
||||
v_mov_b32 v0, 0
|
||||
v_mov_b32 v1, 0
|
||||
v_mov_b32 v2, 0
|
||||
v_mov_b32 v3, 0
|
||||
v_mov_b32 v4, 0
|
||||
v_mov_b32 v5, 0
|
||||
v_mov_b32 v6, 0
|
||||
v_mov_b32 v7, 0
|
||||
s_sub_u32 s2, s2, 8
|
||||
s_set_gpr_idx_idx s2
|
||||
s_cbranch_scc0 label_0005
|
||||
s_set_gpr_idx_off
|
||||
|
||||
//
|
||||
//
|
||||
|
||||
s_mov_b32 s2, 0x80000000 // Bit31 is first_wave
|
||||
s_and_b32 s2, s2, s1 // sgpr0 has tg_size (first_wave) term as in ucode only COMPUTE_PGM_RSRC2.tg_size_en is set
|
||||
s_cbranch_scc0 label_clean_sgpr_1 // Clean LDS if its first wave of ThreadGroup/WorkGroup
|
||||
// CLEAR LDS
|
||||
//
|
||||
s_mov_b32 exec_lo, 0xffffffff
|
||||
s_mov_b32 exec_hi, 0xffffffff
|
||||
v_mbcnt_lo_u32_b32 v1, exec_hi, 0 // Set V1 to thread-ID (0..63)
|
||||
v_mbcnt_hi_u32_b32 v1, exec_lo, v1 // Set V1 to thread-ID (0..63)
|
||||
v_mul_u32_u24 v1, 0x00000008, v1 // * 8, so each thread is a double-dword address (8byte)
|
||||
s_mov_b32 s2, 0x00000003f // 64 loop iteraions
|
||||
s_mov_b32 m0, 0xffffffff
|
||||
// Clear all of LDS space
|
||||
// Each FirstWave of WorkGroup clears 64kbyte block
|
||||
|
||||
label_001F:
|
||||
ds_write2_b64 v1, v[2:3], v[2:3] offset1:32
|
||||
ds_write2_b64 v1, v[4:5], v[4:5] offset0:64 offset1:96
|
||||
v_add_co_u32 v1, vcc, 0x00000400, v1
|
||||
s_sub_u32 s2, s2, 1
|
||||
s_cbranch_scc0 label_001F
|
||||
//
|
||||
// CLEAR SGPRs
|
||||
//
|
||||
label_clean_sgpr_1:
|
||||
s_mov_b32 m0, 0x0000005c // Loop 96/4=24 times (loop unrolled for performance)
|
||||
s_nop 0
|
||||
label_sgpr_loop:
|
||||
s_movreld_b32 s0, 0
|
||||
s_movreld_b32 s1, 0
|
||||
s_movreld_b32 s2, 0
|
||||
s_movreld_b32 s3, 0
|
||||
s_sub_u32 m0, m0, 4
|
||||
s_cbranch_scc0 label_sgpr_loop
|
||||
|
||||
//clear vcc, flat scratch
|
||||
s_mov_b32 flat_scratch_lo, 0 //clear flat scratch lo SGPR
|
||||
s_mov_b32 flat_scratch_hi, 0 //clear flat scratch hi SGPR
|
||||
s_mov_b64 vcc, 0 //clear vcc
|
||||
s_mov_b64 ttmp0, 0 //Clear ttmp0 and ttmp1
|
||||
s_mov_b64 ttmp2, 0 //Clear ttmp2 and ttmp3
|
||||
s_mov_b64 ttmp4, 0 //Clear ttmp4 and ttmp5
|
||||
s_mov_b64 ttmp6, 0 //Clear ttmp6 and ttmp7
|
||||
s_mov_b64 ttmp8, 0 //Clear ttmp8 and ttmp9
|
||||
s_mov_b64 ttmp10, 0 //Clear ttmp10 and ttmp11
|
||||
s_mov_b64 ttmp12, 0 //Clear ttmp12 and ttmp13
|
||||
s_mov_b64 ttmp14, 0 //Clear ttmp14 and ttmp15
|
||||
s_endpgm
|
||||
|
||||
label_0023:
|
||||
|
||||
s_sethalt 1
|
||||
|
||||
s_mov_b32 m0, 0x0000005c // Loop 96/4=24 times (loop unrolled for performance)
|
||||
s_nop 0
|
||||
label_sgpr_loop1:
|
||||
|
||||
s_movreld_b32 s0, 0
|
||||
s_movreld_b32 s1, 0
|
||||
s_movreld_b32 s2, 0
|
||||
s_movreld_b32 s3, 0
|
||||
s_sub_u32 m0, m0, 4
|
||||
s_cbranch_scc0 label_sgpr_loop1
|
||||
|
||||
//clear vcc, flat scratch
|
||||
s_mov_b32 flat_scratch_lo, 0 //clear flat scratch lo SGPR
|
||||
s_mov_b32 flat_scratch_hi, 0 //clear flat scratch hi SGPR
|
||||
s_mov_b64 vcc, 0xee //clear vcc
|
||||
|
||||
s_endpgm
|
||||
end
|
||||
|
64
drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3_cleaner_shader.h
Normal file
64
drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3_cleaner_shader.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright 2024 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Define the cleaner shader gfx_9_4_3 */
|
||||
static const u32 gfx_9_4_3_cleaner_shader_hex[] = {
|
||||
0xbf068100, 0xbf84003b,
|
||||
0xbf8a0000, 0xb07c0000,
|
||||
0xbe8200ff, 0x00000078,
|
||||
0xbf110802, 0x7e000280,
|
||||
0x7e020280, 0x7e040280,
|
||||
0x7e060280, 0x7e080280,
|
||||
0x7e0a0280, 0x7e0c0280,
|
||||
0x7e0e0280, 0x80828802,
|
||||
0xbe803202, 0xbf84fff5,
|
||||
0xbf9c0000, 0xbe8200ff,
|
||||
0x80000000, 0x86020102,
|
||||
0xbf840011, 0xbefe00c1,
|
||||
0xbeff00c1, 0xd28c0001,
|
||||
0x0001007f, 0xd28d0001,
|
||||
0x0002027e, 0x10020288,
|
||||
0xbe8200bf, 0xbefc00c1,
|
||||
0xd89c2000, 0x00020201,
|
||||
0xd89c6040, 0x00040401,
|
||||
0x320202ff, 0x00000400,
|
||||
0x80828102, 0xbf84fff8,
|
||||
0xbefc00ff, 0x0000005c,
|
||||
0xbf800000, 0xbe802c80,
|
||||
0xbe812c80, 0xbe822c80,
|
||||
0xbe832c80, 0x80fc847c,
|
||||
0xbf84fffa, 0xbee60080,
|
||||
0xbee70080, 0xbeea0180,
|
||||
0xbeec0180, 0xbeee0180,
|
||||
0xbef00180, 0xbef20180,
|
||||
0xbef40180, 0xbef60180,
|
||||
0xbef80180, 0xbefa0180,
|
||||
0xbf810000, 0xbf8d0001,
|
||||
0xbefc00ff, 0x0000005c,
|
||||
0xbf800000, 0xbe802c80,
|
||||
0xbe812c80, 0xbe822c80,
|
||||
0xbe832c80, 0x80fc847c,
|
||||
0xbf84fffa, 0xbee60080,
|
||||
0xbee70080, 0xbeea01ff,
|
||||
0x000000ee, 0xbf810000,
|
||||
};
|
@ -443,23 +443,6 @@ static void gfxhub_v1_0_init(struct amdgpu_device *adev)
|
||||
mmVM_INVALIDATE_ENG0_ADDR_RANGE_LO32;
|
||||
}
|
||||
|
||||
static bool gfxhub_v1_0_query_utcl2_poison_status(struct amdgpu_device *adev,
|
||||
int xcc_id)
|
||||
{
|
||||
u32 status = 0;
|
||||
struct amdgpu_vmhub *hub;
|
||||
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 2))
|
||||
return false;
|
||||
|
||||
hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
|
||||
status = RREG32(hub->vm_l2_pro_fault_status);
|
||||
/* reset page fault status */
|
||||
WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1);
|
||||
|
||||
return REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, FED);
|
||||
}
|
||||
|
||||
const struct amdgpu_gfxhub_funcs gfxhub_v1_0_funcs = {
|
||||
.get_mc_fb_offset = gfxhub_v1_0_get_mc_fb_offset,
|
||||
.setup_vm_pt_regs = gfxhub_v1_0_setup_vm_pt_regs,
|
||||
@ -468,5 +451,4 @@ const struct amdgpu_gfxhub_funcs gfxhub_v1_0_funcs = {
|
||||
.set_fault_enable_default = gfxhub_v1_0_set_fault_enable_default,
|
||||
.init = gfxhub_v1_0_init,
|
||||
.get_xgmi_info = gfxhub_v1_1_get_xgmi_info,
|
||||
.query_utcl2_poison_status = gfxhub_v1_0_query_utcl2_poison_status,
|
||||
};
|
||||
|
@ -622,22 +622,6 @@ static int gfxhub_v1_2_get_xgmi_info(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool gfxhub_v1_2_query_utcl2_poison_status(struct amdgpu_device *adev,
|
||||
int xcc_id)
|
||||
{
|
||||
u32 fed, status;
|
||||
|
||||
status = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regVM_L2_PROTECTION_FAULT_STATUS);
|
||||
fed = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, FED);
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
/* clear page fault status and address */
|
||||
WREG32_P(SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id),
|
||||
regVM_L2_PROTECTION_FAULT_CNTL), 1, ~1);
|
||||
}
|
||||
|
||||
return fed;
|
||||
}
|
||||
|
||||
const struct amdgpu_gfxhub_funcs gfxhub_v1_2_funcs = {
|
||||
.get_mc_fb_offset = gfxhub_v1_2_get_mc_fb_offset,
|
||||
.setup_vm_pt_regs = gfxhub_v1_2_setup_vm_pt_regs,
|
||||
@ -646,7 +630,6 @@ const struct amdgpu_gfxhub_funcs gfxhub_v1_2_funcs = {
|
||||
.set_fault_enable_default = gfxhub_v1_2_set_fault_enable_default,
|
||||
.init = gfxhub_v1_2_init,
|
||||
.get_xgmi_info = gfxhub_v1_2_get_xgmi_info,
|
||||
.query_utcl2_poison_status = gfxhub_v1_2_query_utcl2_poison_status,
|
||||
};
|
||||
|
||||
static int gfxhub_v1_2_xcp_resume(void *handle, uint32_t inst_mask)
|
||||
|
@ -132,7 +132,8 @@ static int gmc_v10_0_process_interrupt(struct amdgpu_device *adev,
|
||||
/* Try to handle the recoverable page faults by filling page
|
||||
* tables
|
||||
*/
|
||||
if (amdgpu_vm_handle_fault(adev, entry->pasid, 0, 0, addr, write_fault))
|
||||
if (amdgpu_vm_handle_fault(adev, entry->pasid, 0, 0, addr,
|
||||
entry->timestamp, write_fault))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -595,7 +595,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
|
||||
cam_index = entry->src_data[2] & 0x3ff;
|
||||
|
||||
ret = amdgpu_vm_handle_fault(adev, entry->pasid, entry->vmid, node_id,
|
||||
addr, write_fault);
|
||||
addr, entry->timestamp, write_fault);
|
||||
WDOORBELL32(adev->irq.retry_cam_doorbell_index, cam_index);
|
||||
if (ret)
|
||||
return 1;
|
||||
@ -618,7 +618,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
|
||||
* tables
|
||||
*/
|
||||
if (amdgpu_vm_handle_fault(adev, entry->pasid, entry->vmid, node_id,
|
||||
addr, write_fault))
|
||||
addr, entry->timestamp, write_fault))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ static void hdp_v4_0_flush_hdp(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring)
|
||||
{
|
||||
if (!ring || !ring->funcs->emit_wreg)
|
||||
WREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
|
||||
WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
|
||||
else
|
||||
amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ static void hdp_v5_0_flush_hdp(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring)
|
||||
{
|
||||
if (!ring || !ring->funcs->emit_wreg)
|
||||
WREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
|
||||
WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
|
||||
else
|
||||
amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ static void hdp_v6_0_flush_hdp(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring)
|
||||
{
|
||||
if (!ring || !ring->funcs->emit_wreg)
|
||||
WREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
|
||||
WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
|
||||
else
|
||||
amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ static void hdp_v7_0_flush_hdp(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring)
|
||||
{
|
||||
if (!ring || !ring->funcs->emit_wreg)
|
||||
WREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
|
||||
WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
|
||||
else
|
||||
amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
|
||||
}
|
||||
|
@ -42,23 +42,23 @@ static const unsigned int isp_4_1_0_int_srcid[MAX_ISP410_INT_SRC] = {
|
||||
static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp)
|
||||
{
|
||||
struct amdgpu_device *adev = isp->adev;
|
||||
int idx, int_idx, num_res, r;
|
||||
u64 isp_base;
|
||||
int int_idx;
|
||||
int r;
|
||||
|
||||
if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289)
|
||||
return -EINVAL;
|
||||
|
||||
isp_base = adev->rmmio_base;
|
||||
|
||||
isp->isp_cell = kcalloc(1, sizeof(struct mfd_cell), GFP_KERNEL);
|
||||
isp->isp_cell = kcalloc(2, sizeof(struct mfd_cell), GFP_KERNEL);
|
||||
if (!isp->isp_cell) {
|
||||
r = -ENOMEM;
|
||||
DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
isp->isp_res = kcalloc(MAX_ISP410_INT_SRC + 1, sizeof(struct resource),
|
||||
num_res = MAX_ISP410_MEM_RES + MAX_ISP410_SENSOR_RES + MAX_ISP410_INT_SRC;
|
||||
isp->isp_res = kcalloc(num_res, sizeof(struct resource),
|
||||
GFP_KERNEL);
|
||||
if (!isp->isp_res) {
|
||||
r = -ENOMEM;
|
||||
@ -83,22 +83,53 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp)
|
||||
isp->isp_res[0].start = isp_base;
|
||||
isp->isp_res[0].end = isp_base + ISP_REGS_OFFSET_END;
|
||||
|
||||
for (int_idx = 0; int_idx < MAX_ISP410_INT_SRC; int_idx++) {
|
||||
isp->isp_res[int_idx + 1].name = "isp_4_1_0_irq";
|
||||
isp->isp_res[int_idx + 1].flags = IORESOURCE_IRQ;
|
||||
isp->isp_res[int_idx + 1].start =
|
||||
isp->isp_res[1].name = "isp_4_1_phy0_reg";
|
||||
isp->isp_res[1].flags = IORESOURCE_MEM;
|
||||
isp->isp_res[1].start = isp_base + ISP410_PHY0_OFFSET;
|
||||
isp->isp_res[1].end = isp_base + ISP410_PHY0_OFFSET + ISP410_PHY0_SIZE;
|
||||
|
||||
isp->isp_res[2].name = "isp_gpio_sensor0_reg";
|
||||
isp->isp_res[2].flags = IORESOURCE_MEM;
|
||||
isp->isp_res[2].start = isp_base + ISP410_GPIO_SENSOR0_OFFSET;
|
||||
isp->isp_res[2].end = isp_base + ISP410_GPIO_SENSOR0_OFFSET +
|
||||
ISP410_GPIO_SENSOR0_SIZE;
|
||||
|
||||
for (idx = MAX_ISP410_MEM_RES + MAX_ISP410_SENSOR_RES, int_idx = 0;
|
||||
idx < num_res; idx++, int_idx++) {
|
||||
isp->isp_res[idx].name = "isp_4_1_0_irq";
|
||||
isp->isp_res[idx].flags = IORESOURCE_IRQ;
|
||||
isp->isp_res[idx].start =
|
||||
amdgpu_irq_create_mapping(adev, isp_4_1_0_int_srcid[int_idx]);
|
||||
isp->isp_res[int_idx + 1].end =
|
||||
isp->isp_res[int_idx + 1].start;
|
||||
isp->isp_res[idx].end =
|
||||
isp->isp_res[idx].start;
|
||||
}
|
||||
|
||||
isp->isp_cell[0].name = "amd_isp_capture";
|
||||
isp->isp_cell[0].num_resources = MAX_ISP410_INT_SRC + 1;
|
||||
isp->isp_cell[0].num_resources = num_res;
|
||||
isp->isp_cell[0].resources = &isp->isp_res[0];
|
||||
isp->isp_cell[0].platform_data = isp->isp_pdata;
|
||||
isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data);
|
||||
|
||||
r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 1);
|
||||
isp->isp_i2c_res = kcalloc(1, sizeof(struct resource),
|
||||
GFP_KERNEL);
|
||||
if (!isp->isp_i2c_res) {
|
||||
r = -ENOMEM;
|
||||
DRM_ERROR("%s: isp mfd res alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
isp->isp_i2c_res[0].name = "isp_i2c0_reg";
|
||||
isp->isp_i2c_res[0].flags = IORESOURCE_MEM;
|
||||
isp->isp_i2c_res[0].start = isp_base + ISP410_I2C0_OFFSET;
|
||||
isp->isp_i2c_res[0].end = isp_base + ISP410_I2C0_OFFSET + ISP410_I2C0_SIZE;
|
||||
|
||||
isp->isp_cell[1].name = "amd_isp_i2c_designware";
|
||||
isp->isp_cell[1].num_resources = 1;
|
||||
isp->isp_cell[1].resources = &isp->isp_i2c_res[0];
|
||||
isp->isp_cell[1].platform_data = isp->isp_pdata;
|
||||
isp->isp_cell[1].pdata_size = sizeof(struct isp_platform_data);
|
||||
|
||||
r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 2);
|
||||
if (r) {
|
||||
DRM_ERROR("%s: add mfd hotplug device failed\n", __func__);
|
||||
goto failure;
|
||||
@ -111,6 +142,7 @@ failure:
|
||||
kfree(isp->isp_pdata);
|
||||
kfree(isp->isp_res);
|
||||
kfree(isp->isp_cell);
|
||||
kfree(isp->isp_i2c_res);
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -122,6 +154,7 @@ static int isp_v4_1_0_hw_fini(struct amdgpu_isp *isp)
|
||||
kfree(isp->isp_res);
|
||||
kfree(isp->isp_cell);
|
||||
kfree(isp->isp_pdata);
|
||||
kfree(isp->isp_i2c_res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -32,8 +32,19 @@
|
||||
|
||||
#include "ivsrcid/isp/irqsrcs_isp_4_1.h"
|
||||
|
||||
#define MAX_ISP410_MEM_RES 2
|
||||
#define MAX_ISP410_SENSOR_RES 1
|
||||
#define MAX_ISP410_INT_SRC 8
|
||||
|
||||
#define ISP410_PHY0_OFFSET 0x66700
|
||||
#define ISP410_PHY0_SIZE 0xD30
|
||||
|
||||
#define ISP410_I2C0_OFFSET 0x66400
|
||||
#define ISP410_I2C0_SIZE 0x100
|
||||
|
||||
#define ISP410_GPIO_SENSOR0_OFFSET 0x6613C
|
||||
#define ISP410_GPIO_SENSOR0_SIZE 0x4
|
||||
|
||||
void isp_v4_1_0_set_isp_funcs(struct amdgpu_isp *isp);
|
||||
|
||||
#endif
|
||||
|
@ -42,23 +42,24 @@ static const unsigned int isp_4_1_1_int_srcid[MAX_ISP411_INT_SRC] = {
|
||||
static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
|
||||
{
|
||||
struct amdgpu_device *adev = isp->adev;
|
||||
int idx, int_idx, num_res, r;
|
||||
u64 isp_base;
|
||||
int int_idx;
|
||||
int r;
|
||||
|
||||
if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289)
|
||||
return -EINVAL;
|
||||
|
||||
isp_base = adev->rmmio_base;
|
||||
|
||||
isp->isp_cell = kcalloc(1, sizeof(struct mfd_cell), GFP_KERNEL);
|
||||
isp->isp_cell = kcalloc(2, sizeof(struct mfd_cell), GFP_KERNEL);
|
||||
if (!isp->isp_cell) {
|
||||
r = -ENOMEM;
|
||||
DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
isp->isp_res = kcalloc(MAX_ISP411_INT_SRC + 1, sizeof(struct resource),
|
||||
num_res = MAX_ISP411_MEM_RES + MAX_ISP411_SENSOR_RES + MAX_ISP411_INT_SRC;
|
||||
|
||||
isp->isp_res = kcalloc(num_res, sizeof(struct resource),
|
||||
GFP_KERNEL);
|
||||
if (!isp->isp_res) {
|
||||
r = -ENOMEM;
|
||||
@ -83,22 +84,52 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
|
||||
isp->isp_res[0].start = isp_base;
|
||||
isp->isp_res[0].end = isp_base + ISP_REGS_OFFSET_END;
|
||||
|
||||
for (int_idx = 0; int_idx < MAX_ISP411_INT_SRC; int_idx++) {
|
||||
isp->isp_res[int_idx + 1].name = "isp_4_1_1_irq";
|
||||
isp->isp_res[int_idx + 1].flags = IORESOURCE_IRQ;
|
||||
isp->isp_res[int_idx + 1].start =
|
||||
isp->isp_res[1].name = "isp_4_1_1_phy0_reg";
|
||||
isp->isp_res[1].flags = IORESOURCE_MEM;
|
||||
isp->isp_res[1].start = isp_base + ISP411_PHY0_OFFSET;
|
||||
isp->isp_res[1].end = isp_base + ISP411_PHY0_OFFSET + ISP411_PHY0_SIZE;
|
||||
|
||||
isp->isp_res[2].name = "isp_4_1_1_sensor0_reg";
|
||||
isp->isp_res[2].flags = IORESOURCE_MEM;
|
||||
isp->isp_res[2].start = isp_base + ISP411_GPIO_SENSOR0_OFFSET;
|
||||
isp->isp_res[2].end = isp_base + ISP411_GPIO_SENSOR0_OFFSET +
|
||||
ISP411_GPIO_SENSOR0_SIZE;
|
||||
|
||||
for (idx = MAX_ISP411_MEM_RES + MAX_ISP411_SENSOR_RES, int_idx = 0;
|
||||
idx < num_res; idx++, int_idx++) {
|
||||
isp->isp_res[idx].name = "isp_4_1_1_irq";
|
||||
isp->isp_res[idx].flags = IORESOURCE_IRQ;
|
||||
isp->isp_res[idx].start =
|
||||
amdgpu_irq_create_mapping(adev, isp_4_1_1_int_srcid[int_idx]);
|
||||
isp->isp_res[int_idx + 1].end =
|
||||
isp->isp_res[int_idx + 1].start;
|
||||
isp->isp_res[idx].end =
|
||||
isp->isp_res[idx].start;
|
||||
}
|
||||
|
||||
isp->isp_cell[0].name = "amd_isp_capture";
|
||||
isp->isp_cell[0].num_resources = MAX_ISP411_INT_SRC + 1;
|
||||
isp->isp_cell[0].num_resources = num_res;
|
||||
isp->isp_cell[0].resources = &isp->isp_res[0];
|
||||
isp->isp_cell[0].platform_data = isp->isp_pdata;
|
||||
isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data);
|
||||
|
||||
r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 1);
|
||||
isp->isp_i2c_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL);
|
||||
if (!isp->isp_i2c_res) {
|
||||
r = -ENOMEM;
|
||||
DRM_ERROR("%s: isp mfd res alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
isp->isp_i2c_res[0].name = "isp_i2c0_reg";
|
||||
isp->isp_i2c_res[0].flags = IORESOURCE_MEM;
|
||||
isp->isp_i2c_res[0].start = isp_base + ISP411_I2C0_OFFSET;
|
||||
isp->isp_i2c_res[0].end = isp_base + ISP411_I2C0_OFFSET + ISP411_I2C0_SIZE;
|
||||
|
||||
isp->isp_cell[1].name = "amd_isp_i2c_designware";
|
||||
isp->isp_cell[1].num_resources = 1;
|
||||
isp->isp_cell[1].resources = &isp->isp_i2c_res[0];
|
||||
isp->isp_cell[1].platform_data = isp->isp_pdata;
|
||||
isp->isp_cell[1].pdata_size = sizeof(struct isp_platform_data);
|
||||
|
||||
r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 2);
|
||||
if (r) {
|
||||
DRM_ERROR("%s: add mfd hotplug device failed\n", __func__);
|
||||
goto failure;
|
||||
@ -111,6 +142,7 @@ failure:
|
||||
kfree(isp->isp_pdata);
|
||||
kfree(isp->isp_res);
|
||||
kfree(isp->isp_cell);
|
||||
kfree(isp->isp_i2c_res);
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -122,6 +154,7 @@ static int isp_v4_1_1_hw_fini(struct amdgpu_isp *isp)
|
||||
kfree(isp->isp_res);
|
||||
kfree(isp->isp_cell);
|
||||
kfree(isp->isp_pdata);
|
||||
kfree(isp->isp_i2c_res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -32,8 +32,19 @@
|
||||
|
||||
#include "ivsrcid/isp/irqsrcs_isp_4_1.h"
|
||||
|
||||
#define MAX_ISP411_MEM_RES 2
|
||||
#define MAX_ISP411_SENSOR_RES 1
|
||||
#define MAX_ISP411_INT_SRC 8
|
||||
|
||||
#define ISP411_PHY0_OFFSET 0x66700
|
||||
#define ISP411_PHY0_SIZE 0xD30
|
||||
|
||||
#define ISP411_I2C0_OFFSET 0x66400
|
||||
#define ISP411_I2C0_SIZE 0x100
|
||||
|
||||
#define ISP411_GPIO_SENSOR0_OFFSET 0x6613C
|
||||
#define ISP411_GPIO_SENSOR0_SIZE 0x4
|
||||
|
||||
void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp);
|
||||
|
||||
#endif
|
||||
|
@ -360,6 +360,26 @@ static int mes_v11_0_remove_hw_queue(struct amdgpu_mes *mes,
|
||||
offsetof(union MESAPI__REMOVE_QUEUE, api_status));
|
||||
}
|
||||
|
||||
static int mes_v11_0_reset_hw_queue(struct amdgpu_mes *mes,
|
||||
struct mes_reset_queue_input *input)
|
||||
{
|
||||
union MESAPI__RESET mes_reset_queue_pkt;
|
||||
|
||||
memset(&mes_reset_queue_pkt, 0, sizeof(mes_reset_queue_pkt));
|
||||
|
||||
mes_reset_queue_pkt.header.type = MES_API_TYPE_SCHEDULER;
|
||||
mes_reset_queue_pkt.header.opcode = MES_SCH_API_RESET;
|
||||
mes_reset_queue_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
|
||||
|
||||
mes_reset_queue_pkt.doorbell_offset = input->doorbell_offset;
|
||||
mes_reset_queue_pkt.gang_context_addr = input->gang_context_addr;
|
||||
/*mes_reset_queue_pkt.reset_queue_only = 1;*/
|
||||
|
||||
return mes_v11_0_submit_pkt_and_poll_completion(mes,
|
||||
&mes_reset_queue_pkt, sizeof(mes_reset_queue_pkt),
|
||||
offsetof(union MESAPI__REMOVE_QUEUE, api_status));
|
||||
}
|
||||
|
||||
static int mes_v11_0_map_legacy_queue(struct amdgpu_mes *mes,
|
||||
struct mes_map_legacy_queue_input *input)
|
||||
{
|
||||
@ -421,13 +441,41 @@ static int mes_v11_0_unmap_legacy_queue(struct amdgpu_mes *mes,
|
||||
static int mes_v11_0_suspend_gang(struct amdgpu_mes *mes,
|
||||
struct mes_suspend_gang_input *input)
|
||||
{
|
||||
return 0;
|
||||
union MESAPI__SUSPEND mes_suspend_gang_pkt;
|
||||
|
||||
memset(&mes_suspend_gang_pkt, 0, sizeof(mes_suspend_gang_pkt));
|
||||
|
||||
mes_suspend_gang_pkt.header.type = MES_API_TYPE_SCHEDULER;
|
||||
mes_suspend_gang_pkt.header.opcode = MES_SCH_API_SUSPEND;
|
||||
mes_suspend_gang_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
|
||||
|
||||
mes_suspend_gang_pkt.suspend_all_gangs = input->suspend_all_gangs;
|
||||
mes_suspend_gang_pkt.gang_context_addr = input->gang_context_addr;
|
||||
mes_suspend_gang_pkt.suspend_fence_addr = input->suspend_fence_addr;
|
||||
mes_suspend_gang_pkt.suspend_fence_value = input->suspend_fence_value;
|
||||
|
||||
return mes_v11_0_submit_pkt_and_poll_completion(mes,
|
||||
&mes_suspend_gang_pkt, sizeof(mes_suspend_gang_pkt),
|
||||
offsetof(union MESAPI__SUSPEND, api_status));
|
||||
}
|
||||
|
||||
static int mes_v11_0_resume_gang(struct amdgpu_mes *mes,
|
||||
struct mes_resume_gang_input *input)
|
||||
{
|
||||
return 0;
|
||||
union MESAPI__RESUME mes_resume_gang_pkt;
|
||||
|
||||
memset(&mes_resume_gang_pkt, 0, sizeof(mes_resume_gang_pkt));
|
||||
|
||||
mes_resume_gang_pkt.header.type = MES_API_TYPE_SCHEDULER;
|
||||
mes_resume_gang_pkt.header.opcode = MES_SCH_API_RESUME;
|
||||
mes_resume_gang_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
|
||||
|
||||
mes_resume_gang_pkt.resume_all_gangs = input->resume_all_gangs;
|
||||
mes_resume_gang_pkt.gang_context_addr = input->gang_context_addr;
|
||||
|
||||
return mes_v11_0_submit_pkt_and_poll_completion(mes,
|
||||
&mes_resume_gang_pkt, sizeof(mes_resume_gang_pkt),
|
||||
offsetof(union MESAPI__RESUME, api_status));
|
||||
}
|
||||
|
||||
static int mes_v11_0_query_sched_status(struct amdgpu_mes *mes)
|
||||
@ -595,6 +643,38 @@ static int mes_v11_0_set_hw_resources_1(struct amdgpu_mes *mes)
|
||||
offsetof(union MESAPI_SET_HW_RESOURCES_1, api_status));
|
||||
}
|
||||
|
||||
static int mes_v11_0_reset_legacy_queue(struct amdgpu_mes *mes,
|
||||
struct mes_reset_legacy_queue_input *input)
|
||||
{
|
||||
union MESAPI__RESET mes_reset_queue_pkt;
|
||||
|
||||
memset(&mes_reset_queue_pkt, 0, sizeof(mes_reset_queue_pkt));
|
||||
|
||||
mes_reset_queue_pkt.header.type = MES_API_TYPE_SCHEDULER;
|
||||
mes_reset_queue_pkt.header.opcode = MES_SCH_API_RESET;
|
||||
mes_reset_queue_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
|
||||
|
||||
mes_reset_queue_pkt.queue_type =
|
||||
convert_to_mes_queue_type(input->queue_type);
|
||||
|
||||
if (mes_reset_queue_pkt.queue_type == MES_QUEUE_TYPE_GFX) {
|
||||
mes_reset_queue_pkt.reset_legacy_gfx = 1;
|
||||
mes_reset_queue_pkt.pipe_id_lp = input->pipe_id;
|
||||
mes_reset_queue_pkt.queue_id_lp = input->queue_id;
|
||||
mes_reset_queue_pkt.mqd_mc_addr_lp = input->mqd_addr;
|
||||
mes_reset_queue_pkt.doorbell_offset_lp = input->doorbell_offset;
|
||||
mes_reset_queue_pkt.wptr_addr_lp = input->wptr_addr;
|
||||
mes_reset_queue_pkt.vmid_id_lp = input->vmid;
|
||||
} else {
|
||||
mes_reset_queue_pkt.reset_queue_only = 1;
|
||||
mes_reset_queue_pkt.doorbell_offset = input->doorbell_offset;
|
||||
}
|
||||
|
||||
return mes_v11_0_submit_pkt_and_poll_completion(mes,
|
||||
&mes_reset_queue_pkt, sizeof(mes_reset_queue_pkt),
|
||||
offsetof(union MESAPI__RESET, api_status));
|
||||
}
|
||||
|
||||
static const struct amdgpu_mes_funcs mes_v11_0_funcs = {
|
||||
.add_hw_queue = mes_v11_0_add_hw_queue,
|
||||
.remove_hw_queue = mes_v11_0_remove_hw_queue,
|
||||
@ -603,6 +683,8 @@ static const struct amdgpu_mes_funcs mes_v11_0_funcs = {
|
||||
.suspend_gang = mes_v11_0_suspend_gang,
|
||||
.resume_gang = mes_v11_0_resume_gang,
|
||||
.misc_op = mes_v11_0_misc_op,
|
||||
.reset_legacy_queue = mes_v11_0_reset_legacy_queue,
|
||||
.reset_hw_queue = mes_v11_0_reset_hw_queue,
|
||||
};
|
||||
|
||||
static int mes_v11_0_allocate_ucode_buffer(struct amdgpu_device *adev,
|
||||
|
@ -350,6 +350,32 @@ static int mes_v12_0_remove_hw_queue(struct amdgpu_mes *mes,
|
||||
offsetof(union MESAPI__REMOVE_QUEUE, api_status));
|
||||
}
|
||||
|
||||
static int mes_v12_0_reset_hw_queue(struct amdgpu_mes *mes,
|
||||
struct mes_reset_queue_input *input)
|
||||
{
|
||||
union MESAPI__RESET mes_reset_queue_pkt;
|
||||
int pipe;
|
||||
|
||||
memset(&mes_reset_queue_pkt, 0, sizeof(mes_reset_queue_pkt));
|
||||
|
||||
mes_reset_queue_pkt.header.type = MES_API_TYPE_SCHEDULER;
|
||||
mes_reset_queue_pkt.header.opcode = MES_SCH_API_RESET;
|
||||
mes_reset_queue_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
|
||||
|
||||
mes_reset_queue_pkt.doorbell_offset = input->doorbell_offset;
|
||||
mes_reset_queue_pkt.gang_context_addr = input->gang_context_addr;
|
||||
/*mes_reset_queue_pkt.reset_queue_only = 1;*/
|
||||
|
||||
if (mes->adev->enable_uni_mes)
|
||||
pipe = AMDGPU_MES_KIQ_PIPE;
|
||||
else
|
||||
pipe = AMDGPU_MES_SCHED_PIPE;
|
||||
|
||||
return mes_v12_0_submit_pkt_and_poll_completion(mes, pipe,
|
||||
&mes_reset_queue_pkt, sizeof(mes_reset_queue_pkt),
|
||||
offsetof(union MESAPI__REMOVE_QUEUE, api_status));
|
||||
}
|
||||
|
||||
static int mes_v12_0_map_legacy_queue(struct amdgpu_mes *mes,
|
||||
struct mes_map_legacy_queue_input *input)
|
||||
{
|
||||
@ -676,6 +702,44 @@ static void mes_v12_0_enable_unmapped_doorbell_handling(
|
||||
WREG32_SOC15(GC, 0, regCP_UNMAPPED_DOORBELL, data);
|
||||
}
|
||||
|
||||
static int mes_v12_0_reset_legacy_queue(struct amdgpu_mes *mes,
|
||||
struct mes_reset_legacy_queue_input *input)
|
||||
{
|
||||
union MESAPI__RESET mes_reset_queue_pkt;
|
||||
int pipe;
|
||||
|
||||
memset(&mes_reset_queue_pkt, 0, sizeof(mes_reset_queue_pkt));
|
||||
|
||||
mes_reset_queue_pkt.header.type = MES_API_TYPE_SCHEDULER;
|
||||
mes_reset_queue_pkt.header.opcode = MES_SCH_API_RESET;
|
||||
mes_reset_queue_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
|
||||
|
||||
mes_reset_queue_pkt.queue_type =
|
||||
convert_to_mes_queue_type(input->queue_type);
|
||||
|
||||
if (mes_reset_queue_pkt.queue_type == MES_QUEUE_TYPE_GFX) {
|
||||
mes_reset_queue_pkt.reset_legacy_gfx = 1;
|
||||
mes_reset_queue_pkt.pipe_id_lp = input->pipe_id;
|
||||
mes_reset_queue_pkt.queue_id_lp = input->queue_id;
|
||||
mes_reset_queue_pkt.mqd_mc_addr_lp = input->mqd_addr;
|
||||
mes_reset_queue_pkt.doorbell_offset_lp = input->doorbell_offset;
|
||||
mes_reset_queue_pkt.wptr_addr_lp = input->wptr_addr;
|
||||
mes_reset_queue_pkt.vmid_id_lp = input->vmid;
|
||||
} else {
|
||||
mes_reset_queue_pkt.reset_queue_only = 1;
|
||||
mes_reset_queue_pkt.doorbell_offset = input->doorbell_offset;
|
||||
}
|
||||
|
||||
if (mes->adev->enable_uni_mes)
|
||||
pipe = AMDGPU_MES_KIQ_PIPE;
|
||||
else
|
||||
pipe = AMDGPU_MES_SCHED_PIPE;
|
||||
|
||||
return mes_v12_0_submit_pkt_and_poll_completion(mes, pipe,
|
||||
&mes_reset_queue_pkt, sizeof(mes_reset_queue_pkt),
|
||||
offsetof(union MESAPI__RESET, api_status));
|
||||
}
|
||||
|
||||
static const struct amdgpu_mes_funcs mes_v12_0_funcs = {
|
||||
.add_hw_queue = mes_v12_0_add_hw_queue,
|
||||
.remove_hw_queue = mes_v12_0_remove_hw_queue,
|
||||
@ -684,6 +748,8 @@ static const struct amdgpu_mes_funcs mes_v12_0_funcs = {
|
||||
.suspend_gang = mes_v12_0_suspend_gang,
|
||||
.resume_gang = mes_v12_0_resume_gang,
|
||||
.misc_op = mes_v12_0_misc_op,
|
||||
.reset_legacy_queue = mes_v12_0_reset_legacy_queue,
|
||||
.reset_hw_queue = mes_v12_0_reset_hw_queue,
|
||||
};
|
||||
|
||||
static int mes_v12_0_allocate_ucode_buffer(struct amdgpu_device *adev,
|
||||
|
@ -559,22 +559,6 @@ static void mmhub_v1_8_get_clockgating(struct amdgpu_device *adev, u64 *flags)
|
||||
|
||||
}
|
||||
|
||||
static bool mmhub_v1_8_query_utcl2_poison_status(struct amdgpu_device *adev,
|
||||
int hub_inst)
|
||||
{
|
||||
u32 fed, status;
|
||||
|
||||
status = RREG32_SOC15(MMHUB, hub_inst, regVM_L2_PROTECTION_FAULT_STATUS);
|
||||
fed = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, FED);
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
/* clear page fault status and address */
|
||||
WREG32_P(SOC15_REG_OFFSET(MMHUB, hub_inst,
|
||||
regVM_L2_PROTECTION_FAULT_CNTL), 1, ~1);
|
||||
}
|
||||
|
||||
return fed;
|
||||
}
|
||||
|
||||
const struct amdgpu_mmhub_funcs mmhub_v1_8_funcs = {
|
||||
.get_fb_location = mmhub_v1_8_get_fb_location,
|
||||
.init = mmhub_v1_8_init,
|
||||
@ -584,7 +568,6 @@ const struct amdgpu_mmhub_funcs mmhub_v1_8_funcs = {
|
||||
.setup_vm_pt_regs = mmhub_v1_8_setup_vm_pt_regs,
|
||||
.set_clockgating = mmhub_v1_8_set_clockgating,
|
||||
.get_clockgating = mmhub_v1_8_get_clockgating,
|
||||
.query_utcl2_poison_status = mmhub_v1_8_query_utcl2_poison_status,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ras_err_status_reg_entry mmhub_v1_8_ce_reg_list[] = {
|
||||
@ -670,8 +653,8 @@ static void mmhub_v1_8_inst_query_ras_error_count(struct amdgpu_device *adev,
|
||||
AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
|
||||
&ue_count);
|
||||
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, NULL, ce_count);
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, NULL, ue_count);
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, ce_count);
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, ue_count);
|
||||
}
|
||||
|
||||
static void mmhub_v1_8_query_ras_error_count(struct amdgpu_device *adev,
|
||||
|
@ -25,7 +25,7 @@
|
||||
#define __MXGPU_NV_H__
|
||||
|
||||
#define NV_MAILBOX_POLL_ACK_TIMEDOUT 500
|
||||
#define NV_MAILBOX_POLL_MSG_TIMEDOUT 6000
|
||||
#define NV_MAILBOX_POLL_MSG_TIMEDOUT 15000
|
||||
#define NV_MAILBOX_POLL_FLR_TIMEDOUT 10000
|
||||
#define NV_MAILBOX_POLL_MSG_REP_MAX 11
|
||||
|
||||
|
@ -72,6 +72,53 @@ MODULE_FIRMWARE("amdgpu/renoir_sdma.bin");
|
||||
MODULE_FIRMWARE("amdgpu/green_sardine_sdma.bin");
|
||||
MODULE_FIRMWARE("amdgpu/aldebaran_sdma.bin");
|
||||
|
||||
static const struct amdgpu_hwip_reg_entry sdma_reg_list_4_0[] = {
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_STATUS_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_STATUS1_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_STATUS2_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_STATUS3_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UCODE_CHECKSUM),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RB_RPTR_FETCH_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RB_RPTR_FETCH),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_RD_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_WR_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_RD_XNACK0),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_RD_XNACK1),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_WR_XNACK0),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_WR_XNACK1),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_RB_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_RB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_RB_RPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_RB_WPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_RB_WPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_OFFSET),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_BASE_LO),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_BASE_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_SUB_REMAIN),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_DUMMY_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_RB_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_RB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_RB_RPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_RB_WPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_RB_WPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_IB_OFFSET),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_IB_BASE_LO),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_IB_BASE_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_DUMMY_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_RB_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_RB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_RB_RPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_RB_WPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_RB_WPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_IB_OFFSET),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_IB_BASE_LO),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_IB_BASE_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_DUMMY_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_VM_CNTL)
|
||||
};
|
||||
|
||||
#define SDMA0_POWER_CNTL__ON_OFF_CONDITION_HOLD_TIME_MASK 0x000000F8L
|
||||
#define SDMA0_POWER_CNTL__ON_OFF_STATUS_DURATION_TIME_MASK 0xFC000000L
|
||||
|
||||
@ -1750,6 +1797,8 @@ static int sdma_v4_0_sw_init(void *handle)
|
||||
struct amdgpu_ring *ring;
|
||||
int r, i;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
uint32_t reg_count = ARRAY_SIZE(sdma_reg_list_4_0);
|
||||
uint32_t *ptr;
|
||||
|
||||
/* SDMA trap event */
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
@ -1870,6 +1919,13 @@ static int sdma_v4_0_sw_init(void *handle)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Allocate memory for SDMA IP Dump buffer */
|
||||
ptr = kcalloc(adev->sdma.num_instances * reg_count, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (ptr)
|
||||
adev->sdma.ip_dump = ptr;
|
||||
else
|
||||
DRM_ERROR("Failed to allocated memory for SDMA IP Dump\n");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -1890,6 +1946,8 @@ static int sdma_v4_0_sw_fini(void *handle)
|
||||
else
|
||||
amdgpu_sdma_destroy_inst_ctx(adev, false);
|
||||
|
||||
kfree(adev->sdma.ip_dump);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2292,6 +2350,48 @@ static void sdma_v4_0_get_clockgating_state(void *handle, u64 *flags)
|
||||
*flags |= AMD_CG_SUPPORT_SDMA_LS;
|
||||
}
|
||||
|
||||
static void sdma_v4_0_print_ip_state(void *handle, struct drm_printer *p)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int i, j;
|
||||
uint32_t reg_count = ARRAY_SIZE(sdma_reg_list_4_0);
|
||||
uint32_t instance_offset;
|
||||
|
||||
if (!adev->sdma.ip_dump)
|
||||
return;
|
||||
|
||||
drm_printf(p, "num_instances:%d\n", adev->sdma.num_instances);
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
instance_offset = i * reg_count;
|
||||
drm_printf(p, "\nInstance:%d\n", i);
|
||||
|
||||
for (j = 0; j < reg_count; j++)
|
||||
drm_printf(p, "%-50s \t 0x%08x\n", sdma_reg_list_4_0[j].reg_name,
|
||||
adev->sdma.ip_dump[instance_offset + j]);
|
||||
}
|
||||
}
|
||||
|
||||
static void sdma_v4_0_dump_ip_state(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int i, j;
|
||||
uint32_t instance_offset;
|
||||
uint32_t reg_count = ARRAY_SIZE(sdma_reg_list_4_0);
|
||||
|
||||
if (!adev->sdma.ip_dump)
|
||||
return;
|
||||
|
||||
amdgpu_gfx_off_ctrl(adev, false);
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
instance_offset = i * reg_count;
|
||||
for (j = 0; j < reg_count; j++)
|
||||
adev->sdma.ip_dump[instance_offset + j] =
|
||||
RREG32(sdma_v4_0_get_reg_offset(adev, i,
|
||||
sdma_reg_list_4_0[j].reg_offset));
|
||||
}
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
}
|
||||
|
||||
const struct amd_ip_funcs sdma_v4_0_ip_funcs = {
|
||||
.name = "sdma_v4_0",
|
||||
.early_init = sdma_v4_0_early_init,
|
||||
@ -2308,6 +2408,8 @@ const struct amd_ip_funcs sdma_v4_0_ip_funcs = {
|
||||
.set_clockgating_state = sdma_v4_0_set_clockgating_state,
|
||||
.set_powergating_state = sdma_v4_0_set_powergating_state,
|
||||
.get_clockgating_state = sdma_v4_0_get_clockgating_state,
|
||||
.dump_ip_state = sdma_v4_0_dump_ip_state,
|
||||
.print_ip_state = sdma_v4_0_print_ip_state,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ring_funcs sdma_v4_0_ring_funcs = {
|
||||
|
@ -46,6 +46,53 @@
|
||||
MODULE_FIRMWARE("amdgpu/sdma_4_4_2.bin");
|
||||
MODULE_FIRMWARE("amdgpu/sdma_4_4_5.bin");
|
||||
|
||||
static const struct amdgpu_hwip_reg_entry sdma_reg_list_4_4_2[] = {
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_STATUS_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_STATUS1_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_STATUS2_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_STATUS3_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_UCODE_CHECKSUM),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_RB_RPTR_FETCH_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_RB_RPTR_FETCH),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_UTCL1_RD_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_UTCL1_WR_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_UTCL1_RD_XNACK0),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_UTCL1_RD_XNACK1),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_UTCL1_WR_XNACK0),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_UTCL1_WR_XNACK1),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_GFX_RB_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_GFX_RB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_GFX_RB_RPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_GFX_RB_WPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_GFX_RB_WPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_GFX_IB_OFFSET),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_GFX_IB_BASE_LO),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_GFX_IB_BASE_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_GFX_IB_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_GFX_IB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_GFX_IB_SUB_REMAIN),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_GFX_DUMMY_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_PAGE_RB_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_PAGE_RB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_PAGE_RB_RPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_PAGE_RB_WPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_PAGE_RB_WPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_PAGE_IB_OFFSET),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_PAGE_IB_BASE_LO),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_PAGE_IB_BASE_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_PAGE_DUMMY_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_RLC0_RB_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_RLC0_RB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_RLC0_RB_RPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_RLC0_RB_WPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_RLC0_RB_WPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_RLC0_IB_OFFSET),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_RLC0_IB_BASE_LO),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_RLC0_IB_BASE_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_RLC0_DUMMY_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regSDMA_VM_CNTL)
|
||||
};
|
||||
|
||||
#define mmSMNAID_AID0_MCA_SMU 0x03b30400
|
||||
|
||||
#define WREG32_SDMA(instance, offset, value) \
|
||||
@ -1291,6 +1338,8 @@ static int sdma_v4_4_2_sw_init(void *handle)
|
||||
int r, i;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
u32 aid_id;
|
||||
uint32_t reg_count = ARRAY_SIZE(sdma_reg_list_4_4_2);
|
||||
uint32_t *ptr;
|
||||
|
||||
/* SDMA trap event */
|
||||
for (i = 0; i < adev->sdma.num_inst_per_aid; i++) {
|
||||
@ -1386,6 +1435,13 @@ static int sdma_v4_4_2_sw_init(void *handle)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Allocate memory for SDMA IP Dump buffer */
|
||||
ptr = kcalloc(adev->sdma.num_instances * reg_count, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (ptr)
|
||||
adev->sdma.ip_dump = ptr;
|
||||
else
|
||||
DRM_ERROR("Failed to allocated memory for SDMA IP Dump\n");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -1406,6 +1462,8 @@ static int sdma_v4_4_2_sw_fini(void *handle)
|
||||
else
|
||||
amdgpu_sdma_destroy_inst_ctx(adev, false);
|
||||
|
||||
kfree(adev->sdma.ip_dump);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1799,6 +1857,48 @@ static void sdma_v4_4_2_get_clockgating_state(void *handle, u64 *flags)
|
||||
*flags |= AMD_CG_SUPPORT_SDMA_LS;
|
||||
}
|
||||
|
||||
static void sdma_v4_4_2_print_ip_state(void *handle, struct drm_printer *p)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int i, j;
|
||||
uint32_t reg_count = ARRAY_SIZE(sdma_reg_list_4_4_2);
|
||||
uint32_t instance_offset;
|
||||
|
||||
if (!adev->sdma.ip_dump)
|
||||
return;
|
||||
|
||||
drm_printf(p, "num_instances:%d\n", adev->sdma.num_instances);
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
instance_offset = i * reg_count;
|
||||
drm_printf(p, "\nInstance:%d\n", i);
|
||||
|
||||
for (j = 0; j < reg_count; j++)
|
||||
drm_printf(p, "%-50s \t 0x%08x\n", sdma_reg_list_4_4_2[j].reg_name,
|
||||
adev->sdma.ip_dump[instance_offset + j]);
|
||||
}
|
||||
}
|
||||
|
||||
static void sdma_v4_4_2_dump_ip_state(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int i, j;
|
||||
uint32_t instance_offset;
|
||||
uint32_t reg_count = ARRAY_SIZE(sdma_reg_list_4_4_2);
|
||||
|
||||
if (!adev->sdma.ip_dump)
|
||||
return;
|
||||
|
||||
amdgpu_gfx_off_ctrl(adev, false);
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
instance_offset = i * reg_count;
|
||||
for (j = 0; j < reg_count; j++)
|
||||
adev->sdma.ip_dump[instance_offset + j] =
|
||||
RREG32(sdma_v4_4_2_get_reg_offset(adev, i,
|
||||
sdma_reg_list_4_4_2[j].reg_offset));
|
||||
}
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
}
|
||||
|
||||
const struct amd_ip_funcs sdma_v4_4_2_ip_funcs = {
|
||||
.name = "sdma_v4_4_2",
|
||||
.early_init = sdma_v4_4_2_early_init,
|
||||
@ -1815,6 +1915,8 @@ const struct amd_ip_funcs sdma_v4_4_2_ip_funcs = {
|
||||
.set_clockgating_state = sdma_v4_4_2_set_clockgating_state,
|
||||
.set_powergating_state = sdma_v4_4_2_set_powergating_state,
|
||||
.get_clockgating_state = sdma_v4_4_2_get_clockgating_state,
|
||||
.dump_ip_state = sdma_v4_4_2_dump_ip_state,
|
||||
.print_ip_state = sdma_v4_4_2_print_ip_state,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ring_funcs sdma_v4_4_2_ring_funcs = {
|
||||
@ -2141,7 +2243,7 @@ static void sdma_v4_4_2_inst_query_ras_error_count(struct amdgpu_device *adev,
|
||||
AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
|
||||
&ue_count);
|
||||
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, NULL, ue_count);
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, ue_count);
|
||||
}
|
||||
|
||||
static void sdma_v4_4_2_query_ras_error_count(struct amdgpu_device *adev,
|
||||
|
@ -59,6 +59,55 @@ MODULE_FIRMWARE("amdgpu/cyan_skillfish2_sdma1.bin");
|
||||
#define SDMA0_HYP_DEC_REG_END 0x5893
|
||||
#define SDMA1_HYP_DEC_REG_OFFSET 0x20
|
||||
|
||||
static const struct amdgpu_hwip_reg_entry sdma_reg_list_5_0[] = {
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_STATUS_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_STATUS1_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_STATUS2_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_STATUS3_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UCODE_CHECKSUM),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RB_RPTR_FETCH_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RB_RPTR_FETCH),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_RD_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_WR_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_RD_XNACK0),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_RD_XNACK1),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_WR_XNACK0),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_WR_XNACK1),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_RB_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_RB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_RB_RPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_RB_WPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_RB_WPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_OFFSET),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_BASE_LO),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_BASE_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_SUB_REMAIN),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_DUMMY_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_RB_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_RB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_RB_RPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_RB_WPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_RB_WPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_IB_OFFSET),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_IB_BASE_LO),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_IB_BASE_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_DUMMY_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_RB_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_RB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_RB_RPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_RB_WPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_RB_WPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_IB_OFFSET),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_IB_BASE_LO),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_IB_BASE_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_DUMMY_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_INT_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_VM_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmGRBM_STATUS2)
|
||||
};
|
||||
|
||||
static void sdma_v5_0_set_ring_funcs(struct amdgpu_device *adev);
|
||||
static void sdma_v5_0_set_buffer_funcs(struct amdgpu_device *adev);
|
||||
static void sdma_v5_0_set_vm_pte_funcs(struct amdgpu_device *adev);
|
||||
@ -1341,6 +1390,8 @@ static int sdma_v5_0_sw_init(void *handle)
|
||||
struct amdgpu_ring *ring;
|
||||
int r, i;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
uint32_t reg_count = ARRAY_SIZE(sdma_reg_list_5_0);
|
||||
uint32_t *ptr;
|
||||
|
||||
/* SDMA trap event */
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_SDMA0,
|
||||
@ -1378,6 +1429,13 @@ static int sdma_v5_0_sw_init(void *handle)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Allocate memory for SDMA IP Dump buffer */
|
||||
ptr = kcalloc(adev->sdma.num_instances * reg_count, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (ptr)
|
||||
adev->sdma.ip_dump = ptr;
|
||||
else
|
||||
DRM_ERROR("Failed to allocated memory for SDMA IP Dump\n");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -1391,6 +1449,8 @@ static int sdma_v5_0_sw_fini(void *handle)
|
||||
|
||||
amdgpu_sdma_destroy_inst_ctx(adev, false);
|
||||
|
||||
kfree(adev->sdma.ip_dump);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1718,7 +1778,49 @@ static void sdma_v5_0_get_clockgating_state(void *handle, u64 *flags)
|
||||
*flags |= AMD_CG_SUPPORT_SDMA_LS;
|
||||
}
|
||||
|
||||
const struct amd_ip_funcs sdma_v5_0_ip_funcs = {
|
||||
static void sdma_v5_0_print_ip_state(void *handle, struct drm_printer *p)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int i, j;
|
||||
uint32_t reg_count = ARRAY_SIZE(sdma_reg_list_5_0);
|
||||
uint32_t instance_offset;
|
||||
|
||||
if (!adev->sdma.ip_dump)
|
||||
return;
|
||||
|
||||
drm_printf(p, "num_instances:%d\n", adev->sdma.num_instances);
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
instance_offset = i * reg_count;
|
||||
drm_printf(p, "\nInstance:%d\n", i);
|
||||
|
||||
for (j = 0; j < reg_count; j++)
|
||||
drm_printf(p, "%-50s \t 0x%08x\n", sdma_reg_list_5_0[j].reg_name,
|
||||
adev->sdma.ip_dump[instance_offset + j]);
|
||||
}
|
||||
}
|
||||
|
||||
static void sdma_v5_0_dump_ip_state(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int i, j;
|
||||
uint32_t instance_offset;
|
||||
uint32_t reg_count = ARRAY_SIZE(sdma_reg_list_5_0);
|
||||
|
||||
if (!adev->sdma.ip_dump)
|
||||
return;
|
||||
|
||||
amdgpu_gfx_off_ctrl(adev, false);
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
instance_offset = i * reg_count;
|
||||
for (j = 0; j < reg_count; j++)
|
||||
adev->sdma.ip_dump[instance_offset + j] =
|
||||
RREG32(sdma_v5_0_get_reg_offset(adev, i,
|
||||
sdma_reg_list_5_0[j].reg_offset));
|
||||
}
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
}
|
||||
|
||||
static const struct amd_ip_funcs sdma_v5_0_ip_funcs = {
|
||||
.name = "sdma_v5_0",
|
||||
.early_init = sdma_v5_0_early_init,
|
||||
.late_init = NULL,
|
||||
@ -1734,6 +1836,8 @@ const struct amd_ip_funcs sdma_v5_0_ip_funcs = {
|
||||
.set_clockgating_state = sdma_v5_0_set_clockgating_state,
|
||||
.set_powergating_state = sdma_v5_0_set_powergating_state,
|
||||
.get_clockgating_state = sdma_v5_0_get_clockgating_state,
|
||||
.dump_ip_state = sdma_v5_0_dump_ip_state,
|
||||
.print_ip_state = sdma_v5_0_print_ip_state,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ring_funcs sdma_v5_0_ring_funcs = {
|
||||
|
@ -24,7 +24,6 @@
|
||||
#ifndef __SDMA_V5_0_H__
|
||||
#define __SDMA_V5_0_H__
|
||||
|
||||
extern const struct amd_ip_funcs sdma_v5_0_ip_funcs;
|
||||
extern const struct amdgpu_ip_block_version sdma_v5_0_ip_block;
|
||||
|
||||
#endif /* __SDMA_V5_0_H__ */
|
||||
|
@ -60,6 +60,55 @@ MODULE_FIRMWARE("amdgpu/sdma_5_2_7.bin");
|
||||
#define SDMA0_HYP_DEC_REG_END 0x5893
|
||||
#define SDMA1_HYP_DEC_REG_OFFSET 0x20
|
||||
|
||||
static const struct amdgpu_hwip_reg_entry sdma_reg_list_5_2[] = {
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_STATUS_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_STATUS1_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_STATUS2_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_STATUS3_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UCODE_CHECKSUM),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RB_RPTR_FETCH_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RB_RPTR_FETCH),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_RD_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_WR_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_RD_XNACK0),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_RD_XNACK1),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_WR_XNACK0),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_UTCL1_WR_XNACK1),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_RB_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_RB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_RB_RPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_RB_WPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_RB_WPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_OFFSET),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_BASE_LO),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_BASE_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_IB_SUB_REMAIN),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_GFX_DUMMY_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_RB_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_RB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_RB_RPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_RB_WPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_RB_WPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_IB_OFFSET),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_IB_BASE_LO),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_IB_BASE_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_PAGE_DUMMY_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_RB_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_RB_RPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_RB_RPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_RB_WPTR),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_RB_WPTR_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_IB_OFFSET),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_IB_BASE_LO),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_IB_BASE_HI),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_RLC0_DUMMY_REG),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_INT_STATUS),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmSDMA0_VM_CNTL),
|
||||
SOC15_REG_ENTRY_STR(GC, 0, mmGRBM_STATUS2)
|
||||
};
|
||||
|
||||
static void sdma_v5_2_set_ring_funcs(struct amdgpu_device *adev);
|
||||
static void sdma_v5_2_set_buffer_funcs(struct amdgpu_device *adev);
|
||||
static void sdma_v5_2_set_vm_pte_funcs(struct amdgpu_device *adev);
|
||||
@ -1224,6 +1273,8 @@ static int sdma_v5_2_sw_init(void *handle)
|
||||
struct amdgpu_ring *ring;
|
||||
int r, i;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
uint32_t reg_count = ARRAY_SIZE(sdma_reg_list_5_2);
|
||||
uint32_t *ptr;
|
||||
|
||||
/* SDMA trap event */
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
@ -1255,6 +1306,13 @@ static int sdma_v5_2_sw_init(void *handle)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Allocate memory for SDMA IP Dump buffer */
|
||||
ptr = kcalloc(adev->sdma.num_instances * reg_count, sizeof(uint32_t), GFP_KERNEL);
|
||||
if (ptr)
|
||||
adev->sdma.ip_dump = ptr;
|
||||
else
|
||||
DRM_ERROR("Failed to allocated memory for SDMA IP Dump\n");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -1268,6 +1326,8 @@ static int sdma_v5_2_sw_fini(void *handle)
|
||||
|
||||
amdgpu_sdma_destroy_inst_ctx(adev, true);
|
||||
|
||||
kfree(adev->sdma.ip_dump);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1676,7 +1736,49 @@ static void sdma_v5_2_ring_end_use(struct amdgpu_ring *ring)
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
}
|
||||
|
||||
const struct amd_ip_funcs sdma_v5_2_ip_funcs = {
|
||||
static void sdma_v5_2_print_ip_state(void *handle, struct drm_printer *p)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int i, j;
|
||||
uint32_t reg_count = ARRAY_SIZE(sdma_reg_list_5_2);
|
||||
uint32_t instance_offset;
|
||||
|
||||
if (!adev->sdma.ip_dump)
|
||||
return;
|
||||
|
||||
drm_printf(p, "num_instances:%d\n", adev->sdma.num_instances);
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
instance_offset = i * reg_count;
|
||||
drm_printf(p, "\nInstance:%d\n", i);
|
||||
|
||||
for (j = 0; j < reg_count; j++)
|
||||
drm_printf(p, "%-50s \t 0x%08x\n", sdma_reg_list_5_2[j].reg_name,
|
||||
adev->sdma.ip_dump[instance_offset + j]);
|
||||
}
|
||||
}
|
||||
|
||||
static void sdma_v5_2_dump_ip_state(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int i, j;
|
||||
uint32_t instance_offset;
|
||||
uint32_t reg_count = ARRAY_SIZE(sdma_reg_list_5_2);
|
||||
|
||||
if (!adev->sdma.ip_dump)
|
||||
return;
|
||||
|
||||
amdgpu_gfx_off_ctrl(adev, false);
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
instance_offset = i * reg_count;
|
||||
for (j = 0; j < reg_count; j++)
|
||||
adev->sdma.ip_dump[instance_offset + j] =
|
||||
RREG32(sdma_v5_2_get_reg_offset(adev, i,
|
||||
sdma_reg_list_5_2[j].reg_offset));
|
||||
}
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
}
|
||||
|
||||
static const struct amd_ip_funcs sdma_v5_2_ip_funcs = {
|
||||
.name = "sdma_v5_2",
|
||||
.early_init = sdma_v5_2_early_init,
|
||||
.late_init = NULL,
|
||||
@ -1692,6 +1794,8 @@ const struct amd_ip_funcs sdma_v5_2_ip_funcs = {
|
||||
.set_clockgating_state = sdma_v5_2_set_clockgating_state,
|
||||
.set_powergating_state = sdma_v5_2_set_powergating_state,
|
||||
.get_clockgating_state = sdma_v5_2_get_clockgating_state,
|
||||
.dump_ip_state = sdma_v5_2_dump_ip_state,
|
||||
.print_ip_state = sdma_v5_2_print_ip_state,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ring_funcs sdma_v5_2_ring_funcs = {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user