mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 18:13:41 +02:00
amdgpu:
- Fix spelling typos - RAS updates - VCN 5.0.1 updates - SubVP fixes - DCN 4.0.1 fixes - MSO DPCD fixes - DIO encoder refactor - PCON fixes - Misc cleanups - DMCUB fixes - USB4 DP fixes - DM cleanups - Backlight cleanups and fixes - Support platform backlight curves - Misc code cleanups - SMU 14 fixes - JPEG 4.0.3 reset updates - SR-IOV fixes - SVM fixes - GC 12 DCC fixes - DC DCE 6.x fix - Hiberation fix amdkfd: - Fix possible NULL pointer in queue validation - Remove unnecessary CP domain validation - SDMA queue reset support - Add per process flags radeon: - Fix spelling typos - RS400 hyperZ fix UAPI: - Add KFD per process flags for setting precision Proposed user space:2a64fa5e06-----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCZ8tfmgAKCRC93/aFa7yZ 2CmkAP4xoy09aHecz6WOdNN9VBJiSMSZ3UOyBL9Ll2i5nI3YegEA7Co+AmQpXOPn HKeD6Vy1tt1XE/Liuur5dbLUKsVYSAI= =IQ45 -----END PGP SIGNATURE----- Merge tag 'amd-drm-next-6.15-2025-03-07' of https://gitlab.freedesktop.org/agd5f/linux into drm-next amdgpu: - Fix spelling typos - RAS updates - VCN 5.0.1 updates - SubVP fixes - DCN 4.0.1 fixes - MSO DPCD fixes - DIO encoder refactor - PCON fixes - Misc cleanups - DMCUB fixes - USB4 DP fixes - DM cleanups - Backlight cleanups and fixes - Support platform backlight curves - Misc code cleanups - SMU 14 fixes - JPEG 4.0.3 reset updates - SR-IOV fixes - SVM fixes - GC 12 DCC fixes - DC DCE 6.x fix - Hiberation fix amdkfd: - Fix possible NULL pointer in queue validation - Remove unnecessary CP domain validation - SDMA queue reset support - Add per process flags radeon: - Fix spelling typos - RS400 hyperZ fix UAPI: - Add KFD per process flags for setting precision Proposed user space:2a64fa5e06Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20250307211051.1880472-1-alexander.deucher@amd.com
This commit is contained in:
commit
236f475d29
2
.mailmap
2
.mailmap
|
|
@ -614,6 +614,8 @@ Richard Leitner <richard.leitner@linux.dev> <me@g0hl1n.net>
|
|||
Richard Leitner <richard.leitner@linux.dev> <richard.leitner@skidata.com>
|
||||
Robert Foss <rfoss@kernel.org> <robert.foss@linaro.org>
|
||||
Rocky Liao <quic_rjliao@quicinc.com> <rjliao@codeaurora.org>
|
||||
Rodrigo Siqueira <siqueira@igalia.com> <rodrigosiqueiramelo@gmail.com>
|
||||
Rodrigo Siqueira <siqueira@igalia.com> <Rodrigo.Siqueira@amd.com>
|
||||
Roman Gushchin <roman.gushchin@linux.dev> <guro@fb.com>
|
||||
Roman Gushchin <roman.gushchin@linux.dev> <guroan@gmail.com>
|
||||
Roman Gushchin <roman.gushchin@linux.dev> <klamm@yandex-team.ru>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ we have a dedicated glossary for Display Core at
|
|||
The number of CUs that are active on the system. The number of active
|
||||
CUs may be less than SE * SH * CU depending on the board configuration.
|
||||
|
||||
CE
|
||||
Constant Engine
|
||||
|
||||
CP
|
||||
Command Processor
|
||||
|
||||
|
|
@ -68,6 +71,9 @@ we have a dedicated glossary for Display Core at
|
|||
IB
|
||||
Indirect Buffer
|
||||
|
||||
IMU
|
||||
Integrated Management Unit (Power Management support)
|
||||
|
||||
IP
|
||||
Intellectual Property blocks
|
||||
|
||||
|
|
@ -80,6 +86,12 @@ we have a dedicated glossary for Display Core at
|
|||
KIQ
|
||||
Kernel Interface Queue
|
||||
|
||||
MC
|
||||
Memory Controller
|
||||
|
||||
ME
|
||||
MicroEngine (Graphics)
|
||||
|
||||
MEC
|
||||
MicroEngine Compute
|
||||
|
||||
|
|
@ -92,6 +104,9 @@ we have a dedicated glossary for Display Core at
|
|||
MQD
|
||||
Memory Queue Descriptor
|
||||
|
||||
PFP
|
||||
Pre-Fetch Parser (Graphics)
|
||||
|
||||
PPLib
|
||||
PowerPlay Library - PowerPlay is the power management component.
|
||||
|
||||
|
|
@ -99,7 +114,10 @@ we have a dedicated glossary for Display Core at
|
|||
Platform Security Processor
|
||||
|
||||
RLC
|
||||
RunList Controller
|
||||
RunList Controller. This name is a remnant of past ages and doesn't have
|
||||
much meaning today. It's a group of general-purpose helper engines for
|
||||
the GFX block. It's involved in GFX power management and SR-IOV, among
|
||||
other things.
|
||||
|
||||
SDMA
|
||||
System DMA
|
||||
|
|
@ -110,14 +128,35 @@ we have a dedicated glossary for Display Core at
|
|||
SH
|
||||
SHader array
|
||||
|
||||
SMU
|
||||
System Management Unit
|
||||
SMU/SMC
|
||||
System Management Unit / System Management Controller
|
||||
|
||||
SRLC
|
||||
Save/Restore List Control
|
||||
|
||||
SRLG
|
||||
Save/Restore List GPM_MEM
|
||||
|
||||
SRLS
|
||||
Save/Restore List SRM_MEM
|
||||
|
||||
SS
|
||||
Spread Spectrum
|
||||
|
||||
TA
|
||||
Trusted Application
|
||||
|
||||
TOC
|
||||
Table of Contents
|
||||
|
||||
UVD
|
||||
Unified Video Decoder
|
||||
|
||||
VCE
|
||||
Video Compression Engine
|
||||
|
||||
VCN
|
||||
Video Codec Next
|
||||
|
||||
VPE
|
||||
Video Processing Engine
|
||||
|
|
|
|||
|
|
@ -167,9 +167,6 @@ consider asking in the amdgfx and update this page.
|
|||
MALL
|
||||
Memory Access at Last Level
|
||||
|
||||
MC
|
||||
Memory Controller
|
||||
|
||||
MPC/MPCC
|
||||
Multiple pipes and plane combine
|
||||
|
||||
|
|
@ -232,6 +229,3 @@ consider asking in the amdgfx and update this page.
|
|||
|
||||
VRR
|
||||
Variable Refresh Rate
|
||||
|
||||
UVD
|
||||
Unified Video Decoder
|
||||
|
|
|
|||
|
|
@ -1046,14 +1046,14 @@ F: drivers/crypto/ccp/hsti.*
|
|||
AMD DISPLAY CORE
|
||||
M: Harry Wentland <harry.wentland@amd.com>
|
||||
M: Leo Li <sunpeng.li@amd.com>
|
||||
M: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
|
||||
R: Rodrigo Siqueira <siqueira@igalia.com>
|
||||
L: amd-gfx@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git https://gitlab.freedesktop.org/agd5f/linux.git
|
||||
F: drivers/gpu/drm/amd/display/
|
||||
|
||||
AMD DISPLAY CORE - DML
|
||||
M: Chaitanya Dhere <chaitanya.dhere@amd.com>
|
||||
M: Austin Zheng <austin.zheng@amd.com>
|
||||
M: Jun Lei <jun.lei@amd.com>
|
||||
S: Supported
|
||||
F: drivers/gpu/drm/amd/display/dc/dml/
|
||||
|
|
@ -19681,7 +19681,6 @@ F: drivers/net/wireless/quantenna
|
|||
RADEON and AMDGPU DRM DRIVERS
|
||||
M: Alex Deucher <alexander.deucher@amd.com>
|
||||
M: Christian König <christian.koenig@amd.com>
|
||||
M: Xinhui Pan <Xinhui.Pan@amd.com>
|
||||
L: amd-gfx@lists.freedesktop.org
|
||||
S: Supported
|
||||
B: https://gitlab.freedesktop.org/drm/amd/-/issues
|
||||
|
|
|
|||
|
|
@ -1192,6 +1192,7 @@ struct amdgpu_device {
|
|||
bool debug_use_vram_fw_buf;
|
||||
bool debug_enable_ras_aca;
|
||||
bool debug_exp_resets;
|
||||
bool debug_disable_gpu_ring_reset;
|
||||
|
||||
bool enforce_isolation[MAX_XCP];
|
||||
/* Added this mutex for cleaner shader isolation between GFX and compute processes */
|
||||
|
|
|
|||
|
|
@ -392,6 +392,9 @@ static void aca_banks_generate_cper(struct amdgpu_device *adev,
|
|||
struct aca_bank_node *node;
|
||||
struct aca_bank *bank;
|
||||
|
||||
if (!adev->cper.enabled)
|
||||
return;
|
||||
|
||||
if (!banks || !count) {
|
||||
dev_warn(adev->dev, "fail to generate cper records\n");
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -76,6 +76,12 @@ struct ras_query_context;
|
|||
#define mmSMNAID_XCD1_MCA_SMU 0x38430400 /* SMN AID XCD1 */
|
||||
#define mmSMNXCD_XCD0_MCA_SMU 0x40430400 /* SMN XCD XCD0 */
|
||||
|
||||
#define ACA_BANK_ERR_CE_DE_DECODE(bank) \
|
||||
((ACA_REG__STATUS__POISON((bank)->regs[ACA_REG_IDX_STATUS]) || \
|
||||
ACA_REG__STATUS__DEFERRED((bank)->regs[ACA_REG_IDX_STATUS])) ? \
|
||||
ACA_ERROR_TYPE_DEFERRED : \
|
||||
ACA_ERROR_TYPE_CE)
|
||||
|
||||
enum aca_reg_idx {
|
||||
ACA_REG_IDX_CTL = 0,
|
||||
ACA_REG_IDX_STATUS = 1,
|
||||
|
|
|
|||
|
|
@ -579,7 +579,7 @@ static int acp_resume(struct amdgpu_ip_block *ip_block)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool acp_is_idle(void *handle)
|
||||
static bool acp_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -394,6 +394,10 @@ static int amdgpu_atif_query_backlight_caps(struct amdgpu_atif *atif)
|
|||
characteristics.max_input_signal;
|
||||
atif->backlight_caps.ac_level = characteristics.ac_level;
|
||||
atif->backlight_caps.dc_level = characteristics.dc_level;
|
||||
atif->backlight_caps.data_points = characteristics.number_of_points;
|
||||
memcpy(atif->backlight_caps.luminance_data,
|
||||
characteristics.data_points,
|
||||
sizeof(atif->backlight_caps.luminance_data));
|
||||
out:
|
||||
kfree(info);
|
||||
return err;
|
||||
|
|
@ -1277,11 +1281,7 @@ void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps)
|
|||
{
|
||||
struct amdgpu_atif *atif = &amdgpu_acpi_priv.atif;
|
||||
|
||||
caps->caps_valid = atif->backlight_caps.caps_valid;
|
||||
caps->min_input_signal = atif->backlight_caps.min_input_signal;
|
||||
caps->max_input_signal = atif->backlight_caps.max_input_signal;
|
||||
caps->ac_level = atif->backlight_caps.ac_level;
|
||||
caps->dc_level = atif->backlight_caps.dc_level;
|
||||
memcpy(caps, &atif->backlight_caps, sizeof(*caps));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -555,48 +555,6 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
|
|||
return r;
|
||||
}
|
||||
|
||||
uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct amdgpu_device *dst,
|
||||
struct amdgpu_device *src)
|
||||
{
|
||||
struct amdgpu_device *peer_adev = src;
|
||||
struct amdgpu_device *adev = dst;
|
||||
int ret = amdgpu_xgmi_get_hops_count(adev, peer_adev);
|
||||
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("amdgpu: failed to get xgmi hops count between node %d and %d. ret = %d\n",
|
||||
adev->gmc.xgmi.physical_node_id,
|
||||
peer_adev->gmc.xgmi.physical_node_id, ret);
|
||||
ret = 0;
|
||||
}
|
||||
return (uint8_t)ret;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct amdgpu_device *dst,
|
||||
struct amdgpu_device *src,
|
||||
bool is_min)
|
||||
{
|
||||
struct amdgpu_device *adev = dst, *peer_adev;
|
||||
int num_links;
|
||||
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(9, 4, 2))
|
||||
return 0;
|
||||
|
||||
if (src)
|
||||
peer_adev = src;
|
||||
|
||||
/* num links returns 0 for indirect peers since indirect route is unknown. */
|
||||
num_links = is_min ? 1 : amdgpu_xgmi_get_num_links(adev, peer_adev);
|
||||
if (num_links < 0) {
|
||||
DRM_ERROR("amdgpu: failed to get xgmi num links between node %d and %d. ret = %d\n",
|
||||
adev->gmc.xgmi.physical_node_id,
|
||||
peer_adev->gmc.xgmi.physical_node_id, num_links);
|
||||
num_links = 0;
|
||||
}
|
||||
|
||||
/* Aldebaran xGMI DPM is defeatured so assume x16 x 25Gbps for bandwidth. */
|
||||
return (num_links * 16 * 25000)/BITS_PER_BYTE;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_min)
|
||||
{
|
||||
int num_lanes_shift = (is_min ? ffs(adev->pm.pcie_mlw_mask) :
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ int kfd_debugfs_kfd_mem_limits(struct seq_file *m, void *data);
|
|||
#if IS_ENABLED(CONFIG_HSA_AMD)
|
||||
bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm);
|
||||
struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f);
|
||||
int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo);
|
||||
void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo);
|
||||
int amdgpu_amdkfd_evict_userptr(struct mmu_interval_notifier *mni,
|
||||
unsigned long cur_seq, struct kgd_mem *mem);
|
||||
int amdgpu_amdkfd_bo_validate_and_fence(struct amdgpu_bo *bo,
|
||||
|
|
@ -213,9 +213,8 @@ struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f)
|
|||
}
|
||||
|
||||
static inline
|
||||
int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo)
|
||||
void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
|
|
@ -255,11 +254,6 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
|
|||
uint64_t *bo_size, void *metadata_buffer,
|
||||
size_t buffer_size, uint32_t *metadata_size,
|
||||
uint32_t *flags, int8_t *xcp_id);
|
||||
uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct amdgpu_device *dst,
|
||||
struct amdgpu_device *src);
|
||||
int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct amdgpu_device *dst,
|
||||
struct amdgpu_device *src,
|
||||
bool is_min);
|
||||
int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_min);
|
||||
int amdgpu_amdkfd_send_close_event_drain_irq(struct amdgpu_device *adev,
|
||||
uint32_t *payload);
|
||||
|
|
|
|||
|
|
@ -193,4 +193,5 @@ const struct kfd2kgd_calls aldebaran_kfd2kgd = {
|
|||
.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,
|
||||
.hqd_sdma_get_doorbell = kgd_gfx_v9_hqd_sdma_get_doorbell
|
||||
};
|
||||
|
|
|
|||
|
|
@ -419,5 +419,6 @@ const struct kfd2kgd_calls arcturus_kfd2kgd = {
|
|||
.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
|
||||
.hqd_reset = kgd_gfx_v9_hqd_reset,
|
||||
.hqd_sdma_get_doorbell = kgd_gfx_v9_hqd_sdma_get_doorbell
|
||||
};
|
||||
|
|
|
|||
|
|
@ -509,6 +509,17 @@ static uint32_t kgd_gfx_v9_4_3_clear_address_watch(struct amdgpu_device *adev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t kgd_gfx_v9_4_3_hqd_sdma_get_doorbell(struct amdgpu_device *adev,
|
||||
int engine, int queue)
|
||||
{
|
||||
uint32_t reg_offset = get_sdma_rlc_reg_offset(adev, engine, queue);
|
||||
uint32_t status = RREG32(regSDMA_RLC0_CONTEXT_STATUS + reg_offset);
|
||||
uint32_t doorbell_off = RREG32(regSDMA_RLC0_DOORBELL_OFFSET + reg_offset);
|
||||
bool is_active = !!REG_GET_FIELD(status, SDMA_RLC0_CONTEXT_STATUS, SELECTED);
|
||||
|
||||
return is_active ? doorbell_off >> 2 : 0;
|
||||
}
|
||||
|
||||
const struct kfd2kgd_calls gc_9_4_3_kfd2kgd = {
|
||||
.program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings,
|
||||
.set_pasid_vmid_mapping = kgd_gfx_v9_4_3_set_pasid_vmid_mapping,
|
||||
|
|
@ -543,5 +554,6 @@ const struct kfd2kgd_calls gc_9_4_3_kfd2kgd = {
|
|||
.set_address_watch = kgd_gfx_v9_4_3_set_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
|
||||
.hqd_reset = kgd_gfx_v9_hqd_reset,
|
||||
.hqd_sdma_get_doorbell = kgd_gfx_v9_4_3_hqd_sdma_get_doorbell
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1084,6 +1084,12 @@ uint64_t kgd_gfx_v10_hqd_reset(struct amdgpu_device *adev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t kgd_gfx_v10_hqd_sdma_get_doorbell(struct amdgpu_device *adev,
|
||||
int engine, int queue)
|
||||
{
|
||||
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,
|
||||
|
|
@ -1112,5 +1118,6 @@ const struct kfd2kgd_calls gfx_v10_kfd2kgd = {
|
|||
.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
|
||||
.hqd_reset = kgd_gfx_v10_hqd_reset,
|
||||
.hqd_sdma_get_doorbell = kgd_gfx_v10_hqd_sdma_get_doorbell
|
||||
};
|
||||
|
|
|
|||
|
|
@ -65,3 +65,5 @@ uint64_t kgd_gfx_v10_hqd_reset(struct amdgpu_device *adev,
|
|||
uint32_t queue_id,
|
||||
uint32_t inst,
|
||||
unsigned int utimeout);
|
||||
uint32_t kgd_gfx_v10_hqd_sdma_get_doorbell(struct amdgpu_device *adev,
|
||||
int engine, int queue);
|
||||
|
|
|
|||
|
|
@ -682,5 +682,6 @@ const struct kfd2kgd_calls gfx_v10_3_kfd2kgd = {
|
|||
.set_address_watch = kgd_gfx_v10_set_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
|
||||
.hqd_reset = kgd_gfx_v10_hqd_reset,
|
||||
.hqd_sdma_get_doorbell = kgd_gfx_v10_hqd_sdma_get_doorbell
|
||||
};
|
||||
|
|
|
|||
|
|
@ -800,6 +800,12 @@ static uint64_t kgd_gfx_v11_hqd_reset(struct amdgpu_device *adev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t kgd_gfx_v11_hqd_sdma_get_doorbell(struct amdgpu_device *adev,
|
||||
int engine, int queue)
|
||||
{
|
||||
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,
|
||||
|
|
@ -824,5 +830,6 @@ const struct kfd2kgd_calls gfx_v11_kfd2kgd = {
|
|||
.set_address_watch = kgd_gfx_v11_set_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
|
||||
.hqd_reset = kgd_gfx_v11_hqd_reset,
|
||||
.hqd_sdma_get_doorbell = kgd_gfx_v11_hqd_sdma_get_doorbell
|
||||
};
|
||||
|
|
|
|||
|
|
@ -361,6 +361,12 @@ static uint32_t kgd_gfx_v12_clear_address_watch(struct amdgpu_device *adev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t kgd_gfx_v12_hqd_sdma_get_doorbell(struct amdgpu_device *adev,
|
||||
int engine, int queue)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct kfd2kgd_calls gfx_v12_kfd2kgd = {
|
||||
.init_interrupts = init_interrupts_v12,
|
||||
.hqd_dump = hqd_dump_v12,
|
||||
|
|
@ -374,4 +380,5 @@ const struct kfd2kgd_calls gfx_v12_kfd2kgd = {
|
|||
.set_wave_launch_mode = kgd_gfx_v12_set_wave_launch_mode,
|
||||
.set_address_watch = kgd_gfx_v12_set_address_watch,
|
||||
.clear_address_watch = kgd_gfx_v12_clear_address_watch,
|
||||
.hqd_sdma_get_doorbell = kgd_gfx_v12_hqd_sdma_get_doorbell
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1131,9 +1131,6 @@ uint64_t kgd_gfx_v9_hqd_get_pq_addr(struct amdgpu_device *adev,
|
|||
uint32_t low, high;
|
||||
uint64_t queue_addr = 0;
|
||||
|
||||
if (!amdgpu_gpu_recovery)
|
||||
return 0;
|
||||
|
||||
kgd_gfx_v9_acquire_queue(adev, pipe_id, queue_id, inst);
|
||||
amdgpu_gfx_rlc_enter_safe_mode(adev, inst);
|
||||
|
||||
|
|
@ -1182,9 +1179,6 @@ uint64_t kgd_gfx_v9_hqd_reset(struct amdgpu_device *adev,
|
|||
uint32_t low, high, pipe_reset_data = 0;
|
||||
uint64_t queue_addr = 0;
|
||||
|
||||
if (!amdgpu_gpu_recovery)
|
||||
return 0;
|
||||
|
||||
kgd_gfx_v9_acquire_queue(adev, pipe_id, queue_id, inst);
|
||||
amdgpu_gfx_rlc_enter_safe_mode(adev, inst);
|
||||
|
||||
|
|
@ -1229,6 +1223,13 @@ uint64_t kgd_gfx_v9_hqd_reset(struct amdgpu_device *adev,
|
|||
return queue_addr;
|
||||
}
|
||||
|
||||
uint32_t kgd_gfx_v9_hqd_sdma_get_doorbell(struct amdgpu_device *adev,
|
||||
int engine, int queue)
|
||||
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
@ -1258,5 +1259,6 @@ const struct kfd2kgd_calls gfx_v9_kfd2kgd = {
|
|||
.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
|
||||
.hqd_reset = kgd_gfx_v9_hqd_reset,
|
||||
.hqd_sdma_get_doorbell = kgd_gfx_v9_hqd_sdma_get_doorbell
|
||||
};
|
||||
|
|
|
|||
|
|
@ -111,3 +111,5 @@ uint64_t kgd_gfx_v9_hqd_reset(struct amdgpu_device *adev,
|
|||
uint32_t queue_id,
|
||||
uint32_t inst,
|
||||
unsigned int utimeout);
|
||||
uint32_t kgd_gfx_v9_hqd_sdma_get_doorbell(struct amdgpu_device *adev,
|
||||
int engine, int queue);
|
||||
|
|
|
|||
|
|
@ -370,40 +370,32 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo)
|
||||
/**
|
||||
* amdgpu_amdkfd_remove_all_eviction_fences - Remove all eviction fences
|
||||
* @bo: the BO where to remove the evictions fences from.
|
||||
*
|
||||
* This functions should only be used on release when all references to the BO
|
||||
* are already dropped. We remove the eviction fence from the private copy of
|
||||
* the dma_resv object here since that is what is used during release to
|
||||
* determine of the BO is idle or not.
|
||||
*/
|
||||
void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo)
|
||||
{
|
||||
struct amdgpu_bo *root = bo;
|
||||
struct amdgpu_vm_bo_base *vm_bo;
|
||||
struct amdgpu_vm *vm;
|
||||
struct amdkfd_process_info *info;
|
||||
struct amdgpu_amdkfd_fence *ef;
|
||||
int ret;
|
||||
struct dma_resv *resv = &bo->tbo.base._resv;
|
||||
struct dma_fence *fence, *stub;
|
||||
struct dma_resv_iter cursor;
|
||||
|
||||
/* we can always get vm_bo from root PD bo.*/
|
||||
while (root->parent)
|
||||
root = root->parent;
|
||||
dma_resv_assert_held(resv);
|
||||
|
||||
vm_bo = root->vm_bo;
|
||||
if (!vm_bo)
|
||||
return 0;
|
||||
stub = dma_fence_get_stub();
|
||||
dma_resv_for_each_fence(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP, fence) {
|
||||
if (!to_amdgpu_amdkfd_fence(fence))
|
||||
continue;
|
||||
|
||||
vm = vm_bo->vm;
|
||||
if (!vm)
|
||||
return 0;
|
||||
|
||||
info = vm->process_info;
|
||||
if (!info || !info->eviction_fence)
|
||||
return 0;
|
||||
|
||||
ef = container_of(dma_fence_get(&info->eviction_fence->base),
|
||||
struct amdgpu_amdkfd_fence, base);
|
||||
|
||||
BUG_ON(!dma_resv_trylock(bo->tbo.base.resv));
|
||||
ret = amdgpu_amdkfd_remove_eviction_fence(bo, ef);
|
||||
dma_resv_unlock(bo->tbo.base.resv);
|
||||
|
||||
dma_fence_put(&ef->base);
|
||||
return ret;
|
||||
dma_resv_replace_fences(resv, fence->context, stub,
|
||||
DMA_RESV_USAGE_BOOKKEEP);
|
||||
}
|
||||
dma_fence_put(stub);
|
||||
}
|
||||
|
||||
static int amdgpu_amdkfd_bo_validate(struct amdgpu_bo *bo, uint32_t domain,
|
||||
|
|
@ -603,12 +595,6 @@ kfd_mem_dmamap_dmabuf(struct kfd_mem_attachment *attachment)
|
|||
{
|
||||
struct ttm_operation_ctx ctx = {.interruptible = true};
|
||||
struct amdgpu_bo *bo = attachment->bo_va->base.bo;
|
||||
int ret;
|
||||
|
||||
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU);
|
||||
ret = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_GTT);
|
||||
return ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ void amdgpu_cper_entry_fill_hdr(struct amdgpu_device *adev,
|
|||
enum amdgpu_cper_type type,
|
||||
enum cper_error_severity sev)
|
||||
{
|
||||
char record_id[16];
|
||||
|
||||
hdr->signature[0] = 'C';
|
||||
hdr->signature[1] = 'P';
|
||||
hdr->signature[2] = 'E';
|
||||
|
|
@ -71,7 +73,13 @@ void amdgpu_cper_entry_fill_hdr(struct amdgpu_device *adev,
|
|||
|
||||
amdgpu_cper_get_timestamp(&hdr->timestamp);
|
||||
|
||||
snprintf(hdr->record_id, 8, "%d", atomic_inc_return(&adev->cper.unique_id));
|
||||
snprintf(record_id, 9, "%d:%X",
|
||||
(adev->smuio.funcs && adev->smuio.funcs->get_socket_id) ?
|
||||
adev->smuio.funcs->get_socket_id(adev) :
|
||||
0,
|
||||
atomic_inc_return(&adev->cper.unique_id));
|
||||
memcpy(hdr->record_id, record_id, 8);
|
||||
|
||||
snprintf(hdr->platform_id, 16, "0x%04X:0x%04X",
|
||||
adev->pdev->vendor, adev->pdev->device);
|
||||
/* pmfw version should be part of creator_id according to CPER spec */
|
||||
|
|
@ -112,18 +120,15 @@ static int amdgpu_cper_entry_fill_section_desc(struct amdgpu_device *adev,
|
|||
section_desc->revision_major = CPER_SEC_MAJOR_REV_22;
|
||||
section_desc->sec_offset = section_offset;
|
||||
section_desc->sec_length = section_length;
|
||||
section_desc->valid_bits.fru_id = 1;
|
||||
section_desc->valid_bits.fru_text = 1;
|
||||
section_desc->flag_bits.primary = 1;
|
||||
section_desc->severity = sev;
|
||||
section_desc->sec_type = sec_type;
|
||||
|
||||
if (adev->smuio.funcs &&
|
||||
adev->smuio.funcs->get_socket_id)
|
||||
snprintf(section_desc->fru_text, 20, "OAM%d",
|
||||
adev->smuio.funcs->get_socket_id(adev));
|
||||
/* TODO: fru_id is 16 bytes in CPER spec, but driver defines it as 20 bytes */
|
||||
snprintf(section_desc->fru_id, 16, "%llx", adev->unique_id);
|
||||
snprintf(section_desc->fru_text, 20, "OAM%d",
|
||||
(adev->smuio.funcs && adev->smuio.funcs->get_socket_id) ?
|
||||
adev->smuio.funcs->get_socket_id(adev) :
|
||||
0);
|
||||
|
||||
if (bp_threshold)
|
||||
section_desc->flag_bits.exceed_err_threshold = 1;
|
||||
|
|
@ -304,6 +309,7 @@ int amdgpu_cper_generate_ue_record(struct amdgpu_device *adev,
|
|||
return ret;
|
||||
|
||||
amdgpu_cper_ring_write(ring, fatal, fatal->record_length);
|
||||
kfree(fatal);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -326,6 +332,7 @@ int amdgpu_cper_generate_bp_threshold_record(struct amdgpu_device *adev)
|
|||
return ret;
|
||||
|
||||
amdgpu_cper_ring_write(ring, bp_threshold, bp_threshold->record_length);
|
||||
kfree(bp_threshold);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -376,7 +383,7 @@ int amdgpu_cper_generate_ce_records(struct amdgpu_device *adev,
|
|||
|
||||
amdgpu_cper_entry_fill_hdr(adev, corrected, AMDGPU_CPER_TYPE_RUNTIME, sev);
|
||||
|
||||
/* Combine CE and UE in cper record */
|
||||
/* Combine CE and DE in cper record */
|
||||
list_for_each_entry(node, &banks->list, node) {
|
||||
bank = &node->bank;
|
||||
reg_data[CPER_ACA_REG_CTL_LO] = lower_32_bits(bank->regs[ACA_REG_IDX_CTL]);
|
||||
|
|
@ -402,6 +409,7 @@ int amdgpu_cper_generate_ce_records(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
amdgpu_cper_ring_write(ring, corrected, corrected->record_length);
|
||||
kfree(corrected);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -538,15 +546,23 @@ static int amdgpu_cper_ring_init(struct amdgpu_device *adev)
|
|||
|
||||
int amdgpu_cper_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!amdgpu_aca_is_enabled(adev))
|
||||
return 0;
|
||||
|
||||
r = amdgpu_cper_ring_init(adev);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "failed to initialize cper ring, r = %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
mutex_init(&adev->cper.cper_lock);
|
||||
|
||||
adev->cper.enabled = true;
|
||||
adev->cper.max_count = CPER_MAX_ALLOWED_COUNT;
|
||||
|
||||
return amdgpu_cper_ring_init(adev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_cper_fini(struct amdgpu_device *adev)
|
||||
|
|
|
|||
|
|
@ -364,5 +364,9 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
|
|||
|
||||
dev_coredumpm(dev->dev, THIS_MODULE, coredump, 0, GFP_NOWAIT,
|
||||
amdgpu_devcoredump_read, amdgpu_devcoredump_free);
|
||||
|
||||
drm_info(dev, "AMDGPU device coredump file has been created\n");
|
||||
drm_info(dev, "Check your /sys/class/drm/card%d/device/devcoredump/data\n",
|
||||
dev->primary->index);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1662,6 +1662,13 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
|
|||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
/* resizing on Dell G5 SE platforms causes problems with runtime pm */
|
||||
if ((amdgpu_runtime_pm != 0) &&
|
||||
adev->pdev->vendor == PCI_VENDOR_ID_ATI &&
|
||||
adev->pdev->device == 0x731f &&
|
||||
adev->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
|
||||
return 0;
|
||||
|
||||
/* PCI_EXT_CAP_ID_VNDR extended capability is located at 0x100 */
|
||||
if (!pci_find_ext_capability(adev->pdev, PCI_EXT_CAP_ID_VNDR))
|
||||
DRM_WARN("System can't access extended configuration space, please check!!\n");
|
||||
|
|
@ -3098,7 +3105,8 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
|||
|
||||
amdgpu_fru_get_product_info(adev);
|
||||
|
||||
r = amdgpu_cper_init(adev);
|
||||
if (!amdgpu_sriov_vf(adev) || amdgpu_sriov_ras_cper_en(adev))
|
||||
r = amdgpu_cper_init(adev);
|
||||
|
||||
init_failed:
|
||||
|
||||
|
|
@ -4332,10 +4340,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||
* for throttling interrupt) = 60 seconds.
|
||||
*/
|
||||
ratelimit_state_init(&adev->throttling_logging_rs, (60 - 1) * HZ, 1);
|
||||
ratelimit_state_init(&adev->virt.ras_telemetry_rs, 5 * HZ, 1);
|
||||
|
||||
ratelimit_set_flags(&adev->throttling_logging_rs, RATELIMIT_MSG_ON_RELEASE);
|
||||
ratelimit_set_flags(&adev->virt.ras_telemetry_rs, RATELIMIT_MSG_ON_RELEASE);
|
||||
|
||||
/* Registers mapping */
|
||||
/* TODO: block userspace mapping of io register */
|
||||
|
|
@ -4367,7 +4373,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||
return -ENOMEM;
|
||||
|
||||
/* detect hw virtualization here */
|
||||
amdgpu_detect_virtualization(adev);
|
||||
amdgpu_virt_init(adev);
|
||||
|
||||
amdgpu_device_get_pcie_info(adev);
|
||||
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ enum AMDGPU_DEBUG_MASK {
|
|||
AMDGPU_DEBUG_USE_VRAM_FW_BUF = BIT(3),
|
||||
AMDGPU_DEBUG_ENABLE_RAS_ACA = BIT(4),
|
||||
AMDGPU_DEBUG_ENABLE_EXP_RESETS = BIT(5),
|
||||
AMDGPU_DEBUG_DISABLE_GPU_RING_RESET = BIT(6),
|
||||
};
|
||||
|
||||
unsigned int amdgpu_vram_limit = UINT_MAX;
|
||||
|
|
@ -2223,6 +2224,11 @@ static void amdgpu_init_debug_options(struct amdgpu_device *adev)
|
|||
pr_info("debug: enable experimental reset features\n");
|
||||
adev->debug_exp_resets = true;
|
||||
}
|
||||
|
||||
if (amdgpu_debug_mask & AMDGPU_DEBUG_DISABLE_GPU_RING_RESET) {
|
||||
pr_info("debug: ring reset disabled\n");
|
||||
adev->debug_disable_gpu_ring_reset = true;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long amdgpu_fix_asic_type(struct pci_dev *pdev, unsigned long flags)
|
||||
|
|
@ -2557,7 +2563,6 @@ static int amdgpu_pmops_freeze(struct device *dev)
|
|||
int r;
|
||||
|
||||
r = amdgpu_device_suspend(drm_dev, true);
|
||||
adev->in_s4 = false;
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
|
@ -2569,8 +2574,13 @@ static int amdgpu_pmops_freeze(struct device *dev)
|
|||
static int amdgpu_pmops_thaw(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(drm_dev);
|
||||
int r;
|
||||
|
||||
return amdgpu_device_resume(drm_dev, true);
|
||||
r = amdgpu_device_resume(drm_dev, true);
|
||||
adev->in_s4 = false;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int amdgpu_pmops_poweroff(struct device *dev)
|
||||
|
|
@ -2583,6 +2593,9 @@ static int amdgpu_pmops_poweroff(struct device *dev)
|
|||
static int amdgpu_pmops_restore(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(drm_dev);
|
||||
|
||||
adev->in_s4 = false;
|
||||
|
||||
return amdgpu_device_resume(drm_dev, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#define FRU_EEPROM_MADDR_6 0x60000
|
||||
#define FRU_EEPROM_MADDR_8 0x80000
|
||||
#define FRU_EEPROM_MADDR_INV 0xFFFFF
|
||||
|
||||
static bool is_fru_eeprom_supported(struct amdgpu_device *adev, u32 *fru_addr)
|
||||
{
|
||||
|
|
@ -104,6 +105,10 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev, u32 *fru_addr)
|
|||
if (fru_addr)
|
||||
*fru_addr = FRU_EEPROM_MADDR_8;
|
||||
return true;
|
||||
case IP_VERSION(13, 0, 12):
|
||||
if (fru_addr)
|
||||
*fru_addr = FRU_EEPROM_MADDR_INV;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
@ -120,6 +125,10 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
|||
if (!is_fru_eeprom_supported(adev, &fru_addr))
|
||||
return 0;
|
||||
|
||||
/* FRU data avaialble, but no direct EEPROM access */
|
||||
if (fru_addr == FRU_EEPROM_MADDR_INV)
|
||||
return 0;
|
||||
|
||||
if (!adev->fru_info) {
|
||||
adev->fru_info = kzalloc(sizeof(*adev->fru_info), GFP_KERNEL);
|
||||
if (!adev->fru_info)
|
||||
|
|
|
|||
|
|
@ -1665,24 +1665,19 @@ static ssize_t amdgpu_gfx_set_enforce_isolation(struct device *dev,
|
|||
}
|
||||
|
||||
mutex_lock(&adev->enforce_isolation_mutex);
|
||||
|
||||
for (i = 0; i < num_partitions; i++) {
|
||||
if (adev->enforce_isolation[i] && !partition_values[i]) {
|
||||
if (adev->enforce_isolation[i] && !partition_values[i])
|
||||
/* Going from enabled to disabled */
|
||||
amdgpu_vmid_free_reserved(adev, AMDGPU_GFXHUB(i));
|
||||
if (adev->enable_mes && adev->gfx.enable_cleaner_shader)
|
||||
amdgpu_mes_set_enforce_isolation(adev, i, false);
|
||||
} else if (!adev->enforce_isolation[i] && partition_values[i]) {
|
||||
else if (!adev->enforce_isolation[i] && partition_values[i])
|
||||
/* Going from disabled to enabled */
|
||||
amdgpu_vmid_alloc_reserved(adev, AMDGPU_GFXHUB(i));
|
||||
if (adev->enable_mes && adev->gfx.enable_cleaner_shader)
|
||||
amdgpu_mes_set_enforce_isolation(adev, i, true);
|
||||
}
|
||||
adev->enforce_isolation[i] = partition_values[i];
|
||||
}
|
||||
|
||||
mutex_unlock(&adev->enforce_isolation_mutex);
|
||||
|
||||
amdgpu_mes_update_enforce_isolation(adev);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ void amdgpu_gmc_sysvm_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc
|
|||
* @mc: memory controller structure holding memory information
|
||||
* @gart_placement: GART placement policy with respect to VRAM
|
||||
*
|
||||
* Function will place try to place GART before or after VRAM.
|
||||
* Function will try to place GART before or after VRAM.
|
||||
* If GART size is bigger than space left then we ajust GART size.
|
||||
* Thus function will never fails.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/types.h>
|
||||
|
||||
#include "amdgpu_irq.h"
|
||||
#include "amdgpu_xgmi.h"
|
||||
#include "amdgpu_ras.h"
|
||||
|
||||
/* VA hole for 48bit addresses on Vega10 */
|
||||
|
|
@ -174,28 +175,6 @@ struct amdgpu_gmc_funcs {
|
|||
bool (*need_reset_on_init)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
struct amdgpu_xgmi_ras {
|
||||
struct amdgpu_ras_block_object ras_block;
|
||||
};
|
||||
|
||||
struct amdgpu_xgmi {
|
||||
/* from psp */
|
||||
u64 node_id;
|
||||
u64 hive_id;
|
||||
/* fixed per family */
|
||||
u64 node_segment_size;
|
||||
/* physical node (0-3) */
|
||||
unsigned physical_node_id;
|
||||
/* number of nodes (0-4) */
|
||||
unsigned num_physical_nodes;
|
||||
/* gpu list in the same hive */
|
||||
struct list_head head;
|
||||
bool supported;
|
||||
struct ras_common_if *ras_if;
|
||||
bool connected_to_cpu;
|
||||
struct amdgpu_xgmi_ras *ras;
|
||||
};
|
||||
|
||||
struct amdgpu_mem_partition_info {
|
||||
union {
|
||||
struct {
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ struct amdgpu_ih_ring {
|
|||
#define amdgpu_ih_ts_after(t1, t2) \
|
||||
(((int64_t)((t2) << 16) - (int64_t)((t1) << 16)) > 0LL)
|
||||
|
||||
#define amdgpu_ih_ts_after_or_equal(t1, t2) \
|
||||
(((int64_t)((t2) << 16) - (int64_t)((t1) << 16)) >= 0LL)
|
||||
|
||||
/* provided by the ih block */
|
||||
struct amdgpu_ih_funcs {
|
||||
/* ring read/write ptr handling, called from interrupt context */
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ static int isp_early_init(struct amdgpu_ip_block *ip_block)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool isp_is_idle(void *handle)
|
||||
static bool isp_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ struct amdgpu_isp {
|
|||
struct mfd_cell *isp_cell;
|
||||
struct resource *isp_res;
|
||||
struct resource *isp_i2c_res;
|
||||
struct resource *isp_gpio_res;
|
||||
struct isp_platform_data *isp_pdata;
|
||||
unsigned int harvest_config;
|
||||
const struct firmware *fw;
|
||||
|
|
|
|||
|
|
@ -130,29 +130,47 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
|
|||
amdgpu_vm_put_task_info(ti);
|
||||
}
|
||||
|
||||
dma_fence_set_error(&s_job->s_fence->finished, -ETIME);
|
||||
|
||||
/* attempt a per ring reset */
|
||||
if (amdgpu_gpu_recovery &&
|
||||
ring->funcs->reset) {
|
||||
if (unlikely(adev->debug_disable_gpu_ring_reset)) {
|
||||
dev_err(adev->dev, "Ring reset disabled by debug mask\n");
|
||||
} else if (amdgpu_gpu_recovery && ring->funcs->reset) {
|
||||
bool is_guilty;
|
||||
|
||||
dev_err(adev->dev, "Starting %s ring reset\n", s_job->sched->name);
|
||||
/* 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);
|
||||
|
||||
/* for engine resets, we need to reset the engine,
|
||||
* but individual queues may be unaffected.
|
||||
* check here to make sure the accounting is correct.
|
||||
*/
|
||||
if (ring->funcs->is_guilty)
|
||||
is_guilty = ring->funcs->is_guilty(ring);
|
||||
else
|
||||
is_guilty = true;
|
||||
|
||||
if (is_guilty)
|
||||
dma_fence_set_error(&s_job->s_fence->finished, -ETIME);
|
||||
|
||||
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 (is_guilty) {
|
||||
atomic_inc(&ring->adev->gpu_reset_counter);
|
||||
amdgpu_fence_driver_force_completion(ring);
|
||||
}
|
||||
if (amdgpu_ring_sched_ready(ring))
|
||||
drm_sched_start(&ring->sched, 0);
|
||||
dev_err(adev->dev, "Ring %s reset succeeded\n", ring->sched.name);
|
||||
goto exit;
|
||||
}
|
||||
dev_err(adev->dev, "Ring %s reset failure\n", ring->sched.name);
|
||||
}
|
||||
dma_fence_set_error(&s_job->s_fence->finished, -ETIME);
|
||||
|
||||
if (amdgpu_device_should_recover_gpu(ring->adev)) {
|
||||
struct amdgpu_reset_context reset_context;
|
||||
|
|
|
|||
|
|
@ -459,7 +459,7 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
|
|||
if (adev->vcn.harvest_config & (1 << i))
|
||||
continue;
|
||||
|
||||
for (j = 0; j < adev->vcn.num_enc_rings; j++)
|
||||
for (j = 0; j < adev->vcn.inst[i].num_enc_rings; j++)
|
||||
if (adev->vcn.inst[i].ring_enc[j].sched.ready)
|
||||
++num_rings;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1681,7 +1681,8 @@ bool amdgpu_mes_suspend_resume_all_supported(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
/* Fix me -- node_id is used to identify the correct MES instances in the future */
|
||||
int amdgpu_mes_set_enforce_isolation(struct amdgpu_device *adev, uint32_t node_id, bool enable)
|
||||
static int amdgpu_mes_set_enforce_isolation(struct amdgpu_device *adev,
|
||||
uint32_t node_id, bool enable)
|
||||
{
|
||||
struct mes_misc_op_input op_input = {0};
|
||||
int r;
|
||||
|
|
@ -1703,6 +1704,23 @@ int amdgpu_mes_set_enforce_isolation(struct amdgpu_device *adev, uint32_t node_i
|
|||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_mes_update_enforce_isolation(struct amdgpu_device *adev)
|
||||
{
|
||||
int i, r = 0;
|
||||
|
||||
if (adev->enable_mes && adev->gfx.enable_cleaner_shader) {
|
||||
mutex_lock(&adev->enforce_isolation_mutex);
|
||||
for (i = 0; i < (adev->xcp_mgr ? adev->xcp_mgr->num_xcps : 1); i++) {
|
||||
if (adev->enforce_isolation[i])
|
||||
r |= amdgpu_mes_set_enforce_isolation(adev, i, true);
|
||||
else
|
||||
r |= amdgpu_mes_set_enforce_isolation(adev, i, false);
|
||||
}
|
||||
mutex_unlock(&adev->enforce_isolation_mutex);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
||||
static int amdgpu_debugfs_mes_event_log_show(struct seq_file *m, void *unused)
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ enum amdgpu_mes_priority_level {
|
|||
|
||||
struct amdgpu_mes_funcs;
|
||||
|
||||
enum admgpu_mes_pipe {
|
||||
enum amdgpu_mes_pipe {
|
||||
AMDGPU_MES_SCHED_PIPE = 0,
|
||||
AMDGPU_MES_KIQ_PIPE,
|
||||
AMDGPU_MAX_MES_PIPES = 2,
|
||||
|
|
@ -534,6 +534,6 @@ static inline void amdgpu_mes_unlock(struct amdgpu_mes *mes)
|
|||
|
||||
bool amdgpu_mes_suspend_resume_all_supported(struct amdgpu_device *adev);
|
||||
|
||||
int amdgpu_mes_set_enforce_isolation(struct amdgpu_device *adev, uint32_t node_id, bool enable);
|
||||
int amdgpu_mes_update_enforce_isolation(struct amdgpu_device *adev);
|
||||
|
||||
#endif /* __AMDGPU_MES_H__ */
|
||||
|
|
|
|||
|
|
@ -1295,28 +1295,36 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)
|
|||
if (abo->kfd_bo)
|
||||
amdgpu_amdkfd_release_notify(abo);
|
||||
|
||||
/* We only remove the fence if the resv has individualized. */
|
||||
WARN_ON_ONCE(bo->type == ttm_bo_type_kernel
|
||||
&& bo->base.resv != &bo->base._resv);
|
||||
if (bo->base.resv == &bo->base._resv)
|
||||
amdgpu_amdkfd_remove_fence_on_pt_pd_bos(abo);
|
||||
/*
|
||||
* We lock the private dma_resv object here and since the BO is about to
|
||||
* be released nobody else should have a pointer to it.
|
||||
* So when this locking here fails something is wrong with the reference
|
||||
* counting.
|
||||
*/
|
||||
if (WARN_ON_ONCE(!dma_resv_trylock(&bo->base._resv)))
|
||||
return;
|
||||
|
||||
amdgpu_amdkfd_remove_all_eviction_fences(abo);
|
||||
|
||||
if (!bo->resource || bo->resource->mem_type != TTM_PL_VRAM ||
|
||||
!(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE) ||
|
||||
adev->in_suspend || drm_dev_is_unplugged(adev_to_drm(adev)))
|
||||
return;
|
||||
goto out;
|
||||
|
||||
if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv)))
|
||||
return;
|
||||
r = dma_resv_reserve_fences(&bo->base._resv, 1);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
r = amdgpu_fill_buffer(abo, 0, bo->base.resv, &fence, true);
|
||||
if (!WARN_ON(r)) {
|
||||
amdgpu_vram_mgr_set_cleared(bo->resource);
|
||||
amdgpu_bo_fence(abo, fence, false);
|
||||
dma_fence_put(fence);
|
||||
}
|
||||
r = amdgpu_fill_buffer(abo, 0, &bo->base._resv, &fence, true);
|
||||
if (WARN_ON(r))
|
||||
goto out;
|
||||
|
||||
dma_resv_unlock(bo->base.resv);
|
||||
amdgpu_vram_mgr_set_cleared(bo->resource);
|
||||
dma_resv_add_fence(&bo->base._resv, fence, DMA_RESV_USAGE_KERNEL);
|
||||
dma_fence_put(fence);
|
||||
|
||||
out:
|
||||
dma_resv_unlock(&bo->base._resv);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2799,20 +2799,100 @@ static int amdgpu_ras_mca2pa(struct amdgpu_device *adev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int __amdgpu_ras_restore_bad_pages(struct amdgpu_device *adev,
|
||||
struct eeprom_table_record *bps, int count)
|
||||
{
|
||||
int j;
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct ras_err_handler_data *data = con->eh_data;
|
||||
|
||||
for (j = 0; j < count; j++) {
|
||||
if (amdgpu_ras_check_bad_page_unlock(con,
|
||||
bps[j].retired_page << AMDGPU_GPU_PAGE_SHIFT))
|
||||
continue;
|
||||
|
||||
if (!data->space_left &&
|
||||
amdgpu_ras_realloc_eh_data_space(adev, data, 256)) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
amdgpu_ras_reserve_page(adev, bps[j].retired_page);
|
||||
|
||||
memcpy(&data->bps[data->count], &(bps[j]),
|
||||
sizeof(struct eeprom_table_record));
|
||||
data->count++;
|
||||
data->space_left--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __amdgpu_ras_convert_rec_array_from_rom(struct amdgpu_device *adev,
|
||||
struct eeprom_table_record *bps, struct ras_err_data *err_data,
|
||||
enum amdgpu_memory_partition nps)
|
||||
{
|
||||
int i = 0;
|
||||
enum amdgpu_memory_partition save_nps;
|
||||
|
||||
save_nps = (bps[0].retired_page >> UMC_NPS_SHIFT) & UMC_NPS_MASK;
|
||||
|
||||
for (i = 0; i < adev->umc.retire_unit; i++)
|
||||
bps[i].retired_page &= ~(UMC_NPS_MASK << UMC_NPS_SHIFT);
|
||||
|
||||
if (save_nps) {
|
||||
if (save_nps == nps) {
|
||||
if (amdgpu_umc_pages_in_a_row(adev, err_data,
|
||||
bps[0].retired_page << AMDGPU_GPU_PAGE_SHIFT))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (amdgpu_ras_mca2pa_by_idx(adev, &bps[0], err_data))
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
if (amdgpu_ras_mca2pa(adev, &bps[0], err_data)) {
|
||||
if (nps == AMDGPU_NPS1_PARTITION_MODE)
|
||||
memcpy(err_data->err_addr, bps,
|
||||
sizeof(struct eeprom_table_record) * adev->umc.retire_unit);
|
||||
else
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
return __amdgpu_ras_restore_bad_pages(adev, err_data->err_addr, adev->umc.retire_unit);
|
||||
}
|
||||
|
||||
static int __amdgpu_ras_convert_rec_from_rom(struct amdgpu_device *adev,
|
||||
struct eeprom_table_record *bps, struct ras_err_data *err_data,
|
||||
enum amdgpu_memory_partition nps)
|
||||
{
|
||||
enum amdgpu_memory_partition save_nps;
|
||||
|
||||
save_nps = (bps->retired_page >> UMC_NPS_SHIFT) & UMC_NPS_MASK;
|
||||
bps->retired_page &= ~(UMC_NPS_MASK << UMC_NPS_SHIFT);
|
||||
|
||||
if (save_nps == nps) {
|
||||
if (amdgpu_umc_pages_in_a_row(adev, err_data,
|
||||
bps->retired_page << AMDGPU_GPU_PAGE_SHIFT))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (amdgpu_ras_mca2pa_by_idx(adev, bps, err_data))
|
||||
return -EINVAL;
|
||||
}
|
||||
return __amdgpu_ras_restore_bad_pages(adev, err_data->err_addr,
|
||||
adev->umc.retire_unit);
|
||||
}
|
||||
|
||||
/* it deal with vram only. */
|
||||
int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev,
|
||||
struct eeprom_table_record *bps, int pages, bool from_rom)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct ras_err_handler_data *data;
|
||||
struct ras_err_data err_data;
|
||||
struct eeprom_table_record *err_rec;
|
||||
struct amdgpu_ras_eeprom_control *control =
|
||||
&adev->psp.ras_context.ras->eeprom_control;
|
||||
enum amdgpu_memory_partition nps = AMDGPU_NPS1_PARTITION_MODE;
|
||||
int ret = 0;
|
||||
uint32_t i, j, loop_cnt = 1;
|
||||
bool find_pages_per_pa = false;
|
||||
uint32_t i;
|
||||
|
||||
if (!con || !con->eh_data || !bps || pages <= 0)
|
||||
return 0;
|
||||
|
|
@ -2823,114 +2903,46 @@ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev,
|
|||
sizeof(struct eeprom_table_record), GFP_KERNEL);
|
||||
if (!err_data.err_addr) {
|
||||
dev_warn(adev->dev, "Failed to alloc UMC error address record in mca2pa conversion!\n");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
err_rec = err_data.err_addr;
|
||||
loop_cnt = adev->umc.retire_unit;
|
||||
if (adev->gmc.gmc_funcs->query_mem_partition_mode)
|
||||
nps = adev->gmc.gmc_funcs->query_mem_partition_mode(adev);
|
||||
}
|
||||
|
||||
mutex_lock(&con->recovery_lock);
|
||||
data = con->eh_data;
|
||||
if (!data) {
|
||||
/* Returning 0 as the absence of eh_data is acceptable */
|
||||
goto free;
|
||||
}
|
||||
|
||||
for (i = 0; i < pages; i++) {
|
||||
if (from_rom &&
|
||||
control->rec_type == AMDGPU_RAS_EEPROM_REC_MCA) {
|
||||
if (!find_pages_per_pa) {
|
||||
if (amdgpu_ras_mca2pa_by_idx(adev, &bps[i], &err_data)) {
|
||||
if (!i && nps == AMDGPU_NPS1_PARTITION_MODE) {
|
||||
/* may use old RAS TA, use PA to find pages in
|
||||
* one row
|
||||
*/
|
||||
if (amdgpu_umc_pages_in_a_row(adev, &err_data,
|
||||
bps[i].retired_page <<
|
||||
AMDGPU_GPU_PAGE_SHIFT)) {
|
||||
ret = -EINVAL;
|
||||
goto free;
|
||||
} else {
|
||||
find_pages_per_pa = true;
|
||||
}
|
||||
} else {
|
||||
/* unsupported cases */
|
||||
ret = -EOPNOTSUPP;
|
||||
if (from_rom) {
|
||||
for (i = 0; i < pages; i++) {
|
||||
if (control->ras_num_recs - i >= adev->umc.retire_unit) {
|
||||
if ((bps[i].address == bps[i + 1].address) &&
|
||||
(bps[i].mem_channel == bps[i + 1].mem_channel)) {
|
||||
//deal with retire_unit records a time
|
||||
ret = __amdgpu_ras_convert_rec_array_from_rom(adev,
|
||||
&bps[i], &err_data, nps);
|
||||
if (ret)
|
||||
goto free;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (amdgpu_umc_pages_in_a_row(adev, &err_data,
|
||||
bps[i].retired_page << AMDGPU_GPU_PAGE_SHIFT)) {
|
||||
ret = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (from_rom && !find_pages_per_pa) {
|
||||
if (bps[i].retired_page & UMC_CHANNEL_IDX_V2) {
|
||||
/* bad page in any NPS mode in eeprom */
|
||||
if (amdgpu_ras_mca2pa_by_idx(adev, &bps[i], &err_data)) {
|
||||
ret = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
} else {
|
||||
/* legacy bad page in eeprom, generated only in
|
||||
* NPS1 mode
|
||||
*/
|
||||
if (amdgpu_ras_mca2pa(adev, &bps[i], &err_data)) {
|
||||
/* old RAS TA or ASICs which don't support to
|
||||
* convert addrss via mca address
|
||||
*/
|
||||
if (!i && nps == AMDGPU_NPS1_PARTITION_MODE) {
|
||||
find_pages_per_pa = true;
|
||||
err_rec = &bps[i];
|
||||
loop_cnt = 1;
|
||||
} else {
|
||||
/* non-nps1 mode, old RAS TA
|
||||
* can't support it
|
||||
*/
|
||||
ret = -EOPNOTSUPP;
|
||||
goto free;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!find_pages_per_pa)
|
||||
i += (adev->umc.retire_unit - 1);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
err_rec = &bps[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < loop_cnt; j++) {
|
||||
if (amdgpu_ras_check_bad_page_unlock(con,
|
||||
err_rec[j].retired_page << AMDGPU_GPU_PAGE_SHIFT))
|
||||
continue;
|
||||
|
||||
if (!data->space_left &&
|
||||
amdgpu_ras_realloc_eh_data_space(adev, data, 256)) {
|
||||
ret = -ENOMEM;
|
||||
for (; i < pages; i++) {
|
||||
ret = __amdgpu_ras_convert_rec_from_rom(adev,
|
||||
&bps[i], &err_data, nps);
|
||||
if (ret)
|
||||
goto free;
|
||||
}
|
||||
|
||||
amdgpu_ras_reserve_page(adev, err_rec[j].retired_page);
|
||||
|
||||
memcpy(&data->bps[data->count], &(err_rec[j]),
|
||||
sizeof(struct eeprom_table_record));
|
||||
data->count++;
|
||||
data->space_left--;
|
||||
}
|
||||
} else {
|
||||
ret = __amdgpu_ras_restore_bad_pages(adev, bps, pages);
|
||||
}
|
||||
|
||||
free:
|
||||
if (from_rom)
|
||||
kfree(err_data.err_addr);
|
||||
out:
|
||||
mutex_unlock(&con->recovery_lock);
|
||||
|
||||
return ret;
|
||||
|
|
@ -2969,24 +2981,14 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev,
|
|||
|
||||
/* only new entries are saved */
|
||||
if (save_count > 0) {
|
||||
if (control->rec_type == AMDGPU_RAS_EEPROM_REC_PA) {
|
||||
for (i = 0; i < unit_num; i++) {
|
||||
if (amdgpu_ras_eeprom_append(control,
|
||||
&data->bps[control->ras_num_recs],
|
||||
save_count)) {
|
||||
&data->bps[bad_page_num + i * adev->umc.retire_unit],
|
||||
1)) {
|
||||
dev_err(adev->dev, "Failed to save EEPROM table data!");
|
||||
return -EIO;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < unit_num; i++) {
|
||||
if (amdgpu_ras_eeprom_append(control,
|
||||
&data->bps[bad_page_num + i * adev->umc.retire_unit],
|
||||
1)) {
|
||||
dev_err(adev->dev, "Failed to save EEPROM table data!");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dev_info(adev->dev, "Saved %d pages to EEPROM table.\n", save_count);
|
||||
}
|
||||
|
||||
|
|
@ -3002,7 +3004,7 @@ static int amdgpu_ras_load_bad_pages(struct amdgpu_device *adev)
|
|||
struct amdgpu_ras_eeprom_control *control =
|
||||
&adev->psp.ras_context.ras->eeprom_control;
|
||||
struct eeprom_table_record *bps;
|
||||
int ret;
|
||||
int ret, i = 0;
|
||||
|
||||
/* no bad page record, skip eeprom access */
|
||||
if (control->ras_num_recs == 0 || amdgpu_bad_page_threshold == 0)
|
||||
|
|
@ -3016,13 +3018,23 @@ static int amdgpu_ras_load_bad_pages(struct amdgpu_device *adev)
|
|||
if (ret) {
|
||||
dev_err(adev->dev, "Failed to load EEPROM table records!");
|
||||
} else {
|
||||
if (control->ras_num_recs > 1 &&
|
||||
adev->umc.ras && adev->umc.ras->convert_ras_err_addr) {
|
||||
if ((bps[0].address == bps[1].address) &&
|
||||
(bps[0].mem_channel == bps[1].mem_channel))
|
||||
control->rec_type = AMDGPU_RAS_EEPROM_REC_PA;
|
||||
else
|
||||
control->rec_type = AMDGPU_RAS_EEPROM_REC_MCA;
|
||||
if (adev->umc.ras && adev->umc.ras->convert_ras_err_addr) {
|
||||
for (i = 0; i < control->ras_num_recs; i++) {
|
||||
if ((control->ras_num_recs - i) >= adev->umc.retire_unit) {
|
||||
if ((bps[i].address == bps[i + 1].address) &&
|
||||
(bps[i].mem_channel == bps[i + 1].mem_channel)) {
|
||||
control->ras_num_pa_recs += adev->umc.retire_unit;
|
||||
i += (adev->umc.retire_unit - 1);
|
||||
} else {
|
||||
control->ras_num_mca_recs +=
|
||||
(control->ras_num_recs - i);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
control->ras_num_mca_recs += (control->ras_num_recs - i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = amdgpu_ras_eeprom_check(control);
|
||||
|
|
@ -3428,12 +3440,7 @@ int amdgpu_ras_init_badpage_info(struct amdgpu_device *adev)
|
|||
return ret;
|
||||
|
||||
if (!adev->umc.ras || !adev->umc.ras->convert_ras_err_addr)
|
||||
control->rec_type = AMDGPU_RAS_EEPROM_REC_PA;
|
||||
|
||||
/* default status is MCA storage */
|
||||
if (control->ras_num_recs <= 1 &&
|
||||
adev->umc.ras && adev->umc.ras->convert_ras_err_addr)
|
||||
control->rec_type = AMDGPU_RAS_EEPROM_REC_MCA;
|
||||
control->ras_num_pa_recs = control->ras_num_recs;
|
||||
|
||||
if (control->ras_num_recs) {
|
||||
ret = amdgpu_ras_load_bad_pages(adev);
|
||||
|
|
@ -5131,9 +5138,9 @@ static void amdgpu_ras_boot_time_error_reporting(struct amdgpu_device *adev,
|
|||
"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))
|
||||
if (AMDGPU_RAS_GPU_ERR_GENERIC(boot_error))
|
||||
dev_info(adev->dev,
|
||||
"socket: %d, aid: %d, fw_status: 0x%x, unknown boot time errors\n",
|
||||
"socket: %d, aid: %d, fw_status: 0x%x, Boot Controller Generic Error\n",
|
||||
socket_id, aid_id, fw_status);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ struct amdgpu_iv_entry;
|
|||
#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_GPU_ERR_GENERIC(x) AMDGPU_GET_REG_FIELD(x, 30, 30)
|
||||
|
||||
#define AMDGPU_RAS_BOOT_STATUS_POLLING_LIMIT 100
|
||||
#define AMDGPU_RAS_BOOT_STEADY_STATUS 0xBA
|
||||
|
|
|
|||
|
|
@ -727,11 +727,9 @@ amdgpu_ras_eeprom_append_table(struct amdgpu_ras_eeprom_control *control,
|
|||
- control->ras_fri)
|
||||
% control->ras_max_record_count;
|
||||
|
||||
if (control->rec_type == AMDGPU_RAS_EEPROM_REC_PA)
|
||||
control->ras_num_bad_pages = control->ras_num_recs;
|
||||
else
|
||||
control->ras_num_bad_pages =
|
||||
control->ras_num_recs * adev->umc.retire_unit;
|
||||
control->ras_num_mca_recs += num;
|
||||
control->ras_num_bad_pages += num * adev->umc.retire_unit;
|
||||
|
||||
Out:
|
||||
kfree(buf);
|
||||
return res;
|
||||
|
|
@ -749,7 +747,7 @@ amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control)
|
|||
/* Modify the header if it exceeds.
|
||||
*/
|
||||
if (amdgpu_bad_page_threshold != 0 &&
|
||||
control->ras_num_bad_pages >= ras->bad_page_cnt_threshold) {
|
||||
control->ras_num_bad_pages > ras->bad_page_cnt_threshold) {
|
||||
dev_warn(adev->dev,
|
||||
"Saved bad pages %d reaches threshold value %d\n",
|
||||
control->ras_num_bad_pages, ras->bad_page_cnt_threshold);
|
||||
|
|
@ -808,7 +806,7 @@ amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control)
|
|||
*/
|
||||
if (amdgpu_bad_page_threshold != 0 &&
|
||||
control->tbl_hdr.version == RAS_TABLE_VER_V2_1 &&
|
||||
control->ras_num_bad_pages < ras->bad_page_cnt_threshold)
|
||||
control->ras_num_bad_pages <= ras->bad_page_cnt_threshold)
|
||||
control->tbl_rai.health_percent = ((ras->bad_page_cnt_threshold -
|
||||
control->ras_num_bad_pages) * 100) /
|
||||
ras->bad_page_cnt_threshold;
|
||||
|
|
@ -852,6 +850,7 @@ int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control,
|
|||
{
|
||||
struct amdgpu_device *adev = to_amdgpu_device(control);
|
||||
int res, i;
|
||||
uint64_t nps = AMDGPU_NPS1_PARTITION_MODE;
|
||||
|
||||
if (!__is_ras_eeprom_supported(adev))
|
||||
return 0;
|
||||
|
|
@ -865,9 +864,12 @@ int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (adev->gmc.gmc_funcs->query_mem_partition_mode)
|
||||
nps = adev->gmc.gmc_funcs->query_mem_partition_mode(adev);
|
||||
|
||||
/* set the new channel index flag */
|
||||
for (i = 0; i < num; i++)
|
||||
record[i].retired_page |= UMC_CHANNEL_IDX_V2;
|
||||
record[i].retired_page |= (nps << UMC_NPS_SHIFT);
|
||||
|
||||
mutex_lock(&control->ras_tbl_mutex);
|
||||
|
||||
|
|
@ -881,7 +883,7 @@ int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control,
|
|||
|
||||
/* clear channel index flag, the flag is only saved on eeprom */
|
||||
for (i = 0; i < num; i++)
|
||||
record[i].retired_page &= ~UMC_CHANNEL_IDX_V2;
|
||||
record[i].retired_page &= ~(nps << UMC_NPS_SHIFT);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -1392,6 +1394,8 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
|
|||
}
|
||||
control->ras_fri = RAS_OFFSET_TO_INDEX(control, hdr->first_rec_offset);
|
||||
|
||||
control->ras_num_mca_recs = 0;
|
||||
control->ras_num_pa_recs = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1412,11 +1416,8 @@ int amdgpu_ras_eeprom_check(struct amdgpu_ras_eeprom_control *control)
|
|||
if (!__get_eeprom_i2c_addr(adev, control))
|
||||
return -EINVAL;
|
||||
|
||||
if (control->rec_type == AMDGPU_RAS_EEPROM_REC_PA)
|
||||
control->ras_num_bad_pages = control->ras_num_recs;
|
||||
else
|
||||
control->ras_num_bad_pages =
|
||||
control->ras_num_recs * adev->umc.retire_unit;
|
||||
control->ras_num_bad_pages = control->ras_num_pa_recs +
|
||||
control->ras_num_mca_recs * adev->umc.retire_unit;
|
||||
|
||||
if (hdr->header == RAS_TABLE_HDR_VAL) {
|
||||
DRM_DEBUG_DRIVER("Found existing EEPROM table with %d records",
|
||||
|
|
@ -1455,7 +1456,7 @@ int amdgpu_ras_eeprom_check(struct amdgpu_ras_eeprom_control *control)
|
|||
res);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ras->bad_page_cnt_threshold > control->ras_num_bad_pages) {
|
||||
if (ras->bad_page_cnt_threshold >= control->ras_num_bad_pages) {
|
||||
/* This means that, the threshold was increased since
|
||||
* the last time the system was booted, and now,
|
||||
* ras->bad_page_cnt_threshold - control->num_recs > 0,
|
||||
|
|
|
|||
|
|
@ -43,19 +43,6 @@ enum amdgpu_ras_eeprom_err_type {
|
|||
AMDGPU_RAS_EEPROM_ERR_COUNT,
|
||||
};
|
||||
|
||||
/*
|
||||
* one UMC MCA address could map to multiply physical address (PA),
|
||||
* such as 1:16, we use eeprom_table_record.address to store MCA
|
||||
* address and use eeprom_table_record.retired_page to save PA.
|
||||
*
|
||||
* AMDGPU_RAS_EEPROM_REC_PA: one record store one PA
|
||||
* AMDGPU_RAS_EEPROM_REC_MCA: one record store one MCA address
|
||||
*/
|
||||
enum amdgpu_ras_eeprom_rec_type {
|
||||
AMDGPU_RAS_EEPROM_REC_PA,
|
||||
AMDGPU_RAS_EEPROM_REC_MCA,
|
||||
};
|
||||
|
||||
struct amdgpu_ras_eeprom_table_header {
|
||||
uint32_t header;
|
||||
uint32_t version;
|
||||
|
|
@ -100,6 +87,12 @@ struct amdgpu_ras_eeprom_control {
|
|||
*/
|
||||
u32 ras_num_bad_pages;
|
||||
|
||||
/* Number of records store mca address */
|
||||
u32 ras_num_mca_recs;
|
||||
|
||||
/* Number of records store physical address */
|
||||
u32 ras_num_pa_recs;
|
||||
|
||||
/* First record index to read, 0-based.
|
||||
* Range is [0, num_recs-1]. This is
|
||||
* an absolute index, starting right after
|
||||
|
|
@ -120,7 +113,6 @@ struct amdgpu_ras_eeprom_control {
|
|||
/* Record channel info which occurred bad pages
|
||||
*/
|
||||
u32 bad_channel_bitmap;
|
||||
enum amdgpu_ras_eeprom_rec_type rec_type;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -349,6 +349,8 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
|
|||
ring->buf_mask = (ring->ring_size / 4) - 1;
|
||||
ring->ptr_mask = ring->funcs->support_64bit_ptrs ?
|
||||
0xffffffffffffffff : ring->buf_mask;
|
||||
/* Initialize cached_rptr to 0 */
|
||||
ring->cached_rptr = 0;
|
||||
|
||||
/* Allocate ring buffer */
|
||||
if (ring->is_mes_queue) {
|
||||
|
|
@ -576,12 +578,32 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,
|
|||
return result;
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_debugfs_virt_ring_read(struct file *f, char __user *buf,
|
||||
size_t size, loff_t *pos)
|
||||
{
|
||||
struct amdgpu_ring *ring = file_inode(f)->i_private;
|
||||
|
||||
if (*pos & 3 || size & 3)
|
||||
return -EINVAL;
|
||||
|
||||
if (ring->funcs->type == AMDGPU_RING_TYPE_CPER)
|
||||
amdgpu_virt_req_ras_cper_dump(ring->adev, false);
|
||||
|
||||
return amdgpu_debugfs_ring_read(f, buf, size, pos);
|
||||
}
|
||||
|
||||
static const struct file_operations amdgpu_debugfs_ring_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = amdgpu_debugfs_ring_read,
|
||||
.llseek = default_llseek
|
||||
};
|
||||
|
||||
static const struct file_operations amdgpu_debugfs_virt_ring_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = amdgpu_debugfs_virt_ring_read,
|
||||
.llseek = default_llseek
|
||||
};
|
||||
|
||||
static ssize_t amdgpu_debugfs_mqd_read(struct file *f, char __user *buf,
|
||||
size_t size, loff_t *pos)
|
||||
{
|
||||
|
|
@ -669,9 +691,14 @@ void amdgpu_debugfs_ring_init(struct amdgpu_device *adev,
|
|||
char name[32];
|
||||
|
||||
sprintf(name, "amdgpu_ring_%s", ring->name);
|
||||
debugfs_create_file_size(name, S_IFREG | 0444, root, ring,
|
||||
&amdgpu_debugfs_ring_fops,
|
||||
ring->ring_size + 12);
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
debugfs_create_file_size(name, S_IFREG | 0444, root, ring,
|
||||
&amdgpu_debugfs_virt_ring_fops,
|
||||
ring->ring_size + 12);
|
||||
else
|
||||
debugfs_create_file_size(name, S_IFREG | 0444, root, ring,
|
||||
&amdgpu_debugfs_ring_fops,
|
||||
ring->ring_size + 12);
|
||||
|
||||
if (ring->mqd_obj) {
|
||||
sprintf(name, "amdgpu_mqd_%s", ring->name);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ struct amdgpu_job;
|
|||
struct amdgpu_vm;
|
||||
|
||||
/* max number of rings */
|
||||
#define AMDGPU_MAX_RINGS 132
|
||||
#define AMDGPU_MAX_RINGS 133
|
||||
#define AMDGPU_MAX_HWIP_RINGS 64
|
||||
#define AMDGPU_MAX_GFX_RINGS 2
|
||||
#define AMDGPU_MAX_SW_GFX_RINGS 2
|
||||
|
|
@ -238,6 +238,7 @@ struct amdgpu_ring_funcs {
|
|||
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);
|
||||
bool (*is_guilty)(struct amdgpu_ring *ring);
|
||||
};
|
||||
|
||||
struct amdgpu_ring {
|
||||
|
|
@ -307,6 +308,8 @@ struct amdgpu_ring {
|
|||
|
||||
bool is_sw_ring;
|
||||
unsigned int entry_index;
|
||||
/* store the cached rptr to restore after reset */
|
||||
uint64_t cached_rptr;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "amdgpu.h"
|
||||
#include "amdgpu_sdma.h"
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_reset.h"
|
||||
|
||||
#define AMDGPU_CSA_SDMA_SIZE 64
|
||||
/* SDMA CSA reside in the 3rd page of CSA */
|
||||
|
|
@ -355,23 +356,44 @@ int amdgpu_sdma_ras_sw_init(struct amdgpu_device *adev)
|
|||
static int amdgpu_debugfs_sdma_sched_mask_set(void *data, u64 val)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)data;
|
||||
u32 i;
|
||||
u64 i, num_ring;
|
||||
u64 mask = 0;
|
||||
struct amdgpu_ring *ring;
|
||||
struct amdgpu_ring *ring, *page = NULL;
|
||||
|
||||
if (!adev)
|
||||
return -ENODEV;
|
||||
|
||||
mask = BIT_ULL(adev->sdma.num_instances) - 1;
|
||||
/* Determine the number of rings per SDMA instance
|
||||
* (1 for sdma gfx ring, 2 if page queue exists)
|
||||
*/
|
||||
if (adev->sdma.has_page_queue)
|
||||
num_ring = 2;
|
||||
else
|
||||
num_ring = 1;
|
||||
|
||||
/* Calculate the maximum possible mask value
|
||||
* based on the number of SDMA instances and rings
|
||||
*/
|
||||
mask = BIT_ULL(adev->sdma.num_instances * num_ring) - 1;
|
||||
|
||||
if ((val & mask) == 0)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < adev->sdma.num_instances; ++i) {
|
||||
ring = &adev->sdma.instance[i].ring;
|
||||
if (val & BIT_ULL(i))
|
||||
if (adev->sdma.has_page_queue)
|
||||
page = &adev->sdma.instance[i].page;
|
||||
if (val & BIT_ULL(i * num_ring))
|
||||
ring->sched.ready = true;
|
||||
else
|
||||
ring->sched.ready = false;
|
||||
|
||||
if (page) {
|
||||
if (val & BIT_ULL(i * num_ring + 1))
|
||||
page->sched.ready = true;
|
||||
else
|
||||
page->sched.ready = false;
|
||||
}
|
||||
}
|
||||
/* publish sched.ready flag update effective immediately across smp */
|
||||
smp_rmb();
|
||||
|
|
@ -381,16 +403,37 @@ static int amdgpu_debugfs_sdma_sched_mask_set(void *data, u64 val)
|
|||
static int amdgpu_debugfs_sdma_sched_mask_get(void *data, u64 *val)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)data;
|
||||
u32 i;
|
||||
u64 i, num_ring;
|
||||
u64 mask = 0;
|
||||
struct amdgpu_ring *ring;
|
||||
struct amdgpu_ring *ring, *page = NULL;
|
||||
|
||||
if (!adev)
|
||||
return -ENODEV;
|
||||
|
||||
/* Determine the number of rings per SDMA instance
|
||||
* (1 for sdma gfx ring, 2 if page queue exists)
|
||||
*/
|
||||
if (adev->sdma.has_page_queue)
|
||||
num_ring = 2;
|
||||
else
|
||||
num_ring = 1;
|
||||
|
||||
for (i = 0; i < adev->sdma.num_instances; ++i) {
|
||||
ring = &adev->sdma.instance[i].ring;
|
||||
if (adev->sdma.has_page_queue)
|
||||
page = &adev->sdma.instance[i].page;
|
||||
|
||||
if (ring->sched.ready)
|
||||
mask |= 1 << i;
|
||||
mask |= BIT_ULL(i * num_ring);
|
||||
else
|
||||
mask &= ~BIT_ULL(i * num_ring);
|
||||
|
||||
if (page) {
|
||||
if (page->sched.ready)
|
||||
mask |= BIT_ULL(i * num_ring + 1);
|
||||
else
|
||||
mask &= ~BIT_ULL(i * num_ring + 1);
|
||||
}
|
||||
}
|
||||
|
||||
*val = mask;
|
||||
|
|
@ -460,3 +503,123 @@ void amdgpu_sdma_sysfs_reset_mask_fini(struct amdgpu_device *adev)
|
|||
device_remove_file(adev->dev, &dev_attr_sdma_reset_mask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_sdma_register_on_reset_callbacks - Register SDMA reset callbacks
|
||||
* @funcs: Pointer to the callback structure containing pre_reset and post_reset functions
|
||||
*
|
||||
* This function allows KFD and AMDGPU to register their own callbacks for handling
|
||||
* pre-reset and post-reset operations for engine reset. These are needed because engine
|
||||
* reset will stop all queues on that engine.
|
||||
*/
|
||||
void amdgpu_sdma_register_on_reset_callbacks(struct amdgpu_device *adev, struct sdma_on_reset_funcs *funcs)
|
||||
{
|
||||
if (!funcs)
|
||||
return;
|
||||
|
||||
/* Ensure the reset_callback_list is initialized */
|
||||
if (!adev->sdma.reset_callback_list.next) {
|
||||
INIT_LIST_HEAD(&adev->sdma.reset_callback_list);
|
||||
}
|
||||
/* Initialize the list node in the callback structure */
|
||||
INIT_LIST_HEAD(&funcs->list);
|
||||
|
||||
/* Add the callback structure to the global list */
|
||||
list_add_tail(&funcs->list, &adev->sdma.reset_callback_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_sdma_reset_engine - Reset a specific SDMA engine
|
||||
* @adev: Pointer to the AMDGPU device
|
||||
* @instance_id: ID of the SDMA engine instance to reset
|
||||
* @suspend_user_queues: check if suspend user queue.
|
||||
*
|
||||
* This function performs the following steps:
|
||||
* 1. Calls all registered pre_reset callbacks to allow KFD and AMDGPU to save their state.
|
||||
* 2. Resets the specified SDMA engine instance.
|
||||
* 3. Calls all registered post_reset callbacks to allow KFD and AMDGPU to restore their state.
|
||||
*
|
||||
* Returns: 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id, bool suspend_user_queues)
|
||||
{
|
||||
struct sdma_on_reset_funcs *funcs;
|
||||
int ret = 0;
|
||||
struct amdgpu_sdma_instance *sdma_instance = &adev->sdma.instance[instance_id];;
|
||||
struct amdgpu_ring *gfx_ring = &sdma_instance->ring;
|
||||
struct amdgpu_ring *page_ring = &sdma_instance->page;
|
||||
bool gfx_sched_stopped = false, page_sched_stopped = false;
|
||||
|
||||
/* Suspend KFD if suspend_user_queues is true.
|
||||
* prevent the destruction of in-flight healthy user queue packets and
|
||||
* avoid race conditions between KFD and KGD during the reset process.
|
||||
*/
|
||||
if (suspend_user_queues)
|
||||
amdgpu_amdkfd_suspend(adev, false);
|
||||
|
||||
/* Stop the scheduler's work queue for the GFX and page rings if they are running.
|
||||
* This ensures that no new tasks are submitted to the queues while
|
||||
* the reset is in progress.
|
||||
*/
|
||||
if (!amdgpu_ring_sched_ready(gfx_ring)) {
|
||||
drm_sched_wqueue_stop(&gfx_ring->sched);
|
||||
gfx_sched_stopped = true;
|
||||
}
|
||||
|
||||
if (adev->sdma.has_page_queue && !amdgpu_ring_sched_ready(page_ring)) {
|
||||
drm_sched_wqueue_stop(&page_ring->sched);
|
||||
page_sched_stopped = true;
|
||||
}
|
||||
|
||||
/* Invoke all registered pre_reset callbacks */
|
||||
list_for_each_entry(funcs, &adev->sdma.reset_callback_list, list) {
|
||||
if (funcs->pre_reset) {
|
||||
ret = funcs->pre_reset(adev, instance_id);
|
||||
if (ret) {
|
||||
dev_err(adev->dev,
|
||||
"beforeReset callback failed for instance %u: %d\n",
|
||||
instance_id, ret);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform the SDMA reset for the specified instance */
|
||||
ret = amdgpu_dpm_reset_sdma(adev, 1 << instance_id);
|
||||
if (ret) {
|
||||
dev_err(adev->dev, "Failed to reset SDMA instance %u\n", instance_id);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Invoke all registered post_reset callbacks */
|
||||
list_for_each_entry(funcs, &adev->sdma.reset_callback_list, list) {
|
||||
if (funcs->post_reset) {
|
||||
ret = funcs->post_reset(adev, instance_id);
|
||||
if (ret) {
|
||||
dev_err(adev->dev,
|
||||
"afterReset callback failed for instance %u: %d\n",
|
||||
instance_id, ret);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
/* Restart the scheduler's work queue for the GFX and page rings
|
||||
* if they were stopped by this function. This allows new tasks
|
||||
* to be submitted to the queues after the reset is complete.
|
||||
*/
|
||||
if (ret) {
|
||||
if (gfx_sched_stopped && amdgpu_ring_sched_ready(gfx_ring)) {
|
||||
drm_sched_wqueue_start(&gfx_ring->sched);
|
||||
}
|
||||
if (page_sched_stopped && amdgpu_ring_sched_ready(page_ring)) {
|
||||
drm_sched_wqueue_start(&page_ring->sched);
|
||||
}
|
||||
}
|
||||
|
||||
if (suspend_user_queues)
|
||||
amdgpu_amdkfd_resume(adev, false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,6 +98,13 @@ struct amdgpu_sdma_ras {
|
|||
struct amdgpu_ras_block_object ras_block;
|
||||
};
|
||||
|
||||
struct sdma_on_reset_funcs {
|
||||
int (*pre_reset)(struct amdgpu_device *adev, uint32_t instance_id);
|
||||
int (*post_reset)(struct amdgpu_device *adev, uint32_t instance_id);
|
||||
/* Linked list node to store this structure in a list; */
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct amdgpu_sdma {
|
||||
struct amdgpu_sdma_instance instance[AMDGPU_MAX_SDMA_INSTANCES];
|
||||
struct amdgpu_irq_src trap_irq;
|
||||
|
|
@ -118,6 +125,10 @@ struct amdgpu_sdma {
|
|||
struct amdgpu_sdma_ras *ras;
|
||||
uint32_t *ip_dump;
|
||||
uint32_t supported_reset;
|
||||
struct list_head reset_callback_list;
|
||||
/* track guilty state of GFX and PAGE queues */
|
||||
bool gfx_guilty;
|
||||
bool page_guilty;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -157,6 +168,9 @@ struct amdgpu_buffer_funcs {
|
|||
uint32_t byte_count);
|
||||
};
|
||||
|
||||
void amdgpu_sdma_register_on_reset_callbacks(struct amdgpu_device *adev, struct sdma_on_reset_funcs *funcs);
|
||||
int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id, bool suspend_user_queues);
|
||||
|
||||
#define amdgpu_emit_copy_buffer(adev, ib, s, d, b, t) (adev)->mman.buffer_funcs->emit_copy_buffer((ib), (s), (d), (b), (t))
|
||||
#define amdgpu_emit_fill_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_fill_buffer((ib), (s), (d), (b))
|
||||
|
||||
|
|
|
|||
|
|
@ -2295,7 +2295,7 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo,
|
|||
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
|
||||
struct amdgpu_res_cursor cursor;
|
||||
u64 addr;
|
||||
int r;
|
||||
int r = 0;
|
||||
|
||||
if (!adev->mman.buffer_funcs_enabled)
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -71,6 +71,13 @@
|
|||
*/
|
||||
#define UMC_CHANNEL_IDX_V2 BIT_ULL(47)
|
||||
|
||||
/*
|
||||
* save nps value to eeprom_table_record.retired_page[47:40],
|
||||
* the channel index flag above will be retired.
|
||||
*/
|
||||
#define UMC_NPS_SHIFT 40
|
||||
#define UMC_NPS_MASK 0xffULL
|
||||
|
||||
typedef int (*umc_func)(struct amdgpu_device *adev, uint32_t node_inst,
|
||||
uint32_t umc_inst, uint32_t ch_inst, void *data);
|
||||
|
||||
|
|
|
|||
|
|
@ -93,47 +93,53 @@ MODULE_FIRMWARE(FIRMWARE_VCN5_0_1);
|
|||
|
||||
static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
|
||||
|
||||
int amdgpu_vcn_early_init(struct amdgpu_device *adev)
|
||||
int amdgpu_vcn_early_init(struct amdgpu_device *adev, int i)
|
||||
{
|
||||
char ucode_prefix[25];
|
||||
int r, i;
|
||||
int r;
|
||||
|
||||
adev->vcn.inst[i].adev = adev;
|
||||
adev->vcn.inst[i].inst = i;
|
||||
amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix));
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
|
||||
if (i == 1 && amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 6))
|
||||
r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
|
||||
AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/%s_%d.bin", ucode_prefix, i);
|
||||
else
|
||||
r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
|
||||
|
||||
if (i != 0 && adev->vcn.per_inst_fw) {
|
||||
r = amdgpu_ucode_request(adev, &adev->vcn.inst[i].fw,
|
||||
AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/%s_%d.bin", ucode_prefix, i);
|
||||
if (r)
|
||||
amdgpu_ucode_release(&adev->vcn.inst[i].fw);
|
||||
} else {
|
||||
if (!adev->vcn.inst[0].fw) {
|
||||
r = amdgpu_ucode_request(adev, &adev->vcn.inst[0].fw,
|
||||
AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/%s.bin", ucode_prefix);
|
||||
if (r) {
|
||||
amdgpu_ucode_release(&adev->vcn.inst[i].fw);
|
||||
return r;
|
||||
if (r)
|
||||
amdgpu_ucode_release(&adev->vcn.inst[0].fw);
|
||||
} else {
|
||||
r = 0;
|
||||
}
|
||||
adev->vcn.inst[i].fw = adev->vcn.inst[0].fw;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
|
||||
int amdgpu_vcn_sw_init(struct amdgpu_device *adev, int i)
|
||||
{
|
||||
unsigned long bo_size;
|
||||
const struct common_firmware_header *hdr;
|
||||
unsigned char fw_check;
|
||||
unsigned int fw_shared_size, log_offset;
|
||||
int i, r;
|
||||
|
||||
INIT_DELAYED_WORK(&adev->vcn.idle_work, amdgpu_vcn_idle_work_handler);
|
||||
mutex_init(&adev->vcn.vcn_pg_lock);
|
||||
mutex_init(&adev->vcn.vcn1_jpeg1_workaround);
|
||||
atomic_set(&adev->vcn.total_submission_cnt, 0);
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; i++)
|
||||
atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
|
||||
int r;
|
||||
|
||||
mutex_init(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
|
||||
mutex_init(&adev->vcn.inst[i].vcn_pg_lock);
|
||||
atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0);
|
||||
INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler);
|
||||
atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
adev->vcn.inst[i].indirect_sram = true;
|
||||
|
||||
/*
|
||||
* Some Steam Deck's BIOS versions are incompatible with the
|
||||
|
|
@ -146,18 +152,19 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
|
|||
const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
|
||||
|
||||
if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
|
||||
!strncmp("F7A0114", bios_ver, 7))) {
|
||||
adev->vcn.indirect_sram = false;
|
||||
!strncmp("F7A0114", bios_ver, 7))) {
|
||||
adev->vcn.inst[i].indirect_sram = false;
|
||||
dev_info(adev->dev,
|
||||
"Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
|
||||
"Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
|
||||
}
|
||||
}
|
||||
|
||||
/* from vcn4 and above, only unified queue is used */
|
||||
adev->vcn.using_unified_queue =
|
||||
adev->vcn.inst[i].using_unified_queue =
|
||||
amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0);
|
||||
|
||||
hdr = (const struct common_firmware_header *)adev->vcn.inst[0].fw->data;
|
||||
hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
|
||||
adev->vcn.inst[i].fw_version = le32_to_cpu(hdr->ucode_version);
|
||||
adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
|
||||
|
||||
/* Bit 20-23, it is encode major and non-zero for new naming convention.
|
||||
|
|
@ -175,16 +182,17 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
|
|||
enc_major = fw_check;
|
||||
dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
|
||||
vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
|
||||
DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
|
||||
enc_major, enc_minor, dec_ver, vep, fw_rev);
|
||||
dev_info(adev->dev,
|
||||
"Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",
|
||||
enc_major, enc_minor, dec_ver, vep, fw_rev);
|
||||
} else {
|
||||
unsigned int version_major, version_minor, family_id;
|
||||
|
||||
family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
|
||||
version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
|
||||
version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
|
||||
DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",
|
||||
version_major, version_minor, family_id);
|
||||
dev_info(adev->dev, "Found VCN firmware Version: %u.%u Family ID: %u\n",
|
||||
version_major, version_minor, family_id);
|
||||
}
|
||||
|
||||
bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;
|
||||
|
|
@ -207,80 +215,77 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
|
|||
if (amdgpu_vcnfw_log)
|
||||
bo_size += AMDGPU_VCNFW_LOG_SIZE;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
continue;
|
||||
r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->vcn.inst[i].vcpu_bo,
|
||||
&adev->vcn.inst[i].gpu_addr,
|
||||
&adev->vcn.inst[i].cpu_addr);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "(%d) failed to allocate vcn bo\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
|
||||
adev->vcn.inst[i].fw_shared.cpu_addr = adev->vcn.inst[i].cpu_addr +
|
||||
bo_size - fw_shared_size;
|
||||
adev->vcn.inst[i].fw_shared.gpu_addr = adev->vcn.inst[i].gpu_addr +
|
||||
bo_size - fw_shared_size;
|
||||
|
||||
adev->vcn.inst[i].fw_shared.mem_size = fw_shared_size;
|
||||
|
||||
if (amdgpu_vcnfw_log) {
|
||||
adev->vcn.inst[i].fw_shared.cpu_addr -= AMDGPU_VCNFW_LOG_SIZE;
|
||||
adev->vcn.inst[i].fw_shared.gpu_addr -= AMDGPU_VCNFW_LOG_SIZE;
|
||||
adev->vcn.inst[i].fw_shared.log_offset = log_offset;
|
||||
}
|
||||
|
||||
if (adev->vcn.inst[i].indirect_sram) {
|
||||
r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->vcn.inst[i].vcpu_bo,
|
||||
&adev->vcn.inst[i].gpu_addr,
|
||||
&adev->vcn.inst[i].cpu_addr);
|
||||
&adev->vcn.inst[i].dpg_sram_bo,
|
||||
&adev->vcn.inst[i].dpg_sram_gpu_addr,
|
||||
&adev->vcn.inst[i].dpg_sram_cpu_addr);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "(%d) failed to allocate vcn bo\n", r);
|
||||
dev_err(adev->dev, "VCN %d (%d) failed to allocate DPG bo\n", i, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
adev->vcn.inst[i].fw_shared.cpu_addr = adev->vcn.inst[i].cpu_addr +
|
||||
bo_size - fw_shared_size;
|
||||
adev->vcn.inst[i].fw_shared.gpu_addr = adev->vcn.inst[i].gpu_addr +
|
||||
bo_size - fw_shared_size;
|
||||
|
||||
adev->vcn.inst[i].fw_shared.mem_size = fw_shared_size;
|
||||
|
||||
if (amdgpu_vcnfw_log) {
|
||||
adev->vcn.inst[i].fw_shared.cpu_addr -= AMDGPU_VCNFW_LOG_SIZE;
|
||||
adev->vcn.inst[i].fw_shared.gpu_addr -= AMDGPU_VCNFW_LOG_SIZE;
|
||||
adev->vcn.inst[i].fw_shared.log_offset = log_offset;
|
||||
}
|
||||
|
||||
if (adev->vcn.indirect_sram) {
|
||||
r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->vcn.inst[i].dpg_sram_bo,
|
||||
&adev->vcn.inst[i].dpg_sram_gpu_addr,
|
||||
&adev->vcn.inst[i].dpg_sram_cpu_addr);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "VCN %d (%d) failed to allocate DPG bo\n", i, r);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
|
||||
int amdgpu_vcn_sw_fini(struct amdgpu_device *adev, int i)
|
||||
{
|
||||
int i, j;
|
||||
int j;
|
||||
|
||||
for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
|
||||
if (adev->vcn.harvest_config & (1 << j))
|
||||
continue;
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
return 0;
|
||||
|
||||
amdgpu_bo_free_kernel(
|
||||
&adev->vcn.inst[j].dpg_sram_bo,
|
||||
&adev->vcn.inst[j].dpg_sram_gpu_addr,
|
||||
(void **)&adev->vcn.inst[j].dpg_sram_cpu_addr);
|
||||
amdgpu_bo_free_kernel(
|
||||
&adev->vcn.inst[i].dpg_sram_bo,
|
||||
&adev->vcn.inst[i].dpg_sram_gpu_addr,
|
||||
(void **)&adev->vcn.inst[i].dpg_sram_cpu_addr);
|
||||
|
||||
kvfree(adev->vcn.inst[j].saved_bo);
|
||||
kvfree(adev->vcn.inst[i].saved_bo);
|
||||
|
||||
amdgpu_bo_free_kernel(&adev->vcn.inst[j].vcpu_bo,
|
||||
&adev->vcn.inst[j].gpu_addr,
|
||||
(void **)&adev->vcn.inst[j].cpu_addr);
|
||||
amdgpu_bo_free_kernel(&adev->vcn.inst[i].vcpu_bo,
|
||||
&adev->vcn.inst[i].gpu_addr,
|
||||
(void **)&adev->vcn.inst[i].cpu_addr);
|
||||
|
||||
amdgpu_ring_fini(&adev->vcn.inst[j].ring_dec);
|
||||
amdgpu_ring_fini(&adev->vcn.inst[i].ring_dec);
|
||||
|
||||
for (i = 0; i < adev->vcn.num_enc_rings; ++i)
|
||||
amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]);
|
||||
for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j)
|
||||
amdgpu_ring_fini(&adev->vcn.inst[i].ring_enc[j]);
|
||||
|
||||
amdgpu_ucode_release(&adev->vcn.inst[j].fw);
|
||||
if (adev->vcn.per_inst_fw) {
|
||||
amdgpu_ucode_release(&adev->vcn.inst[i].fw);
|
||||
} else {
|
||||
amdgpu_ucode_release(&adev->vcn.inst[0].fw);
|
||||
adev->vcn.inst[i].fw = NULL;
|
||||
}
|
||||
|
||||
mutex_destroy(&adev->vcn.vcn1_jpeg1_workaround);
|
||||
mutex_destroy(&adev->vcn.vcn_pg_lock);
|
||||
mutex_destroy(&adev->vcn.inst[i].vcn_pg_lock);
|
||||
mutex_destroy(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -300,179 +305,190 @@ bool amdgpu_vcn_is_disabled_vcn(struct amdgpu_device *adev, enum vcn_ring_type t
|
|||
return ret;
|
||||
}
|
||||
|
||||
int amdgpu_vcn_save_vcpu_bo(struct amdgpu_device *adev)
|
||||
static int amdgpu_vcn_save_vcpu_bo_inst(struct amdgpu_device *adev, int i)
|
||||
{
|
||||
unsigned int size;
|
||||
void *ptr;
|
||||
int i, idx;
|
||||
int idx;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
continue;
|
||||
if (adev->vcn.inst[i].vcpu_bo == NULL)
|
||||
return 0;
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
return 0;
|
||||
if (adev->vcn.inst[i].vcpu_bo == NULL)
|
||||
return 0;
|
||||
|
||||
size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);
|
||||
ptr = adev->vcn.inst[i].cpu_addr;
|
||||
size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);
|
||||
ptr = adev->vcn.inst[i].cpu_addr;
|
||||
|
||||
adev->vcn.inst[i].saved_bo = kvmalloc(size, GFP_KERNEL);
|
||||
if (!adev->vcn.inst[i].saved_bo)
|
||||
return -ENOMEM;
|
||||
adev->vcn.inst[i].saved_bo = kvmalloc(size, GFP_KERNEL);
|
||||
if (!adev->vcn.inst[i].saved_bo)
|
||||
return -ENOMEM;
|
||||
|
||||
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
|
||||
memcpy_fromio(adev->vcn.inst[i].saved_bo, ptr, size);
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
|
||||
memcpy_fromio(adev->vcn.inst[i].saved_bo, ptr, size);
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_vcn_suspend(struct amdgpu_device *adev)
|
||||
int amdgpu_vcn_save_vcpu_bo(struct amdgpu_device *adev)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
||||
ret = amdgpu_vcn_save_vcpu_bo_inst(adev, i);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_vcn_suspend(struct amdgpu_device *adev, int i)
|
||||
{
|
||||
bool in_ras_intr = amdgpu_ras_intr_triggered();
|
||||
|
||||
cancel_delayed_work_sync(&adev->vcn.idle_work);
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
return 0;
|
||||
|
||||
cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work);
|
||||
|
||||
/* err_event_athub will corrupt VCPU buffer, so we need to
|
||||
* restore fw data and clear buffer in amdgpu_vcn_resume() */
|
||||
if (in_ras_intr)
|
||||
return 0;
|
||||
|
||||
return amdgpu_vcn_save_vcpu_bo(adev);
|
||||
return amdgpu_vcn_save_vcpu_bo_inst(adev, i);
|
||||
}
|
||||
|
||||
int amdgpu_vcn_resume(struct amdgpu_device *adev)
|
||||
int amdgpu_vcn_resume(struct amdgpu_device *adev, int i)
|
||||
{
|
||||
unsigned int size;
|
||||
void *ptr;
|
||||
int i, idx;
|
||||
int idx;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
continue;
|
||||
if (adev->vcn.inst[i].vcpu_bo == NULL)
|
||||
return -EINVAL;
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
return 0;
|
||||
if (adev->vcn.inst[i].vcpu_bo == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);
|
||||
ptr = adev->vcn.inst[i].cpu_addr;
|
||||
size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);
|
||||
ptr = adev->vcn.inst[i].cpu_addr;
|
||||
|
||||
if (adev->vcn.inst[i].saved_bo != NULL) {
|
||||
if (adev->vcn.inst[i].saved_bo != NULL) {
|
||||
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
|
||||
memcpy_toio(ptr, adev->vcn.inst[i].saved_bo, size);
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
kvfree(adev->vcn.inst[i].saved_bo);
|
||||
adev->vcn.inst[i].saved_bo = NULL;
|
||||
} else {
|
||||
const struct common_firmware_header *hdr;
|
||||
unsigned int offset;
|
||||
|
||||
hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
|
||||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
|
||||
offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
|
||||
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
|
||||
memcpy_toio(ptr, adev->vcn.inst[i].saved_bo, size);
|
||||
memcpy_toio(adev->vcn.inst[i].cpu_addr,
|
||||
adev->vcn.inst[i].fw->data + offset,
|
||||
le32_to_cpu(hdr->ucode_size_bytes));
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
kvfree(adev->vcn.inst[i].saved_bo);
|
||||
adev->vcn.inst[i].saved_bo = NULL;
|
||||
} else {
|
||||
const struct common_firmware_header *hdr;
|
||||
unsigned int offset;
|
||||
|
||||
hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
|
||||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
|
||||
offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
|
||||
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
|
||||
memcpy_toio(adev->vcn.inst[i].cpu_addr,
|
||||
adev->vcn.inst[i].fw->data + offset,
|
||||
le32_to_cpu(hdr->ucode_size_bytes));
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
size -= le32_to_cpu(hdr->ucode_size_bytes);
|
||||
ptr += le32_to_cpu(hdr->ucode_size_bytes);
|
||||
}
|
||||
memset_io(ptr, 0, size);
|
||||
size -= le32_to_cpu(hdr->ucode_size_bytes);
|
||||
ptr += le32_to_cpu(hdr->ucode_size_bytes);
|
||||
}
|
||||
memset_io(ptr, 0, size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_device *adev =
|
||||
container_of(work, struct amdgpu_device, vcn.idle_work.work);
|
||||
struct amdgpu_vcn_inst *vcn_inst =
|
||||
container_of(work, struct amdgpu_vcn_inst, idle_work.work);
|
||||
struct amdgpu_device *adev = vcn_inst->adev;
|
||||
unsigned int fences = 0, fence[AMDGPU_MAX_VCN_INSTANCES] = {0};
|
||||
unsigned int i, j;
|
||||
unsigned int i = vcn_inst->inst, j;
|
||||
int r = 0;
|
||||
|
||||
for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
|
||||
if (adev->vcn.harvest_config & (1 << j))
|
||||
continue;
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
return;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_enc_rings; ++i)
|
||||
fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_enc[i]);
|
||||
for (j = 0; j < adev->vcn.inst[i].num_enc_rings; ++j)
|
||||
fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_enc[j]);
|
||||
|
||||
/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
|
||||
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
|
||||
!adev->vcn.using_unified_queue) {
|
||||
struct dpg_pause_state new_state;
|
||||
/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
|
||||
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
|
||||
!adev->vcn.inst[i].using_unified_queue) {
|
||||
struct dpg_pause_state new_state;
|
||||
|
||||
if (fence[j] ||
|
||||
unlikely(atomic_read(&adev->vcn.inst[j].dpg_enc_submission_cnt)))
|
||||
new_state.fw_based = VCN_DPG_STATE__PAUSE;
|
||||
else
|
||||
new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
|
||||
if (fence[i] ||
|
||||
unlikely(atomic_read(&vcn_inst->dpg_enc_submission_cnt)))
|
||||
new_state.fw_based = VCN_DPG_STATE__PAUSE;
|
||||
else
|
||||
new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
|
||||
|
||||
adev->vcn.pause_dpg_mode(adev, j, &new_state);
|
||||
}
|
||||
|
||||
fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_dec);
|
||||
fences += fence[j];
|
||||
adev->vcn.inst[i].pause_dpg_mode(vcn_inst, &new_state);
|
||||
}
|
||||
|
||||
if (!fences && !atomic_read(&adev->vcn.total_submission_cnt)) {
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
|
||||
AMD_PG_STATE_GATE);
|
||||
fence[i] += amdgpu_fence_count_emitted(&vcn_inst->ring_dec);
|
||||
fences += fence[i];
|
||||
|
||||
if (!fences && !atomic_read(&vcn_inst->total_submission_cnt)) {
|
||||
vcn_inst->set_pg_state(vcn_inst, AMD_PG_STATE_GATE);
|
||||
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
|
||||
false);
|
||||
false);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "(%d) failed to disable video power profile mode\n", r);
|
||||
} else {
|
||||
schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
|
||||
schedule_delayed_work(&vcn_inst->idle_work, VCN_IDLE_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_vcn_inst *vcn_inst = &adev->vcn.inst[ring->me];
|
||||
int r = 0;
|
||||
|
||||
atomic_inc(&adev->vcn.total_submission_cnt);
|
||||
atomic_inc(&vcn_inst->total_submission_cnt);
|
||||
|
||||
if (!cancel_delayed_work_sync(&adev->vcn.idle_work)) {
|
||||
if (!cancel_delayed_work_sync(&vcn_inst->idle_work)) {
|
||||
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
|
||||
true);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r);
|
||||
}
|
||||
|
||||
mutex_lock(&adev->vcn.vcn_pg_lock);
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
|
||||
AMD_PG_STATE_UNGATE);
|
||||
mutex_lock(&vcn_inst->vcn_pg_lock);
|
||||
vcn_inst->set_pg_state(vcn_inst, AMD_PG_STATE_UNGATE);
|
||||
|
||||
/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
|
||||
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
|
||||
!adev->vcn.using_unified_queue) {
|
||||
!vcn_inst->using_unified_queue) {
|
||||
struct dpg_pause_state new_state;
|
||||
|
||||
if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) {
|
||||
atomic_inc(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt);
|
||||
atomic_inc(&vcn_inst->dpg_enc_submission_cnt);
|
||||
new_state.fw_based = VCN_DPG_STATE__PAUSE;
|
||||
} else {
|
||||
unsigned int fences = 0;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_enc_rings; ++i)
|
||||
fences += amdgpu_fence_count_emitted(&adev->vcn.inst[ring->me].ring_enc[i]);
|
||||
for (i = 0; i < vcn_inst->num_enc_rings; ++i)
|
||||
fences += amdgpu_fence_count_emitted(&vcn_inst->ring_enc[i]);
|
||||
|
||||
if (fences || atomic_read(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt))
|
||||
if (fences || atomic_read(&vcn_inst->dpg_enc_submission_cnt))
|
||||
new_state.fw_based = VCN_DPG_STATE__PAUSE;
|
||||
else
|
||||
new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
|
||||
}
|
||||
|
||||
adev->vcn.pause_dpg_mode(adev, ring->me, &new_state);
|
||||
vcn_inst->pause_dpg_mode(vcn_inst, &new_state);
|
||||
}
|
||||
mutex_unlock(&adev->vcn.vcn_pg_lock);
|
||||
mutex_unlock(&vcn_inst->vcn_pg_lock);
|
||||
}
|
||||
|
||||
void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
|
||||
|
|
@ -482,12 +498,13 @@ void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
|
|||
/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
|
||||
if (ring->adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
|
||||
ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC &&
|
||||
!adev->vcn.using_unified_queue)
|
||||
!adev->vcn.inst[ring->me].using_unified_queue)
|
||||
atomic_dec(&ring->adev->vcn.inst[ring->me].dpg_enc_submission_cnt);
|
||||
|
||||
atomic_dec(&ring->adev->vcn.total_submission_cnt);
|
||||
atomic_dec(&ring->adev->vcn.inst[ring->me].total_submission_cnt);
|
||||
|
||||
schedule_delayed_work(&ring->adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
|
||||
schedule_delayed_work(&ring->adev->vcn.inst[ring->me].idle_work,
|
||||
VCN_IDLE_TIMEOUT);
|
||||
}
|
||||
|
||||
int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)
|
||||
|
|
@ -505,7 +522,7 @@ int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)
|
|||
r = amdgpu_ring_alloc(ring, 3);
|
||||
if (r)
|
||||
return r;
|
||||
amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0));
|
||||
amdgpu_ring_write(ring, PACKET0(adev->vcn.inst[ring->me].internal.scratch9, 0));
|
||||
amdgpu_ring_write(ring, 0xDEADBEEF);
|
||||
amdgpu_ring_commit(ring);
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
|
|
@ -570,14 +587,14 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
|
|||
goto err;
|
||||
|
||||
ib = &job->ibs[0];
|
||||
ib->ptr[0] = PACKET0(adev->vcn.internal.data0, 0);
|
||||
ib->ptr[0] = PACKET0(adev->vcn.inst[ring->me].internal.data0, 0);
|
||||
ib->ptr[1] = addr;
|
||||
ib->ptr[2] = PACKET0(adev->vcn.internal.data1, 0);
|
||||
ib->ptr[2] = PACKET0(adev->vcn.inst[ring->me].internal.data1, 0);
|
||||
ib->ptr[3] = addr >> 32;
|
||||
ib->ptr[4] = PACKET0(adev->vcn.internal.cmd, 0);
|
||||
ib->ptr[4] = PACKET0(adev->vcn.inst[ring->me].internal.cmd, 0);
|
||||
ib->ptr[5] = 0;
|
||||
for (i = 6; i < 16; i += 2) {
|
||||
ib->ptr[i] = PACKET0(adev->vcn.internal.nop, 0);
|
||||
ib->ptr[i] = PACKET0(adev->vcn.inst[ring->me].internal.nop, 0);
|
||||
ib->ptr[i+1] = 0;
|
||||
}
|
||||
ib->length_dw = 16;
|
||||
|
|
@ -740,7 +757,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
|
|||
uint32_t ib_pack_in_dw;
|
||||
int i, r;
|
||||
|
||||
if (adev->vcn.using_unified_queue)
|
||||
if (adev->vcn.inst[ring->me].using_unified_queue)
|
||||
ib_size_dw += 8;
|
||||
|
||||
r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
|
||||
|
|
@ -753,7 +770,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
|
|||
ib->length_dw = 0;
|
||||
|
||||
/* single queue headers */
|
||||
if (adev->vcn.using_unified_queue) {
|
||||
if (adev->vcn.inst[ring->me].using_unified_queue) {
|
||||
ib_pack_in_dw = sizeof(struct amdgpu_vcn_decode_buffer) / sizeof(uint32_t)
|
||||
+ 4 + 2; /* engine info + decoding ib in dw */
|
||||
ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, ib_pack_in_dw, false);
|
||||
|
|
@ -772,7 +789,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
|
|||
for (i = ib->length_dw; i < ib_size_dw; ++i)
|
||||
ib->ptr[i] = 0x0;
|
||||
|
||||
if (adev->vcn.using_unified_queue)
|
||||
if (adev->vcn.inst[ring->me].using_unified_queue)
|
||||
amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, ib_pack_in_dw);
|
||||
|
||||
r = amdgpu_job_submit_direct(job, ring, &f);
|
||||
|
|
@ -870,7 +887,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
|
|||
uint64_t addr;
|
||||
int i, r;
|
||||
|
||||
if (adev->vcn.using_unified_queue)
|
||||
if (adev->vcn.inst[ring->me].using_unified_queue)
|
||||
ib_size_dw += 8;
|
||||
|
||||
r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
|
||||
|
|
@ -884,7 +901,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
|
|||
|
||||
ib->length_dw = 0;
|
||||
|
||||
if (adev->vcn.using_unified_queue)
|
||||
if (adev->vcn.inst[ring->me].using_unified_queue)
|
||||
ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true);
|
||||
|
||||
ib->ptr[ib->length_dw++] = 0x00000018;
|
||||
|
|
@ -906,7 +923,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
|
|||
for (i = ib->length_dw; i < ib_size_dw; ++i)
|
||||
ib->ptr[i] = 0x0;
|
||||
|
||||
if (adev->vcn.using_unified_queue)
|
||||
if (adev->vcn.inst[ring->me].using_unified_queue)
|
||||
amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11);
|
||||
|
||||
r = amdgpu_job_submit_direct(job, ring, &f);
|
||||
|
|
@ -937,7 +954,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
|
|||
uint64_t addr;
|
||||
int i, r;
|
||||
|
||||
if (adev->vcn.using_unified_queue)
|
||||
if (adev->vcn.inst[ring->me].using_unified_queue)
|
||||
ib_size_dw += 8;
|
||||
|
||||
r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
|
||||
|
|
@ -951,7 +968,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
|
|||
|
||||
ib->length_dw = 0;
|
||||
|
||||
if (adev->vcn.using_unified_queue)
|
||||
if (adev->vcn.inst[ring->me].using_unified_queue)
|
||||
ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true);
|
||||
|
||||
ib->ptr[ib->length_dw++] = 0x00000018;
|
||||
|
|
@ -973,7 +990,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
|
|||
for (i = ib->length_dw; i < ib_size_dw; ++i)
|
||||
ib->ptr[i] = 0x0;
|
||||
|
||||
if (adev->vcn.using_unified_queue)
|
||||
if (adev->vcn.inst[ring->me].using_unified_queue)
|
||||
amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11);
|
||||
|
||||
r = amdgpu_job_submit_direct(job, ring, &f);
|
||||
|
|
@ -1058,36 +1075,32 @@ enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring)
|
|||
}
|
||||
}
|
||||
|
||||
void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev)
|
||||
void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev, int i)
|
||||
{
|
||||
int i;
|
||||
unsigned int idx;
|
||||
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
|
||||
const struct common_firmware_header *hdr;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
continue;
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
return;
|
||||
|
||||
hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
|
||||
/* currently only support 2 FW instances */
|
||||
if (i >= 2) {
|
||||
dev_info(adev->dev, "More then 2 VCN FW instances!\n");
|
||||
break;
|
||||
}
|
||||
idx = AMDGPU_UCODE_ID_VCN + i;
|
||||
adev->firmware.ucode[idx].ucode_id = idx;
|
||||
adev->firmware.ucode[idx].fw = adev->vcn.inst[i].fw;
|
||||
adev->firmware.fw_size +=
|
||||
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
|
||||
if ((amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 3) ||
|
||||
amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(5, 0, 1))
|
||||
&& (i > 0))
|
||||
return;
|
||||
|
||||
if (amdgpu_ip_version(adev, UVD_HWIP, 0) ==
|
||||
IP_VERSION(4, 0, 3) ||
|
||||
amdgpu_ip_version(adev, UVD_HWIP, 0) ==
|
||||
IP_VERSION(5, 0, 1))
|
||||
break;
|
||||
hdr = (const struct common_firmware_header *)adev->vcn.inst[i].fw->data;
|
||||
/* currently only support 2 FW instances */
|
||||
if (i >= 2) {
|
||||
dev_info(adev->dev, "More then 2 VCN FW instances!\n");
|
||||
return;
|
||||
}
|
||||
idx = AMDGPU_UCODE_ID_VCN + i;
|
||||
adev->firmware.ucode[idx].ucode_id = idx;
|
||||
adev->firmware.ucode[idx].fw = adev->vcn.inst[i].fw;
|
||||
adev->firmware.fw_size +=
|
||||
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1390,10 +1403,33 @@ void amdgpu_debugfs_vcn_sched_mask_init(struct amdgpu_device *adev)
|
|||
struct dentry *root = minor->debugfs_root;
|
||||
char name[32];
|
||||
|
||||
if (adev->vcn.num_vcn_inst <= 1 || !adev->vcn.using_unified_queue)
|
||||
if (adev->vcn.num_vcn_inst <= 1 || !adev->vcn.inst[0].using_unified_queue)
|
||||
return;
|
||||
sprintf(name, "amdgpu_vcn_sched_mask");
|
||||
debugfs_create_file(name, 0600, root, adev,
|
||||
&amdgpu_debugfs_vcn_sched_mask_fops);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_set_powergating_state - set VCN block powergating state
|
||||
*
|
||||
* @ip_block: amdgpu_ip_block pointer
|
||||
* @state: power gating state
|
||||
*
|
||||
* Set VCN block powergating state
|
||||
*/
|
||||
int vcn_set_powergating_state(struct amdgpu_ip_block *ip_block,
|
||||
enum amd_powergating_state state)
|
||||
{
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
int ret = 0, i;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
||||
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i];
|
||||
|
||||
ret |= vinst->set_pg_state(vinst, state);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -295,6 +295,8 @@ struct amdgpu_vcn_fw_shared {
|
|||
};
|
||||
|
||||
struct amdgpu_vcn_inst {
|
||||
struct amdgpu_device *adev;
|
||||
int inst;
|
||||
struct amdgpu_bo *vcpu_bo;
|
||||
void *cpu_addr;
|
||||
uint64_t gpu_addr;
|
||||
|
|
@ -316,6 +318,20 @@ struct amdgpu_vcn_inst {
|
|||
const struct firmware *fw; /* VCN firmware */
|
||||
uint8_t vcn_config;
|
||||
uint32_t vcn_codec_disable_mask;
|
||||
atomic_t total_submission_cnt;
|
||||
struct mutex vcn_pg_lock;
|
||||
enum amd_powergating_state cur_state;
|
||||
struct delayed_work idle_work;
|
||||
unsigned fw_version;
|
||||
unsigned num_enc_rings;
|
||||
bool indirect_sram;
|
||||
struct amdgpu_vcn_reg internal;
|
||||
struct mutex vcn1_jpeg1_workaround;
|
||||
int (*pause_dpg_mode)(struct amdgpu_vcn_inst *vinst,
|
||||
struct dpg_pause_state *new_state);
|
||||
int (*set_pg_state)(struct amdgpu_vcn_inst *vinst,
|
||||
enum amd_powergating_state state);
|
||||
bool using_unified_queue;
|
||||
};
|
||||
|
||||
struct amdgpu_vcn_ras {
|
||||
|
|
@ -323,35 +339,25 @@ struct amdgpu_vcn_ras {
|
|||
};
|
||||
|
||||
struct amdgpu_vcn {
|
||||
unsigned fw_version;
|
||||
struct delayed_work idle_work;
|
||||
unsigned num_enc_rings;
|
||||
enum amd_powergating_state cur_state;
|
||||
bool indirect_sram;
|
||||
|
||||
uint8_t num_vcn_inst;
|
||||
struct amdgpu_vcn_inst inst[AMDGPU_MAX_VCN_INSTANCES];
|
||||
struct amdgpu_vcn_reg internal;
|
||||
struct mutex vcn_pg_lock;
|
||||
struct mutex vcn1_jpeg1_workaround;
|
||||
atomic_t total_submission_cnt;
|
||||
|
||||
unsigned harvest_config;
|
||||
int (*pause_dpg_mode)(struct amdgpu_device *adev,
|
||||
int inst_idx, struct dpg_pause_state *new_state);
|
||||
|
||||
struct ras_common_if *ras_if;
|
||||
struct amdgpu_vcn_ras *ras;
|
||||
|
||||
uint16_t inst_mask;
|
||||
uint8_t num_inst_per_aid;
|
||||
bool using_unified_queue;
|
||||
|
||||
/* IP reg dump */
|
||||
uint32_t *ip_dump;
|
||||
|
||||
uint32_t supported_reset;
|
||||
uint32_t caps;
|
||||
|
||||
bool per_inst_fw;
|
||||
unsigned fw_version;
|
||||
};
|
||||
|
||||
struct amdgpu_fw_shared_rb_ptrs_struct {
|
||||
|
|
@ -500,11 +506,11 @@ enum vcn_ring_type {
|
|||
VCN_UNIFIED_RING,
|
||||
};
|
||||
|
||||
int amdgpu_vcn_early_init(struct amdgpu_device *adev);
|
||||
int amdgpu_vcn_sw_init(struct amdgpu_device *adev);
|
||||
int amdgpu_vcn_sw_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_vcn_suspend(struct amdgpu_device *adev);
|
||||
int amdgpu_vcn_resume(struct amdgpu_device *adev);
|
||||
int amdgpu_vcn_early_init(struct amdgpu_device *adev, int i);
|
||||
int amdgpu_vcn_sw_init(struct amdgpu_device *adev, int i);
|
||||
int amdgpu_vcn_sw_fini(struct amdgpu_device *adev, int i);
|
||||
int amdgpu_vcn_suspend(struct amdgpu_device *adev, int i);
|
||||
int amdgpu_vcn_resume(struct amdgpu_device *adev, int i);
|
||||
void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring);
|
||||
void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring);
|
||||
|
||||
|
|
@ -522,7 +528,7 @@ int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout);
|
|||
|
||||
enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring);
|
||||
|
||||
void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev);
|
||||
void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev, int i);
|
||||
|
||||
void amdgpu_vcn_fwlog_init(struct amdgpu_vcn_inst *vcn);
|
||||
void amdgpu_debugfs_vcn_fwlog_init(struct amdgpu_device *adev,
|
||||
|
|
@ -542,4 +548,7 @@ int amdgpu_vcn_sysfs_reset_mask_init(struct amdgpu_device *adev);
|
|||
void amdgpu_vcn_sysfs_reset_mask_fini(struct amdgpu_device *adev);
|
||||
void amdgpu_debugfs_vcn_sched_mask_init(struct amdgpu_device *adev);
|
||||
|
||||
int vcn_set_powergating_state(struct amdgpu_ip_block *ip_block,
|
||||
enum amd_powergating_state state);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -739,7 +739,7 @@ void amdgpu_virt_exchange_data(struct amdgpu_device *adev)
|
|||
}
|
||||
}
|
||||
|
||||
void amdgpu_detect_virtualization(struct amdgpu_device *adev)
|
||||
static u32 amdgpu_virt_init_detect_asic(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
|
|
@ -775,8 +775,17 @@ void amdgpu_detect_virtualization(struct amdgpu_device *adev)
|
|||
adev->virt.caps |= AMDGPU_PASSTHROUGH_MODE;
|
||||
}
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
static bool amdgpu_virt_init_req_data(struct amdgpu_device *adev, u32 reg)
|
||||
{
|
||||
bool is_sriov = false;
|
||||
|
||||
/* we have the ability to check now */
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
is_sriov = true;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_TONGA:
|
||||
case CHIP_FIJI:
|
||||
|
|
@ -805,10 +814,39 @@ void amdgpu_detect_virtualization(struct amdgpu_device *adev)
|
|||
amdgpu_virt_request_init_data(adev);
|
||||
break;
|
||||
default: /* other chip doesn't support SRIOV */
|
||||
is_sriov = false;
|
||||
DRM_ERROR("Unknown asic type: %d!\n", adev->asic_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return is_sriov;
|
||||
}
|
||||
|
||||
static void amdgpu_virt_init_ras(struct amdgpu_device *adev)
|
||||
{
|
||||
ratelimit_state_init(&adev->virt.ras.ras_error_cnt_rs, 5 * HZ, 1);
|
||||
ratelimit_state_init(&adev->virt.ras.ras_cper_dump_rs, 5 * HZ, 1);
|
||||
|
||||
ratelimit_set_flags(&adev->virt.ras.ras_error_cnt_rs,
|
||||
RATELIMIT_MSG_ON_RELEASE);
|
||||
ratelimit_set_flags(&adev->virt.ras.ras_cper_dump_rs,
|
||||
RATELIMIT_MSG_ON_RELEASE);
|
||||
|
||||
mutex_init(&adev->virt.ras.ras_telemetry_mutex);
|
||||
|
||||
adev->virt.ras.cper_rptr = 0;
|
||||
}
|
||||
|
||||
void amdgpu_virt_init(struct amdgpu_device *adev)
|
||||
{
|
||||
bool is_sriov = false;
|
||||
uint32_t reg = amdgpu_virt_init_detect_asic(adev);
|
||||
|
||||
is_sriov = amdgpu_virt_init_req_data(adev, reg);
|
||||
|
||||
if (is_sriov)
|
||||
amdgpu_virt_init_ras(adev);
|
||||
}
|
||||
|
||||
static bool amdgpu_virt_access_debugfs_is_mmio(struct amdgpu_device *adev)
|
||||
|
|
@ -1288,10 +1326,12 @@ static int amdgpu_virt_req_ras_err_count_internal(struct amdgpu_device *adev, bo
|
|||
* will ignore incoming guest messages. Ratelimit the guest messages to
|
||||
* prevent guest self DOS.
|
||||
*/
|
||||
if (__ratelimit(&adev->virt.ras_telemetry_rs) || force_update) {
|
||||
if (__ratelimit(&virt->ras.ras_error_cnt_rs) || force_update) {
|
||||
mutex_lock(&virt->ras.ras_telemetry_mutex);
|
||||
if (!virt->ops->req_ras_err_count(adev))
|
||||
amdgpu_virt_cache_host_error_counts(adev,
|
||||
adev->virt.fw_reserve.ras_telemetry);
|
||||
virt->fw_reserve.ras_telemetry);
|
||||
mutex_unlock(&virt->ras.ras_telemetry_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1322,6 +1362,98 @@ int amdgpu_virt_req_ras_err_count(struct amdgpu_device *adev, enum amdgpu_ras_bl
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
amdgpu_virt_write_cpers_to_ring(struct amdgpu_device *adev,
|
||||
struct amdsriov_ras_telemetry *host_telemetry,
|
||||
u32 *more)
|
||||
{
|
||||
struct amd_sriov_ras_cper_dump *cper_dump = NULL;
|
||||
struct cper_hdr *entry = NULL;
|
||||
struct amdgpu_ring *ring = &adev->cper.ring_buf;
|
||||
uint32_t checksum, used_size, i;
|
||||
int ret = 0;
|
||||
|
||||
checksum = host_telemetry->header.checksum;
|
||||
used_size = host_telemetry->header.used_size;
|
||||
|
||||
if (used_size > (AMD_SRIOV_RAS_TELEMETRY_SIZE_KB << 10))
|
||||
return 0;
|
||||
|
||||
cper_dump = kmemdup(&host_telemetry->body.cper_dump, used_size, GFP_KERNEL);
|
||||
if (!cper_dump)
|
||||
return -ENOMEM;
|
||||
|
||||
if (checksum != amd_sriov_msg_checksum(cper_dump, used_size, 0, 0))
|
||||
goto out;
|
||||
|
||||
*more = cper_dump->more;
|
||||
|
||||
if (cper_dump->wptr < adev->virt.ras.cper_rptr) {
|
||||
dev_warn(
|
||||
adev->dev,
|
||||
"guest specified rptr that was too high! guest rptr: 0x%llx, host rptr: 0x%llx\n",
|
||||
adev->virt.ras.cper_rptr, cper_dump->wptr);
|
||||
|
||||
adev->virt.ras.cper_rptr = cper_dump->wptr;
|
||||
goto out;
|
||||
}
|
||||
|
||||
entry = (struct cper_hdr *)&cper_dump->buf[0];
|
||||
|
||||
for (i = 0; i < cper_dump->count; i++) {
|
||||
amdgpu_cper_ring_write(ring, entry, entry->record_length);
|
||||
entry = (struct cper_hdr *)((char *)entry +
|
||||
entry->record_length);
|
||||
}
|
||||
|
||||
if (cper_dump->overflow_count)
|
||||
dev_warn(adev->dev,
|
||||
"host reported CPER overflow of 0x%llx entries!\n",
|
||||
cper_dump->overflow_count);
|
||||
|
||||
adev->virt.ras.cper_rptr = cper_dump->wptr;
|
||||
out:
|
||||
kfree(cper_dump);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int amdgpu_virt_req_ras_cper_dump_internal(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_virt *virt = &adev->virt;
|
||||
int ret = 0;
|
||||
uint32_t more = 0;
|
||||
|
||||
if (!amdgpu_sriov_ras_cper_en(adev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
do {
|
||||
if (!virt->ops->req_ras_cper_dump(adev, virt->ras.cper_rptr))
|
||||
ret = amdgpu_virt_write_cpers_to_ring(
|
||||
adev, virt->fw_reserve.ras_telemetry, &more);
|
||||
else
|
||||
ret = 0;
|
||||
} while (more);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int amdgpu_virt_req_ras_cper_dump(struct amdgpu_device *adev, bool force_update)
|
||||
{
|
||||
struct amdgpu_virt *virt = &adev->virt;
|
||||
int ret = 0;
|
||||
|
||||
if ((__ratelimit(&virt->ras.ras_cper_dump_rs) || force_update) &&
|
||||
down_read_trylock(&adev->reset_domain->sem)) {
|
||||
mutex_lock(&virt->ras.ras_telemetry_mutex);
|
||||
ret = amdgpu_virt_req_ras_cper_dump_internal(adev);
|
||||
mutex_unlock(&virt->ras.ras_telemetry_mutex);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int amdgpu_virt_ras_telemetry_post_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
unsigned long ue_count, ce_count;
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ struct amdgpu_virt_ops {
|
|||
enum amdgpu_ras_block block);
|
||||
bool (*rcvd_ras_intr)(struct amdgpu_device *adev);
|
||||
int (*req_ras_err_count)(struct amdgpu_device *adev);
|
||||
int (*req_ras_cper_dump)(struct amdgpu_device *adev, u64 vf_rptr);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -140,6 +141,7 @@ enum AMDGIM_FEATURE_FLAG {
|
|||
AMDGIM_FEATURE_MES_INFO_ENABLE = (1 << 8),
|
||||
AMDGIM_FEATURE_RAS_CAPS = (1 << 9),
|
||||
AMDGIM_FEATURE_RAS_TELEMETRY = (1 << 10),
|
||||
AMDGIM_FEATURE_RAS_CPER = (1 << 11),
|
||||
};
|
||||
|
||||
enum AMDGIM_REG_ACCESS_FLAG {
|
||||
|
|
@ -242,6 +244,13 @@ struct amdgpu_virt_ras_err_handler_data {
|
|||
int last_reserved;
|
||||
};
|
||||
|
||||
struct amdgpu_virt_ras {
|
||||
struct ratelimit_state ras_error_cnt_rs;
|
||||
struct ratelimit_state ras_cper_dump_rs;
|
||||
struct mutex ras_telemetry_mutex;
|
||||
uint64_t cper_rptr;
|
||||
};
|
||||
|
||||
/* GPU virtualization */
|
||||
struct amdgpu_virt {
|
||||
uint32_t caps;
|
||||
|
|
@ -284,8 +293,7 @@ struct amdgpu_virt {
|
|||
|
||||
union amd_sriov_ras_caps ras_en_caps;
|
||||
union amd_sriov_ras_caps ras_telemetry_en_caps;
|
||||
|
||||
struct ratelimit_state ras_telemetry_rs;
|
||||
struct amdgpu_virt_ras ras;
|
||||
struct amd_sriov_ras_telemetry_error_count count_cache;
|
||||
};
|
||||
|
||||
|
|
@ -340,6 +348,9 @@ struct amdgpu_video_codec_info;
|
|||
#define amdgpu_sriov_ras_telemetry_block_en(adev, sriov_blk) \
|
||||
(amdgpu_sriov_ras_telemetry_en((adev)) && (adev)->virt.ras_telemetry_en_caps.all & BIT(sriov_blk))
|
||||
|
||||
#define amdgpu_sriov_ras_cper_en(adev) \
|
||||
((adev)->virt.gim_feature & AMDGIM_FEATURE_RAS_CPER)
|
||||
|
||||
static inline bool is_virtual_machine(void)
|
||||
{
|
||||
#if defined(CONFIG_X86)
|
||||
|
|
@ -378,7 +389,7 @@ void amdgpu_virt_release_ras_err_handler_data(struct amdgpu_device *adev);
|
|||
void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_exchange_data(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_fini_data_exchange(struct amdgpu_device *adev);
|
||||
void amdgpu_detect_virtualization(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_init(struct amdgpu_device *adev);
|
||||
|
||||
bool amdgpu_virt_can_access_debugfs(struct amdgpu_device *adev);
|
||||
int amdgpu_virt_enable_access_debugfs(struct amdgpu_device *adev);
|
||||
|
|
@ -406,6 +417,7 @@ u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 f
|
|||
bool amdgpu_virt_get_ras_capability(struct amdgpu_device *adev);
|
||||
int amdgpu_virt_req_ras_err_count(struct amdgpu_device *adev, enum amdgpu_ras_block block,
|
||||
struct ras_err_data *err_data);
|
||||
int amdgpu_virt_req_ras_cper_dump(struct amdgpu_device *adev, bool force_update);
|
||||
int amdgpu_virt_ras_telemetry_post_reset(struct amdgpu_device *adev);
|
||||
bool amdgpu_virt_ras_telemetry_block_en(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block);
|
||||
|
|
|
|||
|
|
@ -627,7 +627,7 @@ static int amdgpu_vkms_resume(struct amdgpu_ip_block *ip_block)
|
|||
return drm_mode_config_helper_resume(adev_to_drm(ip_block->adev));
|
||||
}
|
||||
|
||||
static bool amdgpu_vkms_is_idle(void *handle)
|
||||
static bool amdgpu_vkms_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -315,6 +315,7 @@ int amdgpu_get_xgmi_link_status(struct amdgpu_device *adev, int global_link_num)
|
|||
|
||||
switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
|
||||
case IP_VERSION(6, 4, 0):
|
||||
case IP_VERSION(6, 4, 1):
|
||||
xgmi_state_reg_val = xgmi_v6_4_get_link_status(adev, global_link_num);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -818,28 +819,69 @@ int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_dev
|
|||
* num_hops[2:0] = number of hops
|
||||
*/
|
||||
int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev,
|
||||
struct amdgpu_device *peer_adev)
|
||||
struct amdgpu_device *peer_adev)
|
||||
{
|
||||
struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info;
|
||||
uint8_t num_hops_mask = 0x7;
|
||||
int i;
|
||||
|
||||
if (!adev->gmc.xgmi.supported)
|
||||
return 0;
|
||||
|
||||
for (i = 0 ; i < top->num_nodes; ++i)
|
||||
if (top->nodes[i].node_id == peer_adev->gmc.xgmi.node_id)
|
||||
return top->nodes[i].num_hops & num_hops_mask;
|
||||
return -EINVAL;
|
||||
|
||||
dev_err(adev->dev, "Failed to get xgmi hops count for peer %d.\n",
|
||||
peer_adev->gmc.xgmi.physical_node_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_xgmi_get_num_links(struct amdgpu_device *adev,
|
||||
struct amdgpu_device *peer_adev)
|
||||
int amdgpu_xgmi_get_bandwidth(struct amdgpu_device *adev, struct amdgpu_device *peer_adev,
|
||||
enum amdgpu_xgmi_bw_mode bw_mode, enum amdgpu_xgmi_bw_unit bw_unit,
|
||||
uint32_t *min_bw, uint32_t *max_bw)
|
||||
{
|
||||
struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info;
|
||||
int i;
|
||||
bool peer_mode = bw_mode == AMDGPU_XGMI_BW_MODE_PER_PEER;
|
||||
int unit_scale = bw_unit == AMDGPU_XGMI_BW_UNIT_MBYTES ? 1000 : 1;
|
||||
int speed = 25, num_lanes = 16, num_links = !peer_mode ? 1 : -1;
|
||||
|
||||
for (i = 0 ; i < top->num_nodes; ++i)
|
||||
if (top->nodes[i].node_id == peer_adev->gmc.xgmi.node_id)
|
||||
return top->nodes[i].num_links;
|
||||
return -EINVAL;
|
||||
if (!(min_bw && max_bw))
|
||||
return -EINVAL;
|
||||
|
||||
*min_bw = 0;
|
||||
*max_bw = 0;
|
||||
|
||||
if (!adev->gmc.xgmi.supported)
|
||||
return -ENODATA;
|
||||
|
||||
if (peer_mode && !peer_adev)
|
||||
return -EINVAL;
|
||||
|
||||
if (peer_mode) {
|
||||
struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info;
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < top->num_nodes; ++i) {
|
||||
if (top->nodes[i].node_id != peer_adev->gmc.xgmi.node_id)
|
||||
continue;
|
||||
|
||||
num_links = top->nodes[i].num_links;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_links == -1) {
|
||||
dev_err(adev->dev, "Failed to get number of xgmi links for peer %d.\n",
|
||||
peer_adev->gmc.xgmi.physical_node_id);
|
||||
} else if (num_links) {
|
||||
int per_link_bw = (speed * num_lanes * unit_scale)/BITS_PER_BYTE;
|
||||
|
||||
*min_bw = per_link_bw;
|
||||
*max_bw = num_links * per_link_bw;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool amdgpu_xgmi_get_is_sharing_enabled(struct amdgpu_device *adev,
|
||||
|
|
@ -1128,8 +1170,8 @@ static int xgmi_v6_4_0_aca_bank_parser(struct aca_handle *handle, struct aca_ban
|
|||
break;
|
||||
case ACA_SMU_TYPE_CE:
|
||||
count = ext_error_code == 6 ? count : 0ULL;
|
||||
bank->aca_err_type = ACA_ERROR_TYPE_CE;
|
||||
ret = aca_error_cache_log_bank_error(handle, &info, ACA_ERROR_TYPE_CE, count);
|
||||
bank->aca_err_type = ACA_BANK_ERR_CE_DE_DECODE(bank);
|
||||
ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type, count);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
@ -1164,6 +1206,7 @@ static int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev, struct ras_comm
|
|||
|
||||
switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
|
||||
case IP_VERSION(6, 4, 0):
|
||||
case IP_VERSION(6, 4, 1):
|
||||
r = amdgpu_ras_bind_aca(adev, AMDGPU_RAS_BLOCK__XGMI_WAFL,
|
||||
&xgmi_v6_4_0_aca_info, NULL);
|
||||
if (r)
|
||||
|
|
@ -1223,6 +1266,7 @@ static void amdgpu_xgmi_legacy_reset_ras_error_count(struct amdgpu_device *adev)
|
|||
|
||||
switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
|
||||
case IP_VERSION(6, 4, 0):
|
||||
case IP_VERSION(6, 4, 1):
|
||||
for (i = 0; i < ARRAY_SIZE(xgmi3x16_pcs_err_status_reg_v6_4); i++)
|
||||
pcs_clear_status(adev,
|
||||
xgmi3x16_pcs_err_status_reg_v6_4[i]);
|
||||
|
|
@ -1257,6 +1301,7 @@ static void amdgpu_xgmi_reset_ras_error_count(struct amdgpu_device *adev)
|
|||
{
|
||||
switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
|
||||
case IP_VERSION(6, 4, 0):
|
||||
case IP_VERSION(6, 4, 1):
|
||||
xgmi_v6_4_0_reset_ras_error_count(adev);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -1282,7 +1327,9 @@ static int amdgpu_xgmi_query_pcs_error_status(struct amdgpu_device *adev,
|
|||
if (amdgpu_ip_version(adev, XGMI_HWIP, 0) ==
|
||||
IP_VERSION(6, 1, 0) ||
|
||||
amdgpu_ip_version(adev, XGMI_HWIP, 0) ==
|
||||
IP_VERSION(6, 4, 0)) {
|
||||
IP_VERSION(6, 4, 0) ||
|
||||
amdgpu_ip_version(adev, XGMI_HWIP, 0) ==
|
||||
IP_VERSION(6, 4, 1)) {
|
||||
pcs_ras_fields = &xgmi3x16_pcs_ras_fields[0];
|
||||
field_array_size = ARRAY_SIZE(xgmi3x16_pcs_ras_fields);
|
||||
} else {
|
||||
|
|
@ -1390,6 +1437,7 @@ static void amdgpu_xgmi_legacy_query_ras_error_count(struct amdgpu_device *adev,
|
|||
|
||||
switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
|
||||
case IP_VERSION(6, 4, 0):
|
||||
case IP_VERSION(6, 4, 1):
|
||||
/* check xgmi3x16 pcs error */
|
||||
for (i = 0; i < ARRAY_SIZE(xgmi3x16_pcs_err_status_reg_v6_4); i++) {
|
||||
data = RREG32_PCIE(xgmi3x16_pcs_err_status_reg_v6_4[i]);
|
||||
|
|
@ -1486,6 +1534,7 @@ static void amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
|
|||
{
|
||||
switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
|
||||
case IP_VERSION(6, 4, 0):
|
||||
case IP_VERSION(6, 4, 1):
|
||||
xgmi_v6_4_0_query_ras_error_count(adev, ras_error_status);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -1673,3 +1722,34 @@ int amdgpu_xgmi_request_nps_change(struct amdgpu_device *adev,
|
|||
|
||||
return r;
|
||||
}
|
||||
|
||||
bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev,
|
||||
struct amdgpu_device *bo_adev)
|
||||
{
|
||||
return (amdgpu_use_xgmi_p2p && adev != bo_adev &&
|
||||
adev->gmc.xgmi.hive_id &&
|
||||
adev->gmc.xgmi.hive_id == bo_adev->gmc.xgmi.hive_id);
|
||||
}
|
||||
|
||||
void amdgpu_xgmi_early_init(struct amdgpu_device *adev)
|
||||
{
|
||||
if (!adev->gmc.xgmi.supported)
|
||||
return;
|
||||
|
||||
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
|
||||
case IP_VERSION(9, 4, 0):
|
||||
case IP_VERSION(9, 4, 1):
|
||||
case IP_VERSION(9, 4, 2):
|
||||
adev->gmc.xgmi.max_speed = XGMI_SPEED_25GT;
|
||||
adev->gmc.xgmi.max_width = 16;
|
||||
break;
|
||||
case IP_VERSION(9, 4, 3):
|
||||
case IP_VERSION(9, 4, 4):
|
||||
case IP_VERSION(9, 5, 0):
|
||||
adev->gmc.xgmi.max_speed = XGMI_SPEED_32GT;
|
||||
adev->gmc.xgmi.max_width = 16;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,14 @@
|
|||
#define __AMDGPU_XGMI_H__
|
||||
|
||||
#include <drm/task_barrier.h>
|
||||
#include "amdgpu_psp.h"
|
||||
#include "amdgpu_ras.h"
|
||||
|
||||
enum amdgpu_xgmi_link_speed {
|
||||
XGMI_SPEED_16GT = 16,
|
||||
XGMI_SPEED_25GT = 25,
|
||||
XGMI_SPEED_32GT = 32
|
||||
};
|
||||
|
||||
struct amdgpu_hive_info {
|
||||
struct kobject kobj;
|
||||
uint64_t hive_id;
|
||||
|
|
@ -55,29 +60,63 @@ struct amdgpu_pcs_ras_field {
|
|||
uint32_t pcs_err_shift;
|
||||
};
|
||||
|
||||
extern struct amdgpu_xgmi_ras xgmi_ras;
|
||||
/**
|
||||
* Bandwidth range reporting comes in two modes.
|
||||
*
|
||||
* PER_LINK - range for any xgmi link
|
||||
* PER_PEER - range of max of single xgmi link to max of multiple links based on source peer
|
||||
*/
|
||||
enum amdgpu_xgmi_bw_mode {
|
||||
AMDGPU_XGMI_BW_MODE_PER_LINK = 0,
|
||||
AMDGPU_XGMI_BW_MODE_PER_PEER
|
||||
};
|
||||
|
||||
enum amdgpu_xgmi_bw_unit {
|
||||
AMDGPU_XGMI_BW_UNIT_GBYTES = 0,
|
||||
AMDGPU_XGMI_BW_UNIT_MBYTES
|
||||
};
|
||||
|
||||
struct amdgpu_xgmi_ras {
|
||||
struct amdgpu_ras_block_object ras_block;
|
||||
};
|
||||
extern struct amdgpu_xgmi_ras xgmi_ras;
|
||||
|
||||
struct amdgpu_xgmi {
|
||||
/* from psp */
|
||||
u64 node_id;
|
||||
u64 hive_id;
|
||||
/* fixed per family */
|
||||
u64 node_segment_size;
|
||||
/* physical node (0-3) */
|
||||
unsigned physical_node_id;
|
||||
/* number of nodes (0-4) */
|
||||
unsigned num_physical_nodes;
|
||||
/* gpu list in the same hive */
|
||||
struct list_head head;
|
||||
bool supported;
|
||||
struct ras_common_if *ras_if;
|
||||
bool connected_to_cpu;
|
||||
struct amdgpu_xgmi_ras *ras;
|
||||
enum amdgpu_xgmi_link_speed max_speed;
|
||||
uint8_t max_width;
|
||||
};
|
||||
|
||||
struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev);
|
||||
void amdgpu_put_xgmi_hive(struct amdgpu_hive_info *hive);
|
||||
int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev);
|
||||
int amdgpu_xgmi_add_device(struct amdgpu_device *adev);
|
||||
int amdgpu_xgmi_remove_device(struct amdgpu_device *adev);
|
||||
int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate);
|
||||
int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev,
|
||||
struct amdgpu_device *peer_adev);
|
||||
int amdgpu_xgmi_get_num_links(struct amdgpu_device *adev,
|
||||
struct amdgpu_device *peer_adev);
|
||||
int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev, struct amdgpu_device *peer_adev);
|
||||
int amdgpu_xgmi_get_bandwidth(struct amdgpu_device *adev, struct amdgpu_device *peer_adev,
|
||||
enum amdgpu_xgmi_bw_mode bw_mode, enum amdgpu_xgmi_bw_unit bw_unit,
|
||||
uint32_t *min_bw, uint32_t *max_bw);
|
||||
bool amdgpu_xgmi_get_is_sharing_enabled(struct amdgpu_device *adev,
|
||||
struct amdgpu_device *peer_adev);
|
||||
uint64_t amdgpu_xgmi_get_relative_phy_addr(struct amdgpu_device *adev,
|
||||
uint64_t addr);
|
||||
static inline bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev,
|
||||
struct amdgpu_device *bo_adev)
|
||||
{
|
||||
return (amdgpu_use_xgmi_p2p &&
|
||||
adev != bo_adev &&
|
||||
adev->gmc.xgmi.hive_id &&
|
||||
adev->gmc.xgmi.hive_id == bo_adev->gmc.xgmi.hive_id);
|
||||
}
|
||||
bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev,
|
||||
struct amdgpu_device *bo_adev);
|
||||
int amdgpu_xgmi_ras_sw_init(struct amdgpu_device *adev);
|
||||
int amdgpu_xgmi_reset_on_init(struct amdgpu_device *adev);
|
||||
|
||||
|
|
@ -87,4 +126,7 @@ int amdgpu_xgmi_request_nps_change(struct amdgpu_device *adev,
|
|||
int amdgpu_get_xgmi_link_status(struct amdgpu_device *adev,
|
||||
int global_link_num);
|
||||
|
||||
void amdgpu_xgmi_early_init(struct amdgpu_device *adev);
|
||||
uint32_t amdgpu_xgmi_get_max_bandwidth(struct amdgpu_device *adev);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -97,11 +97,12 @@ union amd_sriov_msg_feature_flags {
|
|||
uint32_t pp_one_vf_mode : 1;
|
||||
uint32_t reg_indirect_acc : 1;
|
||||
uint32_t av1_support : 1;
|
||||
uint32_t vcn_rb_decouple : 1;
|
||||
uint32_t vcn_rb_decouple : 1;
|
||||
uint32_t mes_info_dump_enable : 1;
|
||||
uint32_t ras_caps : 1;
|
||||
uint32_t ras_telemetry : 1;
|
||||
uint32_t reserved : 21;
|
||||
uint32_t ras_cper : 1;
|
||||
uint32_t reserved : 20;
|
||||
} flags;
|
||||
uint32_t all;
|
||||
};
|
||||
|
|
@ -328,21 +329,25 @@ enum amd_sriov_mailbox_request_message {
|
|||
MB_REQ_MSG_READY_TO_RESET = 201,
|
||||
MB_REQ_MSG_RAS_POISON = 202,
|
||||
MB_REQ_RAS_ERROR_COUNT = 203,
|
||||
MB_REQ_RAS_CPER_DUMP = 204,
|
||||
};
|
||||
|
||||
/* mailbox message send from host to guest */
|
||||
enum amd_sriov_mailbox_response_message {
|
||||
MB_RES_MSG_CLR_MSG_BUF = 0,
|
||||
MB_RES_MSG_READY_TO_ACCESS_GPU = 1,
|
||||
MB_RES_MSG_FLR_NOTIFICATION,
|
||||
MB_RES_MSG_FLR_NOTIFICATION_COMPLETION,
|
||||
MB_RES_MSG_SUCCESS,
|
||||
MB_RES_MSG_FAIL,
|
||||
MB_RES_MSG_QUERY_ALIVE,
|
||||
MB_RES_MSG_GPU_INIT_DATA_READY,
|
||||
MB_RES_MSG_RAS_ERROR_COUNT_READY = 11,
|
||||
|
||||
MB_RES_MSG_TEXT_MESSAGE = 255
|
||||
MB_RES_MSG_CLR_MSG_BUF = 0,
|
||||
MB_RES_MSG_READY_TO_ACCESS_GPU = 1,
|
||||
MB_RES_MSG_FLR_NOTIFICATION = 2,
|
||||
MB_RES_MSG_FLR_NOTIFICATION_COMPLETION = 3,
|
||||
MB_RES_MSG_SUCCESS = 4,
|
||||
MB_RES_MSG_FAIL = 5,
|
||||
MB_RES_MSG_QUERY_ALIVE = 6,
|
||||
MB_RES_MSG_GPU_INIT_DATA_READY = 7,
|
||||
MB_RES_MSG_RAS_POISON_READY = 8,
|
||||
MB_RES_MSG_PF_SOFT_FLR_NOTIFICATION = 9,
|
||||
MB_RES_MSG_GPU_RMA = 10,
|
||||
MB_RES_MSG_RAS_ERROR_COUNT_READY = 11,
|
||||
MB_REQ_RAS_CPER_DUMP_READY = 14,
|
||||
MB_RES_MSG_TEXT_MESSAGE = 255
|
||||
};
|
||||
|
||||
enum amd_sriov_ras_telemetry_gpu_block {
|
||||
|
|
@ -386,11 +391,20 @@ struct amd_sriov_ras_telemetry_error_count {
|
|||
} block[RAS_TELEMETRY_GPU_BLOCK_COUNT];
|
||||
};
|
||||
|
||||
struct amd_sriov_ras_cper_dump {
|
||||
uint32_t more;
|
||||
uint64_t overflow_count;
|
||||
uint64_t count;
|
||||
uint64_t wptr;
|
||||
uint32_t buf[];
|
||||
};
|
||||
|
||||
struct amdsriov_ras_telemetry {
|
||||
struct amd_sriov_ras_telemetry_header header;
|
||||
|
||||
union {
|
||||
struct amd_sriov_ras_telemetry_error_count error_count;
|
||||
struct amd_sriov_ras_cper_dump cper_dump;
|
||||
} body;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2148,7 +2148,7 @@ static int cik_common_resume(struct amdgpu_ip_block *ip_block)
|
|||
return cik_common_hw_init(ip_block);
|
||||
}
|
||||
|
||||
static bool cik_common_is_idle(void *handle)
|
||||
static bool cik_common_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -345,9 +345,9 @@ static int cik_ih_resume(struct amdgpu_ip_block *ip_block)
|
|||
return cik_ih_hw_init(ip_block);
|
||||
}
|
||||
|
||||
static bool cik_ih_is_idle(void *handle)
|
||||
static bool cik_ih_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
u32 tmp = RREG32(mmSRBM_STATUS);
|
||||
|
||||
if (tmp & SRBM_STATUS__IH_BUSY_MASK)
|
||||
|
|
|
|||
|
|
@ -1025,9 +1025,9 @@ static int cik_sdma_resume(struct amdgpu_ip_block *ip_block)
|
|||
return cik_sdma_hw_init(ip_block);
|
||||
}
|
||||
|
||||
static bool cik_sdma_is_idle(void *handle)
|
||||
static bool cik_sdma_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
u32 tmp = RREG32(mmSRBM_STATUS2);
|
||||
|
||||
if (tmp & (SRBM_STATUS2__SDMA_BUSY_MASK |
|
||||
|
|
|
|||
|
|
@ -51,6 +51,15 @@
|
|||
#define HPD4_REGISTER_OFFSET (0x1813 - 0x1807)
|
||||
#define HPD5_REGISTER_OFFSET (0x1816 - 0x1807)
|
||||
|
||||
/* audio endpt instance offsets */
|
||||
#define AUD0_REGISTER_OFFSET (0x1780 - 0x1780)
|
||||
#define AUD1_REGISTER_OFFSET (0x1786 - 0x1780)
|
||||
#define AUD2_REGISTER_OFFSET (0x178c - 0x1780)
|
||||
#define AUD3_REGISTER_OFFSET (0x1792 - 0x1780)
|
||||
#define AUD4_REGISTER_OFFSET (0x1798 - 0x1780)
|
||||
#define AUD5_REGISTER_OFFSET (0x179d - 0x1780)
|
||||
#define AUD6_REGISTER_OFFSET (0x17a4 - 0x1780)
|
||||
|
||||
#define BONAIRE_GB_ADDR_CONFIG_GOLDEN 0x12010001
|
||||
#define HAWAII_GB_ADDR_CONFIG_GOLDEN 0x12011003
|
||||
|
||||
|
|
|
|||
|
|
@ -341,9 +341,9 @@ static int cz_ih_resume(struct amdgpu_ip_block *ip_block)
|
|||
return cz_ih_hw_init(ip_block);
|
||||
}
|
||||
|
||||
static bool cz_ih_is_idle(void *handle)
|
||||
static bool cz_ih_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
u32 tmp = RREG32(mmSRBM_STATUS);
|
||||
|
||||
if (REG_GET_FIELD(tmp, SRBM_STATUS, IH_BUSY))
|
||||
|
|
|
|||
|
|
@ -2970,7 +2970,7 @@ static int dce_v10_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return amdgpu_display_resume_helper(adev);
|
||||
}
|
||||
|
||||
static bool dce_v10_0_is_idle(void *handle)
|
||||
static bool dce_v10_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3108,7 +3108,7 @@ static int dce_v11_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return amdgpu_display_resume_helper(adev);
|
||||
}
|
||||
|
||||
static bool dce_v11_0_is_idle(void *handle)
|
||||
static bool dce_v11_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,9 +206,9 @@ static void dce_v6_0_page_flip(struct amdgpu_device *adev,
|
|||
/* update the scanout addresses */
|
||||
WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
|
||||
upper_32_bits(crtc_base));
|
||||
/* writing to the low address triggers the update */
|
||||
WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
|
||||
(u32)crtc_base);
|
||||
|
||||
/* post the write */
|
||||
RREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset);
|
||||
}
|
||||
|
|
@ -218,11 +218,11 @@ static int dce_v6_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
|
|||
{
|
||||
if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
|
||||
return -EINVAL;
|
||||
|
||||
*vbl = RREG32(mmCRTC_V_BLANK_START_END + crtc_offsets[crtc]);
|
||||
*position = RREG32(mmCRTC_STATUS_POSITION + crtc_offsets[crtc]);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -242,7 +242,8 @@ static bool dce_v6_0_hpd_sense(struct amdgpu_device *adev,
|
|||
if (hpd >= adev->mode_info.num_hpd)
|
||||
return connected;
|
||||
|
||||
if (RREG32(mmDC_HPD1_INT_STATUS + hpd_offsets[hpd]) & DC_HPD1_INT_STATUS__DC_HPD1_SENSE_MASK)
|
||||
if (RREG32(mmDC_HPD1_INT_STATUS + hpd_offsets[hpd]) &
|
||||
DC_HPD1_INT_STATUS__DC_HPD1_SENSE_MASK)
|
||||
connected = true;
|
||||
|
||||
return connected;
|
||||
|
|
@ -370,13 +371,41 @@ static u32 dce_v6_0_hpd_get_gpio_reg(struct amdgpu_device *adev)
|
|||
return mmDC_GPIO_HPD_A;
|
||||
}
|
||||
|
||||
static bool dce_v6_0_is_display_hung(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 crtc_hung = 0;
|
||||
u32 crtc_status[6];
|
||||
u32 i, j, tmp;
|
||||
|
||||
for (i = 0; i < adev->mode_info.num_crtc; i++) {
|
||||
if (RREG32(mmCRTC_CONTROL + crtc_offsets[i]) & CRTC_CONTROL__CRTC_MASTER_EN_MASK) {
|
||||
crtc_status[i] = RREG32(mmCRTC_STATUS_HV_COUNT + crtc_offsets[i]);
|
||||
crtc_hung |= (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < 10; j++) {
|
||||
for (i = 0; i < adev->mode_info.num_crtc; i++) {
|
||||
if (crtc_hung & (1 << i)) {
|
||||
tmp = RREG32(mmCRTC_STATUS_HV_COUNT + crtc_offsets[i]);
|
||||
if (tmp != crtc_status[i])
|
||||
crtc_hung &= ~(1 << i);
|
||||
}
|
||||
}
|
||||
if (crtc_hung == 0)
|
||||
return false;
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dce_v6_0_set_vga_render_state(struct amdgpu_device *adev,
|
||||
bool render)
|
||||
{
|
||||
if (!render)
|
||||
WREG32(mmVGA_RENDER_CONTROL,
|
||||
RREG32(mmVGA_RENDER_CONTROL) & VGA_VSTATUS_CNTL);
|
||||
|
||||
}
|
||||
|
||||
static int dce_v6_0_get_num_crtc(struct amdgpu_device *adev)
|
||||
|
|
@ -419,7 +448,6 @@ void dce_v6_0_disable_dce(struct amdgpu_device *adev)
|
|||
|
||||
static void dce_v6_0_program_fmt(struct drm_encoder *encoder)
|
||||
{
|
||||
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
|
||||
|
|
@ -895,8 +923,8 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev,
|
|||
wm_high.dram_channels = dram_channels;
|
||||
wm_high.num_heads = num_heads;
|
||||
|
||||
if (adev->pm.dpm_enabled) {
|
||||
/* watermark for low clocks */
|
||||
if (adev->pm.dpm_enabled) {
|
||||
wm_low.yclk =
|
||||
amdgpu_dpm_get_mclk(adev, true) * 10;
|
||||
wm_low.sclk =
|
||||
|
|
@ -1006,6 +1034,20 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
/* watermark setup */
|
||||
/**
|
||||
* dce_v6_0_line_buffer_adjust - Set up the line buffer
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @amdgpu_crtc: the selected display controller
|
||||
* @mode: the current display mode on the selected display
|
||||
* controller
|
||||
* @other_mode: the display mode of another display controller
|
||||
* that may be sharing the line buffer
|
||||
*
|
||||
* Setup up the line buffer allocation for
|
||||
* the selected display controller (CIK).
|
||||
* Returns the line buffer size in pixels.
|
||||
*/
|
||||
static u32 dce_v6_0_line_buffer_adjust(struct amdgpu_device *adev,
|
||||
struct amdgpu_crtc *amdgpu_crtc,
|
||||
struct drm_display_mode *mode,
|
||||
|
|
@ -1386,6 +1428,8 @@ static int dce_v6_0_audio_init(struct amdgpu_device *adev)
|
|||
adev->mode_info.audio.pin[i].connected = false;
|
||||
adev->mode_info.audio.pin[i].offset = pin_offsets[i];
|
||||
adev->mode_info.audio.pin[i].id = i;
|
||||
/* disable audio. it will be set up later */
|
||||
/* XXX remove once we switch to ip funcs */
|
||||
dce_v6_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
|
||||
}
|
||||
|
||||
|
|
@ -2865,14 +2909,35 @@ static int dce_v6_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return amdgpu_display_resume_helper(adev);
|
||||
}
|
||||
|
||||
static bool dce_v6_0_is_idle(void *handle)
|
||||
static bool dce_v6_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static int dce_v6_0_soft_reset(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
DRM_INFO("xxxx: dce_v6_0_soft_reset --- no impl!!\n");
|
||||
u32 srbm_soft_reset = 0, tmp;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
if (dce_v6_0_is_display_hung(adev))
|
||||
srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_DC_MASK;
|
||||
|
||||
if (srbm_soft_reset) {
|
||||
tmp = RREG32(mmSRBM_SOFT_RESET);
|
||||
tmp |= srbm_soft_reset;
|
||||
dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
|
||||
WREG32(mmSRBM_SOFT_RESET, tmp);
|
||||
tmp = RREG32(mmSRBM_SOFT_RESET);
|
||||
|
||||
udelay(50);
|
||||
|
||||
tmp &= ~srbm_soft_reset;
|
||||
WREG32(mmSRBM_SOFT_RESET, tmp);
|
||||
tmp = RREG32(mmSRBM_SOFT_RESET);
|
||||
|
||||
/* Wait a little for things to settle down */
|
||||
udelay(50);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3148,7 +3213,6 @@ static int dce_v6_0_hpd_irq(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int dce_v6_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
|
||||
|
|
@ -3281,8 +3345,7 @@ static void dce_v6_0_ext_commit(struct drm_encoder *encoder)
|
|||
|
||||
}
|
||||
|
||||
static void
|
||||
dce_v6_0_ext_mode_set(struct drm_encoder *encoder,
|
||||
static void dce_v6_0_ext_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
|
|
@ -3294,8 +3357,7 @@ static void dce_v6_0_ext_disable(struct drm_encoder *encoder)
|
|||
|
||||
}
|
||||
|
||||
static void
|
||||
dce_v6_0_ext_dpms(struct drm_encoder *encoder, int mode)
|
||||
static void dce_v6_0_ext_dpms(struct drm_encoder *encoder, int mode)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -3366,7 +3428,6 @@ static void dce_v6_0_encoder_add(struct amdgpu_device *adev,
|
|||
amdgpu_encoder->devices |= supported_device;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* add a new one */
|
||||
|
|
|
|||
|
|
@ -1395,13 +1395,13 @@ static void dce_v8_0_audio_enable(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
static const u32 pin_offsets[7] = {
|
||||
(0x1780 - 0x1780),
|
||||
(0x1786 - 0x1780),
|
||||
(0x178c - 0x1780),
|
||||
(0x1792 - 0x1780),
|
||||
(0x1798 - 0x1780),
|
||||
(0x179d - 0x1780),
|
||||
(0x17a4 - 0x1780),
|
||||
AUD0_REGISTER_OFFSET,
|
||||
AUD1_REGISTER_OFFSET,
|
||||
AUD2_REGISTER_OFFSET,
|
||||
AUD3_REGISTER_OFFSET,
|
||||
AUD4_REGISTER_OFFSET,
|
||||
AUD5_REGISTER_OFFSET,
|
||||
AUD6_REGISTER_OFFSET,
|
||||
};
|
||||
|
||||
static int dce_v8_0_audio_init(struct amdgpu_device *adev)
|
||||
|
|
@ -2887,7 +2887,7 @@ static int dce_v8_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return amdgpu_display_resume_helper(adev);
|
||||
}
|
||||
|
||||
static bool dce_v8_0_is_idle(void *handle)
|
||||
static bool dce_v8_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7583,9 +7583,9 @@ static int gfx_v10_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return gfx_v10_0_hw_init(ip_block);
|
||||
}
|
||||
|
||||
static bool gfx_v10_0_is_idle(void *handle)
|
||||
static bool gfx_v10_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
if (REG_GET_FIELD(RREG32_SOC15(GC, 0, mmGRBM_STATUS),
|
||||
GRBM_STATUS, GUI_ACTIVE))
|
||||
|
|
|
|||
|
|
@ -4787,9 +4787,9 @@ static int gfx_v11_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return gfx_v11_0_hw_init(ip_block);
|
||||
}
|
||||
|
||||
static bool gfx_v11_0_is_idle(void *handle)
|
||||
static bool gfx_v11_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
if (REG_GET_FIELD(RREG32_SOC15(GC, 0, regGRBM_STATUS),
|
||||
GRBM_STATUS, GUI_ACTIVE))
|
||||
|
|
|
|||
|
|
@ -3695,9 +3695,9 @@ static int gfx_v12_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return gfx_v12_0_hw_init(ip_block);
|
||||
}
|
||||
|
||||
static bool gfx_v12_0_is_idle(void *handle)
|
||||
static bool gfx_v12_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
if (REG_GET_FIELD(RREG32_SOC15(GC, 0, regGRBM_STATUS),
|
||||
GRBM_STATUS, GUI_ACTIVE))
|
||||
|
|
|
|||
|
|
@ -3167,9 +3167,9 @@ static int gfx_v6_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return gfx_v6_0_hw_init(ip_block);
|
||||
}
|
||||
|
||||
static bool gfx_v6_0_is_idle(void *handle)
|
||||
static bool gfx_v6_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
if (RREG32(mmGRBM_STATUS) & GRBM_STATUS__GUI_ACTIVE_MASK)
|
||||
return false;
|
||||
|
|
@ -3183,7 +3183,7 @@ static int gfx_v6_0_wait_for_idle(struct amdgpu_ip_block *ip_block)
|
|||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
if (gfx_v6_0_is_idle(adev))
|
||||
if (gfx_v6_0_is_idle(ip_block))
|
||||
return 0;
|
||||
udelay(1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4515,9 +4515,9 @@ static int gfx_v7_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return gfx_v7_0_hw_init(ip_block);
|
||||
}
|
||||
|
||||
static bool gfx_v7_0_is_idle(void *handle)
|
||||
static bool gfx_v7_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
if (RREG32(mmGRBM_STATUS) & GRBM_STATUS__GUI_ACTIVE_MASK)
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -4851,9 +4851,9 @@ static int gfx_v8_0_kcq_disable(struct amdgpu_device *adev)
|
|||
return r;
|
||||
}
|
||||
|
||||
static bool gfx_v8_0_is_idle(void *handle)
|
||||
static bool gfx_v8_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
if (REG_GET_FIELD(RREG32(mmGRBM_STATUS), GRBM_STATUS, GUI_ACTIVE)
|
||||
|| RREG32(mmGRBM_STATUS2) != 0x8)
|
||||
|
|
@ -4892,7 +4892,7 @@ static int gfx_v8_0_wait_for_idle(struct amdgpu_ip_block *ip_block)
|
|||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
if (gfx_v8_0_is_idle(adev))
|
||||
if (gfx_v8_0_is_idle(ip_block))
|
||||
return 0;
|
||||
|
||||
udelay(1);
|
||||
|
|
|
|||
|
|
@ -2637,7 +2637,10 @@ static void gfx_v9_0_constants_init(struct amdgpu_device *adev)
|
|||
u32 tmp;
|
||||
int i;
|
||||
|
||||
WREG32_FIELD15_RLC(GC, 0, GRBM_CNTL, READ_TIMEOUT, 0xff);
|
||||
if (!amdgpu_sriov_vf(adev) ||
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 2)) {
|
||||
WREG32_FIELD15_RLC(GC, 0, GRBM_CNTL, READ_TIMEOUT, 0xff);
|
||||
}
|
||||
|
||||
gfx_v9_0_tiling_mode_table_init(adev);
|
||||
|
||||
|
|
@ -4042,7 +4045,8 @@ static int gfx_v9_0_hw_init(struct amdgpu_ip_block *ip_block)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 2))
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 2) &&
|
||||
!amdgpu_sriov_vf(adev))
|
||||
gfx_v9_4_2_set_power_brake_sequence(adev);
|
||||
|
||||
return r;
|
||||
|
|
@ -4110,9 +4114,9 @@ static int gfx_v9_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return gfx_v9_0_hw_init(ip_block);
|
||||
}
|
||||
|
||||
static bool gfx_v9_0_is_idle(void *handle)
|
||||
static bool gfx_v9_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
if (REG_GET_FIELD(RREG32_SOC15(GC, 0, mmGRBM_STATUS),
|
||||
GRBM_STATUS, GUI_ACTIVE))
|
||||
|
|
@ -4127,7 +4131,7 @@ static int gfx_v9_0_wait_for_idle(struct amdgpu_ip_block *ip_block)
|
|||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
if (gfx_v9_0_is_idle(adev))
|
||||
if (gfx_v9_0_is_idle(ip_block))
|
||||
return 0;
|
||||
udelay(1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -349,18 +349,7 @@ static void gfx_v9_4_3_init_golden_registers(struct amdgpu_device *adev)
|
|||
|
||||
WREG32_SOC15(GC, dev_inst, regGB_ADDR_CONFIG,
|
||||
GOLDEN_GB_ADDR_CONFIG);
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 5, 0)) {
|
||||
WREG32_FIELD15_PREREG(GC, dev_inst, TCP_UTCL1_CNTL2, SPARE, 0x1);
|
||||
} else {
|
||||
/* Golden settings applied by driver for ASIC with rev_id 0 */
|
||||
if (adev->rev_id == 0) {
|
||||
WREG32_FIELD15_PREREG(GC, dev_inst, TCP_UTCL1_CNTL1,
|
||||
REDUCE_FIFO_DEPTH_BY_2, 2);
|
||||
} else {
|
||||
WREG32_FIELD15_PREREG(GC, dev_inst, TCP_UTCL1_CNTL2,
|
||||
SPARE, 0x1);
|
||||
}
|
||||
}
|
||||
WREG32_FIELD15_PREREG(GC, dev_inst, TCP_UTCL1_CNTL2, SPARE, 0x1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -563,17 +552,6 @@ static int gfx_v9_4_3_init_rlc_microcode(struct amdgpu_device *adev,
|
|||
return err;
|
||||
}
|
||||
|
||||
static bool gfx_v9_4_3_should_disable_gfxoff(struct pci_dev *pdev)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void gfx_v9_4_3_check_if_need_gfxoff(struct amdgpu_device *adev)
|
||||
{
|
||||
if (gfx_v9_4_3_should_disable_gfxoff(adev->pdev))
|
||||
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
|
||||
}
|
||||
|
||||
static int gfx_v9_4_3_init_cp_compute_microcode(struct amdgpu_device *adev,
|
||||
const char *chip_name)
|
||||
{
|
||||
|
|
@ -600,8 +578,6 @@ static int gfx_v9_4_3_init_cp_compute_microcode(struct amdgpu_device *adev,
|
|||
adev->gfx.mec2_fw_version = adev->gfx.mec_fw_version;
|
||||
adev->gfx.mec2_feature_version = adev->gfx.mec_feature_version;
|
||||
|
||||
gfx_v9_4_3_check_if_need_gfxoff(adev);
|
||||
|
||||
out:
|
||||
if (err)
|
||||
amdgpu_ucode_release(&adev->gfx.mec_fw);
|
||||
|
|
@ -896,9 +872,10 @@ static int gfx_v9_4_3_aca_bank_parser(struct aca_handle *handle,
|
|||
ACA_ERROR_TYPE_UE, 1ULL);
|
||||
break;
|
||||
case ACA_SMU_TYPE_CE:
|
||||
bank->aca_err_type = ACA_ERROR_TYPE_CE;
|
||||
bank->aca_err_type = ACA_BANK_ERR_CE_DE_DECODE(bank);
|
||||
ret = aca_error_cache_log_bank_error(handle, &info,
|
||||
ACA_ERROR_TYPE_CE, ACA_REG__MISC0__ERRCNT(misc0));
|
||||
bank->aca_err_type,
|
||||
ACA_REG__MISC0__ERRCNT(misc0));
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
@ -939,8 +916,6 @@ static const struct aca_info gfx_v9_4_3_aca_info = {
|
|||
|
||||
static int gfx_v9_4_3_gpu_early_init(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 gb_addr_config;
|
||||
|
||||
adev->gfx.funcs = &gfx_v9_4_3_gfx_funcs;
|
||||
adev->gfx.ras = &gfx_v9_4_3_ras;
|
||||
|
||||
|
|
@ -949,9 +924,7 @@ static int gfx_v9_4_3_gpu_early_init(struct amdgpu_device *adev)
|
|||
adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
|
||||
adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
|
||||
adev->gfx.config.sc_earlyz_tile_fifo_size = 0x4C0;
|
||||
gb_addr_config = RREG32_SOC15(GC, GET_INST(GC, 0), regGB_ADDR_CONFIG);
|
||||
|
||||
adev->gfx.config.gb_addr_config = gb_addr_config;
|
||||
adev->gfx.config.gb_addr_config = GOLDEN_GB_ADDR_CONFIG;
|
||||
|
||||
adev->gfx.config.gb_addr_config_fields.num_pipes = 1 <<
|
||||
REG_GET_FIELD(
|
||||
|
|
@ -1362,10 +1335,8 @@ static void gfx_v9_4_3_xcc_init_pg(struct amdgpu_device *adev, int xcc_id)
|
|||
{
|
||||
/*
|
||||
* Rlc save restore list is workable since v2_1.
|
||||
* And it's needed by gfxoff feature.
|
||||
*/
|
||||
if (adev->gfx.rlc.is_rlc_v2_1)
|
||||
gfx_v9_4_3_xcc_enable_save_restore_machine(adev, xcc_id);
|
||||
gfx_v9_4_3_xcc_enable_save_restore_machine(adev, xcc_id);
|
||||
}
|
||||
|
||||
static void gfx_v9_4_3_xcc_disable_gpa_mode(struct amdgpu_device *adev, int xcc_id)
|
||||
|
|
@ -2408,9 +2379,9 @@ static int gfx_v9_4_3_resume(struct amdgpu_ip_block *ip_block)
|
|||
return gfx_v9_4_3_hw_init(ip_block);
|
||||
}
|
||||
|
||||
static bool gfx_v9_4_3_is_idle(void *handle)
|
||||
static bool gfx_v9_4_3_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
int i, num_xcc;
|
||||
|
||||
num_xcc = NUM_XCC(adev->gfx.xcc_mask);
|
||||
|
|
@ -2428,7 +2399,7 @@ static int gfx_v9_4_3_wait_for_idle(struct amdgpu_ip_block *ip_block)
|
|||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
if (gfx_v9_4_3_is_idle(adev))
|
||||
if (gfx_v9_4_3_is_idle(ip_block))
|
||||
return 0;
|
||||
udelay(1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,12 +92,12 @@ static void gfxhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev)
|
|||
{
|
||||
uint64_t value;
|
||||
|
||||
/* Program the AGP BAR */
|
||||
WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BASE, 0);
|
||||
WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BOT, adev->gmc.agp_start >> 24);
|
||||
WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_TOP, adev->gmc.agp_end >> 24);
|
||||
|
||||
if (!amdgpu_sriov_vf(adev) || adev->asic_type <= CHIP_VEGA10) {
|
||||
/* Program the AGP BAR */
|
||||
WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BASE, 0);
|
||||
WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BOT, adev->gmc.agp_start >> 24);
|
||||
WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_TOP, adev->gmc.agp_end >> 24);
|
||||
|
||||
/* Program the system aperture low logical page number. */
|
||||
WREG32_SOC15_RLC(GC, 0, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR,
|
||||
min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
|
||||
|
|
|
|||
|
|
@ -1076,7 +1076,7 @@ static int gmc_v10_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool gmc_v10_0_is_idle(void *handle)
|
||||
static bool gmc_v10_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
/* MC is always ready in GMC v10.*/
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -987,7 +987,7 @@ static int gmc_v11_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool gmc_v11_0_is_idle(void *handle)
|
||||
static bool gmc_v11_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
/* MC is always ready in GMC v11.*/
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -984,7 +984,7 @@ static int gmc_v12_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool gmc_v12_0_is_idle(void *handle)
|
||||
static bool gmc_v12_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
/* MC is always ready in GMC v11.*/
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -957,9 +957,9 @@ static int gmc_v6_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool gmc_v6_0_is_idle(void *handle)
|
||||
static bool gmc_v6_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
u32 tmp = RREG32(mmSRBM_STATUS);
|
||||
|
||||
|
|
@ -976,7 +976,7 @@ static int gmc_v6_0_wait_for_idle(struct amdgpu_ip_block *ip_block)
|
|||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
if (gmc_v6_0_is_idle(adev))
|
||||
if (gmc_v6_0_is_idle(ip_block))
|
||||
return 0;
|
||||
udelay(1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1142,9 +1142,9 @@ static int gmc_v7_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool gmc_v7_0_is_idle(void *handle)
|
||||
static bool gmc_v7_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
u32 tmp = RREG32(mmSRBM_STATUS);
|
||||
|
||||
if (tmp & (SRBM_STATUS__MCB_BUSY_MASK | SRBM_STATUS__MCB_NON_DISPLAY_BUSY_MASK |
|
||||
|
|
|
|||
|
|
@ -1263,9 +1263,9 @@ static int gmc_v8_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool gmc_v8_0_is_idle(void *handle)
|
||||
static bool gmc_v8_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
u32 tmp = RREG32(mmSRBM_STATUS);
|
||||
|
||||
if (tmp & (SRBM_STATUS__MCB_BUSY_MASK | SRBM_STATUS__MCB_NON_DISPLAY_BUSY_MASK |
|
||||
|
|
|
|||
|
|
@ -1607,9 +1607,8 @@ static void gmc_v9_0_init_nps_details(struct amdgpu_device *adev)
|
|||
|
||||
/* Mode detected by hardware and supported modes available */
|
||||
if ((mode != UNKNOWN_MEMORY_PARTITION_MODE) && supp_modes) {
|
||||
for (i = AMDGPU_NPS1_PARTITION_MODE;
|
||||
supp_modes && i <= AMDGPU_NPS8_PARTITION_MODE; i++) {
|
||||
if (supp_modes & BIT(i - 1))
|
||||
while ((i = ffs(supp_modes))) {
|
||||
if (AMDGPU_ALL_NPS_MASK & BIT(i))
|
||||
adev->gmc.supported_nps_modes |= BIT(i);
|
||||
supp_modes &= supp_modes - 1;
|
||||
}
|
||||
|
|
@ -2543,7 +2542,7 @@ static int gmc_v9_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool gmc_v9_0_is_idle(void *handle)
|
||||
static bool gmc_v9_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
/* MC is always ready in GMC v9.*/
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -335,9 +335,9 @@ static int iceland_ih_resume(struct amdgpu_ip_block *ip_block)
|
|||
return iceland_ih_hw_init(ip_block);
|
||||
}
|
||||
|
||||
static bool iceland_ih_is_idle(void *handle)
|
||||
static bool iceland_ih_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
u32 tmp = RREG32(mmSRBM_STATUS);
|
||||
|
||||
if (REG_GET_FIELD(tmp, SRBM_STATUS, IH_BUSY))
|
||||
|
|
|
|||
|
|
@ -652,7 +652,7 @@ static int ih_v6_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return ih_v6_0_hw_init(ip_block);
|
||||
}
|
||||
|
||||
static bool ih_v6_0_is_idle(void *handle)
|
||||
static bool ih_v6_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
/* todo */
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -631,7 +631,7 @@ static int ih_v6_1_resume(struct amdgpu_ip_block *ip_block)
|
|||
return ih_v6_1_hw_init(ip_block);
|
||||
}
|
||||
|
||||
static bool ih_v6_1_is_idle(void *handle)
|
||||
static bool ih_v6_1_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
/* todo */
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -621,7 +621,7 @@ static int ih_v7_0_resume(struct amdgpu_ip_block *ip_block)
|
|||
return ih_v7_0_hw_init(ip_block);
|
||||
}
|
||||
|
||||
static bool ih_v7_0_is_idle(void *handle)
|
||||
static bool ih_v7_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
/* todo */
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -50,26 +50,29 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp)
|
|||
|
||||
isp_base = adev->rmmio_base;
|
||||
|
||||
isp->isp_cell = kcalloc(2, sizeof(struct mfd_cell), GFP_KERNEL);
|
||||
isp->isp_cell = kcalloc(3, sizeof(struct mfd_cell), GFP_KERNEL);
|
||||
if (!isp->isp_cell) {
|
||||
r = -ENOMEM;
|
||||
DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__);
|
||||
drm_err(&adev->ddev,
|
||||
"%s: isp mfd cell alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
num_res = MAX_ISP410_MEM_RES + MAX_ISP410_SENSOR_RES + MAX_ISP410_INT_SRC;
|
||||
num_res = MAX_ISP410_MEM_RES + MAX_ISP410_INT_SRC;
|
||||
isp->isp_res = kcalloc(num_res, sizeof(struct resource),
|
||||
GFP_KERNEL);
|
||||
if (!isp->isp_res) {
|
||||
r = -ENOMEM;
|
||||
DRM_ERROR("%s: isp mfd res alloc failed\n", __func__);
|
||||
drm_err(&adev->ddev,
|
||||
"%s: isp mfd res alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
isp->isp_pdata = kzalloc(sizeof(*isp->isp_pdata), GFP_KERNEL);
|
||||
if (!isp->isp_pdata) {
|
||||
r = -ENOMEM;
|
||||
DRM_ERROR("%s: isp platform data alloc failed\n", __func__);
|
||||
drm_err(&adev->ddev,
|
||||
"%s: isp platform data alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
|
|
@ -88,14 +91,7 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp)
|
|||
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++) {
|
||||
for (idx = MAX_ISP410_MEM_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 =
|
||||
|
|
@ -110,11 +106,12 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp)
|
|||
isp->isp_cell[0].platform_data = isp->isp_pdata;
|
||||
isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data);
|
||||
|
||||
isp->isp_i2c_res = kcalloc(1, sizeof(struct resource),
|
||||
GFP_KERNEL);
|
||||
/* initialize isp i2c platform data */
|
||||
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__);
|
||||
drm_err(&adev->ddev,
|
||||
"%s: isp mfd res alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
|
|
@ -129,9 +126,31 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp)
|
|||
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);
|
||||
/* initialize isp gpiochip platform data */
|
||||
isp->isp_gpio_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL);
|
||||
if (!isp->isp_gpio_res) {
|
||||
r = -ENOMEM;
|
||||
drm_err(&adev->ddev,
|
||||
"%s: isp gpio res alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
isp->isp_gpio_res[0].name = "isp_gpio_reg";
|
||||
isp->isp_gpio_res[0].flags = IORESOURCE_MEM;
|
||||
isp->isp_gpio_res[0].start = isp_base + ISP410_GPIO_SENSOR_OFFSET;
|
||||
isp->isp_gpio_res[0].end = isp_base + ISP410_GPIO_SENSOR_OFFSET +
|
||||
ISP410_GPIO_SENSOR_SIZE;
|
||||
|
||||
isp->isp_cell[2].name = "amdisp-pinctrl";
|
||||
isp->isp_cell[2].num_resources = 1;
|
||||
isp->isp_cell[2].resources = &isp->isp_gpio_res[0];
|
||||
isp->isp_cell[2].platform_data = isp->isp_pdata;
|
||||
isp->isp_cell[2].pdata_size = sizeof(struct isp_platform_data);
|
||||
|
||||
r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 3);
|
||||
if (r) {
|
||||
DRM_ERROR("%s: add mfd hotplug device failed\n", __func__);
|
||||
drm_err(&adev->ddev,
|
||||
"%s: add mfd hotplug device failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
|
|
@ -143,6 +162,7 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp)
|
|||
kfree(isp->isp_res);
|
||||
kfree(isp->isp_cell);
|
||||
kfree(isp->isp_i2c_res);
|
||||
kfree(isp->isp_gpio_res);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
@ -155,6 +175,7 @@ static int isp_v4_1_0_hw_fini(struct amdgpu_isp *isp)
|
|||
kfree(isp->isp_cell);
|
||||
kfree(isp->isp_pdata);
|
||||
kfree(isp->isp_i2c_res);
|
||||
kfree(isp->isp_gpio_res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@
|
|||
#define ISP410_I2C0_OFFSET 0x66400
|
||||
#define ISP410_I2C0_SIZE 0x100
|
||||
|
||||
#define ISP410_GPIO_SENSOR0_OFFSET 0x6613C
|
||||
#define ISP410_GPIO_SENSOR0_SIZE 0x4
|
||||
#define ISP410_GPIO_SENSOR_OFFSET 0x6613C
|
||||
#define ISP410_GPIO_SENSOR_SIZE 0x54
|
||||
|
||||
void isp_v4_1_0_set_isp_funcs(struct amdgpu_isp *isp);
|
||||
|
||||
|
|
|
|||
|
|
@ -50,27 +50,30 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
|
|||
|
||||
isp_base = adev->rmmio_base;
|
||||
|
||||
isp->isp_cell = kcalloc(2, sizeof(struct mfd_cell), GFP_KERNEL);
|
||||
isp->isp_cell = kcalloc(3, sizeof(struct mfd_cell), GFP_KERNEL);
|
||||
if (!isp->isp_cell) {
|
||||
r = -ENOMEM;
|
||||
DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__);
|
||||
drm_err(&adev->ddev,
|
||||
"%s: isp mfd cell alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
num_res = MAX_ISP411_MEM_RES + MAX_ISP411_SENSOR_RES + MAX_ISP411_INT_SRC;
|
||||
num_res = MAX_ISP411_MEM_RES + MAX_ISP411_INT_SRC;
|
||||
|
||||
isp->isp_res = kcalloc(num_res, sizeof(struct resource),
|
||||
GFP_KERNEL);
|
||||
if (!isp->isp_res) {
|
||||
r = -ENOMEM;
|
||||
DRM_ERROR("%s: isp mfd res alloc failed\n", __func__);
|
||||
drm_err(&adev->ddev,
|
||||
"%s: isp mfd res alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
isp->isp_pdata = kzalloc(sizeof(*isp->isp_pdata), GFP_KERNEL);
|
||||
if (!isp->isp_pdata) {
|
||||
r = -ENOMEM;
|
||||
DRM_ERROR("%s: isp platform data alloc failed\n", __func__);
|
||||
drm_err(&adev->ddev,
|
||||
"%s: isp platform data alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
|
|
@ -89,14 +92,7 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
|
|||
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++) {
|
||||
for (idx = MAX_ISP411_MEM_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 =
|
||||
|
|
@ -111,10 +107,12 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
|
|||
isp->isp_cell[0].platform_data = isp->isp_pdata;
|
||||
isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data);
|
||||
|
||||
/* initialize isp i2c platform data */
|
||||
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__);
|
||||
drm_err(&adev->ddev,
|
||||
"%s: isp mfd res alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
|
|
@ -129,9 +127,31 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
|
|||
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);
|
||||
/* initialize isp gpiochip platform data */
|
||||
isp->isp_gpio_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL);
|
||||
if (!isp->isp_gpio_res) {
|
||||
r = -ENOMEM;
|
||||
drm_err(&adev->ddev,
|
||||
"%s: isp gpio res alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
isp->isp_gpio_res[0].name = "isp_gpio_reg";
|
||||
isp->isp_gpio_res[0].flags = IORESOURCE_MEM;
|
||||
isp->isp_gpio_res[0].start = isp_base + ISP411_GPIO_SENSOR_OFFSET;
|
||||
isp->isp_gpio_res[0].end = isp_base + ISP411_GPIO_SENSOR_OFFSET +
|
||||
ISP411_GPIO_SENSOR_SIZE;
|
||||
|
||||
isp->isp_cell[2].name = "amdisp-pinctrl";
|
||||
isp->isp_cell[2].num_resources = 1;
|
||||
isp->isp_cell[2].resources = &isp->isp_gpio_res[0];
|
||||
isp->isp_cell[2].platform_data = isp->isp_pdata;
|
||||
isp->isp_cell[2].pdata_size = sizeof(struct isp_platform_data);
|
||||
|
||||
r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 3);
|
||||
if (r) {
|
||||
DRM_ERROR("%s: add mfd hotplug device failed\n", __func__);
|
||||
drm_err(&adev->ddev,
|
||||
"%s: add mfd hotplug device failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
|
|
@ -143,6 +163,7 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
|
|||
kfree(isp->isp_res);
|
||||
kfree(isp->isp_cell);
|
||||
kfree(isp->isp_i2c_res);
|
||||
kfree(isp->isp_gpio_res);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
@ -155,6 +176,7 @@ static int isp_v4_1_1_hw_fini(struct amdgpu_isp *isp)
|
|||
kfree(isp->isp_cell);
|
||||
kfree(isp->isp_pdata);
|
||||
kfree(isp->isp_i2c_res);
|
||||
kfree(isp->isp_gpio_res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
#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
|
||||
|
|
@ -42,8 +41,8 @@
|
|||
#define ISP411_I2C0_OFFSET 0x66400
|
||||
#define ISP411_I2C0_SIZE 0x100
|
||||
|
||||
#define ISP411_GPIO_SENSOR0_OFFSET 0x6613C
|
||||
#define ISP411_GPIO_SENSOR0_SIZE 0x4
|
||||
#define ISP411_GPIO_SENSOR_OFFSET 0x6613C
|
||||
#define ISP411_GPIO_SENSOR_SIZE 0x54
|
||||
|
||||
void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp);
|
||||
|
||||
|
|
|
|||
|
|
@ -604,15 +604,15 @@ static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev)
|
|||
static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);
|
||||
bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work);
|
||||
int cnt = 0;
|
||||
|
||||
mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
|
||||
mutex_lock(&adev->vcn.inst[0].vcn1_jpeg1_workaround);
|
||||
|
||||
if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_dec))
|
||||
DRM_ERROR("JPEG dec: vcn dec ring may not be empty\n");
|
||||
|
||||
for (cnt = 0; cnt < adev->vcn.num_enc_rings; cnt++) {
|
||||
for (cnt = 0; cnt < adev->vcn.inst[0].num_enc_rings; cnt++) {
|
||||
if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_enc[cnt]))
|
||||
DRM_ERROR("JPEG dec: vcn enc ring[%d] may not be empty\n", cnt);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -680,9 +680,9 @@ void jpeg_v2_0_dec_ring_nop(struct amdgpu_ring *ring, uint32_t count)
|
|||
}
|
||||
}
|
||||
|
||||
static bool jpeg_v2_0_is_idle(void *handle)
|
||||
static bool jpeg_v2_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
return ((RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS) &
|
||||
UVD_JRBC_STATUS__RB_JOB_DONE_MASK) ==
|
||||
|
|
@ -707,7 +707,7 @@ static int jpeg_v2_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
|
|||
bool enable = (state == AMD_CG_STATE_GATE);
|
||||
|
||||
if (enable) {
|
||||
if (!jpeg_v2_0_is_idle(adev))
|
||||
if (!jpeg_v2_0_is_idle(ip_block))
|
||||
return -EBUSY;
|
||||
jpeg_v2_0_enable_clock_gating(adev);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -515,9 +515,9 @@ static void jpeg_v2_6_dec_ring_insert_end(struct amdgpu_ring *ring)
|
|||
amdgpu_ring_write(ring, (1 << (ring->me * 2 + 14)));
|
||||
}
|
||||
|
||||
static bool jpeg_v2_5_is_idle(void *handle)
|
||||
static bool jpeg_v2_5_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
int i, ret = 1;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
|
|
@ -563,7 +563,7 @@ static int jpeg_v2_5_set_clockgating_state(struct amdgpu_ip_block *ip_block,
|
|||
continue;
|
||||
|
||||
if (enable) {
|
||||
if (!jpeg_v2_5_is_idle(adev))
|
||||
if (!jpeg_v2_5_is_idle(ip_block))
|
||||
return -EBUSY;
|
||||
jpeg_v2_5_enable_clock_gating(adev, i);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -470,9 +470,9 @@ static void jpeg_v3_0_dec_ring_set_wptr(struct amdgpu_ring *ring)
|
|||
}
|
||||
}
|
||||
|
||||
static bool jpeg_v3_0_is_idle(void *handle)
|
||||
static bool jpeg_v3_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
int ret = 1;
|
||||
|
||||
ret &= (((RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS) &
|
||||
|
|
@ -498,7 +498,7 @@ static int jpeg_v3_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
|
|||
bool enable = state == AMD_CG_STATE_GATE;
|
||||
|
||||
if (enable) {
|
||||
if (!jpeg_v3_0_is_idle(adev))
|
||||
if (!jpeg_v3_0_is_idle(ip_block))
|
||||
return -EBUSY;
|
||||
jpeg_v3_0_enable_clock_gating(adev);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -630,9 +630,9 @@ static void jpeg_v4_0_dec_ring_set_wptr(struct amdgpu_ring *ring)
|
|||
}
|
||||
}
|
||||
|
||||
static bool jpeg_v4_0_is_idle(void *handle)
|
||||
static bool jpeg_v4_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
int ret = 1;
|
||||
|
||||
ret &= (((RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS) &
|
||||
|
|
@ -658,7 +658,7 @@ static int jpeg_v4_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
|
|||
bool enable = state == AMD_CG_STATE_GATE;
|
||||
|
||||
if (enable) {
|
||||
if (!jpeg_v4_0_is_idle(adev))
|
||||
if (!jpeg_v4_0_is_idle(ip_block))
|
||||
return -EBUSY;
|
||||
jpeg_v4_0_enable_clock_gating(adev);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -634,12 +634,6 @@ static void jpeg_v4_0_3_stop_inst(struct amdgpu_device *adev, int inst)
|
|||
UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,
|
||||
~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
|
||||
|
||||
WREG32_SOC15(JPEG, jpeg_inst, regUVD_PGFSM_CONFIG,
|
||||
2 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT);
|
||||
SOC15_WAIT_ON_RREG(JPEG, jpeg_inst, regUVD_PGFSM_STATUS,
|
||||
UVD_PGFSM_STATUS__UVDJ_PWR_OFF <<
|
||||
UVD_PGFSM_STATUS__UVDJ_PWR_STATUS__SHIFT,
|
||||
UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -692,7 +686,7 @@ static uint64_t jpeg_v4_0_3_dec_ring_get_wptr(struct amdgpu_ring *ring)
|
|||
jpeg_v4_0_3_core_reg_offset(ring->pipe));
|
||||
}
|
||||
|
||||
static void jpeg_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring)
|
||||
void jpeg_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring)
|
||||
{
|
||||
/* JPEG engine access for HDP flush doesn't work when RRMT is enabled.
|
||||
* This is a workaround to avoid any HDP flush through JPEG ring.
|
||||
|
|
@ -960,9 +954,9 @@ void jpeg_v4_0_3_dec_ring_nop(struct amdgpu_ring *ring, uint32_t count)
|
|||
}
|
||||
}
|
||||
|
||||
static bool jpeg_v4_0_3_is_idle(void *handle)
|
||||
static bool jpeg_v4_0_3_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
bool ret = false;
|
||||
int i, j;
|
||||
|
||||
|
|
@ -1004,7 +998,7 @@ static int jpeg_v4_0_3_set_clockgating_state(struct amdgpu_ip_block *ip_block,
|
|||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
if (enable) {
|
||||
if (!jpeg_v4_0_3_is_idle(adev))
|
||||
if (!jpeg_v4_0_3_is_idle(ip_block))
|
||||
return -EBUSY;
|
||||
jpeg_v4_0_3_enable_clock_gating(adev, i);
|
||||
} else {
|
||||
|
|
@ -1110,24 +1104,20 @@ static void jpeg_v4_0_3_core_stall_reset(struct amdgpu_ring *ring)
|
|||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JMI0_UVD_JMI_CLIENT_STALL,
|
||||
reg_offset, 0x1F);
|
||||
SOC15_WAIT_ON_RREG(JPEG, jpeg_inst,
|
||||
regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS,
|
||||
0x1F, 0x1F);
|
||||
SOC15_WAIT_ON_RREG_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS,
|
||||
reg_offset, 0x1F, 0x1F);
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JMI0_JPEG_LMI_DROP,
|
||||
reg_offset, 0x1F);
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regJPEG_CORE_RST_CTRL,
|
||||
reg_offset, 1 << ring->pipe);
|
||||
WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CORE_RST_CTRL, 1 << ring->pipe);
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JMI0_UVD_JMI_CLIENT_STALL,
|
||||
reg_offset, 0x00);
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JMI0_JPEG_LMI_DROP,
|
||||
reg_offset, 0x00);
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regJPEG_CORE_RST_CTRL,
|
||||
reg_offset, 0x00);
|
||||
WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CORE_RST_CTRL, 0x00);
|
||||
}
|
||||
|
||||
static int jpeg_v4_0_3_ring_reset(struct amdgpu_ring *ring, unsigned int vmid)
|
||||
|
|
@ -1338,8 +1328,8 @@ static int jpeg_v4_0_3_aca_bank_parser(struct aca_handle *handle, struct aca_ban
|
|||
1ULL);
|
||||
break;
|
||||
case ACA_SMU_TYPE_CE:
|
||||
bank->aca_err_type = ACA_ERROR_TYPE_CE;
|
||||
ret = aca_error_cache_log_bank_error(handle, &info, ACA_ERROR_TYPE_CE,
|
||||
bank->aca_err_type = ACA_BANK_ERR_CE_DE_DECODE(bank);
|
||||
ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type,
|
||||
ACA_REG__MISC0__ERRCNT(misc0));
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ void jpeg_v4_0_3_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq
|
|||
unsigned int flags);
|
||||
void jpeg_v4_0_3_dec_ring_emit_vm_flush(struct amdgpu_ring *ring,
|
||||
unsigned int vmid, uint64_t pd_addr);
|
||||
void jpeg_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring);
|
||||
void jpeg_v4_0_3_dec_ring_nop(struct amdgpu_ring *ring, uint32_t count);
|
||||
void jpeg_v4_0_3_dec_ring_insert_start(struct amdgpu_ring *ring);
|
||||
void jpeg_v4_0_3_dec_ring_insert_end(struct amdgpu_ring *ring);
|
||||
|
|
|
|||
|
|
@ -648,9 +648,9 @@ static void jpeg_v4_0_5_dec_ring_set_wptr(struct amdgpu_ring *ring)
|
|||
}
|
||||
}
|
||||
|
||||
static bool jpeg_v4_0_5_is_idle(void *handle)
|
||||
static bool jpeg_v4_0_5_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
int i, ret = 1;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
|
|
@ -693,7 +693,7 @@ static int jpeg_v4_0_5_set_clockgating_state(struct amdgpu_ip_block *ip_block,
|
|||
continue;
|
||||
|
||||
if (enable) {
|
||||
if (!jpeg_v4_0_5_is_idle(adev))
|
||||
if (!jpeg_v4_0_5_is_idle(ip_block))
|
||||
return -EBUSY;
|
||||
|
||||
jpeg_v4_0_5_enable_clock_gating(adev, i);
|
||||
|
|
|
|||
|
|
@ -559,9 +559,9 @@ static void jpeg_v5_0_0_dec_ring_set_wptr(struct amdgpu_ring *ring)
|
|||
}
|
||||
}
|
||||
|
||||
static bool jpeg_v5_0_0_is_idle(void *handle)
|
||||
static bool jpeg_v5_0_0_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
int ret = 1;
|
||||
|
||||
ret &= (((RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS) &
|
||||
|
|
@ -587,7 +587,7 @@ static int jpeg_v5_0_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
|
|||
bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
|
||||
|
||||
if (enable) {
|
||||
if (!jpeg_v5_0_0_is_idle(adev))
|
||||
if (!jpeg_v5_0_0_is_idle(ip_block))
|
||||
return -EBUSY;
|
||||
jpeg_v5_0_0_enable_clock_gating(adev);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -190,6 +190,13 @@ static int jpeg_v5_0_1_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
adev->jpeg.supported_reset = AMDGPU_RESET_TYPE_PER_QUEUE;
|
||||
r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -209,6 +216,9 @@ static int jpeg_v5_0_1_sw_fini(struct amdgpu_ip_block *ip_block)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
amdgpu_jpeg_sysfs_reset_mask_fini(adev);
|
||||
|
||||
r = amdgpu_jpeg_sw_fini(adev);
|
||||
|
||||
return r;
|
||||
|
|
@ -239,6 +249,9 @@ static int jpeg_v5_0_1_hw_init(struct amdgpu_ip_block *ip_block)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
if (RREG32_SOC15(VCN, GET_INST(VCN, 0), regVCN_RRMT_CNTL) & 0x100)
|
||||
adev->jpeg.caps |= AMDGPU_JPEG_CAPS(RRMT_ENABLED);
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
jpeg_inst = GET_INST(JPEG, i);
|
||||
ring = adev->jpeg.inst[i].ring_dec;
|
||||
|
|
@ -326,11 +339,10 @@ static int jpeg_v5_0_1_resume(struct amdgpu_ip_block *ip_block)
|
|||
return r;
|
||||
}
|
||||
|
||||
static int jpeg_v5_0_1_disable_antihang(struct amdgpu_device *adev, int inst_idx)
|
||||
static void jpeg_v5_0_1_init_inst(struct amdgpu_device *adev, int i)
|
||||
{
|
||||
int jpeg_inst;
|
||||
int jpeg_inst = GET_INST(JPEG, i);
|
||||
|
||||
jpeg_inst = GET_INST(JPEG, inst_idx);
|
||||
/* disable anti hang mechanism */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS), 0,
|
||||
~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
|
||||
|
|
@ -339,20 +351,75 @@ static int jpeg_v5_0_1_disable_antihang(struct amdgpu_device *adev, int inst_idx
|
|||
WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS), 0,
|
||||
~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK);
|
||||
|
||||
return 0;
|
||||
/* MJPEG global tiling registers */
|
||||
WREG32_SOC15(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG,
|
||||
adev->gfx.config.gb_addr_config);
|
||||
|
||||
/* enable JMI channel */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JMI_CNTL), 0,
|
||||
~UVD_JMI_CNTL__SOFT_RESET_MASK);
|
||||
}
|
||||
|
||||
static int jpeg_v5_0_1_enable_antihang(struct amdgpu_device *adev, int inst_idx)
|
||||
static void jpeg_v5_0_1_deinit_inst(struct amdgpu_device *adev, int i)
|
||||
{
|
||||
int jpeg_inst;
|
||||
int jpeg_inst = GET_INST(JPEG, i);
|
||||
/* reset JMI */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JMI_CNTL),
|
||||
UVD_JMI_CNTL__SOFT_RESET_MASK,
|
||||
~UVD_JMI_CNTL__SOFT_RESET_MASK);
|
||||
|
||||
jpeg_inst = GET_INST(JPEG, inst_idx);
|
||||
/* enable anti hang mechanism */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JPEG_POWER_STATUS),
|
||||
UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,
|
||||
~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
|
||||
~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
|
||||
}
|
||||
|
||||
return 0;
|
||||
static void jpeg_v5_0_1_init_jrbc(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
u32 reg, data, mask;
|
||||
int jpeg_inst = GET_INST(JPEG, ring->me);
|
||||
int reg_offset = ring->pipe ? jpeg_v5_0_1_core_reg_offset(ring->pipe) : 0;
|
||||
|
||||
/* enable System Interrupt for JRBC */
|
||||
reg = SOC15_REG_OFFSET(JPEG, jpeg_inst, regJPEG_SYS_INT_EN);
|
||||
if (ring->pipe < AMDGPU_MAX_JPEG_RINGS_4_0_3) {
|
||||
data = JPEG_SYS_INT_EN__DJRBC0_MASK << ring->pipe;
|
||||
mask = ~(JPEG_SYS_INT_EN__DJRBC0_MASK << ring->pipe);
|
||||
WREG32_P(reg, data, mask);
|
||||
} else {
|
||||
data = JPEG_SYS_INT_EN__DJRBC0_MASK << (ring->pipe+12);
|
||||
mask = ~(JPEG_SYS_INT_EN__DJRBC0_MASK << (ring->pipe+12));
|
||||
WREG32_P(reg, data, mask);
|
||||
}
|
||||
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_LMI_JRBC_RB_VMID,
|
||||
reg_offset, 0);
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JRBC_RB_CNTL,
|
||||
reg_offset,
|
||||
(0x00000001L | 0x00000002L));
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
|
||||
reg_offset, lower_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
|
||||
reg_offset, upper_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JRBC_RB_RPTR,
|
||||
reg_offset, 0);
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JRBC_RB_WPTR,
|
||||
reg_offset, 0);
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JRBC_RB_CNTL,
|
||||
reg_offset, 0x00000002L);
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JRBC_RB_SIZE,
|
||||
reg_offset, ring->ring_size / 4);
|
||||
ring->wptr = RREG32_SOC15_OFFSET(JPEG, jpeg_inst, regUVD_JRBC_RB_WPTR,
|
||||
reg_offset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -365,69 +432,13 @@ static int jpeg_v5_0_1_enable_antihang(struct amdgpu_device *adev, int inst_idx)
|
|||
static int jpeg_v5_0_1_start(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ring *ring;
|
||||
int i, j, jpeg_inst, r;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
jpeg_inst = GET_INST(JPEG, i);
|
||||
|
||||
/* disable antihang */
|
||||
r = jpeg_v5_0_1_disable_antihang(adev, i);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* MJPEG global tiling registers */
|
||||
WREG32_SOC15(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG,
|
||||
adev->gfx.config.gb_addr_config);
|
||||
|
||||
/* enable JMI channel */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JMI_CNTL), 0,
|
||||
~UVD_JMI_CNTL__SOFT_RESET_MASK);
|
||||
|
||||
jpeg_v5_0_1_init_inst(adev, i);
|
||||
for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
|
||||
int reg_offset = (j ? jpeg_v5_0_1_core_reg_offset(j) : 0);
|
||||
u32 reg, data, mask;
|
||||
|
||||
ring = &adev->jpeg.inst[i].ring_dec[j];
|
||||
|
||||
/* enable System Interrupt for JRBC */
|
||||
reg = SOC15_REG_OFFSET(JPEG, jpeg_inst, regJPEG_SYS_INT_EN);
|
||||
if (j < AMDGPU_MAX_JPEG_RINGS_4_0_3) {
|
||||
data = JPEG_SYS_INT_EN__DJRBC0_MASK << j;
|
||||
mask = ~(JPEG_SYS_INT_EN__DJRBC0_MASK << j);
|
||||
WREG32_P(reg, data, mask);
|
||||
} else {
|
||||
data = JPEG_SYS_INT_EN__DJRBC0_MASK << (j+12);
|
||||
mask = ~(JPEG_SYS_INT_EN__DJRBC0_MASK << (j+12));
|
||||
WREG32_P(reg, data, mask);
|
||||
}
|
||||
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_LMI_JRBC_RB_VMID,
|
||||
reg_offset, 0);
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JRBC_RB_CNTL,
|
||||
reg_offset,
|
||||
(0x00000001L | 0x00000002L));
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
|
||||
reg_offset, lower_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
|
||||
reg_offset, upper_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JRBC_RB_RPTR,
|
||||
reg_offset, 0);
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JRBC_RB_WPTR,
|
||||
reg_offset, 0);
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JRBC_RB_CNTL,
|
||||
reg_offset, 0x00000002L);
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JRBC_RB_SIZE,
|
||||
reg_offset, ring->ring_size / 4);
|
||||
ring->wptr = RREG32_SOC15_OFFSET(JPEG, jpeg_inst, regUVD_JRBC_RB_WPTR,
|
||||
reg_offset);
|
||||
jpeg_v5_0_1_init_jrbc(ring);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -443,20 +454,10 @@ static int jpeg_v5_0_1_start(struct amdgpu_device *adev)
|
|||
*/
|
||||
static int jpeg_v5_0_1_stop(struct amdgpu_device *adev)
|
||||
{
|
||||
int i, jpeg_inst, r;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
jpeg_inst = GET_INST(JPEG, i);
|
||||
/* reset JMI */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JMI_CNTL),
|
||||
UVD_JMI_CNTL__SOFT_RESET_MASK,
|
||||
~UVD_JMI_CNTL__SOFT_RESET_MASK);
|
||||
|
||||
/* enable antihang */
|
||||
r = jpeg_v5_0_1_enable_antihang(adev, i);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i)
|
||||
jpeg_v5_0_1_deinit_inst(adev, i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -516,9 +517,9 @@ static void jpeg_v5_0_1_dec_ring_set_wptr(struct amdgpu_ring *ring)
|
|||
}
|
||||
}
|
||||
|
||||
static bool jpeg_v5_0_1_is_idle(void *handle)
|
||||
static bool jpeg_v5_0_1_is_idle(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
bool ret = false;
|
||||
int i, j;
|
||||
|
||||
|
|
@ -567,7 +568,7 @@ static int jpeg_v5_0_1_set_clockgating_state(struct amdgpu_ip_block *ip_block,
|
|||
return 0;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
if (!jpeg_v5_0_1_is_idle(adev))
|
||||
if (!jpeg_v5_0_1_is_idle(ip_block))
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
|
@ -662,6 +663,41 @@ static int jpeg_v5_0_1_process_interrupt(struct amdgpu_device *adev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void jpeg_v5_0_1_core_stall_reset(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
int jpeg_inst = GET_INST(JPEG, ring->me);
|
||||
int reg_offset = ring->pipe ? jpeg_v5_0_1_core_reg_offset(ring->pipe) : 0;
|
||||
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JMI0_UVD_JMI_CLIENT_STALL,
|
||||
reg_offset, 0x1F);
|
||||
SOC15_WAIT_ON_RREG_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS,
|
||||
reg_offset, 0x1F, 0x1F);
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JMI0_JPEG_LMI_DROP,
|
||||
reg_offset, 0x1F);
|
||||
WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CORE_RST_CTRL, 1 << ring->pipe);
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JMI0_UVD_JMI_CLIENT_STALL,
|
||||
reg_offset, 0x00);
|
||||
WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
|
||||
regUVD_JMI0_JPEG_LMI_DROP,
|
||||
reg_offset, 0x00);
|
||||
WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CORE_RST_CTRL, 0x00);
|
||||
}
|
||||
|
||||
static int jpeg_v5_0_1_ring_reset(struct amdgpu_ring *ring, unsigned int vmid)
|
||||
{
|
||||
if (amdgpu_sriov_vf(ring->adev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
jpeg_v5_0_1_core_stall_reset(ring);
|
||||
jpeg_v5_0_1_init_jrbc(ring);
|
||||
return amdgpu_ring_test_helper(ring);
|
||||
}
|
||||
|
||||
static const struct amd_ip_funcs jpeg_v5_0_1_ip_funcs = {
|
||||
.name = "jpeg_v5_0_1",
|
||||
.early_init = jpeg_v5_0_1_early_init,
|
||||
|
|
@ -700,6 +736,7 @@ static const struct amdgpu_ring_funcs jpeg_v5_0_1_dec_ring_vm_funcs = {
|
|||
.emit_ib = jpeg_v4_0_3_dec_ring_emit_ib,
|
||||
.emit_fence = jpeg_v4_0_3_dec_ring_emit_fence,
|
||||
.emit_vm_flush = jpeg_v4_0_3_dec_ring_emit_vm_flush,
|
||||
.emit_hdp_flush = jpeg_v4_0_3_ring_emit_hdp_flush,
|
||||
.test_ring = amdgpu_jpeg_dec_ring_test_ring,
|
||||
.test_ib = amdgpu_jpeg_dec_ring_test_ib,
|
||||
.insert_nop = jpeg_v4_0_3_dec_ring_nop,
|
||||
|
|
@ -711,6 +748,7 @@ static const struct amdgpu_ring_funcs jpeg_v5_0_1_dec_ring_vm_funcs = {
|
|||
.emit_wreg = jpeg_v4_0_3_dec_ring_emit_wreg,
|
||||
.emit_reg_wait = jpeg_v4_0_3_dec_ring_emit_reg_wait,
|
||||
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
|
||||
.reset = jpeg_v5_0_1_ring_reset,
|
||||
};
|
||||
|
||||
static void jpeg_v5_0_1_set_dec_ring_funcs(struct amdgpu_device *adev)
|
||||
|
|
|
|||
|
|
@ -26,65 +26,76 @@
|
|||
|
||||
extern const struct amdgpu_ip_block_version jpeg_v5_0_1_ip_block;
|
||||
|
||||
#define regUVD_JRBC0_UVD_JRBC_RB_WPTR 0x0640
|
||||
#define regUVD_JRBC0_UVD_JRBC_RB_WPTR_BASE_IDX 1
|
||||
#define regUVD_JRBC0_UVD_JRBC_STATUS 0x0649
|
||||
#define regUVD_JRBC0_UVD_JRBC_STATUS_BASE_IDX 1
|
||||
#define regUVD_JRBC0_UVD_JRBC_RB_RPTR 0x064a
|
||||
#define regUVD_JRBC0_UVD_JRBC_RB_RPTR_BASE_IDX 1
|
||||
#define regUVD_JRBC1_UVD_JRBC_RB_WPTR 0x0000
|
||||
#define regUVD_JRBC1_UVD_JRBC_RB_WPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC1_UVD_JRBC_STATUS 0x0009
|
||||
#define regUVD_JRBC1_UVD_JRBC_STATUS_BASE_IDX 0
|
||||
#define regUVD_JRBC1_UVD_JRBC_RB_RPTR 0x000a
|
||||
#define regUVD_JRBC1_UVD_JRBC_RB_RPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC2_UVD_JRBC_RB_WPTR 0x0040
|
||||
#define regUVD_JRBC2_UVD_JRBC_RB_WPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC2_UVD_JRBC_STATUS 0x0049
|
||||
#define regUVD_JRBC2_UVD_JRBC_STATUS_BASE_IDX 0
|
||||
#define regUVD_JRBC2_UVD_JRBC_RB_RPTR 0x004a
|
||||
#define regUVD_JRBC2_UVD_JRBC_RB_RPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC3_UVD_JRBC_RB_WPTR 0x0080
|
||||
#define regUVD_JRBC3_UVD_JRBC_RB_WPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC3_UVD_JRBC_STATUS 0x0089
|
||||
#define regUVD_JRBC3_UVD_JRBC_STATUS_BASE_IDX 0
|
||||
#define regUVD_JRBC3_UVD_JRBC_RB_RPTR 0x008a
|
||||
#define regUVD_JRBC3_UVD_JRBC_RB_RPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC4_UVD_JRBC_RB_WPTR 0x00c0
|
||||
#define regUVD_JRBC4_UVD_JRBC_RB_WPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC4_UVD_JRBC_STATUS 0x00c9
|
||||
#define regUVD_JRBC4_UVD_JRBC_STATUS_BASE_IDX 0
|
||||
#define regUVD_JRBC4_UVD_JRBC_RB_RPTR 0x00ca
|
||||
#define regUVD_JRBC4_UVD_JRBC_RB_RPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC5_UVD_JRBC_RB_WPTR 0x0100
|
||||
#define regUVD_JRBC5_UVD_JRBC_RB_WPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC5_UVD_JRBC_STATUS 0x0109
|
||||
#define regUVD_JRBC5_UVD_JRBC_STATUS_BASE_IDX 0
|
||||
#define regUVD_JRBC5_UVD_JRBC_RB_RPTR 0x010a
|
||||
#define regUVD_JRBC5_UVD_JRBC_RB_RPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC6_UVD_JRBC_RB_WPTR 0x0140
|
||||
#define regUVD_JRBC6_UVD_JRBC_RB_WPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC6_UVD_JRBC_STATUS 0x0149
|
||||
#define regUVD_JRBC6_UVD_JRBC_STATUS_BASE_IDX 0
|
||||
#define regUVD_JRBC6_UVD_JRBC_RB_RPTR 0x014a
|
||||
#define regUVD_JRBC6_UVD_JRBC_RB_RPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC7_UVD_JRBC_RB_WPTR 0x0180
|
||||
#define regUVD_JRBC7_UVD_JRBC_RB_WPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC7_UVD_JRBC_STATUS 0x0189
|
||||
#define regUVD_JRBC7_UVD_JRBC_STATUS_BASE_IDX 0
|
||||
#define regUVD_JRBC7_UVD_JRBC_RB_RPTR 0x018a
|
||||
#define regUVD_JRBC7_UVD_JRBC_RB_RPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC8_UVD_JRBC_RB_WPTR 0x01c0
|
||||
#define regUVD_JRBC8_UVD_JRBC_RB_WPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC8_UVD_JRBC_STATUS 0x01c9
|
||||
#define regUVD_JRBC8_UVD_JRBC_STATUS_BASE_IDX 0
|
||||
#define regUVD_JRBC8_UVD_JRBC_RB_RPTR 0x01ca
|
||||
#define regUVD_JRBC8_UVD_JRBC_RB_RPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC9_UVD_JRBC_RB_WPTR 0x0440
|
||||
#define regUVD_JRBC9_UVD_JRBC_RB_WPTR_BASE_IDX 1
|
||||
#define regUVD_JRBC9_UVD_JRBC_STATUS 0x0449
|
||||
#define regUVD_JRBC9_UVD_JRBC_STATUS_BASE_IDX 1
|
||||
#define regUVD_JRBC9_UVD_JRBC_RB_RPTR 0x044a
|
||||
#define regUVD_JRBC9_UVD_JRBC_RB_RPTR_BASE_IDX 1
|
||||
#define regUVD_JRBC0_UVD_JRBC_RB_WPTR 0x0640
|
||||
#define regUVD_JRBC0_UVD_JRBC_RB_WPTR_BASE_IDX 1
|
||||
#define regUVD_JRBC0_UVD_JRBC_STATUS 0x0649
|
||||
#define regUVD_JRBC0_UVD_JRBC_STATUS_BASE_IDX 1
|
||||
#define regUVD_JRBC0_UVD_JRBC_RB_RPTR 0x064a
|
||||
#define regUVD_JRBC0_UVD_JRBC_RB_RPTR_BASE_IDX 1
|
||||
#define regUVD_JRBC1_UVD_JRBC_RB_WPTR 0x0000
|
||||
#define regUVD_JRBC1_UVD_JRBC_RB_WPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC1_UVD_JRBC_STATUS 0x0009
|
||||
#define regUVD_JRBC1_UVD_JRBC_STATUS_BASE_IDX 0
|
||||
#define regUVD_JRBC1_UVD_JRBC_RB_RPTR 0x000a
|
||||
#define regUVD_JRBC1_UVD_JRBC_RB_RPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC2_UVD_JRBC_RB_WPTR 0x0040
|
||||
#define regUVD_JRBC2_UVD_JRBC_RB_WPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC2_UVD_JRBC_STATUS 0x0049
|
||||
#define regUVD_JRBC2_UVD_JRBC_STATUS_BASE_IDX 0
|
||||
#define regUVD_JRBC2_UVD_JRBC_RB_RPTR 0x004a
|
||||
#define regUVD_JRBC2_UVD_JRBC_RB_RPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC3_UVD_JRBC_RB_WPTR 0x0080
|
||||
#define regUVD_JRBC3_UVD_JRBC_RB_WPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC3_UVD_JRBC_STATUS 0x0089
|
||||
#define regUVD_JRBC3_UVD_JRBC_STATUS_BASE_IDX 0
|
||||
#define regUVD_JRBC3_UVD_JRBC_RB_RPTR 0x008a
|
||||
#define regUVD_JRBC3_UVD_JRBC_RB_RPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC4_UVD_JRBC_RB_WPTR 0x00c0
|
||||
#define regUVD_JRBC4_UVD_JRBC_RB_WPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC4_UVD_JRBC_STATUS 0x00c9
|
||||
#define regUVD_JRBC4_UVD_JRBC_STATUS_BASE_IDX 0
|
||||
#define regUVD_JRBC4_UVD_JRBC_RB_RPTR 0x00ca
|
||||
#define regUVD_JRBC4_UVD_JRBC_RB_RPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC5_UVD_JRBC_RB_WPTR 0x0100
|
||||
#define regUVD_JRBC5_UVD_JRBC_RB_WPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC5_UVD_JRBC_STATUS 0x0109
|
||||
#define regUVD_JRBC5_UVD_JRBC_STATUS_BASE_IDX 0
|
||||
#define regUVD_JRBC5_UVD_JRBC_RB_RPTR 0x010a
|
||||
#define regUVD_JRBC5_UVD_JRBC_RB_RPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC6_UVD_JRBC_RB_WPTR 0x0140
|
||||
#define regUVD_JRBC6_UVD_JRBC_RB_WPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC6_UVD_JRBC_STATUS 0x0149
|
||||
#define regUVD_JRBC6_UVD_JRBC_STATUS_BASE_IDX 0
|
||||
#define regUVD_JRBC6_UVD_JRBC_RB_RPTR 0x014a
|
||||
#define regUVD_JRBC6_UVD_JRBC_RB_RPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC7_UVD_JRBC_RB_WPTR 0x0180
|
||||
#define regUVD_JRBC7_UVD_JRBC_RB_WPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC7_UVD_JRBC_STATUS 0x0189
|
||||
#define regUVD_JRBC7_UVD_JRBC_STATUS_BASE_IDX 0
|
||||
#define regUVD_JRBC7_UVD_JRBC_RB_RPTR 0x018a
|
||||
#define regUVD_JRBC7_UVD_JRBC_RB_RPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC8_UVD_JRBC_RB_WPTR 0x01c0
|
||||
#define regUVD_JRBC8_UVD_JRBC_RB_WPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC8_UVD_JRBC_STATUS 0x01c9
|
||||
#define regUVD_JRBC8_UVD_JRBC_STATUS_BASE_IDX 0
|
||||
#define regUVD_JRBC8_UVD_JRBC_RB_RPTR 0x01ca
|
||||
#define regUVD_JRBC8_UVD_JRBC_RB_RPTR_BASE_IDX 0
|
||||
#define regUVD_JRBC9_UVD_JRBC_RB_WPTR 0x0440
|
||||
#define regUVD_JRBC9_UVD_JRBC_RB_WPTR_BASE_IDX 1
|
||||
#define regUVD_JRBC9_UVD_JRBC_STATUS 0x0449
|
||||
#define regUVD_JRBC9_UVD_JRBC_STATUS_BASE_IDX 1
|
||||
#define regUVD_JRBC9_UVD_JRBC_RB_RPTR 0x044a
|
||||
#define regUVD_JRBC9_UVD_JRBC_RB_RPTR_BASE_IDX 1
|
||||
#define regUVD_JMI0_JPEG_LMI_DROP 0x0663
|
||||
#define regUVD_JMI0_JPEG_LMI_DROP_BASE_IDX 1
|
||||
#define regUVD_JMI0_UVD_JMI_CLIENT_STALL 0x067a
|
||||
#define regUVD_JMI0_UVD_JMI_CLIENT_STALL_BASE_IDX 1
|
||||
#define regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS 0x067b
|
||||
#define regUVD_JMI0_UVD_JMI_CLIENT_CLEAN_STATUS_BASE_IDX 1
|
||||
#define regJPEG_CORE_RST_CTRL 0x072e
|
||||
#define regJPEG_CORE_RST_CTRL_BASE_IDX 1
|
||||
|
||||
#endif /* __JPEG_V5_0_0_H__ */
|
||||
#define regVCN_RRMT_CNTL 0x0940
|
||||
#define regVCN_RRMT_CNTL_BASE_IDX 1
|
||||
|
||||
#endif /* __JPEG_V5_0_1_H__ */
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user