- 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: 2a64fa5e06

Signed-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:
Dave Airlie 2025-03-10 08:19:25 +10:00
commit 236f475d29
305 changed files with 7331 additions and 5083 deletions

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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;

View File

@ -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,

View File

@ -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;
}

View File

@ -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));
}
/**

View File

@ -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) :

View File

@ -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);

View File

@ -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
};

View File

@ -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
};

View File

@ -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
};

View File

@ -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
};

View File

@ -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);

View File

@ -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
};

View File

@ -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
};

View File

@ -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
};

View File

@ -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
};

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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)

View File

@ -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;
}

View File

@ -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.
*/

View File

@ -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 {

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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)

View File

@ -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__ */

View File

@ -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);
}
/**

View File

@ -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);
}

View File

@ -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

View File

@ -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,

View File

@ -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;
};
/*

View File

@ -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);

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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))

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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)

View File

@ -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 |

View File

@ -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

View File

@ -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))

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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))

View File

@ -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))

View File

@ -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))

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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 |

View File

@ -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 |

View File

@ -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;

View File

@ -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))

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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:

View File

@ -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);

View File

@ -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);

View File

@ -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 {

View File

@ -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)

View File

@ -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