mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
amd-drm-next-6.7-2023-11-10:
amdgpu: - SR-IOV fixes - DMCUB fixes - DCN3.5 fixes - DP2 fixes - SubVP fixes - SMU14 fixes - SDMA4.x fixes - Suspend/resume fixes - AGP regression fix - UAF fixes for some error cases - SMU 13.0.6 fixes - Documentation fixes - RAS fixes - Hotplug fixes - Scheduling entity ordering fix - GPUVM fixes -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCZU58aAAKCRC93/aFa7yZ 2PvJAQDF1IHj90BAqH3EzOx7p2jkGVeK1p+em2sS051kOvpgiAD/fvZovVUBmt/V tD0NOtkL8bqmIavP3vDV0Yvf9tW48Qs= =Z4Je -----END PGP SIGNATURE----- Merge tag 'amd-drm-next-6.7-2023-11-10' of https://gitlab.freedesktop.org/agd5f/linux into drm-next amd-drm-next-6.7-2023-11-10: amdgpu: - SR-IOV fixes - DMCUB fixes - DCN3.5 fixes - DP2 fixes - SubVP fixes - SMU14 fixes - SDMA4.x fixes - Suspend/resume fixes - AGP regression fix - UAF fixes for some error cases - SMU 13.0.6 fixes - Documentation fixes - RAS fixes - Hotplug fixes - Scheduling entity ordering fix - GPUVM fixes Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20231110190703.4741-1-alexander.deucher@amd.com
This commit is contained in:
commit
03df0fc007
@ -1159,11 +1159,18 @@ uint32_t amdgpu_device_rreg(struct amdgpu_device *adev,
|
||||
uint32_t reg, uint32_t acc_flags);
|
||||
u32 amdgpu_device_indirect_rreg_ext(struct amdgpu_device *adev,
|
||||
u64 reg_addr);
|
||||
uint32_t amdgpu_device_xcc_rreg(struct amdgpu_device *adev,
|
||||
uint32_t reg, uint32_t acc_flags,
|
||||
uint32_t xcc_id);
|
||||
void amdgpu_device_wreg(struct amdgpu_device *adev,
|
||||
uint32_t reg, uint32_t v,
|
||||
uint32_t acc_flags);
|
||||
void amdgpu_device_indirect_wreg_ext(struct amdgpu_device *adev,
|
||||
u64 reg_addr, u32 reg_data);
|
||||
void amdgpu_device_xcc_wreg(struct amdgpu_device *adev,
|
||||
uint32_t reg, uint32_t v,
|
||||
uint32_t acc_flags,
|
||||
uint32_t xcc_id);
|
||||
void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
|
||||
uint32_t reg, uint32_t v, uint32_t xcc_id);
|
||||
void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value);
|
||||
@ -1204,8 +1211,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
|
||||
#define RREG32_NO_KIQ(reg) amdgpu_device_rreg(adev, (reg), AMDGPU_REGS_NO_KIQ)
|
||||
#define WREG32_NO_KIQ(reg, v) amdgpu_device_wreg(adev, (reg), (v), AMDGPU_REGS_NO_KIQ)
|
||||
|
||||
#define RREG32_KIQ(reg) amdgpu_kiq_rreg(adev, (reg))
|
||||
#define WREG32_KIQ(reg, v) amdgpu_kiq_wreg(adev, (reg), (v))
|
||||
#define RREG32_KIQ(reg) amdgpu_kiq_rreg(adev, (reg), 0)
|
||||
#define WREG32_KIQ(reg, v) amdgpu_kiq_wreg(adev, (reg), (v), 0)
|
||||
|
||||
#define RREG8(reg) amdgpu_mm_rreg8(adev, (reg))
|
||||
#define WREG8(reg, v) amdgpu_mm_wreg8(adev, (reg), (v))
|
||||
@ -1215,6 +1222,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
|
||||
#define WREG32(reg, v) amdgpu_device_wreg(adev, (reg), (v), 0)
|
||||
#define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
|
||||
#define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
|
||||
#define RREG32_XCC(reg, inst) amdgpu_device_xcc_rreg(adev, (reg), 0, inst)
|
||||
#define WREG32_XCC(reg, v, inst) amdgpu_device_xcc_wreg(adev, (reg), (v), 0, inst)
|
||||
#define RREG32_PCIE(reg) adev->pcie_rreg(adev, (reg))
|
||||
#define WREG32_PCIE(reg, v) adev->pcie_wreg(adev, (reg), (v))
|
||||
#define RREG32_PCIE_PORT(reg) adev->pciep_rreg(adev, (reg))
|
||||
|
@ -1497,6 +1497,9 @@ bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev)
|
||||
if (adev->asic_type < CHIP_RAVEN)
|
||||
return false;
|
||||
|
||||
if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If ACPI_FADT_LOW_POWER_S0 is not set in the FADT, it is generally
|
||||
* risky to do any special firmware-related preparations for entering
|
||||
|
@ -300,14 +300,13 @@ static int kgd_gfx_v9_4_3_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
hqd_end = SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_AQL_DISPATCH_ID_HI);
|
||||
|
||||
for (reg = hqd_base; reg <= hqd_end; reg++)
|
||||
WREG32_RLC(reg, mqd_hqd[reg - hqd_base]);
|
||||
WREG32_XCC(reg, mqd_hqd[reg - hqd_base], inst);
|
||||
|
||||
|
||||
/* Activate doorbell logic before triggering WPTR poll. */
|
||||
data = REG_SET_FIELD(m->cp_hqd_pq_doorbell_control,
|
||||
CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 1);
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_PQ_DOORBELL_CONTROL),
|
||||
data);
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), regCP_HQD_PQ_DOORBELL_CONTROL, data);
|
||||
|
||||
if (wptr) {
|
||||
/* Don't read wptr with get_user because the user
|
||||
@ -336,27 +335,24 @@ static int kgd_gfx_v9_4_3_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
guessed_wptr += m->cp_hqd_pq_wptr_lo & ~(queue_size - 1);
|
||||
guessed_wptr += (uint64_t)m->cp_hqd_pq_wptr_hi << 32;
|
||||
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_LO),
|
||||
lower_32_bits(guessed_wptr));
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_HI),
|
||||
upper_32_bits(guessed_wptr));
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_POLL_ADDR),
|
||||
lower_32_bits((uintptr_t)wptr));
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst),
|
||||
regCP_HQD_PQ_WPTR_POLL_ADDR_HI),
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_LO,
|
||||
lower_32_bits(guessed_wptr));
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_HI,
|
||||
upper_32_bits(guessed_wptr));
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_POLL_ADDR,
|
||||
lower_32_bits((uintptr_t)wptr));
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_POLL_ADDR_HI,
|
||||
upper_32_bits((uintptr_t)wptr));
|
||||
WREG32(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_PQ_WPTR_POLL_CNTL1),
|
||||
(uint32_t)kgd_gfx_v9_get_queue_mask(adev, pipe_id,
|
||||
queue_id));
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), regCP_PQ_WPTR_POLL_CNTL1,
|
||||
(uint32_t)kgd_gfx_v9_get_queue_mask(adev, pipe_id, queue_id));
|
||||
}
|
||||
|
||||
/* Start the EOP fetcher */
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_EOP_RPTR),
|
||||
REG_SET_FIELD(m->cp_hqd_eop_rptr,
|
||||
CP_HQD_EOP_RPTR, INIT_FETCHER, 1));
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), regCP_HQD_EOP_RPTR,
|
||||
REG_SET_FIELD(m->cp_hqd_eop_rptr, CP_HQD_EOP_RPTR, INIT_FETCHER, 1));
|
||||
|
||||
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_ACTIVE), data);
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), regCP_HQD_ACTIVE, data);
|
||||
|
||||
kgd_gfx_v9_release_queue(adev, inst);
|
||||
|
||||
@ -494,15 +490,15 @@ static uint32_t kgd_gfx_v9_4_3_set_address_watch(
|
||||
VALID,
|
||||
1);
|
||||
|
||||
WREG32_RLC((SOC15_REG_OFFSET(GC, GET_INST(GC, inst),
|
||||
WREG32_XCC((SOC15_REG_OFFSET(GC, GET_INST(GC, inst),
|
||||
regTCP_WATCH0_ADDR_H) +
|
||||
(watch_id * TCP_WATCH_STRIDE)),
|
||||
watch_address_high);
|
||||
watch_address_high, inst);
|
||||
|
||||
WREG32_RLC((SOC15_REG_OFFSET(GC, GET_INST(GC, inst),
|
||||
WREG32_XCC((SOC15_REG_OFFSET(GC, GET_INST(GC, inst),
|
||||
regTCP_WATCH0_ADDR_L) +
|
||||
(watch_id * TCP_WATCH_STRIDE)),
|
||||
watch_address_low);
|
||||
watch_address_low, inst);
|
||||
|
||||
return watch_address_cntl;
|
||||
}
|
||||
|
@ -91,8 +91,8 @@ void kgd_gfx_v9_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmi
|
||||
{
|
||||
kgd_gfx_v9_lock_srbm(adev, 0, 0, 0, vmid, inst);
|
||||
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmSH_MEM_CONFIG), sh_mem_config);
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmSH_MEM_BASES), sh_mem_bases);
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmSH_MEM_CONFIG, sh_mem_config);
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmSH_MEM_BASES, sh_mem_bases);
|
||||
/* APE1 no longer exists on GFX9 */
|
||||
|
||||
kgd_gfx_v9_unlock_srbm(adev, inst);
|
||||
@ -239,14 +239,13 @@ int kgd_gfx_v9_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
|
||||
for (reg = hqd_base;
|
||||
reg <= SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_HI); reg++)
|
||||
WREG32_RLC(reg, mqd_hqd[reg - hqd_base]);
|
||||
WREG32_XCC(reg, mqd_hqd[reg - hqd_base], inst);
|
||||
|
||||
|
||||
/* Activate doorbell logic before triggering WPTR poll. */
|
||||
data = REG_SET_FIELD(m->cp_hqd_pq_doorbell_control,
|
||||
CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 1);
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_DOORBELL_CONTROL),
|
||||
data);
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_HQD_PQ_DOORBELL_CONTROL, data);
|
||||
|
||||
if (wptr) {
|
||||
/* Don't read wptr with get_user because the user
|
||||
@ -275,25 +274,24 @@ int kgd_gfx_v9_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
guessed_wptr += m->cp_hqd_pq_wptr_lo & ~(queue_size - 1);
|
||||
guessed_wptr += (uint64_t)m->cp_hqd_pq_wptr_hi << 32;
|
||||
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_LO),
|
||||
lower_32_bits(guessed_wptr));
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_HI),
|
||||
upper_32_bits(guessed_wptr));
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_POLL_ADDR),
|
||||
lower_32_bits((uintptr_t)wptr));
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_POLL_ADDR_HI),
|
||||
upper_32_bits((uintptr_t)wptr));
|
||||
WREG32_SOC15(GC, GET_INST(GC, inst), mmCP_PQ_WPTR_POLL_CNTL1,
|
||||
(uint32_t)kgd_gfx_v9_get_queue_mask(adev, pipe_id, queue_id));
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_LO,
|
||||
lower_32_bits(guessed_wptr));
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_HI,
|
||||
upper_32_bits(guessed_wptr));
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_POLL_ADDR,
|
||||
lower_32_bits((uintptr_t)wptr));
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_POLL_ADDR_HI,
|
||||
upper_32_bits((uintptr_t)wptr));
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_PQ_WPTR_POLL_CNTL1,
|
||||
(uint32_t)kgd_gfx_v9_get_queue_mask(adev, pipe_id, queue_id));
|
||||
}
|
||||
|
||||
/* Start the EOP fetcher */
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_EOP_RPTR),
|
||||
REG_SET_FIELD(m->cp_hqd_eop_rptr,
|
||||
CP_HQD_EOP_RPTR, INIT_FETCHER, 1));
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_HQD_EOP_RPTR,
|
||||
REG_SET_FIELD(m->cp_hqd_eop_rptr, CP_HQD_EOP_RPTR, INIT_FETCHER, 1));
|
||||
|
||||
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_ACTIVE), data);
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_HQD_ACTIVE, data);
|
||||
|
||||
kgd_gfx_v9_release_queue(adev, inst);
|
||||
|
||||
@ -556,7 +554,7 @@ int kgd_gfx_v9_hqd_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
break;
|
||||
}
|
||||
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_DEQUEUE_REQUEST), type);
|
||||
WREG32_SOC15_RLC(GC, GET_INST(GC, inst), mmCP_HQD_DEQUEUE_REQUEST, type);
|
||||
|
||||
end_jiffies = (utimeout * HZ / 1000) + jiffies;
|
||||
while (true) {
|
||||
@ -908,8 +906,8 @@ void kgd_gfx_v9_get_iq_wait_times(struct amdgpu_device *adev,
|
||||
uint32_t inst)
|
||||
|
||||
{
|
||||
*wait_times = RREG32(SOC15_REG_OFFSET(GC, GET_INST(GC, inst),
|
||||
mmCP_IQ_WAIT_TIME2));
|
||||
*wait_times = RREG32_SOC15_RLC(GC, GET_INST(GC, inst),
|
||||
mmCP_IQ_WAIT_TIME2);
|
||||
}
|
||||
|
||||
void kgd_gfx_v9_set_vm_context_page_table_base(struct amdgpu_device *adev,
|
||||
|
@ -172,6 +172,7 @@ int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id,
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
*result = NULL;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
|
@ -1415,7 +1415,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
if (r == -ENOMEM)
|
||||
DRM_ERROR("Not enough memory for command submission!\n");
|
||||
else if (r != -ERESTARTSYS && r != -EAGAIN)
|
||||
DRM_ERROR("Failed to process the buffer list %d!\n", r);
|
||||
DRM_DEBUG("Failed to process the buffer list %d!\n", r);
|
||||
goto error_fini;
|
||||
}
|
||||
|
||||
|
@ -73,6 +73,7 @@
|
||||
#include "amdgpu_pmu.h"
|
||||
#include "amdgpu_fru_eeprom.h"
|
||||
#include "amdgpu_reset.h"
|
||||
#include "amdgpu_virt.h"
|
||||
|
||||
#include <linux/suspend.h>
|
||||
#include <drm/task_barrier.h>
|
||||
@ -472,7 +473,7 @@ uint32_t amdgpu_device_rreg(struct amdgpu_device *adev,
|
||||
if (!(acc_flags & AMDGPU_REGS_NO_KIQ) &&
|
||||
amdgpu_sriov_runtime(adev) &&
|
||||
down_read_trylock(&adev->reset_domain->sem)) {
|
||||
ret = amdgpu_kiq_rreg(adev, reg);
|
||||
ret = amdgpu_kiq_rreg(adev, reg, 0);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
} else {
|
||||
ret = readl(((void __iomem *)adev->rmmio) + (reg * 4));
|
||||
@ -509,6 +510,49 @@ uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset)
|
||||
BUG();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* amdgpu_device_xcc_rreg - read a memory mapped IO or indirect register with specific XCC
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @reg: dword aligned register offset
|
||||
* @acc_flags: access flags which require special behavior
|
||||
* @xcc_id: xcc accelerated compute core id
|
||||
*
|
||||
* Returns the 32 bit value from the offset specified.
|
||||
*/
|
||||
uint32_t amdgpu_device_xcc_rreg(struct amdgpu_device *adev,
|
||||
uint32_t reg, uint32_t acc_flags,
|
||||
uint32_t xcc_id)
|
||||
{
|
||||
uint32_t ret, rlcg_flag;
|
||||
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
return 0;
|
||||
|
||||
if ((reg * 4) < adev->rmmio_size) {
|
||||
if (amdgpu_sriov_vf(adev) &&
|
||||
!amdgpu_sriov_runtime(adev) &&
|
||||
adev->gfx.rlc.rlcg_reg_access_supported &&
|
||||
amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags,
|
||||
GC_HWIP, false,
|
||||
&rlcg_flag)) {
|
||||
ret = amdgpu_virt_rlcg_reg_rw(adev, reg, 0, rlcg_flag, xcc_id);
|
||||
} else if (!(acc_flags & AMDGPU_REGS_NO_KIQ) &&
|
||||
amdgpu_sriov_runtime(adev) &&
|
||||
down_read_trylock(&adev->reset_domain->sem)) {
|
||||
ret = amdgpu_kiq_rreg(adev, reg, xcc_id);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
} else {
|
||||
ret = readl(((void __iomem *)adev->rmmio) + (reg * 4));
|
||||
}
|
||||
} else {
|
||||
ret = adev->pcie_rreg(adev, reg * 4);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* MMIO register write with bytes helper functions
|
||||
* @offset:bytes offset from MMIO start
|
||||
@ -556,7 +600,7 @@ void amdgpu_device_wreg(struct amdgpu_device *adev,
|
||||
if (!(acc_flags & AMDGPU_REGS_NO_KIQ) &&
|
||||
amdgpu_sriov_runtime(adev) &&
|
||||
down_read_trylock(&adev->reset_domain->sem)) {
|
||||
amdgpu_kiq_wreg(adev, reg, v);
|
||||
amdgpu_kiq_wreg(adev, reg, v, 0);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
} else {
|
||||
writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
|
||||
@ -597,6 +641,47 @@ void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_xcc_wreg - write to a memory mapped IO or indirect register with specific XCC
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @reg: dword aligned register offset
|
||||
* @v: 32 bit value to write to the register
|
||||
* @acc_flags: access flags which require special behavior
|
||||
* @xcc_id: xcc accelerated compute core id
|
||||
*
|
||||
* Writes the value specified to the offset specified.
|
||||
*/
|
||||
void amdgpu_device_xcc_wreg(struct amdgpu_device *adev,
|
||||
uint32_t reg, uint32_t v,
|
||||
uint32_t acc_flags, uint32_t xcc_id)
|
||||
{
|
||||
uint32_t rlcg_flag;
|
||||
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
return;
|
||||
|
||||
if ((reg * 4) < adev->rmmio_size) {
|
||||
if (amdgpu_sriov_vf(adev) &&
|
||||
!amdgpu_sriov_runtime(adev) &&
|
||||
adev->gfx.rlc.rlcg_reg_access_supported &&
|
||||
amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags,
|
||||
GC_HWIP, true,
|
||||
&rlcg_flag)) {
|
||||
amdgpu_virt_rlcg_reg_rw(adev, reg, v, rlcg_flag, xcc_id);
|
||||
} else if (!(acc_flags & AMDGPU_REGS_NO_KIQ) &&
|
||||
amdgpu_sriov_runtime(adev) &&
|
||||
down_read_trylock(&adev->reset_domain->sem)) {
|
||||
amdgpu_kiq_wreg(adev, reg, v, xcc_id);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
} else {
|
||||
writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
|
||||
}
|
||||
} else {
|
||||
adev->pcie_wreg(adev, reg * 4, v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_indirect_rreg - read an indirect register
|
||||
*
|
||||
@ -2499,6 +2584,18 @@ static int amdgpu_device_init_schedulers(struct amdgpu_device *adev)
|
||||
ring->name);
|
||||
return r;
|
||||
}
|
||||
r = amdgpu_uvd_entity_init(adev, ring);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to create UVD scheduling entity on ring %s.\n",
|
||||
ring->name);
|
||||
return r;
|
||||
}
|
||||
r = amdgpu_vce_entity_init(adev, ring);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to create VCE scheduling entity on ring %s.\n",
|
||||
ring->name);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
amdgpu_xcp_update_partition_sched_list(adev);
|
||||
@ -4486,19 +4583,18 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
|
||||
}
|
||||
amdgpu_fence_driver_hw_init(adev);
|
||||
|
||||
r = amdgpu_device_ip_late_init(adev);
|
||||
if (r)
|
||||
goto exit;
|
||||
|
||||
queue_delayed_work(system_wq, &adev->delayed_init_work,
|
||||
msecs_to_jiffies(AMDGPU_RESUME_MS));
|
||||
|
||||
if (!adev->in_s0ix) {
|
||||
r = amdgpu_amdkfd_resume(adev, adev->in_runpm);
|
||||
if (r)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
r = amdgpu_device_ip_late_init(adev);
|
||||
if (r)
|
||||
goto exit;
|
||||
|
||||
queue_delayed_work(system_wq, &adev->delayed_init_work,
|
||||
msecs_to_jiffies(AMDGPU_RESUME_MS));
|
||||
exit:
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
amdgpu_virt_init_data_exchange(adev);
|
||||
|
@ -931,12 +931,12 @@ void amdgpu_gfx_ras_error_func(struct amdgpu_device *adev,
|
||||
func(adev, ras_error_status, i);
|
||||
}
|
||||
|
||||
uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg)
|
||||
uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg, uint32_t xcc_id)
|
||||
{
|
||||
signed long r, cnt = 0;
|
||||
unsigned long flags;
|
||||
uint32_t seq, reg_val_offs = 0, value = 0;
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
|
||||
struct amdgpu_ring *ring = &kiq->ring;
|
||||
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
@ -999,12 +999,12 @@ failed_kiq_read:
|
||||
return ~0;
|
||||
}
|
||||
|
||||
void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v)
|
||||
void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint32_t xcc_id)
|
||||
{
|
||||
signed long r, cnt = 0;
|
||||
unsigned long flags;
|
||||
uint32_t seq;
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
|
||||
struct amdgpu_ring *ring = &kiq->ring;
|
||||
|
||||
BUG_ON(!ring->funcs->emit_wreg);
|
||||
|
@ -521,8 +521,8 @@ int amdgpu_gfx_process_ras_data_cb(struct amdgpu_device *adev,
|
||||
int amdgpu_gfx_cp_ecc_error_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry);
|
||||
uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg);
|
||||
void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v);
|
||||
uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg, uint32_t xcc_id);
|
||||
void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint32_t xcc_id);
|
||||
int amdgpu_gfx_get_num_kcq(struct amdgpu_device *adev);
|
||||
void amdgpu_gfx_cp_init_microcode(struct amdgpu_device *adev, uint32_t ucode_id);
|
||||
|
||||
|
@ -826,7 +826,10 @@ void amdgpu_gmc_noretry_set(struct amdgpu_device *adev)
|
||||
gc_ver == IP_VERSION(9, 4, 3) ||
|
||||
gc_ver >= IP_VERSION(10, 3, 0));
|
||||
|
||||
gmc->noretry = (amdgpu_noretry == -1) ? noretry_default : amdgpu_noretry;
|
||||
if (!amdgpu_sriov_xnack_support(adev))
|
||||
gmc->noretry = 1;
|
||||
else
|
||||
gmc->noretry = (amdgpu_noretry == -1) ? noretry_default : amdgpu_noretry;
|
||||
}
|
||||
|
||||
void amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type,
|
||||
|
@ -143,6 +143,46 @@ int amdgpu_mca_mpio_ras_sw_init(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_mca_bank_set_init(struct mca_bank_set *mca_set)
|
||||
{
|
||||
if (!mca_set)
|
||||
return;
|
||||
|
||||
memset(mca_set, 0, sizeof(*mca_set));
|
||||
INIT_LIST_HEAD(&mca_set->list);
|
||||
}
|
||||
|
||||
int amdgpu_mca_bank_set_add_entry(struct mca_bank_set *mca_set, struct mca_bank_entry *entry)
|
||||
{
|
||||
struct mca_bank_node *node;
|
||||
|
||||
if (!entry)
|
||||
return -EINVAL;
|
||||
|
||||
node = kvzalloc(sizeof(*node), GFP_KERNEL);
|
||||
if (!node)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(&node->entry, entry, sizeof(*entry));
|
||||
|
||||
INIT_LIST_HEAD(&node->node);
|
||||
list_add_tail(&node->node, &mca_set->list);
|
||||
|
||||
mca_set->nr_entries++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_mca_bank_set_release(struct mca_bank_set *mca_set)
|
||||
{
|
||||
struct mca_bank_node *node, *tmp;
|
||||
|
||||
list_for_each_entry_safe(node, tmp, &mca_set->list, node) {
|
||||
list_del(&node->node);
|
||||
kvfree(node);
|
||||
}
|
||||
}
|
||||
|
||||
void amdgpu_mca_smu_init_funcs(struct amdgpu_device *adev, const struct amdgpu_mca_smu_funcs *mca_funcs)
|
||||
{
|
||||
struct amdgpu_mca *mca = &adev->mca;
|
||||
@ -160,6 +200,65 @@ int amdgpu_mca_smu_set_debug_mode(struct amdgpu_device *adev, bool enable)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void amdgpu_mca_smu_mca_bank_dump(struct amdgpu_device *adev, int idx, struct mca_bank_entry *entry)
|
||||
{
|
||||
dev_info(adev->dev, "[Hardware error] Accelerator Check Architecture events logged\n");
|
||||
dev_info(adev->dev, "[Hardware error] aca entry[%02d].STATUS=0x%016llx\n",
|
||||
idx, entry->regs[MCA_REG_IDX_STATUS]);
|
||||
dev_info(adev->dev, "[Hardware error] aca entry[%02d].ADDR=0x%016llx\n",
|
||||
idx, entry->regs[MCA_REG_IDX_ADDR]);
|
||||
dev_info(adev->dev, "[Hardware error] aca entry[%02d].MISC0=0x%016llx\n",
|
||||
idx, entry->regs[MCA_REG_IDX_MISC0]);
|
||||
dev_info(adev->dev, "[Hardware error] aca entry[%02d].IPID=0x%016llx\n",
|
||||
idx, entry->regs[MCA_REG_IDX_IPID]);
|
||||
dev_info(adev->dev, "[Hardware error] aca entry[%02d].SYND=0x%016llx\n",
|
||||
idx, entry->regs[MCA_REG_IDX_SYND]);
|
||||
}
|
||||
|
||||
int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type, struct ras_err_data *err_data)
|
||||
{
|
||||
struct amdgpu_smuio_mcm_config_info mcm_info;
|
||||
struct mca_bank_set mca_set;
|
||||
struct mca_bank_node *node;
|
||||
struct mca_bank_entry *entry;
|
||||
uint32_t count;
|
||||
int ret, i = 0;
|
||||
|
||||
amdgpu_mca_bank_set_init(&mca_set);
|
||||
|
||||
ret = amdgpu_mca_smu_get_mca_set(adev, blk, type, &mca_set);
|
||||
if (ret)
|
||||
goto out_mca_release;
|
||||
|
||||
list_for_each_entry(node, &mca_set.list, node) {
|
||||
entry = &node->entry;
|
||||
|
||||
amdgpu_mca_smu_mca_bank_dump(adev, i++, entry);
|
||||
|
||||
count = 0;
|
||||
ret = amdgpu_mca_smu_parse_mca_error_count(adev, blk, type, entry, &count);
|
||||
if (ret)
|
||||
goto out_mca_release;
|
||||
|
||||
if (!count)
|
||||
continue;
|
||||
|
||||
mcm_info.socket_id = entry->info.socket_id;
|
||||
mcm_info.die_id = entry->info.aid;
|
||||
|
||||
if (type == AMDGPU_MCA_ERROR_TYPE_UE)
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, (uint64_t)count);
|
||||
else
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, (uint64_t)count);
|
||||
}
|
||||
|
||||
out_mca_release:
|
||||
amdgpu_mca_bank_set_release(&mca_set);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int amdgpu_mca_smu_get_valid_mca_count(struct amdgpu_device *adev, enum amdgpu_mca_error_type type, uint32_t *count)
|
||||
{
|
||||
const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
|
||||
@ -173,17 +272,77 @@ int amdgpu_mca_smu_get_valid_mca_count(struct amdgpu_device *adev, enum amdgpu_m
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int amdgpu_mca_smu_get_error_count(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
|
||||
enum amdgpu_mca_error_type type, uint32_t *count)
|
||||
int amdgpu_mca_smu_get_mca_set_error_count(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
|
||||
enum amdgpu_mca_error_type type, uint32_t *total)
|
||||
{
|
||||
const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
|
||||
if (!count)
|
||||
struct mca_bank_set mca_set;
|
||||
struct mca_bank_node *node;
|
||||
struct mca_bank_entry *entry;
|
||||
uint32_t count;
|
||||
int ret;
|
||||
|
||||
if (!total)
|
||||
return -EINVAL;
|
||||
|
||||
if (mca_funcs && mca_funcs->mca_get_error_count)
|
||||
return mca_funcs->mca_get_error_count(adev, blk, type, count);
|
||||
if (!mca_funcs)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
if (!mca_funcs->mca_get_ras_mca_set || !mca_funcs->mca_get_valid_mca_count)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
amdgpu_mca_bank_set_init(&mca_set);
|
||||
|
||||
ret = mca_funcs->mca_get_ras_mca_set(adev, blk, type, &mca_set);
|
||||
if (ret)
|
||||
goto err_mca_set_release;
|
||||
|
||||
*total = 0;
|
||||
list_for_each_entry(node, &mca_set.list, node) {
|
||||
entry = &node->entry;
|
||||
|
||||
count = 0;
|
||||
ret = mca_funcs->mca_parse_mca_error_count(adev, blk, type, entry, &count);
|
||||
if (ret)
|
||||
goto err_mca_set_release;
|
||||
|
||||
*total += count;
|
||||
}
|
||||
|
||||
err_mca_set_release:
|
||||
amdgpu_mca_bank_set_release(&mca_set);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int amdgpu_mca_smu_parse_mca_error_count(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
|
||||
enum amdgpu_mca_error_type type, struct mca_bank_entry *entry, uint32_t *count)
|
||||
{
|
||||
const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
|
||||
if (!count || !entry)
|
||||
return -EINVAL;
|
||||
|
||||
if (!mca_funcs || !mca_funcs->mca_parse_mca_error_count)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
||||
return mca_funcs->mca_parse_mca_error_count(adev, blk, type, entry, count);
|
||||
}
|
||||
|
||||
int amdgpu_mca_smu_get_mca_set(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
|
||||
enum amdgpu_mca_error_type type, struct mca_bank_set *mca_set)
|
||||
{
|
||||
const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
|
||||
|
||||
if (!mca_set)
|
||||
return -EINVAL;
|
||||
|
||||
if (!mca_funcs || !mca_funcs->mca_get_ras_mca_set)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
WARN_ON(!list_empty(&mca_set->list));
|
||||
|
||||
return mca_funcs->mca_get_ras_mca_set(adev, blk, type, mca_set);
|
||||
}
|
||||
|
||||
int amdgpu_mca_smu_get_mca_entry(struct amdgpu_device *adev, enum amdgpu_mca_error_type type,
|
||||
@ -230,14 +389,21 @@ static int amdgpu_mca_smu_debug_mode_set(void *data, u64 val)
|
||||
static void mca_dump_entry(struct seq_file *m, struct mca_bank_entry *entry)
|
||||
{
|
||||
int i, idx = entry->idx;
|
||||
int reg_idx_array[] = {
|
||||
MCA_REG_IDX_STATUS,
|
||||
MCA_REG_IDX_ADDR,
|
||||
MCA_REG_IDX_MISC0,
|
||||
MCA_REG_IDX_IPID,
|
||||
MCA_REG_IDX_SYND,
|
||||
};
|
||||
|
||||
seq_printf(m, "mca entry[%d].type: %s\n", idx, entry->type == AMDGPU_MCA_ERROR_TYPE_UE ? "UE" : "CE");
|
||||
seq_printf(m, "mca entry[%d].ip: %d\n", idx, entry->ip);
|
||||
seq_printf(m, "mca entry[%d].info: socketid:%d aid:%d hwid:0x%03x mcatype:0x%04x\n",
|
||||
idx, entry->info.socket_id, entry->info.aid, entry->info.hwid, entry->info.mcatype);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(entry->regs); i++)
|
||||
seq_printf(m, "mca entry[%d].regs[%d]: 0x%016llx\n", idx, i, entry->regs[i]);
|
||||
for (i = 0; i < ARRAY_SIZE(reg_idx_array); i++)
|
||||
seq_printf(m, "mca entry[%d].regs[%d]: 0x%016llx\n", idx, reg_idx_array[i], entry->regs[reg_idx_array[i]]);
|
||||
}
|
||||
|
||||
static int mca_dump_show(struct seq_file *m, enum amdgpu_mca_error_type type)
|
||||
|
@ -25,6 +25,27 @@
|
||||
|
||||
#define MCA_MAX_REGS_COUNT (16)
|
||||
|
||||
#define MCA_REG_FIELD(x, h, l) (((x) & GENMASK_ULL(h, l)) >> l)
|
||||
#define MCA_REG__STATUS__VAL(x) MCA_REG_FIELD(x, 63, 63)
|
||||
#define MCA_REG__STATUS__OVERFLOW(x) MCA_REG_FIELD(x, 62, 62)
|
||||
#define MCA_REG__STATUS__UC(x) MCA_REG_FIELD(x, 61, 61)
|
||||
#define MCA_REG__STATUS__EN(x) MCA_REG_FIELD(x, 60, 60)
|
||||
#define MCA_REG__STATUS__MISCV(x) MCA_REG_FIELD(x, 59, 59)
|
||||
#define MCA_REG__STATUS__ADDRV(x) MCA_REG_FIELD(x, 58, 58)
|
||||
#define MCA_REG__STATUS__PCC(x) MCA_REG_FIELD(x, 57, 57)
|
||||
#define MCA_REG__STATUS__ERRCOREIDVAL(x) MCA_REG_FIELD(x, 56, 56)
|
||||
#define MCA_REG__STATUS__TCC(x) MCA_REG_FIELD(x, 55, 55)
|
||||
#define MCA_REG__STATUS__SYNDV(x) MCA_REG_FIELD(x, 53, 53)
|
||||
#define MCA_REG__STATUS__CECC(x) MCA_REG_FIELD(x, 46, 46)
|
||||
#define MCA_REG__STATUS__UECC(x) MCA_REG_FIELD(x, 45, 45)
|
||||
#define MCA_REG__STATUS__DEFERRED(x) MCA_REG_FIELD(x, 44, 44)
|
||||
#define MCA_REG__STATUS__POISON(x) MCA_REG_FIELD(x, 43, 43)
|
||||
#define MCA_REG__STATUS__SCRUB(x) MCA_REG_FIELD(x, 40, 40)
|
||||
#define MCA_REG__STATUS__ERRCOREID(x) MCA_REG_FIELD(x, 37, 32)
|
||||
#define MCA_REG__STATUS__ADDRLSB(x) MCA_REG_FIELD(x, 29, 24)
|
||||
#define MCA_REG__STATUS__ERRORCODEEXT(x) MCA_REG_FIELD(x, 21, 16)
|
||||
#define MCA_REG__STATUS__ERRORCODE(x) MCA_REG_FIELD(x, 15, 0)
|
||||
|
||||
enum amdgpu_mca_ip {
|
||||
AMDGPU_MCA_IP_UNKNOW = -1,
|
||||
AMDGPU_MCA_IP_PSP = 0,
|
||||
@ -33,6 +54,7 @@ enum amdgpu_mca_ip {
|
||||
AMDGPU_MCA_IP_SMU,
|
||||
AMDGPU_MCA_IP_MP5,
|
||||
AMDGPU_MCA_IP_UMC,
|
||||
AMDGPU_MCA_IP_PCS_XGMI,
|
||||
AMDGPU_MCA_IP_COUNT,
|
||||
};
|
||||
|
||||
@ -57,6 +79,15 @@ struct amdgpu_mca {
|
||||
const struct amdgpu_mca_smu_funcs *mca_funcs;
|
||||
};
|
||||
|
||||
enum mca_reg_idx {
|
||||
MCA_REG_IDX_STATUS = 1,
|
||||
MCA_REG_IDX_ADDR = 2,
|
||||
MCA_REG_IDX_MISC0 = 3,
|
||||
MCA_REG_IDX_IPID = 5,
|
||||
MCA_REG_IDX_SYND = 6,
|
||||
MCA_REG_IDX_COUNT = 16,
|
||||
};
|
||||
|
||||
struct mca_bank_info {
|
||||
int socket_id;
|
||||
int aid;
|
||||
@ -72,18 +103,28 @@ struct mca_bank_entry {
|
||||
uint64_t regs[MCA_MAX_REGS_COUNT];
|
||||
};
|
||||
|
||||
struct mca_bank_node {
|
||||
struct mca_bank_entry entry;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
struct mca_bank_set {
|
||||
int nr_entries;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct amdgpu_mca_smu_funcs {
|
||||
int max_ue_count;
|
||||
int max_ce_count;
|
||||
int (*mca_set_debug_mode)(struct amdgpu_device *adev, bool enable);
|
||||
int (*mca_get_error_count)(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
|
||||
enum amdgpu_mca_error_type type, uint32_t *count);
|
||||
int (*mca_get_ras_mca_set)(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type,
|
||||
struct mca_bank_set *mca_set);
|
||||
int (*mca_parse_mca_error_count)(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type,
|
||||
struct mca_bank_entry *entry, uint32_t *count);
|
||||
int (*mca_get_valid_mca_count)(struct amdgpu_device *adev, enum amdgpu_mca_error_type type,
|
||||
uint32_t *count);
|
||||
int (*mca_get_mca_entry)(struct amdgpu_device *adev, enum amdgpu_mca_error_type type,
|
||||
int idx, struct mca_bank_entry *entry);
|
||||
int (*mca_get_ras_mca_idx_array)(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
|
||||
enum amdgpu_mca_error_type type, int *idx_array, int *idx_array_size);
|
||||
};
|
||||
|
||||
void amdgpu_mca_query_correctable_error_count(struct amdgpu_device *adev,
|
||||
@ -107,11 +148,22 @@ int amdgpu_mca_mpio_ras_sw_init(struct amdgpu_device *adev);
|
||||
void amdgpu_mca_smu_init_funcs(struct amdgpu_device *adev, const struct amdgpu_mca_smu_funcs *mca_funcs);
|
||||
int amdgpu_mca_smu_set_debug_mode(struct amdgpu_device *adev, bool enable);
|
||||
int amdgpu_mca_smu_get_valid_mca_count(struct amdgpu_device *adev, enum amdgpu_mca_error_type type, uint32_t *count);
|
||||
int amdgpu_mca_smu_get_mca_set_error_count(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
|
||||
enum amdgpu_mca_error_type type, uint32_t *total);
|
||||
int amdgpu_mca_smu_get_error_count(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
|
||||
enum amdgpu_mca_error_type type, uint32_t *count);
|
||||
int amdgpu_mca_smu_parse_mca_error_count(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
|
||||
enum amdgpu_mca_error_type type, struct mca_bank_entry *entry, uint32_t *count);
|
||||
int amdgpu_mca_smu_get_mca_set(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
|
||||
enum amdgpu_mca_error_type type, struct mca_bank_set *mca_set);
|
||||
int amdgpu_mca_smu_get_mca_entry(struct amdgpu_device *adev, enum amdgpu_mca_error_type type,
|
||||
int idx, struct mca_bank_entry *entry);
|
||||
|
||||
void amdgpu_mca_smu_debugfs_init(struct amdgpu_device *adev, struct dentry *root);
|
||||
|
||||
void amdgpu_mca_bank_set_init(struct mca_bank_set *mca_set);
|
||||
int amdgpu_mca_bank_set_add_entry(struct mca_bank_set *mca_set, struct mca_bank_entry *entry);
|
||||
void amdgpu_mca_bank_set_release(struct mca_bank_set *mca_set);
|
||||
int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type, struct ras_err_data *err_data);
|
||||
|
||||
#endif
|
||||
|
@ -1062,9 +1062,6 @@ static const char * const amdgpu_vram_names[] = {
|
||||
*/
|
||||
int amdgpu_bo_init(struct amdgpu_device *adev)
|
||||
{
|
||||
/* set the default AGP aperture state */
|
||||
amdgpu_gmc_set_agp_default(adev, &adev->gmc);
|
||||
|
||||
/* On A+A platform, VRAM can be mapped as WB */
|
||||
if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu) {
|
||||
/* reserve PAT memory space to WC for VRAM */
|
||||
|
@ -1165,13 +1165,53 @@ static void amdgpu_rasmgr_error_data_statistic_update(struct ras_manager *obj, s
|
||||
}
|
||||
}
|
||||
|
||||
/* query/inject/cure begin */
|
||||
int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
|
||||
struct ras_query_if *info)
|
||||
static int amdgpu_ras_query_error_status_helper(struct amdgpu_device *adev,
|
||||
struct ras_query_if *info,
|
||||
struct ras_err_data *err_data,
|
||||
unsigned int error_query_mode)
|
||||
{
|
||||
enum amdgpu_ras_block blk = info ? info->head.block : AMDGPU_RAS_BLOCK_COUNT;
|
||||
struct amdgpu_ras_block_object *block_obj = NULL;
|
||||
|
||||
if (error_query_mode == AMDGPU_RAS_INVALID_ERROR_QUERY)
|
||||
return -EINVAL;
|
||||
|
||||
if (error_query_mode == AMDGPU_RAS_DIRECT_ERROR_QUERY) {
|
||||
if (info->head.block == AMDGPU_RAS_BLOCK__UMC) {
|
||||
amdgpu_ras_get_ecc_info(adev, err_data);
|
||||
} else {
|
||||
block_obj = amdgpu_ras_get_ras_block(adev, info->head.block, 0);
|
||||
if (!block_obj || !block_obj->hw_ops) {
|
||||
dev_dbg_once(adev->dev, "%s doesn't config RAS function\n",
|
||||
get_ras_block_str(&info->head));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (block_obj->hw_ops->query_ras_error_count)
|
||||
block_obj->hw_ops->query_ras_error_count(adev, &err_data);
|
||||
|
||||
if ((info->head.block == AMDGPU_RAS_BLOCK__SDMA) ||
|
||||
(info->head.block == AMDGPU_RAS_BLOCK__GFX) ||
|
||||
(info->head.block == AMDGPU_RAS_BLOCK__MMHUB)) {
|
||||
if (block_obj->hw_ops->query_ras_error_status)
|
||||
block_obj->hw_ops->query_ras_error_status(adev);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* FIXME: add code to check return value later */
|
||||
amdgpu_mca_smu_log_ras_error(adev, blk, AMDGPU_MCA_ERROR_TYPE_UE, err_data);
|
||||
amdgpu_mca_smu_log_ras_error(adev, blk, AMDGPU_MCA_ERROR_TYPE_CE, err_data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* query/inject/cure begin */
|
||||
int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct ras_query_if *info)
|
||||
{
|
||||
struct ras_manager *obj = amdgpu_ras_find_obj(adev, &info->head);
|
||||
struct ras_err_data err_data;
|
||||
unsigned int error_query_mode;
|
||||
int ret;
|
||||
|
||||
if (!obj)
|
||||
@ -1181,27 +1221,14 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (info->head.block == AMDGPU_RAS_BLOCK__UMC) {
|
||||
amdgpu_ras_get_ecc_info(adev, &err_data);
|
||||
} else {
|
||||
block_obj = amdgpu_ras_get_ras_block(adev, info->head.block, 0);
|
||||
if (!block_obj || !block_obj->hw_ops) {
|
||||
dev_dbg_once(adev->dev, "%s doesn't config RAS function\n",
|
||||
get_ras_block_str(&info->head));
|
||||
ret = -EINVAL;
|
||||
goto out_fini_err_data;
|
||||
}
|
||||
if (!amdgpu_ras_get_error_query_mode(adev, &error_query_mode))
|
||||
return -EINVAL;
|
||||
|
||||
if (block_obj->hw_ops->query_ras_error_count)
|
||||
block_obj->hw_ops->query_ras_error_count(adev, &err_data);
|
||||
|
||||
if ((info->head.block == AMDGPU_RAS_BLOCK__SDMA) ||
|
||||
(info->head.block == AMDGPU_RAS_BLOCK__GFX) ||
|
||||
(info->head.block == AMDGPU_RAS_BLOCK__MMHUB)) {
|
||||
if (block_obj->hw_ops->query_ras_error_status)
|
||||
block_obj->hw_ops->query_ras_error_status(adev);
|
||||
}
|
||||
}
|
||||
ret = amdgpu_ras_query_error_status_helper(adev, info,
|
||||
&err_data,
|
||||
error_query_mode);
|
||||
if (ret)
|
||||
goto out_fini_err_data;
|
||||
|
||||
amdgpu_rasmgr_error_data_statistic_update(obj, &err_data);
|
||||
|
||||
@ -1537,7 +1564,8 @@ static void amdgpu_ras_sysfs_remove_bad_page_node(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
|
||||
sysfs_remove_file_from_group(&adev->dev->kobj,
|
||||
if (adev->dev->kobj.sd)
|
||||
sysfs_remove_file_from_group(&adev->dev->kobj,
|
||||
&con->badpages_attr.attr,
|
||||
RAS_FS_NAME);
|
||||
}
|
||||
@ -1556,7 +1584,8 @@ static int amdgpu_ras_sysfs_remove_dev_attr_node(struct amdgpu_device *adev)
|
||||
.attrs = attrs,
|
||||
};
|
||||
|
||||
sysfs_remove_group(&adev->dev->kobj, &group);
|
||||
if (adev->dev->kobj.sd)
|
||||
sysfs_remove_group(&adev->dev->kobj, &group);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1603,7 +1632,8 @@ int amdgpu_ras_sysfs_remove(struct amdgpu_device *adev,
|
||||
if (!obj || !obj->attr_inuse)
|
||||
return -EINVAL;
|
||||
|
||||
sysfs_remove_file_from_group(&adev->dev->kobj,
|
||||
if (adev->dev->kobj.sd)
|
||||
sysfs_remove_file_from_group(&adev->dev->kobj,
|
||||
&obj->sysfs_attr.attr,
|
||||
RAS_FS_NAME);
|
||||
obj->attr_inuse = 0;
|
||||
@ -3397,6 +3427,26 @@ bool amdgpu_ras_get_mca_debug_mode(struct amdgpu_device *adev)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool amdgpu_ras_get_error_query_mode(struct amdgpu_device *adev,
|
||||
unsigned int *error_query_mode)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
|
||||
|
||||
if (!con) {
|
||||
*error_query_mode = AMDGPU_RAS_INVALID_ERROR_QUERY;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mca_funcs && mca_funcs->mca_set_debug_mode)
|
||||
*error_query_mode =
|
||||
(con->is_mca_debug_mode) ? AMDGPU_RAS_DIRECT_ERROR_QUERY : AMDGPU_RAS_FIRMWARE_ERROR_QUERY;
|
||||
else
|
||||
*error_query_mode = AMDGPU_RAS_DIRECT_ERROR_QUERY;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Register each ip ras block into amdgpu ras */
|
||||
int amdgpu_ras_register_ras_block(struct amdgpu_device *adev,
|
||||
struct amdgpu_ras_block_object *ras_block_obj)
|
||||
|
@ -320,6 +320,12 @@ enum amdgpu_ras_ret {
|
||||
AMDGPU_RAS_PT,
|
||||
};
|
||||
|
||||
enum amdgpu_ras_error_query_mode {
|
||||
AMDGPU_RAS_INVALID_ERROR_QUERY = 0,
|
||||
AMDGPU_RAS_DIRECT_ERROR_QUERY = 1,
|
||||
AMDGPU_RAS_FIRMWARE_ERROR_QUERY = 2,
|
||||
};
|
||||
|
||||
/* ras error status reisger fields */
|
||||
#define ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
|
||||
#define ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
|
||||
@ -769,6 +775,8 @@ int amdgpu_ras_set_context(struct amdgpu_device *adev, struct amdgpu_ras *ras_co
|
||||
|
||||
void amdgpu_ras_set_mca_debug_mode(struct amdgpu_device *adev, bool enable);
|
||||
bool amdgpu_ras_get_mca_debug_mode(struct amdgpu_device *adev);
|
||||
bool amdgpu_ras_get_error_query_mode(struct amdgpu_device *adev,
|
||||
unsigned int *mode);
|
||||
|
||||
int amdgpu_ras_register_ras_block(struct amdgpu_device *adev,
|
||||
struct amdgpu_ras_block_object *ras_block_obj);
|
||||
|
@ -399,20 +399,20 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Initialize the entity used for handle management in the kernel driver.
|
||||
*/
|
||||
int amdgpu_uvd_entity_init(struct amdgpu_device *adev)
|
||||
int amdgpu_uvd_entity_init(struct amdgpu_device *adev, struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_ring *ring;
|
||||
struct drm_gpu_scheduler *sched;
|
||||
int r;
|
||||
if (ring == &adev->uvd.inst[0].ring) {
|
||||
struct drm_gpu_scheduler *sched = &ring->sched;
|
||||
int r;
|
||||
|
||||
ring = &adev->uvd.inst[0].ring;
|
||||
sched = &ring->sched;
|
||||
r = drm_sched_entity_init(&adev->uvd.entity, DRM_SCHED_PRIORITY_NORMAL,
|
||||
&sched, 1, NULL);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed setting up UVD kernel entity.\n");
|
||||
return r;
|
||||
r = drm_sched_entity_init(&adev->uvd.entity, DRM_SCHED_PRIORITY_NORMAL,
|
||||
&sched, 1, NULL);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed setting up UVD kernel entity.\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -73,7 +73,7 @@ struct amdgpu_uvd {
|
||||
|
||||
int amdgpu_uvd_sw_init(struct amdgpu_device *adev);
|
||||
int amdgpu_uvd_sw_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_uvd_entity_init(struct amdgpu_device *adev);
|
||||
int amdgpu_uvd_entity_init(struct amdgpu_device *adev, struct amdgpu_ring *ring);
|
||||
int amdgpu_uvd_prepare_suspend(struct amdgpu_device *adev);
|
||||
int amdgpu_uvd_suspend(struct amdgpu_device *adev);
|
||||
int amdgpu_uvd_resume(struct amdgpu_device *adev);
|
||||
|
@ -231,20 +231,20 @@ int amdgpu_vce_sw_fini(struct amdgpu_device *adev)
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Initialize the entity used for handle management in the kernel driver.
|
||||
*/
|
||||
int amdgpu_vce_entity_init(struct amdgpu_device *adev)
|
||||
int amdgpu_vce_entity_init(struct amdgpu_device *adev, struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_ring *ring;
|
||||
struct drm_gpu_scheduler *sched;
|
||||
int r;
|
||||
if (ring == &adev->vce.ring[0]) {
|
||||
struct drm_gpu_scheduler *sched = &ring->sched;
|
||||
int r;
|
||||
|
||||
ring = &adev->vce.ring[0];
|
||||
sched = &ring->sched;
|
||||
r = drm_sched_entity_init(&adev->vce.entity, DRM_SCHED_PRIORITY_NORMAL,
|
||||
&sched, 1, NULL);
|
||||
if (r != 0) {
|
||||
DRM_ERROR("Failed setting up VCE run queue.\n");
|
||||
return r;
|
||||
r = drm_sched_entity_init(&adev->vce.entity, DRM_SCHED_PRIORITY_NORMAL,
|
||||
&sched, 1, NULL);
|
||||
if (r != 0) {
|
||||
DRM_ERROR("Failed setting up VCE run queue.\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -55,7 +55,7 @@ struct amdgpu_vce {
|
||||
|
||||
int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size);
|
||||
int amdgpu_vce_sw_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_vce_entity_init(struct amdgpu_device *adev);
|
||||
int amdgpu_vce_entity_init(struct amdgpu_device *adev, struct amdgpu_ring *ring);
|
||||
int amdgpu_vce_suspend(struct amdgpu_device *adev);
|
||||
int amdgpu_vce_resume(struct amdgpu_device *adev);
|
||||
void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp);
|
||||
|
@ -73,9 +73,10 @@ void amdgpu_virt_init_setting(struct amdgpu_device *adev)
|
||||
|
||||
void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev,
|
||||
uint32_t reg0, uint32_t reg1,
|
||||
uint32_t ref, uint32_t mask)
|
||||
uint32_t ref, uint32_t mask,
|
||||
uint32_t xcc_inst)
|
||||
{
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_inst];
|
||||
struct amdgpu_ring *ring = &kiq->ring;
|
||||
signed long r, cnt = 0;
|
||||
unsigned long flags;
|
||||
@ -942,7 +943,7 @@ void amdgpu_virt_update_sriov_video_codec(struct amdgpu_device *adev,
|
||||
}
|
||||
}
|
||||
|
||||
static bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev,
|
||||
bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev,
|
||||
u32 acc_flags, u32 hwip,
|
||||
bool write, u32 *rlcg_flag)
|
||||
{
|
||||
@ -975,7 +976,7 @@ static bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 flag, u32 xcc_id)
|
||||
u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 flag, u32 xcc_id)
|
||||
{
|
||||
struct amdgpu_rlcg_reg_access_ctrl *reg_access_ctrl;
|
||||
uint32_t timeout = 50000;
|
||||
@ -1093,3 +1094,13 @@ u32 amdgpu_sriov_rreg(struct amdgpu_device *adev,
|
||||
else
|
||||
return RREG32(offset);
|
||||
}
|
||||
|
||||
bool amdgpu_sriov_xnack_support(struct amdgpu_device *adev)
|
||||
{
|
||||
bool xnack_mode = true;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2))
|
||||
xnack_mode = false;
|
||||
|
||||
return xnack_mode;
|
||||
}
|
||||
|
@ -334,7 +334,8 @@ bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_init_setting(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev,
|
||||
uint32_t reg0, uint32_t rreg1,
|
||||
uint32_t ref, uint32_t mask);
|
||||
uint32_t ref, uint32_t mask,
|
||||
uint32_t xcc_inst);
|
||||
int amdgpu_virt_request_full_gpu(struct amdgpu_device *adev, bool init);
|
||||
int amdgpu_virt_release_full_gpu(struct amdgpu_device *adev, bool init);
|
||||
int amdgpu_virt_reset_gpu(struct amdgpu_device *adev);
|
||||
@ -365,4 +366,9 @@ u32 amdgpu_sriov_rreg(struct amdgpu_device *adev,
|
||||
bool amdgpu_virt_fw_load_skip_check(struct amdgpu_device *adev,
|
||||
uint32_t ucode_id);
|
||||
void amdgpu_virt_post_reset(struct amdgpu_device *adev);
|
||||
bool amdgpu_sriov_xnack_support(struct amdgpu_device *adev);
|
||||
bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev,
|
||||
u32 acc_flags, u32 hwip,
|
||||
bool write, u32 *rlcg_flag);
|
||||
u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 flag, u32 xcc_id);
|
||||
#endif
|
||||
|
@ -1098,8 +1098,8 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va,
|
||||
bo = gem_to_amdgpu_bo(gobj);
|
||||
}
|
||||
mem = bo->tbo.resource;
|
||||
if (mem->mem_type == TTM_PL_TT ||
|
||||
mem->mem_type == AMDGPU_PL_PREEMPT)
|
||||
if (mem && (mem->mem_type == TTM_PL_TT ||
|
||||
mem->mem_type == AMDGPU_PL_PREEMPT))
|
||||
pages_addr = bo->tbo.ttm->dma_address;
|
||||
}
|
||||
|
||||
@ -2139,7 +2139,8 @@ long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout)
|
||||
* Returns:
|
||||
* 0 for success, error for failure.
|
||||
*/
|
||||
int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t xcp_id)
|
||||
int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
int32_t xcp_id)
|
||||
{
|
||||
struct amdgpu_bo *root_bo;
|
||||
struct amdgpu_bo_vm *root;
|
||||
@ -2158,6 +2159,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t xcp
|
||||
INIT_LIST_HEAD(&vm->done);
|
||||
INIT_LIST_HEAD(&vm->pt_freed);
|
||||
INIT_WORK(&vm->pt_free_work, amdgpu_vm_pt_free_work);
|
||||
INIT_KFIFO(vm->faults);
|
||||
|
||||
r = amdgpu_vm_init_entities(adev, vm);
|
||||
if (r)
|
||||
@ -2192,34 +2194,33 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t xcp
|
||||
false, &root, xcp_id);
|
||||
if (r)
|
||||
goto error_free_delayed;
|
||||
root_bo = &root->bo;
|
||||
|
||||
root_bo = amdgpu_bo_ref(&root->bo);
|
||||
r = amdgpu_bo_reserve(root_bo, true);
|
||||
if (r) {
|
||||
amdgpu_bo_unref(&root->shadow);
|
||||
amdgpu_bo_unref(&root_bo);
|
||||
goto error_free_delayed;
|
||||
}
|
||||
|
||||
amdgpu_vm_bo_base_init(&vm->root, vm, root_bo);
|
||||
r = dma_resv_reserve_fences(root_bo->tbo.base.resv, 1);
|
||||
if (r)
|
||||
goto error_free_root;
|
||||
|
||||
r = dma_resv_reserve_fences(root_bo->tbo.base.resv, 1);
|
||||
if (r)
|
||||
goto error_unreserve;
|
||||
|
||||
amdgpu_vm_bo_base_init(&vm->root, vm, root_bo);
|
||||
|
||||
r = amdgpu_vm_pt_clear(adev, vm, root, false);
|
||||
if (r)
|
||||
goto error_unreserve;
|
||||
goto error_free_root;
|
||||
|
||||
amdgpu_bo_unreserve(vm->root.bo);
|
||||
|
||||
INIT_KFIFO(vm->faults);
|
||||
amdgpu_bo_unref(&root_bo);
|
||||
|
||||
return 0;
|
||||
|
||||
error_unreserve:
|
||||
amdgpu_bo_unreserve(vm->root.bo);
|
||||
|
||||
error_free_root:
|
||||
amdgpu_bo_unref(&root->shadow);
|
||||
amdgpu_vm_pt_free_root(adev, vm);
|
||||
amdgpu_bo_unreserve(vm->root.bo);
|
||||
amdgpu_bo_unref(&root_bo);
|
||||
vm->root.bo = NULL;
|
||||
|
||||
error_free_delayed:
|
||||
dma_fence_put(vm->last_tlb_flush);
|
||||
|
@ -103,6 +103,53 @@ static const int walf_pcs_err_noncorrectable_mask_reg_aldebaran[] = {
|
||||
smnPCS_GOPX1_PCS_ERROR_NONCORRECTABLE_MASK + 0x100000
|
||||
};
|
||||
|
||||
static const int xgmi3x16_pcs_err_status_reg_v6_4[] = {
|
||||
smnPCS_XGMI3X16_PCS_ERROR_STATUS,
|
||||
smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x100000
|
||||
};
|
||||
|
||||
static const int xgmi3x16_pcs_err_noncorrectable_mask_reg_v6_4[] = {
|
||||
smnPCS_XGMI3X16_PCS_ERROR_NONCORRECTABLE_MASK,
|
||||
smnPCS_XGMI3X16_PCS_ERROR_NONCORRECTABLE_MASK + 0x100000
|
||||
};
|
||||
|
||||
static const u64 xgmi_v6_4_0_mca_base_array[] = {
|
||||
0x11a09200,
|
||||
0x11b09200,
|
||||
};
|
||||
|
||||
static const char *xgmi_v6_4_0_ras_error_code_ext[32] = {
|
||||
[0x00] = "XGMI PCS DataLossErr",
|
||||
[0x01] = "XGMI PCS TrainingErr",
|
||||
[0x02] = "XGMI PCS FlowCtrlAckErr",
|
||||
[0x03] = "XGMI PCS RxFifoUnderflowErr",
|
||||
[0x04] = "XGMI PCS RxFifoOverflowErr",
|
||||
[0x05] = "XGMI PCS CRCErr",
|
||||
[0x06] = "XGMI PCS BERExceededErr",
|
||||
[0x07] = "XGMI PCS TxMetaDataErr",
|
||||
[0x08] = "XGMI PCS ReplayBufParityErr",
|
||||
[0x09] = "XGMI PCS DataParityErr",
|
||||
[0x0a] = "XGMI PCS ReplayFifoOverflowErr",
|
||||
[0x0b] = "XGMI PCS ReplayFifoUnderflowErr",
|
||||
[0x0c] = "XGMI PCS ElasticFifoOverflowErr",
|
||||
[0x0d] = "XGMI PCS DeskewErr",
|
||||
[0x0e] = "XGMI PCS FlowCtrlCRCErr",
|
||||
[0x0f] = "XGMI PCS DataStartupLimitErr",
|
||||
[0x10] = "XGMI PCS FCInitTimeoutErr",
|
||||
[0x11] = "XGMI PCS RecoveryTimeoutErr",
|
||||
[0x12] = "XGMI PCS ReadySerialTimeoutErr",
|
||||
[0x13] = "XGMI PCS ReadySerialAttemptErr",
|
||||
[0x14] = "XGMI PCS RecoveryAttemptErr",
|
||||
[0x15] = "XGMI PCS RecoveryRelockAttemptErr",
|
||||
[0x16] = "XGMI PCS ReplayAttemptErr",
|
||||
[0x17] = "XGMI PCS SyncHdrErr",
|
||||
[0x18] = "XGMI PCS TxReplayTimeoutErr",
|
||||
[0x19] = "XGMI PCS RxReplayTimeoutErr",
|
||||
[0x1a] = "XGMI PCS LinkSubTxTimeoutErr",
|
||||
[0x1b] = "XGMI PCS LinkSubRxTimeoutErr",
|
||||
[0x1c] = "XGMI PCS RxCMDPktErr",
|
||||
};
|
||||
|
||||
static const struct amdgpu_pcs_ras_field xgmi_pcs_ras_fields[] = {
|
||||
{"XGMI PCS DataLossErr",
|
||||
SOC15_REG_FIELD(XGMI0_PCS_GOPX16_PCS_ERROR_STATUS, DataLossErr)},
|
||||
@ -926,7 +973,7 @@ static void pcs_clear_status(struct amdgpu_device *adev, uint32_t pcs_status_reg
|
||||
WREG32_PCIE(pcs_status_reg, 0);
|
||||
}
|
||||
|
||||
static void amdgpu_xgmi_reset_ras_error_count(struct amdgpu_device *adev)
|
||||
static void amdgpu_xgmi_legacy_reset_ras_error_count(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
@ -952,6 +999,49 @@ static void amdgpu_xgmi_reset_ras_error_count(struct amdgpu_device *adev)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
|
||||
case IP_VERSION(6, 4, 0):
|
||||
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]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void __xgmi_v6_4_0_reset_error_count(struct amdgpu_device *adev, int xgmi_inst, u64 mca_base)
|
||||
{
|
||||
WREG64_MCA(xgmi_inst, mca_base, MCA_REG_IDX_STATUS, 0ULL);
|
||||
}
|
||||
|
||||
static void xgmi_v6_4_0_reset_error_count(struct amdgpu_device *adev, int xgmi_inst)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(xgmi_v6_4_0_mca_base_array); i++)
|
||||
__xgmi_v6_4_0_reset_error_count(adev, xgmi_inst, xgmi_v6_4_0_mca_base_array[i]);
|
||||
}
|
||||
|
||||
static void xgmi_v6_4_0_reset_ras_error_count(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for_each_inst(i, adev->aid_mask)
|
||||
xgmi_v6_4_0_reset_error_count(adev, i);
|
||||
}
|
||||
|
||||
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):
|
||||
xgmi_v6_4_0_reset_ras_error_count(adev);
|
||||
break;
|
||||
default:
|
||||
amdgpu_xgmi_legacy_reset_ras_error_count(adev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int amdgpu_xgmi_query_pcs_error_status(struct amdgpu_device *adev,
|
||||
@ -969,7 +1059,9 @@ static int amdgpu_xgmi_query_pcs_error_status(struct amdgpu_device *adev,
|
||||
|
||||
if (is_xgmi_pcs) {
|
||||
if (amdgpu_ip_version(adev, XGMI_HWIP, 0) ==
|
||||
IP_VERSION(6, 1, 0)) {
|
||||
IP_VERSION(6, 1, 0) ||
|
||||
amdgpu_ip_version(adev, XGMI_HWIP, 0) ==
|
||||
IP_VERSION(6, 4, 0)) {
|
||||
pcs_ras_fields = &xgmi3x16_pcs_ras_fields[0];
|
||||
field_array_size = ARRAY_SIZE(xgmi3x16_pcs_ras_fields);
|
||||
} else {
|
||||
@ -1003,11 +1095,11 @@ static int amdgpu_xgmi_query_pcs_error_status(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
static void amdgpu_xgmi_legacy_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
{
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
int i;
|
||||
int i, supported = 1;
|
||||
uint32_t data, mask_data = 0;
|
||||
uint32_t ue_cnt = 0, ce_cnt = 0;
|
||||
|
||||
@ -1071,7 +1163,25 @@ static void amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_warn(adev->dev, "XGMI RAS error query not supported");
|
||||
supported = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
|
||||
case IP_VERSION(6, 4, 0):
|
||||
/* 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]);
|
||||
mask_data =
|
||||
RREG32_PCIE(xgmi3x16_pcs_err_noncorrectable_mask_reg_v6_4[i]);
|
||||
if (data)
|
||||
amdgpu_xgmi_query_pcs_error_status(adev, data,
|
||||
mask_data, &ue_cnt, &ce_cnt, true, true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!supported)
|
||||
dev_warn(adev->dev, "XGMI RAS error query not supported");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1081,32 +1191,116 @@ static void amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
|
||||
err_data->ce_count += ce_cnt;
|
||||
}
|
||||
|
||||
static enum amdgpu_mca_error_type xgmi_v6_4_0_pcs_mca_get_error_type(struct amdgpu_device *adev, u64 status)
|
||||
{
|
||||
const char *error_str;
|
||||
int ext_error_code;
|
||||
|
||||
ext_error_code = MCA_REG__STATUS__ERRORCODEEXT(status);
|
||||
|
||||
error_str = ext_error_code < ARRAY_SIZE(xgmi_v6_4_0_ras_error_code_ext) ?
|
||||
xgmi_v6_4_0_ras_error_code_ext[ext_error_code] : NULL;
|
||||
if (error_str)
|
||||
dev_info(adev->dev, "%s detected\n", error_str);
|
||||
|
||||
switch (ext_error_code) {
|
||||
case 0:
|
||||
return AMDGPU_MCA_ERROR_TYPE_UE;
|
||||
case 6:
|
||||
return AMDGPU_MCA_ERROR_TYPE_CE;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void __xgmi_v6_4_0_query_error_count(struct amdgpu_device *adev, struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
u64 mca_base, struct ras_err_data *err_data)
|
||||
{
|
||||
int xgmi_inst = mcm_info->die_id;
|
||||
u64 status = 0;
|
||||
|
||||
status = RREG64_MCA(xgmi_inst, mca_base, MCA_REG_IDX_STATUS);
|
||||
if (!MCA_REG__STATUS__VAL(status))
|
||||
return;
|
||||
|
||||
switch (xgmi_v6_4_0_pcs_mca_get_error_type(adev, status)) {
|
||||
case AMDGPU_MCA_ERROR_TYPE_UE:
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, mcm_info, 1ULL);
|
||||
break;
|
||||
case AMDGPU_MCA_ERROR_TYPE_CE:
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, mcm_info, 1ULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
WREG64_MCA(xgmi_inst, mca_base, MCA_REG_IDX_STATUS, 0ULL);
|
||||
}
|
||||
|
||||
static void xgmi_v6_4_0_query_error_count(struct amdgpu_device *adev, int xgmi_inst, struct ras_err_data *err_data)
|
||||
{
|
||||
struct amdgpu_smuio_mcm_config_info mcm_info = {
|
||||
.socket_id = adev->smuio.funcs->get_socket_id(adev),
|
||||
.die_id = xgmi_inst,
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(xgmi_v6_4_0_mca_base_array); i++)
|
||||
__xgmi_v6_4_0_query_error_count(adev, &mcm_info, xgmi_v6_4_0_mca_base_array[i], err_data);
|
||||
}
|
||||
|
||||
static void xgmi_v6_4_0_query_ras_error_count(struct amdgpu_device *adev, void *ras_error_status)
|
||||
{
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
int i;
|
||||
|
||||
for_each_inst(i, adev->aid_mask)
|
||||
xgmi_v6_4_0_query_error_count(adev, i, err_data);
|
||||
}
|
||||
|
||||
static void amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
{
|
||||
switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
|
||||
case IP_VERSION(6, 4, 0):
|
||||
xgmi_v6_4_0_query_ras_error_count(adev, ras_error_status);
|
||||
break;
|
||||
default:
|
||||
amdgpu_xgmi_legacy_query_ras_error_count(adev, ras_error_status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Trigger XGMI/WAFL error */
|
||||
static int amdgpu_ras_error_inject_xgmi(struct amdgpu_device *adev,
|
||||
void *inject_if, uint32_t instance_mask)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret1, ret2;
|
||||
struct ta_ras_trigger_error_input *block_info =
|
||||
(struct ta_ras_trigger_error_input *)inject_if;
|
||||
|
||||
if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_DISALLOW))
|
||||
dev_warn(adev->dev, "Failed to disallow df cstate");
|
||||
|
||||
if (amdgpu_dpm_set_xgmi_plpd_mode(adev, XGMI_PLPD_DISALLOW))
|
||||
ret1 = amdgpu_dpm_set_xgmi_plpd_mode(adev, XGMI_PLPD_DISALLOW);
|
||||
if (ret1 && ret1 != -EOPNOTSUPP)
|
||||
dev_warn(adev->dev, "Failed to disallow XGMI power down");
|
||||
|
||||
ret = psp_ras_trigger_error(&adev->psp, block_info, instance_mask);
|
||||
ret2 = psp_ras_trigger_error(&adev->psp, block_info, instance_mask);
|
||||
|
||||
if (amdgpu_ras_intr_triggered())
|
||||
return ret;
|
||||
return ret2;
|
||||
|
||||
if (amdgpu_dpm_set_xgmi_plpd_mode(adev, XGMI_PLPD_DEFAULT))
|
||||
ret1 = amdgpu_dpm_set_xgmi_plpd_mode(adev, XGMI_PLPD_DEFAULT);
|
||||
if (ret1 && ret1 != -EOPNOTSUPP)
|
||||
dev_warn(adev->dev, "Failed to allow XGMI power down");
|
||||
|
||||
if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_ALLOW))
|
||||
dev_warn(adev->dev, "Failed to allow df cstate");
|
||||
|
||||
return ret;
|
||||
return ret2;
|
||||
}
|
||||
|
||||
struct amdgpu_ras_block_hw_ops xgmi_ras_hw_ops = {
|
||||
|
@ -1102,6 +1102,7 @@ static void gfx_v9_4_3_init_rlcg_reg_access_ctrl(struct amdgpu_device *adev)
|
||||
reg_access_ctrl->grbm_idx = SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regGRBM_GFX_INDEX);
|
||||
reg_access_ctrl->spare_int = SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regRLC_SPARE_INT);
|
||||
}
|
||||
adev->gfx.rlc.rlcg_reg_access_supported = true;
|
||||
}
|
||||
|
||||
static int gfx_v9_4_3_rlc_init(struct amdgpu_device *adev)
|
||||
@ -2738,16 +2739,16 @@ static void gfx_v9_4_3_xcc_set_compute_eop_interrupt_state(
|
||||
|
||||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
mec_int_cntl = RREG32(mec_int_cntl_reg);
|
||||
mec_int_cntl = RREG32_XCC(mec_int_cntl_reg, xcc_id);
|
||||
mec_int_cntl = REG_SET_FIELD(mec_int_cntl, CP_ME1_PIPE0_INT_CNTL,
|
||||
TIME_STAMP_INT_ENABLE, 0);
|
||||
WREG32(mec_int_cntl_reg, mec_int_cntl);
|
||||
WREG32_XCC(mec_int_cntl_reg, mec_int_cntl, xcc_id);
|
||||
break;
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
mec_int_cntl = RREG32(mec_int_cntl_reg);
|
||||
mec_int_cntl = RREG32_XCC(mec_int_cntl_reg, xcc_id);
|
||||
mec_int_cntl = REG_SET_FIELD(mec_int_cntl, CP_ME1_PIPE0_INT_CNTL,
|
||||
TIME_STAMP_INT_ENABLE, 1);
|
||||
WREG32(mec_int_cntl_reg, mec_int_cntl);
|
||||
WREG32_XCC(mec_int_cntl_reg, mec_int_cntl, xcc_id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -3799,6 +3800,27 @@ static void gfx_v9_4_3_inst_query_ras_err_count(struct amdgpu_device *adev,
|
||||
}
|
||||
}
|
||||
|
||||
/* handle extra register entries of UE */
|
||||
for (; i < ARRAY_SIZE(gfx_v9_4_3_ue_reg_list); i++) {
|
||||
for (j = 0; j < gfx_v9_4_3_ue_reg_list[i].se_num; j++) {
|
||||
for (k = 0; k < gfx_v9_4_3_ue_reg_list[i].reg_entry.reg_inst; k++) {
|
||||
/* no need to select if instance number is 1 */
|
||||
if (gfx_v9_4_3_ue_reg_list[i].se_num > 1 ||
|
||||
gfx_v9_4_3_ue_reg_list[i].reg_entry.reg_inst > 1)
|
||||
gfx_v9_4_3_xcc_select_se_sh(adev, j, 0, k, xcc_id);
|
||||
|
||||
amdgpu_ras_inst_query_ras_error_count(adev,
|
||||
&(gfx_v9_4_3_ue_reg_list[i].reg_entry),
|
||||
1,
|
||||
gfx_v9_4_3_ras_mem_list_array[gfx_v9_4_3_ue_reg_list[i].mem_id_type].mem_id_ent,
|
||||
gfx_v9_4_3_ras_mem_list_array[gfx_v9_4_3_ue_reg_list[i].mem_id_type].size,
|
||||
GET_INST(GC, xcc_id),
|
||||
AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
|
||||
&ue_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
xcc_id);
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
@ -3838,6 +3860,23 @@ static void gfx_v9_4_3_inst_reset_ras_err_count(struct amdgpu_device *adev,
|
||||
}
|
||||
}
|
||||
|
||||
/* handle extra register entries of UE */
|
||||
for (; i < ARRAY_SIZE(gfx_v9_4_3_ue_reg_list); i++) {
|
||||
for (j = 0; j < gfx_v9_4_3_ue_reg_list[i].se_num; j++) {
|
||||
for (k = 0; k < gfx_v9_4_3_ue_reg_list[i].reg_entry.reg_inst; k++) {
|
||||
/* no need to select if instance number is 1 */
|
||||
if (gfx_v9_4_3_ue_reg_list[i].se_num > 1 ||
|
||||
gfx_v9_4_3_ue_reg_list[i].reg_entry.reg_inst > 1)
|
||||
gfx_v9_4_3_xcc_select_se_sh(adev, j, 0, k, xcc_id);
|
||||
|
||||
amdgpu_ras_inst_reset_ras_error_count(adev,
|
||||
&(gfx_v9_4_3_ue_reg_list[i].reg_entry),
|
||||
1,
|
||||
GET_INST(GC, xcc_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
xcc_id);
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
@ -4300,7 +4339,7 @@ const struct amdgpu_ip_block_version gfx_v9_4_3_ip_block = {
|
||||
.type = AMD_IP_BLOCK_TYPE_GFX,
|
||||
.major = 9,
|
||||
.minor = 4,
|
||||
.rev = 0,
|
||||
.rev = 3,
|
||||
.funcs = &gfx_v9_4_3_ip_funcs,
|
||||
};
|
||||
|
||||
|
@ -268,7 +268,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
||||
if (adev->gfx.kiq[0].ring.sched.ready && !adev->enable_mes &&
|
||||
(amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev))) {
|
||||
amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req,
|
||||
1 << vmid);
|
||||
1 << vmid, GET_INST(GC, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -672,6 +672,7 @@ static void gmc_v10_0_vram_gtt_location(struct amdgpu_device *adev,
|
||||
/* add the xgmi offset of the physical node */
|
||||
base += adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size;
|
||||
|
||||
amdgpu_gmc_set_agp_default(adev, mc);
|
||||
amdgpu_gmc_vram_location(adev, &adev->gmc, base);
|
||||
amdgpu_gmc_gart_location(adev, mc, AMDGPU_GART_PLACEMENT_BEST_FIT);
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
|
@ -229,7 +229,7 @@ static void gmc_v11_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
||||
if ((adev->gfx.kiq[0].ring.sched.ready || adev->mes.ring.sched.ready) &&
|
||||
(amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev))) {
|
||||
amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req,
|
||||
1 << vmid);
|
||||
1 << vmid, GET_INST(GC, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -637,6 +637,7 @@ static void gmc_v11_0_vram_gtt_location(struct amdgpu_device *adev,
|
||||
|
||||
base = adev->mmhub.funcs->get_fb_location(adev);
|
||||
|
||||
amdgpu_gmc_set_agp_default(adev, mc);
|
||||
amdgpu_gmc_vram_location(adev, &adev->gmc, base);
|
||||
amdgpu_gmc_gart_location(adev, mc, AMDGPU_GART_PLACEMENT_HIGH);
|
||||
if (!amdgpu_sriov_vf(adev) ||
|
||||
|
@ -211,6 +211,7 @@ static void gmc_v6_0_vram_gtt_location(struct amdgpu_device *adev,
|
||||
|
||||
base <<= 24;
|
||||
|
||||
amdgpu_gmc_set_agp_default(adev, mc);
|
||||
amdgpu_gmc_vram_location(adev, mc, base);
|
||||
amdgpu_gmc_gart_location(adev, mc, AMDGPU_GART_PLACEMENT_BEST_FIT);
|
||||
}
|
||||
|
@ -239,6 +239,7 @@ static void gmc_v7_0_vram_gtt_location(struct amdgpu_device *adev,
|
||||
|
||||
base <<= 24;
|
||||
|
||||
amdgpu_gmc_set_agp_default(adev, mc);
|
||||
amdgpu_gmc_vram_location(adev, mc, base);
|
||||
amdgpu_gmc_gart_location(adev, mc, AMDGPU_GART_PLACEMENT_BEST_FIT);
|
||||
}
|
||||
|
@ -413,6 +413,7 @@ static void gmc_v8_0_vram_gtt_location(struct amdgpu_device *adev,
|
||||
base = RREG32(mmMC_VM_FB_LOCATION) & 0xFFFF;
|
||||
base <<= 24;
|
||||
|
||||
amdgpu_gmc_set_agp_default(adev, mc);
|
||||
amdgpu_gmc_vram_location(adev, mc, base);
|
||||
amdgpu_gmc_gart_location(adev, mc, AMDGPU_GART_PLACEMENT_BEST_FIT);
|
||||
}
|
||||
|
@ -817,7 +817,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
||||
uint32_t vmhub, uint32_t flush_type)
|
||||
{
|
||||
bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(adev, vmhub);
|
||||
u32 j, inv_req, tmp, sem, req, ack;
|
||||
u32 j, inv_req, tmp, sem, req, ack, inst;
|
||||
const unsigned int eng = 17;
|
||||
struct amdgpu_vmhub *hub;
|
||||
|
||||
@ -832,13 +832,17 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
||||
/* This is necessary for a HW workaround under SRIOV as well
|
||||
* as GFXOFF under bare metal
|
||||
*/
|
||||
if (adev->gfx.kiq[0].ring.sched.ready &&
|
||||
if (vmhub >= AMDGPU_MMHUB0(0))
|
||||
inst = GET_INST(GC, 0);
|
||||
else
|
||||
inst = vmhub;
|
||||
if (adev->gfx.kiq[inst].ring.sched.ready &&
|
||||
(amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev))) {
|
||||
uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
|
||||
uint32_t ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
|
||||
|
||||
amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req,
|
||||
1 << vmid);
|
||||
1 << vmid, inst);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -856,9 +860,9 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
||||
for (j = 0; j < adev->usec_timeout; j++) {
|
||||
/* a read return value of 1 means semaphore acquire */
|
||||
if (vmhub >= AMDGPU_MMHUB0(0))
|
||||
tmp = RREG32_SOC15_IP_NO_KIQ(MMHUB, sem);
|
||||
tmp = RREG32_SOC15_IP_NO_KIQ(MMHUB, sem, inst);
|
||||
else
|
||||
tmp = RREG32_SOC15_IP_NO_KIQ(GC, sem);
|
||||
tmp = RREG32_SOC15_IP_NO_KIQ(GC, sem, inst);
|
||||
if (tmp & 0x1)
|
||||
break;
|
||||
udelay(1);
|
||||
@ -869,9 +873,9 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
||||
}
|
||||
|
||||
if (vmhub >= AMDGPU_MMHUB0(0))
|
||||
WREG32_SOC15_IP_NO_KIQ(MMHUB, req, inv_req);
|
||||
WREG32_SOC15_IP_NO_KIQ(MMHUB, req, inv_req, inst);
|
||||
else
|
||||
WREG32_SOC15_IP_NO_KIQ(GC, req, inv_req);
|
||||
WREG32_SOC15_IP_NO_KIQ(GC, req, inv_req, inst);
|
||||
|
||||
/*
|
||||
* Issue a dummy read to wait for the ACK register to
|
||||
@ -884,9 +888,9 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
||||
|
||||
for (j = 0; j < adev->usec_timeout; j++) {
|
||||
if (vmhub >= AMDGPU_MMHUB0(0))
|
||||
tmp = RREG32_SOC15_IP_NO_KIQ(MMHUB, ack);
|
||||
tmp = RREG32_SOC15_IP_NO_KIQ(MMHUB, ack, inst);
|
||||
else
|
||||
tmp = RREG32_SOC15_IP_NO_KIQ(GC, ack);
|
||||
tmp = RREG32_SOC15_IP_NO_KIQ(GC, ack, inst);
|
||||
if (tmp & (1 << vmid))
|
||||
break;
|
||||
udelay(1);
|
||||
@ -899,9 +903,9 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
||||
* write with 0 means semaphore release
|
||||
*/
|
||||
if (vmhub >= AMDGPU_MMHUB0(0))
|
||||
WREG32_SOC15_IP_NO_KIQ(MMHUB, sem, 0);
|
||||
WREG32_SOC15_IP_NO_KIQ(MMHUB, sem, 0, inst);
|
||||
else
|
||||
WREG32_SOC15_IP_NO_KIQ(GC, sem, 0);
|
||||
WREG32_SOC15_IP_NO_KIQ(GC, sem, 0, inst);
|
||||
}
|
||||
|
||||
spin_unlock(&adev->gmc.invalidate_lock);
|
||||
@ -1176,7 +1180,10 @@ static void gmc_v9_0_get_coherence_flags(struct amdgpu_device *adev,
|
||||
if (uncached) {
|
||||
mtype = MTYPE_UC;
|
||||
} else if (ext_coherent) {
|
||||
mtype = is_local ? MTYPE_CC : MTYPE_UC;
|
||||
if (adev->rev_id)
|
||||
mtype = is_local ? MTYPE_CC : MTYPE_UC;
|
||||
else
|
||||
mtype = MTYPE_UC;
|
||||
} else if (adev->flags & AMD_IS_APU) {
|
||||
mtype = is_local ? mtype_local : MTYPE_NC;
|
||||
} else {
|
||||
@ -1297,7 +1304,7 @@ static void gmc_v9_0_override_vm_pte_flags(struct amdgpu_device *adev,
|
||||
|
||||
*flags = (*flags & ~AMDGPU_PTE_MTYPE_VG10_MASK) |
|
||||
AMDGPU_PTE_MTYPE_VG10(mtype_local);
|
||||
} else {
|
||||
} else if (adev->rev_id) {
|
||||
/* MTYPE_UC case */
|
||||
*flags = (*flags & ~AMDGPU_PTE_MTYPE_VG10_MASK) |
|
||||
AMDGPU_PTE_MTYPE_VG10(MTYPE_CC);
|
||||
@ -1614,6 +1621,8 @@ static void gmc_v9_0_vram_gtt_location(struct amdgpu_device *adev,
|
||||
{
|
||||
u64 base = adev->mmhub.funcs->get_fb_location(adev);
|
||||
|
||||
amdgpu_gmc_set_agp_default(adev, mc);
|
||||
|
||||
/* add the xgmi offset of the physical node */
|
||||
base += adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size;
|
||||
if (adev->gmc.xgmi.connected_to_cpu) {
|
||||
|
@ -145,6 +145,10 @@ static void hdp_v4_0_init_registers(struct amdgpu_device *adev)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Do not program registers if VF */
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return;
|
||||
|
||||
WREG32_FIELD15(HDP, 0, HDP_MISC_CNTL, FLUSH_INVALIDATE_CACHE, 1);
|
||||
|
||||
if (amdgpu_ip_version(adev, HDP_HWIP, 0) == IP_VERSION(4, 4, 0))
|
||||
|
@ -654,9 +654,11 @@ static void jpeg_v4_0_3_dec_ring_set_wptr(struct amdgpu_ring *ring)
|
||||
*/
|
||||
static void jpeg_v4_0_3_dec_ring_insert_start(struct amdgpu_ring *ring)
|
||||
{
|
||||
amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x62a04); /* PCTL0_MMHUB_DEEPSLEEP_IB */
|
||||
if (!amdgpu_sriov_vf(ring->adev)) {
|
||||
amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x62a04); /* PCTL0_MMHUB_DEEPSLEEP_IB */
|
||||
}
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
@ -672,9 +674,11 @@ static void jpeg_v4_0_3_dec_ring_insert_start(struct amdgpu_ring *ring)
|
||||
*/
|
||||
static void jpeg_v4_0_3_dec_ring_insert_end(struct amdgpu_ring *ring)
|
||||
{
|
||||
amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x62a04);
|
||||
if (!amdgpu_sriov_vf(ring->adev)) {
|
||||
amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x62a04);
|
||||
}
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
|
@ -427,6 +427,7 @@ static void sdma_v4_4_2_inst_gfx_stop(struct amdgpu_device *adev,
|
||||
uint32_t inst_mask)
|
||||
{
|
||||
struct amdgpu_ring *sdma[AMDGPU_MAX_SDMA_INSTANCES];
|
||||
u32 doorbell_offset, doorbell;
|
||||
u32 rb_cntl, ib_cntl;
|
||||
int i, unset = 0;
|
||||
|
||||
@ -444,6 +445,18 @@ static void sdma_v4_4_2_inst_gfx_stop(struct amdgpu_device *adev,
|
||||
ib_cntl = RREG32_SDMA(i, regSDMA_GFX_IB_CNTL);
|
||||
ib_cntl = REG_SET_FIELD(ib_cntl, SDMA_GFX_IB_CNTL, IB_ENABLE, 0);
|
||||
WREG32_SDMA(i, regSDMA_GFX_IB_CNTL, ib_cntl);
|
||||
|
||||
if (sdma[i]->use_doorbell) {
|
||||
doorbell = RREG32_SDMA(i, regSDMA_GFX_DOORBELL);
|
||||
doorbell_offset = RREG32_SDMA(i, regSDMA_GFX_DOORBELL_OFFSET);
|
||||
|
||||
doorbell = REG_SET_FIELD(doorbell, SDMA_GFX_DOORBELL, ENABLE, 0);
|
||||
doorbell_offset = REG_SET_FIELD(doorbell_offset,
|
||||
SDMA_GFX_DOORBELL_OFFSET,
|
||||
OFFSET, 0);
|
||||
WREG32_SDMA(i, regSDMA_GFX_DOORBELL, doorbell);
|
||||
WREG32_SDMA(i, regSDMA_GFX_DOORBELL_OFFSET, doorbell_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -631,12 +644,6 @@ static void sdma_v4_4_2_gfx_resume(struct amdgpu_device *adev, unsigned int i)
|
||||
rb_cntl = sdma_v4_4_2_rb_cntl(ring, rb_cntl);
|
||||
WREG32_SDMA(i, regSDMA_GFX_RB_CNTL, rb_cntl);
|
||||
|
||||
/* Initialize the ring buffer's read and write pointers */
|
||||
WREG32_SDMA(i, regSDMA_GFX_RB_RPTR, 0);
|
||||
WREG32_SDMA(i, regSDMA_GFX_RB_RPTR_HI, 0);
|
||||
WREG32_SDMA(i, regSDMA_GFX_RB_WPTR, 0);
|
||||
WREG32_SDMA(i, regSDMA_GFX_RB_WPTR_HI, 0);
|
||||
|
||||
/* set the wb address whether it's enabled or not */
|
||||
WREG32_SDMA(i, regSDMA_GFX_RB_RPTR_ADDR_HI,
|
||||
upper_32_bits(adev->wb.gpu_addr + wb_offset) & 0xFFFFFFFF);
|
||||
@ -654,6 +661,12 @@ static void sdma_v4_4_2_gfx_resume(struct amdgpu_device *adev, unsigned int i)
|
||||
/* before programing wptr to a less value, need set minor_ptr_update first */
|
||||
WREG32_SDMA(i, regSDMA_GFX_MINOR_PTR_UPDATE, 1);
|
||||
|
||||
/* Initialize the ring buffer's read and write pointers */
|
||||
WREG32_SDMA(i, regSDMA_GFX_RB_RPTR, 0);
|
||||
WREG32_SDMA(i, regSDMA_GFX_RB_RPTR_HI, 0);
|
||||
WREG32_SDMA(i, regSDMA_GFX_RB_WPTR, 0);
|
||||
WREG32_SDMA(i, regSDMA_GFX_RB_WPTR_HI, 0);
|
||||
|
||||
doorbell = RREG32_SDMA(i, regSDMA_GFX_DOORBELL);
|
||||
doorbell_offset = RREG32_SDMA(i, regSDMA_GFX_DOORBELL_OFFSET);
|
||||
|
||||
@ -2048,7 +2061,7 @@ const struct amdgpu_ip_block_version sdma_v4_4_2_ip_block = {
|
||||
.type = AMD_IP_BLOCK_TYPE_SDMA,
|
||||
.major = 4,
|
||||
.minor = 4,
|
||||
.rev = 0,
|
||||
.rev = 2,
|
||||
.funcs = &sdma_v4_4_2_ip_funcs,
|
||||
};
|
||||
|
||||
|
@ -69,7 +69,7 @@
|
||||
|
||||
#define RREG32_SOC15_IP(ip, reg) __RREG32_SOC15_RLC__(reg, 0, ip##_HWIP, 0)
|
||||
|
||||
#define RREG32_SOC15_IP_NO_KIQ(ip, reg) __RREG32_SOC15_RLC__(reg, AMDGPU_REGS_NO_KIQ, ip##_HWIP, 0)
|
||||
#define RREG32_SOC15_IP_NO_KIQ(ip, reg, inst) __RREG32_SOC15_RLC__(reg, AMDGPU_REGS_NO_KIQ, ip##_HWIP, inst)
|
||||
|
||||
#define RREG32_SOC15_NO_KIQ(ip, inst, reg) \
|
||||
__RREG32_SOC15_RLC__(adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg, \
|
||||
@ -86,8 +86,8 @@
|
||||
#define WREG32_SOC15_IP(ip, reg, value) \
|
||||
__WREG32_SOC15_RLC__(reg, value, 0, ip##_HWIP, 0)
|
||||
|
||||
#define WREG32_SOC15_IP_NO_KIQ(ip, reg, value) \
|
||||
__WREG32_SOC15_RLC__(reg, value, AMDGPU_REGS_NO_KIQ, ip##_HWIP, 0)
|
||||
#define WREG32_SOC15_IP_NO_KIQ(ip, reg, value, inst) \
|
||||
__WREG32_SOC15_RLC__(reg, value, AMDGPU_REGS_NO_KIQ, ip##_HWIP, inst)
|
||||
|
||||
#define WREG32_SOC15_NO_KIQ(ip, inst, reg, value) \
|
||||
__WREG32_SOC15_RLC__(adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg, \
|
||||
@ -140,7 +140,7 @@
|
||||
|
||||
/* for GC only */
|
||||
#define RREG32_RLC(reg) \
|
||||
__RREG32_SOC15_RLC__(reg, AMDGPU_REGS_RLC, GC_HWIP)
|
||||
__RREG32_SOC15_RLC__(reg, AMDGPU_REGS_RLC, GC_HWIP, 0)
|
||||
|
||||
#define WREG32_RLC_NO_KIQ(reg, value, hwip) \
|
||||
__WREG32_SOC15_RLC__(reg, value, AMDGPU_REGS_NO_KIQ | AMDGPU_REGS_RLC, hwip, 0)
|
||||
@ -204,4 +204,10 @@
|
||||
+ adev->asic_funcs->encode_ext_smn_addressing(ext), \
|
||||
value) \
|
||||
|
||||
#define RREG64_MCA(ext, mca_base, idx) \
|
||||
RREG64_PCIE_EXT(adev->asic_funcs->encode_ext_smn_addressing(ext) + mca_base + (idx * 8))
|
||||
|
||||
#define WREG64_MCA(ext, mca_base, idx, val) \
|
||||
WREG64_PCIE_EXT(adev->asic_funcs->encode_ext_smn_addressing(ext) + mca_base + (idx * 8), val)
|
||||
|
||||
#endif
|
||||
|
@ -381,6 +381,7 @@ soc21_asic_reset_method(struct amdgpu_device *adev)
|
||||
return AMD_RESET_METHOD_MODE1;
|
||||
case IP_VERSION(13, 0, 4):
|
||||
case IP_VERSION(13, 0, 11):
|
||||
case IP_VERSION(14, 0, 0):
|
||||
return AMD_RESET_METHOD_MODE2;
|
||||
default:
|
||||
if (amdgpu_dpm_is_baco_supported(adev))
|
||||
|
@ -88,7 +88,7 @@ static void umc_v12_0_reset_error_count(struct amdgpu_device *adev)
|
||||
umc_v12_0_reset_error_count_per_channel, NULL);
|
||||
}
|
||||
|
||||
static bool umc_v12_0_is_uncorrectable_error(uint64_t mc_umc_status)
|
||||
bool umc_v12_0_is_uncorrectable_error(uint64_t mc_umc_status)
|
||||
{
|
||||
return ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) &&
|
||||
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 ||
|
||||
@ -96,7 +96,7 @@ static bool umc_v12_0_is_uncorrectable_error(uint64_t mc_umc_status)
|
||||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, TCC) == 1));
|
||||
}
|
||||
|
||||
static bool umc_v12_0_is_correctable_error(uint64_t mc_umc_status)
|
||||
bool umc_v12_0_is_correctable_error(uint64_t mc_umc_status)
|
||||
{
|
||||
return (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
|
||||
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1 ||
|
||||
|
@ -117,6 +117,9 @@
|
||||
(pa) |= (UMC_V12_0_CHANNEL_HASH_CH6(channel_idx, pa) << UMC_V12_0_PA_CH6_BIT); \
|
||||
} while (0)
|
||||
|
||||
bool umc_v12_0_is_uncorrectable_error(uint64_t mc_umc_status);
|
||||
bool umc_v12_0_is_correctable_error(uint64_t mc_umc_status);
|
||||
|
||||
extern const uint32_t
|
||||
umc_v12_0_channel_idx_tbl[]
|
||||
[UMC_V12_0_UMC_INSTANCE_NUM]
|
||||
|
@ -577,8 +577,6 @@ static int uvd_v3_1_sw_init(void *handle)
|
||||
ptr += ucode_len;
|
||||
memcpy(&adev->uvd.keyselect, ptr, 4);
|
||||
|
||||
r = amdgpu_uvd_entity_init(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -127,8 +127,6 @@ static int uvd_v4_2_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_uvd_entity_init(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -125,8 +125,6 @@ static int uvd_v5_0_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_uvd_entity_init(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -432,8 +432,6 @@ static int uvd_v6_0_sw_init(void *handle)
|
||||
}
|
||||
}
|
||||
|
||||
r = amdgpu_uvd_entity_init(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -480,10 +480,6 @@ static int uvd_v7_0_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_uvd_entity_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_virt_alloc_mm_table(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
@ -441,8 +441,6 @@ static int vce_v2_0_sw_init(void *handle)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_vce_entity_init(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -450,8 +450,6 @@ static int vce_v3_0_sw_init(void *handle)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_vce_entity_init(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -486,11 +486,6 @@ static int vce_v4_0_sw_init(void *handle)
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
r = amdgpu_vce_entity_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_virt_alloc_mm_table(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
@ -1416,8 +1416,13 @@ bool kfd_process_xnack_mode(struct kfd_process *p, bool supported)
|
||||
* per-process XNACK mode selection. But let the dev->noretry
|
||||
* setting still influence the default XNACK mode.
|
||||
*/
|
||||
if (supported && KFD_SUPPORT_XNACK_PER_PROCESS(dev))
|
||||
if (supported && KFD_SUPPORT_XNACK_PER_PROCESS(dev)) {
|
||||
if (!amdgpu_sriov_xnack_support(dev->kfd->adev)) {
|
||||
pr_debug("SRIOV platform xnack not supported\n");
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* GFXv10 and later GPUs do not support shader preemption
|
||||
* during page faults. This can lead to poor QoS for queue
|
||||
|
@ -1255,9 +1255,11 @@ svm_range_get_pte_flags(struct kfd_node *node,
|
||||
}
|
||||
break;
|
||||
case IP_VERSION(9, 4, 3):
|
||||
mtype_local = amdgpu_mtype_local == 1 ? AMDGPU_VM_MTYPE_NC :
|
||||
(amdgpu_mtype_local == 2 || ext_coherent ?
|
||||
AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW);
|
||||
if (ext_coherent)
|
||||
mtype_local = node->adev->rev_id ? AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_UC;
|
||||
else
|
||||
mtype_local = amdgpu_mtype_local == 1 ? AMDGPU_VM_MTYPE_NC :
|
||||
amdgpu_mtype_local == 2 ? AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW;
|
||||
snoop = true;
|
||||
if (uncached) {
|
||||
mapping_flags |= AMDGPU_VM_MTYPE_UC;
|
||||
|
@ -1216,6 +1216,9 @@ bool dm_helpers_dp_handle_test_pattern_request(
|
||||
|
||||
}
|
||||
|
||||
pipe_ctx->stream->test_pattern.type = test_pattern;
|
||||
pipe_ctx->stream->test_pattern.color_space = test_pattern_color_space;
|
||||
|
||||
dc_link_dp_set_test_pattern(
|
||||
(struct dc_link *) link,
|
||||
test_pattern,
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include "dcn10/dcn10_optc.h"
|
||||
#include "dc/inc/hw/optc.h"
|
||||
|
||||
#include "dc/inc/core_types.h"
|
||||
|
||||
|
@ -111,17 +111,21 @@ static int dcn35_get_active_display_cnt_wa(
|
||||
return display_count;
|
||||
}
|
||||
|
||||
static void dcn35_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable)
|
||||
static void dcn35_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context,
|
||||
bool safe_to_lower, bool disable)
|
||||
{
|
||||
struct dc *dc = clk_mgr_base->ctx->dc;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; ++i) {
|
||||
struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
struct pipe_ctx *pipe = safe_to_lower
|
||||
? &context->res_ctx.pipe_ctx[i]
|
||||
: &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->top_pipe || pipe->prev_odm_pipe)
|
||||
continue;
|
||||
if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal))) {
|
||||
if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal) ||
|
||||
!pipe->stream->link_enc)) {
|
||||
struct stream_encoder *stream_enc = pipe->stream_res.stream_enc;
|
||||
|
||||
if (disable) {
|
||||
@ -301,11 +305,11 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
|
||||
}
|
||||
|
||||
if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
|
||||
dcn35_disable_otg_wa(clk_mgr_base, context, true);
|
||||
dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true);
|
||||
|
||||
clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
|
||||
dcn35_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz);
|
||||
dcn35_disable_otg_wa(clk_mgr_base, context, false);
|
||||
dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false);
|
||||
|
||||
update_dispclk = true;
|
||||
}
|
||||
@ -814,7 +818,8 @@ static void dcn35_set_idle_state(struct clk_mgr *clk_mgr_base, bool allow_idle)
|
||||
struct dc *dc = clk_mgr_base->ctx->dc;
|
||||
uint32_t val = dcn35_smu_read_ips_scratch(clk_mgr);
|
||||
|
||||
if (dc->config.disable_ips == 0) {
|
||||
if (dc->config.disable_ips == DMUB_IPS_ENABLE ||
|
||||
dc->config.disable_ips == DMUB_IPS_DISABLE_DYNAMIC) {
|
||||
val |= DMUB_IPS1_ALLOW_MASK;
|
||||
val |= DMUB_IPS2_ALLOW_MASK;
|
||||
} else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS1) {
|
||||
@ -1114,7 +1119,7 @@ void dcn35_clk_mgr_construct(
|
||||
dm_helpers_free_gpu_mem(clk_mgr->base.base.ctx, DC_MEM_ALLOC_TYPE_FRAME_BUFFER,
|
||||
smu_dpm_clks.dpm_clks);
|
||||
|
||||
if (ctx->dc->config.disable_ips == 0) {
|
||||
if (ctx->dc->config.disable_ips != DMUB_IPS_DISABLE_ALL) {
|
||||
bool ips_support = false;
|
||||
|
||||
/*avoid call pmfw at init*/
|
||||
@ -1127,7 +1132,7 @@ void dcn35_clk_mgr_construct(
|
||||
ctx->dc->debug.disable_hpo_power_gate = false;
|
||||
} else {
|
||||
/*let's reset the config control flag*/
|
||||
ctx->dc->config.disable_ips = 1; /*pmfw not support it, disable it all*/
|
||||
ctx->dc->config.disable_ips = DMUB_IPS_DISABLE_ALL; /*pmfw not support it, disable it all*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2582,6 +2582,9 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
|
||||
if (u->gamut_remap_matrix)
|
||||
update_flags->bits.gamut_remap_change = 1;
|
||||
|
||||
if (u->blend_tf)
|
||||
update_flags->bits.gamma_change = 1;
|
||||
|
||||
if (u->gamma) {
|
||||
enum surface_pixel_format format = SURFACE_PIXEL_FORMAT_GRPH_BEGIN;
|
||||
|
||||
@ -4113,8 +4116,17 @@ static bool commit_minimal_transition_state_for_windowed_mpo_odm(struct dc *dc,
|
||||
bool success = false;
|
||||
struct dc_state *minimal_transition_context;
|
||||
struct pipe_split_policy_backup policy;
|
||||
struct mall_temp_config mall_temp_config;
|
||||
|
||||
/* commit based on new context */
|
||||
/* Since all phantom pipes are removed in full validation,
|
||||
* we have to save and restore the subvp/mall config when
|
||||
* we do a minimal transition since the flags marking the
|
||||
* pipe as subvp/phantom will be cleared (dc copy constructor
|
||||
* creates a shallow copy).
|
||||
*/
|
||||
if (dc->res_pool->funcs->save_mall_state)
|
||||
dc->res_pool->funcs->save_mall_state(dc, context, &mall_temp_config);
|
||||
minimal_transition_context = create_minimal_transition_state(dc,
|
||||
context, &policy);
|
||||
if (minimal_transition_context) {
|
||||
@ -4123,9 +4135,20 @@ static bool commit_minimal_transition_state_for_windowed_mpo_odm(struct dc *dc,
|
||||
dc->hwss.is_pipe_topology_transition_seamless(
|
||||
dc, minimal_transition_context, context)) {
|
||||
DC_LOG_DC("%s base = new state\n", __func__);
|
||||
|
||||
success = dc_commit_state_no_check(dc, minimal_transition_context) == DC_OK;
|
||||
}
|
||||
release_minimal_transition_state(dc, minimal_transition_context, &policy);
|
||||
if (dc->res_pool->funcs->restore_mall_state)
|
||||
dc->res_pool->funcs->restore_mall_state(dc, context, &mall_temp_config);
|
||||
/* If we do a minimal transition with plane removal and the context
|
||||
* has subvp we also have to retain back the phantom stream / planes
|
||||
* since the refcount is decremented as part of the min transition
|
||||
* (we commit a state with no subvp, so the phantom streams / planes
|
||||
* had to be removed).
|
||||
*/
|
||||
if (dc->res_pool->funcs->retain_phantom_pipes)
|
||||
dc->res_pool->funcs->retain_phantom_pipes(dc, context);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
@ -4884,7 +4907,7 @@ void dc_allow_idle_optimizations(struct dc *dc, bool allow)
|
||||
if (dc->debug.disable_idle_power_optimizations)
|
||||
return;
|
||||
|
||||
if (dc->caps.ips_support && dc->config.disable_ips)
|
||||
if (dc->caps.ips_support && (dc->config.disable_ips == DMUB_IPS_DISABLE_ALL))
|
||||
return;
|
||||
|
||||
if (dc->clk_mgr != NULL && dc->clk_mgr->funcs->is_smu_present)
|
||||
@ -4905,7 +4928,7 @@ bool dc_dmub_is_ips_idle_state(struct dc *dc)
|
||||
if (dc->debug.disable_idle_power_optimizations)
|
||||
return false;
|
||||
|
||||
if (!dc->caps.ips_support || dc->config.disable_ips)
|
||||
if (!dc->caps.ips_support || (dc->config.disable_ips == DMUB_IPS_DISABLE_ALL))
|
||||
return false;
|
||||
|
||||
if (dc->hwss.get_idle_state)
|
||||
|
@ -49,7 +49,7 @@ struct aux_payload;
|
||||
struct set_config_cmd_payload;
|
||||
struct dmub_notification;
|
||||
|
||||
#define DC_VER "3.2.256"
|
||||
#define DC_VER "3.2.259"
|
||||
|
||||
#define MAX_SURFACES 3
|
||||
#define MAX_PLANES 6
|
||||
|
@ -120,6 +120,80 @@ void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dc_dmub_srv,
|
||||
}
|
||||
}
|
||||
|
||||
bool dc_dmub_srv_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_srv,
|
||||
unsigned int count,
|
||||
union dmub_rb_cmd *cmd_list)
|
||||
{
|
||||
struct dc_context *dc_ctx = dc_dmub_srv->ctx;
|
||||
struct dmub_srv *dmub;
|
||||
enum dmub_status status;
|
||||
int i;
|
||||
|
||||
if (!dc_dmub_srv || !dc_dmub_srv->dmub)
|
||||
return false;
|
||||
|
||||
dmub = dc_dmub_srv->dmub;
|
||||
|
||||
for (i = 0 ; i < count; i++) {
|
||||
// Queue command
|
||||
status = dmub_srv_cmd_queue(dmub, &cmd_list[i]);
|
||||
|
||||
if (status == DMUB_STATUS_QUEUE_FULL) {
|
||||
/* Execute and wait for queue to become empty again. */
|
||||
dmub_srv_cmd_execute(dmub);
|
||||
dmub_srv_wait_for_idle(dmub, 100000);
|
||||
|
||||
/* Requeue the command. */
|
||||
status = dmub_srv_cmd_queue(dmub, &cmd_list[i]);
|
||||
}
|
||||
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DC_ERROR("Error queueing DMUB command: status=%d\n", status);
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
status = dmub_srv_cmd_execute(dmub);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DC_ERROR("Error starting DMUB execution: status=%d\n", status);
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv,
|
||||
enum dm_dmub_wait_type wait_type,
|
||||
union dmub_rb_cmd *cmd_list)
|
||||
{
|
||||
struct dmub_srv *dmub;
|
||||
enum dmub_status status;
|
||||
|
||||
if (!dc_dmub_srv || !dc_dmub_srv->dmub)
|
||||
return false;
|
||||
|
||||
dmub = dc_dmub_srv->dmub;
|
||||
|
||||
// Wait for DMUB to process command
|
||||
if (wait_type != DM_DMUB_WAIT_TYPE_NO_WAIT) {
|
||||
status = dmub_srv_wait_for_idle(dmub, 100000);
|
||||
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DC_LOG_DEBUG("No reply for DMUB command: status=%d\n", status);
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy data back from ring buffer into command
|
||||
if (wait_type == DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)
|
||||
dmub_rb_get_return_data(&dmub->inbox1_rb, cmd_list);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dc_dmub_srv_cmd_run(struct dc_dmub_srv *dc_dmub_srv, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type)
|
||||
{
|
||||
return dc_dmub_srv_cmd_run_list(dc_dmub_srv, 1, cmd, wait_type);
|
||||
|
@ -56,6 +56,14 @@ void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv);
|
||||
|
||||
bool dc_dmub_srv_optimized_init_done(struct dc_dmub_srv *dc_dmub_srv);
|
||||
|
||||
bool dc_dmub_srv_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_srv,
|
||||
unsigned int count,
|
||||
union dmub_rb_cmd *cmd_list);
|
||||
|
||||
bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv,
|
||||
enum dm_dmub_wait_type wait_type,
|
||||
union dmub_rb_cmd *cmd_list);
|
||||
|
||||
bool dc_dmub_srv_cmd_run(struct dc_dmub_srv *dc_dmub_srv, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type);
|
||||
|
||||
bool dc_dmub_srv_cmd_run_list(struct dc_dmub_srv *dc_dmub_srv, unsigned int count, union dmub_rb_cmd *cmd_list, enum dm_dmub_wait_type wait_type);
|
||||
|
@ -142,7 +142,8 @@ enum dp_test_link_rate {
|
||||
DP_TEST_LINK_RATE_HBR3 = 0x1E,
|
||||
DP_TEST_LINK_RATE_UHBR10 = 0x01,
|
||||
DP_TEST_LINK_RATE_UHBR20 = 0x02,
|
||||
DP_TEST_LINK_RATE_UHBR13_5 = 0x03,
|
||||
DP_TEST_LINK_RATE_UHBR13_5_LEGACY = 0x03, /* For backward compatibility*/
|
||||
DP_TEST_LINK_RATE_UHBR13_5 = 0x04,
|
||||
};
|
||||
|
||||
struct dc_link_settings {
|
||||
|
@ -1037,7 +1037,9 @@ struct replay_config {
|
||||
bool replay_smu_opt_supported; // SMU optimization is supported
|
||||
unsigned int replay_enable_option; // Replay enablement option
|
||||
uint32_t debug_flags; // Replay debug flags
|
||||
bool replay_timing_sync_supported; // Replay desync is supported
|
||||
bool replay_timing_sync_supported; // Replay desync is supported
|
||||
bool force_disable_desync_error_check; // Replay desync is supported
|
||||
bool received_desync_error_hpd; //Replay Received Desync Error HPD.
|
||||
union replay_error_status replay_error_status; // Replay error status
|
||||
};
|
||||
|
||||
|
@ -128,21 +128,6 @@
|
||||
SRI(DC_ABM1_ACE_THRES_12, ABM, id), \
|
||||
NBIO_SR(BIOS_SCRATCH_2)
|
||||
|
||||
#define ABM_DCN32_REG_LIST(id)\
|
||||
SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \
|
||||
SRI(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \
|
||||
SRI(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \
|
||||
SRI(DC_ABM1_HG_MISC_CTRL, ABM, id), \
|
||||
SRI(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \
|
||||
SRI(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \
|
||||
SRI(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \
|
||||
SRI(BL1_PWM_USER_LEVEL, ABM, id), \
|
||||
SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \
|
||||
SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \
|
||||
SRI(DC_ABM1_ACE_OFFSET_SLOPE_0, ABM, id), \
|
||||
SRI(DC_ABM1_ACE_THRES_12, ABM, id), \
|
||||
NBIO_SR(BIOS_SCRATCH_2)
|
||||
|
||||
#define ABM_SF(reg_name, field_name, post_fix)\
|
||||
.field_name = reg_name ## __ ## field_name ## post_fix
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
#ifndef __DC_TIMING_GENERATOR_DCN10_H__
|
||||
#define __DC_TIMING_GENERATOR_DCN10_H__
|
||||
|
||||
#include "timing_generator.h"
|
||||
#include "optc.h"
|
||||
|
||||
#define DCN10TG_FROM_TG(tg)\
|
||||
container_of(tg, struct optc, base)
|
||||
@ -594,190 +594,6 @@ struct dcn_optc_mask {
|
||||
TG_REG_FIELD_LIST_DCN3_5(uint32_t)
|
||||
};
|
||||
|
||||
struct optc {
|
||||
struct timing_generator base;
|
||||
|
||||
const struct dcn_optc_registers *tg_regs;
|
||||
const struct dcn_optc_shift *tg_shift;
|
||||
const struct dcn_optc_mask *tg_mask;
|
||||
|
||||
int opp_count;
|
||||
|
||||
uint32_t max_h_total;
|
||||
uint32_t max_v_total;
|
||||
|
||||
uint32_t min_h_blank;
|
||||
|
||||
uint32_t min_h_sync_width;
|
||||
uint32_t min_v_sync_width;
|
||||
uint32_t min_v_blank;
|
||||
uint32_t min_v_blank_interlace;
|
||||
|
||||
int vstartup_start;
|
||||
int vupdate_offset;
|
||||
int vupdate_width;
|
||||
int vready_offset;
|
||||
struct dc_crtc_timing orginal_patched_timing;
|
||||
enum signal_type signal;
|
||||
};
|
||||
|
||||
void dcn10_timing_generator_init(struct optc *optc);
|
||||
|
||||
struct dcn_otg_state {
|
||||
uint32_t v_blank_start;
|
||||
uint32_t v_blank_end;
|
||||
uint32_t v_sync_a_pol;
|
||||
uint32_t v_total;
|
||||
uint32_t v_total_max;
|
||||
uint32_t v_total_min;
|
||||
uint32_t v_total_min_sel;
|
||||
uint32_t v_total_max_sel;
|
||||
uint32_t v_sync_a_start;
|
||||
uint32_t v_sync_a_end;
|
||||
uint32_t h_blank_start;
|
||||
uint32_t h_blank_end;
|
||||
uint32_t h_sync_a_start;
|
||||
uint32_t h_sync_a_end;
|
||||
uint32_t h_sync_a_pol;
|
||||
uint32_t h_total;
|
||||
uint32_t underflow_occurred_status;
|
||||
uint32_t otg_enabled;
|
||||
uint32_t blank_enabled;
|
||||
uint32_t vertical_interrupt1_en;
|
||||
uint32_t vertical_interrupt1_line;
|
||||
uint32_t vertical_interrupt2_en;
|
||||
uint32_t vertical_interrupt2_line;
|
||||
};
|
||||
|
||||
void optc1_read_otg_state(struct optc *optc1,
|
||||
struct dcn_otg_state *s);
|
||||
|
||||
bool optc1_get_hw_timing(struct timing_generator *tg,
|
||||
struct dc_crtc_timing *hw_crtc_timing);
|
||||
|
||||
bool optc1_validate_timing(
|
||||
struct timing_generator *optc,
|
||||
const struct dc_crtc_timing *timing);
|
||||
|
||||
void optc1_program_timing(
|
||||
struct timing_generator *optc,
|
||||
const struct dc_crtc_timing *dc_crtc_timing,
|
||||
int vready_offset,
|
||||
int vstartup_start,
|
||||
int vupdate_offset,
|
||||
int vupdate_width,
|
||||
const enum signal_type signal,
|
||||
bool use_vbios);
|
||||
|
||||
void optc1_setup_vertical_interrupt0(
|
||||
struct timing_generator *optc,
|
||||
uint32_t start_line,
|
||||
uint32_t end_line);
|
||||
void optc1_setup_vertical_interrupt1(
|
||||
struct timing_generator *optc,
|
||||
uint32_t start_line);
|
||||
void optc1_setup_vertical_interrupt2(
|
||||
struct timing_generator *optc,
|
||||
uint32_t start_line);
|
||||
|
||||
void optc1_program_global_sync(
|
||||
struct timing_generator *optc,
|
||||
int vready_offset,
|
||||
int vstartup_start,
|
||||
int vupdate_offset,
|
||||
int vupdate_width);
|
||||
|
||||
bool optc1_disable_crtc(struct timing_generator *optc);
|
||||
|
||||
bool optc1_is_counter_moving(struct timing_generator *optc);
|
||||
|
||||
void optc1_get_position(struct timing_generator *optc,
|
||||
struct crtc_position *position);
|
||||
|
||||
uint32_t optc1_get_vblank_counter(struct timing_generator *optc);
|
||||
|
||||
void optc1_get_crtc_scanoutpos(
|
||||
struct timing_generator *optc,
|
||||
uint32_t *v_blank_start,
|
||||
uint32_t *v_blank_end,
|
||||
uint32_t *h_position,
|
||||
uint32_t *v_position);
|
||||
|
||||
void optc1_set_early_control(
|
||||
struct timing_generator *optc,
|
||||
uint32_t early_cntl);
|
||||
|
||||
void optc1_wait_for_state(struct timing_generator *optc,
|
||||
enum crtc_state state);
|
||||
|
||||
void optc1_set_blank(struct timing_generator *optc,
|
||||
bool enable_blanking);
|
||||
|
||||
bool optc1_is_blanked(struct timing_generator *optc);
|
||||
|
||||
void optc1_program_blank_color(
|
||||
struct timing_generator *optc,
|
||||
const struct tg_color *black_color);
|
||||
|
||||
bool optc1_did_triggered_reset_occur(
|
||||
struct timing_generator *optc);
|
||||
|
||||
void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst);
|
||||
|
||||
void optc1_disable_reset_trigger(struct timing_generator *optc);
|
||||
|
||||
void optc1_lock(struct timing_generator *optc);
|
||||
|
||||
void optc1_unlock(struct timing_generator *optc);
|
||||
|
||||
void optc1_enable_optc_clock(struct timing_generator *optc, bool enable);
|
||||
|
||||
void optc1_set_drr(
|
||||
struct timing_generator *optc,
|
||||
const struct drr_params *params);
|
||||
|
||||
void optc1_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max);
|
||||
|
||||
void optc1_set_static_screen_control(
|
||||
struct timing_generator *optc,
|
||||
uint32_t event_triggers,
|
||||
uint32_t num_frames);
|
||||
|
||||
void optc1_program_stereo(struct timing_generator *optc,
|
||||
const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags);
|
||||
|
||||
bool optc1_is_stereo_left_eye(struct timing_generator *optc);
|
||||
|
||||
void optc1_clear_optc_underflow(struct timing_generator *optc);
|
||||
|
||||
void optc1_tg_init(struct timing_generator *optc);
|
||||
|
||||
bool optc1_is_tg_enabled(struct timing_generator *optc);
|
||||
|
||||
bool optc1_is_optc_underflow_occurred(struct timing_generator *optc);
|
||||
|
||||
void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable);
|
||||
|
||||
void optc1_set_timing_double_buffer(struct timing_generator *optc, bool enable);
|
||||
|
||||
bool optc1_get_otg_active_size(struct timing_generator *optc,
|
||||
uint32_t *otg_active_width,
|
||||
uint32_t *otg_active_height);
|
||||
|
||||
void optc1_enable_crtc_reset(
|
||||
struct timing_generator *optc,
|
||||
int source_tg_inst,
|
||||
struct crtc_trigger_info *crtc_tp);
|
||||
|
||||
bool optc1_configure_crc(struct timing_generator *optc,
|
||||
const struct crc_params *params);
|
||||
|
||||
bool optc1_get_crc(struct timing_generator *optc,
|
||||
uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb);
|
||||
|
||||
bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing);
|
||||
|
||||
void optc1_set_vtg_params(struct timing_generator *optc,
|
||||
const struct dc_crtc_timing *dc_crtc_timing, bool program_fp2);
|
||||
|
||||
#endif /* __DC_TIMING_GENERATOR_DCN10_H__ */
|
||||
|
@ -137,7 +137,15 @@ void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz)
|
||||
dsc_enc_caps->max_total_throughput_mps = DCN20_MAX_DISPLAY_CLOCK_Mhz * 2;
|
||||
}
|
||||
|
||||
// TODO DSC: This is actually image width limitation, not a slice width. This should be added to the criteria to use ODM.
|
||||
/* For pixel clock bigger than a single-pipe limit needing four engines ODM 4:1, which then quardruples our
|
||||
* throughput and number of slices
|
||||
*/
|
||||
if (pixel_clock_100Hz > DCN20_MAX_PIXEL_CLOCK_Mhz*10000*2) {
|
||||
dsc_enc_caps->slice_caps.bits.NUM_SLICES_12 = 1;
|
||||
dsc_enc_caps->slice_caps.bits.NUM_SLICES_16 = 1;
|
||||
dsc_enc_caps->max_total_throughput_mps = DCN20_MAX_DISPLAY_CLOCK_Mhz * 4;
|
||||
}
|
||||
|
||||
dsc_enc_caps->max_slice_width = 5184; /* (including 64 overlap pixels for eDP MSO mode) */
|
||||
dsc_enc_caps->bpp_increment_div = 16; /* 1/16th of a bit */
|
||||
}
|
||||
|
@ -325,6 +325,43 @@ static void dccg35_set_dpstreamclk(
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg35_set_physymclk_root_clock_gating(
|
||||
struct dccg *dccg,
|
||||
int phy_inst,
|
||||
bool enable)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
|
||||
return;
|
||||
|
||||
switch (phy_inst) {
|
||||
case 0:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
PHYASYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0);
|
||||
break;
|
||||
case 1:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
PHYBSYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0);
|
||||
break;
|
||||
case 2:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
PHYCSYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0);
|
||||
break;
|
||||
case 3:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
PHYDSYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0);
|
||||
break;
|
||||
case 4:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
PHYESYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void dccg35_set_physymclk(
|
||||
struct dccg *dccg,
|
||||
int phy_inst,
|
||||
@ -340,16 +377,10 @@ static void dccg35_set_physymclk(
|
||||
REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
|
||||
PHYASYMCLK_EN, 1,
|
||||
PHYASYMCLK_SRC_SEL, clk_src);
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
PHYASYMCLK_ROOT_GATE_DISABLE, 1);
|
||||
} else {
|
||||
REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
|
||||
PHYASYMCLK_EN, 0,
|
||||
PHYASYMCLK_SRC_SEL, 0);
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
PHYASYMCLK_ROOT_GATE_DISABLE, 0);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
@ -357,16 +388,10 @@ static void dccg35_set_physymclk(
|
||||
REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
|
||||
PHYBSYMCLK_EN, 1,
|
||||
PHYBSYMCLK_SRC_SEL, clk_src);
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
PHYBSYMCLK_ROOT_GATE_DISABLE, 1);
|
||||
} else {
|
||||
REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
|
||||
PHYBSYMCLK_EN, 0,
|
||||
PHYBSYMCLK_SRC_SEL, 0);
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
PHYBSYMCLK_ROOT_GATE_DISABLE, 0);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
@ -374,16 +399,10 @@ static void dccg35_set_physymclk(
|
||||
REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
|
||||
PHYCSYMCLK_EN, 1,
|
||||
PHYCSYMCLK_SRC_SEL, clk_src);
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
PHYCSYMCLK_ROOT_GATE_DISABLE, 1);
|
||||
} else {
|
||||
REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
|
||||
PHYCSYMCLK_EN, 0,
|
||||
PHYCSYMCLK_SRC_SEL, 0);
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
PHYCSYMCLK_ROOT_GATE_DISABLE, 0);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
@ -391,16 +410,10 @@ static void dccg35_set_physymclk(
|
||||
REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
|
||||
PHYDSYMCLK_EN, 1,
|
||||
PHYDSYMCLK_SRC_SEL, clk_src);
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
PHYDSYMCLK_ROOT_GATE_DISABLE, 1);
|
||||
} else {
|
||||
REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
|
||||
PHYDSYMCLK_EN, 0,
|
||||
PHYDSYMCLK_SRC_SEL, 0);
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
PHYDSYMCLK_ROOT_GATE_DISABLE, 0);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
@ -408,16 +421,10 @@ static void dccg35_set_physymclk(
|
||||
REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
|
||||
PHYESYMCLK_EN, 1,
|
||||
PHYESYMCLK_SRC_SEL, clk_src);
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
PHYESYMCLK_ROOT_GATE_DISABLE, 1);
|
||||
} else {
|
||||
REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
|
||||
PHYESYMCLK_EN, 0,
|
||||
PHYESYMCLK_SRC_SEL, 0);
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
|
||||
PHYESYMCLK_ROOT_GATE_DISABLE, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -490,8 +497,8 @@ void dccg35_init(struct dccg *dccg)
|
||||
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
|
||||
for (otg_inst = 0; otg_inst < 5; otg_inst++)
|
||||
dccg35_set_physymclk(dccg, otg_inst,
|
||||
PHYSYMCLK_FORCE_SRC_SYMCLK, false);
|
||||
dccg35_set_physymclk_root_clock_gating(dccg, otg_inst,
|
||||
false);
|
||||
/*
|
||||
dccg35_enable_global_fgcg_rep(
|
||||
dccg, dccg->ctx->dc->debug.enable_fine_grain_clock_gating.bits
|
||||
@ -754,7 +761,9 @@ static const struct dccg_funcs dccg35_funcs = {
|
||||
.disable_symclk32_se = dccg31_disable_symclk32_se,
|
||||
.enable_symclk32_le = dccg31_enable_symclk32_le,
|
||||
.disable_symclk32_le = dccg31_disable_symclk32_le,
|
||||
.set_symclk32_le_root_clock_gating = dccg31_set_symclk32_le_root_clock_gating,
|
||||
.set_physymclk = dccg35_set_physymclk,
|
||||
.set_physymclk_root_clock_gating = dccg35_set_physymclk_root_clock_gating,
|
||||
.set_dtbclk_dto = dccg35_set_dtbclk_dto,
|
||||
.set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
|
||||
.set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
|
||||
|
@ -332,6 +332,13 @@ void pg_cntl35_io_clk_pg_control(struct pg_cntl *pg_cntl, bool power_on)
|
||||
pg_cntl->pg_res_enable[PG_DCIO] = power_on;
|
||||
}
|
||||
|
||||
void pg_cntl35_set_force_poweron_domain22(struct pg_cntl *pg_cntl, bool power_on)
|
||||
{
|
||||
struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
|
||||
|
||||
REG_UPDATE(DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, power_on ? 1 : 0);
|
||||
}
|
||||
|
||||
static bool pg_cntl35_plane_otg_status(struct pg_cntl *pg_cntl)
|
||||
{
|
||||
struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
|
||||
@ -501,7 +508,8 @@ static const struct pg_cntl_funcs pg_cntl35_funcs = {
|
||||
.mpcc_pg_control = pg_cntl35_mpcc_pg_control,
|
||||
.opp_pg_control = pg_cntl35_opp_pg_control,
|
||||
.optc_pg_control = pg_cntl35_optc_pg_control,
|
||||
.dwb_pg_control = pg_cntl35_dwb_pg_control
|
||||
.dwb_pg_control = pg_cntl35_dwb_pg_control,
|
||||
.set_force_poweron_domain22 = pg_cntl35_set_force_poweron_domain22
|
||||
};
|
||||
|
||||
struct pg_cntl *pg_cntl35_create(
|
||||
|
@ -183,6 +183,7 @@ void pg_cntl35_optc_pg_control(struct pg_cntl *pg_cntl,
|
||||
unsigned int optc_inst, bool power_on);
|
||||
void pg_cntl35_dwb_pg_control(struct pg_cntl *pg_cntl, bool power_on);
|
||||
void pg_cntl35_init_pg_status(struct pg_cntl *pg_cntl);
|
||||
void pg_cntl35_set_force_poweron_domain22(struct pg_cntl *pg_cntl, bool power_on);
|
||||
|
||||
struct pg_cntl *pg_cntl35_create(
|
||||
struct dc_context *ctx,
|
||||
|
@ -610,7 +610,23 @@ static struct dce_hwseq_registers hwseq_reg;
|
||||
HWS_SF(, DMU_CLK_CNTL, LONO_FGCG_REP_DIS, mask_sh),\
|
||||
HWS_SF(, DMU_CLK_CNTL, LONO_DISPCLK_GATE_DISABLE, mask_sh),\
|
||||
HWS_SF(, DMU_CLK_CNTL, LONO_SOCCLK_GATE_DISABLE, mask_sh),\
|
||||
HWS_SF(, DMU_CLK_CNTL, LONO_DMCUBCLK_GATE_DISABLE, mask_sh)
|
||||
HWS_SF(, DMU_CLK_CNTL, LONO_DMCUBCLK_GATE_DISABLE, mask_sh),\
|
||||
HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKA_FE_GATE_DISABLE, mask_sh), \
|
||||
HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKB_FE_GATE_DISABLE, mask_sh), \
|
||||
HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKC_FE_GATE_DISABLE, mask_sh), \
|
||||
HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKD_FE_GATE_DISABLE, mask_sh), \
|
||||
HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKE_FE_GATE_DISABLE, mask_sh), \
|
||||
HWS_SF(, DCCG_GATE_DISABLE_CNTL2, HDMICHARCLK0_GATE_DISABLE, mask_sh), \
|
||||
HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKA_GATE_DISABLE, mask_sh), \
|
||||
HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKB_GATE_DISABLE, mask_sh), \
|
||||
HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKC_GATE_DISABLE, mask_sh), \
|
||||
HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKD_GATE_DISABLE, mask_sh), \
|
||||
HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKE_GATE_DISABLE, mask_sh), \
|
||||
HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh), \
|
||||
HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh), \
|
||||
HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh), \
|
||||
HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh), \
|
||||
HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh)
|
||||
|
||||
static const struct dce_hwseq_shift hwseq_shift = {
|
||||
HWSEQ_DCN35_MASK_SH_LIST(__SHIFT)
|
||||
@ -708,7 +724,7 @@ static const struct dc_debug_options debug_defaults_drv = {
|
||||
.i2c = true,
|
||||
.dmcu = false, // This is previously known to cause hang on S3 cycles if enabled
|
||||
.dscl = true,
|
||||
.cm = true,
|
||||
.cm = false,
|
||||
.mpc = true,
|
||||
.optc = true,
|
||||
.vpg = true,
|
||||
@ -719,14 +735,14 @@ static const struct dc_debug_options debug_defaults_drv = {
|
||||
.bits = {
|
||||
.dpp = true,
|
||||
.dsc = true,/*dscclk and dsc pg*/
|
||||
.hdmistream = false,
|
||||
.hdmichar = false,
|
||||
.dpstream = false,
|
||||
.symclk32_se = false,
|
||||
.symclk32_le = false,
|
||||
.symclk_fe = false,
|
||||
.physymclk = false,
|
||||
.dpiasymclk = false,
|
||||
.hdmistream = true,
|
||||
.hdmichar = true,
|
||||
.dpstream = true,
|
||||
.symclk32_se = true,
|
||||
.symclk32_le = true,
|
||||
.symclk_fe = true,
|
||||
.physymclk = true,
|
||||
.dpiasymclk = true,
|
||||
}
|
||||
},
|
||||
.seamless_boot_odm_combine = DML_FAIL_SOURCE_PIXEL_FORMAT,
|
||||
@ -741,7 +757,6 @@ static const struct dc_debug_options debug_defaults_drv = {
|
||||
.disable_boot_optimizations = false,
|
||||
.disable_unbounded_requesting = false,
|
||||
.disable_mem_low_power = false,
|
||||
.enable_hpo_pg_support = false,
|
||||
//must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions
|
||||
.enable_double_buffered_dsc_pg_support = true,
|
||||
.enable_dp_dig_pixel_rate_div_policy = 1,
|
||||
|
@ -5128,7 +5128,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
|
||||
ViewportExceedsSurface = true;
|
||||
|
||||
if (v->SourcePixelFormat[k] != dm_444_64 && v->SourcePixelFormat[k] != dm_444_32 && v->SourcePixelFormat[k] != dm_444_16
|
||||
&& v->SourcePixelFormat[k] != dm_444_16 && v->SourcePixelFormat[k] != dm_444_8 && v->SourcePixelFormat[k] != dm_rgbe) {
|
||||
&& v->SourcePixelFormat[k] != dm_444_8 && v->SourcePixelFormat[k] != dm_rgbe) {
|
||||
if (v->ViewportWidthChroma[k] > v->SurfaceWidthC[k] || v->ViewportHeightChroma[k] > v->SurfaceHeightC[k]) {
|
||||
ViewportExceedsSurface = true;
|
||||
}
|
||||
|
@ -55,10 +55,11 @@ struct dc_pipe_mapping_scratch {
|
||||
struct dc_plane_pipe_pool pipe_pool;
|
||||
};
|
||||
|
||||
static bool get_plane_id(const struct dc_state *state, const struct dc_plane_state *plane,
|
||||
unsigned int stream_id, unsigned int *plane_id)
|
||||
static bool get_plane_id(struct dml2_context *dml2, const struct dc_state *state, const struct dc_plane_state *plane,
|
||||
unsigned int stream_id, unsigned int plane_index, unsigned int *plane_id)
|
||||
{
|
||||
int i, j;
|
||||
bool is_plane_duplicate = dml2->v20.scratch.plane_duplicate_exists;
|
||||
|
||||
if (!plane_id)
|
||||
return false;
|
||||
@ -66,7 +67,8 @@ static bool get_plane_id(const struct dc_state *state, const struct dc_plane_sta
|
||||
for (i = 0; i < state->stream_count; i++) {
|
||||
if (state->streams[i]->stream_id == stream_id) {
|
||||
for (j = 0; j < state->stream_status[i].plane_count; j++) {
|
||||
if (state->stream_status[i].plane_states[j] == plane) {
|
||||
if (state->stream_status[i].plane_states[j] == plane &&
|
||||
(!is_plane_duplicate || (is_plane_duplicate && (j == plane_index)))) {
|
||||
*plane_id = (i << 16) | j;
|
||||
return true;
|
||||
}
|
||||
@ -123,8 +125,9 @@ static struct pipe_ctx *find_master_pipe_of_plane(struct dml2_context *ctx,
|
||||
unsigned int plane_id_assigned_to_pipe;
|
||||
|
||||
for (i = 0; i < ctx->config.dcn_pipe_count; i++) {
|
||||
if (state->res_ctx.pipe_ctx[i].plane_state && get_plane_id(state, state->res_ctx.pipe_ctx[i].plane_state,
|
||||
state->res_ctx.pipe_ctx[i].stream->stream_id, &plane_id_assigned_to_pipe)) {
|
||||
if (state->res_ctx.pipe_ctx[i].plane_state && get_plane_id(ctx, state, state->res_ctx.pipe_ctx[i].plane_state,
|
||||
state->res_ctx.pipe_ctx[i].stream->stream_id,
|
||||
ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_index[state->res_ctx.pipe_ctx[i].pipe_idx], &plane_id_assigned_to_pipe)) {
|
||||
if (plane_id_assigned_to_pipe == plane_id)
|
||||
return &state->res_ctx.pipe_ctx[i];
|
||||
}
|
||||
@ -141,8 +144,9 @@ static unsigned int find_pipes_assigned_to_plane(struct dml2_context *ctx,
|
||||
unsigned int plane_id_assigned_to_pipe;
|
||||
|
||||
for (i = 0; i < ctx->config.dcn_pipe_count; i++) {
|
||||
if (state->res_ctx.pipe_ctx[i].plane_state && get_plane_id(state, state->res_ctx.pipe_ctx[i].plane_state,
|
||||
state->res_ctx.pipe_ctx[i].stream->stream_id, &plane_id_assigned_to_pipe)) {
|
||||
if (state->res_ctx.pipe_ctx[i].plane_state && get_plane_id(ctx, state, state->res_ctx.pipe_ctx[i].plane_state,
|
||||
state->res_ctx.pipe_ctx[i].stream->stream_id,
|
||||
ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_index[state->res_ctx.pipe_ctx[i].pipe_idx], &plane_id_assigned_to_pipe)) {
|
||||
if (plane_id_assigned_to_pipe == plane_id)
|
||||
pipes[num_found++] = i;
|
||||
}
|
||||
@ -609,6 +613,7 @@ static struct pipe_ctx *assign_pipes_to_plane(struct dml2_context *ctx, struct d
|
||||
const struct dc_plane_state *plane,
|
||||
int odm_factor,
|
||||
int mpc_factor,
|
||||
int plane_index,
|
||||
struct dc_plane_pipe_pool *pipe_pool,
|
||||
const struct dc_state *existing_state)
|
||||
{
|
||||
@ -620,7 +625,7 @@ static struct pipe_ctx *assign_pipes_to_plane(struct dml2_context *ctx, struct d
|
||||
unsigned int next_pipe_to_assign;
|
||||
int odm_slice, mpc_slice;
|
||||
|
||||
if (!get_plane_id(state, plane, stream->stream_id, &plane_id)) {
|
||||
if (!get_plane_id(ctx, state, plane, stream->stream_id, plane_index, &plane_id)) {
|
||||
ASSERT(false);
|
||||
return master_pipe;
|
||||
}
|
||||
@ -667,12 +672,16 @@ static void free_pipe(struct pipe_ctx *pipe)
|
||||
}
|
||||
|
||||
static void free_unused_pipes_for_plane(struct dml2_context *ctx, struct dc_state *state,
|
||||
const struct dc_plane_state *plane, const struct dc_plane_pipe_pool *pool, unsigned int stream_id)
|
||||
const struct dc_plane_state *plane, const struct dc_plane_pipe_pool *pool, unsigned int stream_id, int plane_index)
|
||||
{
|
||||
int i;
|
||||
bool is_plane_duplicate = ctx->v20.scratch.plane_duplicate_exists;
|
||||
|
||||
for (i = 0; i < ctx->config.dcn_pipe_count; i++) {
|
||||
if (state->res_ctx.pipe_ctx[i].plane_state == plane &&
|
||||
state->res_ctx.pipe_ctx[i].stream->stream_id == stream_id &&
|
||||
(!is_plane_duplicate || (is_plane_duplicate &&
|
||||
ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_index[state->res_ctx.pipe_ctx[i].pipe_idx] == plane_index)) &&
|
||||
!is_pipe_used(pool, state->res_ctx.pipe_ctx[i].pipe_idx)) {
|
||||
free_pipe(&state->res_ctx.pipe_ctx[i]);
|
||||
}
|
||||
@ -717,19 +726,20 @@ static void map_pipes_for_stream(struct dml2_context *ctx, struct dc_state *stat
|
||||
}
|
||||
|
||||
static void map_pipes_for_plane(struct dml2_context *ctx, struct dc_state *state, const struct dc_stream_state *stream, const struct dc_plane_state *plane,
|
||||
struct dc_pipe_mapping_scratch *scratch, const struct dc_state *existing_state)
|
||||
int plane_index, struct dc_pipe_mapping_scratch *scratch, const struct dc_state *existing_state)
|
||||
{
|
||||
int odm_slice_index;
|
||||
unsigned int plane_id;
|
||||
struct pipe_ctx *master_pipe = NULL;
|
||||
int i;
|
||||
|
||||
if (!get_plane_id(state, plane, stream->stream_id, &plane_id)) {
|
||||
if (!get_plane_id(ctx, state, plane, stream->stream_id, plane_index, &plane_id)) {
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
master_pipe = assign_pipes_to_plane(ctx, state, stream, plane, scratch->odm_info.odm_factor, scratch->mpc_info.mpc_factor, &scratch->pipe_pool, existing_state);
|
||||
master_pipe = assign_pipes_to_plane(ctx, state, stream, plane, scratch->odm_info.odm_factor,
|
||||
scratch->mpc_info.mpc_factor, plane_index, &scratch->pipe_pool, existing_state);
|
||||
sort_pipes_for_splitting(&scratch->pipe_pool);
|
||||
|
||||
for (odm_slice_index = 0; odm_slice_index < scratch->odm_info.odm_factor; odm_slice_index++) {
|
||||
@ -755,7 +765,7 @@ static void map_pipes_for_plane(struct dml2_context *ctx, struct dc_state *state
|
||||
}
|
||||
}
|
||||
|
||||
free_unused_pipes_for_plane(ctx, state, plane, &scratch->pipe_pool, stream->stream_id);
|
||||
free_unused_pipes_for_plane(ctx, state, plane, &scratch->pipe_pool, stream->stream_id, plane_index);
|
||||
}
|
||||
|
||||
static unsigned int get_mpc_factor(struct dml2_context *ctx,
|
||||
@ -768,7 +778,7 @@ static unsigned int get_mpc_factor(struct dml2_context *ctx,
|
||||
unsigned int plane_id;
|
||||
unsigned int cfg_idx;
|
||||
|
||||
get_plane_id(state, status->plane_states[plane_idx], stream_id, &plane_id);
|
||||
get_plane_id(ctx, state, status->plane_states[plane_idx], stream_id, plane_idx, &plane_id);
|
||||
cfg_idx = find_disp_cfg_idx_by_plane_id(mapping, plane_id);
|
||||
if (ctx->architecture == dml2_architecture_20)
|
||||
return (unsigned int)disp_cfg->hw.DPPPerSurface[cfg_idx];
|
||||
@ -911,26 +921,14 @@ bool dml2_map_dc_pipes(struct dml2_context *ctx, struct dc_state *state, const s
|
||||
unsigned int stream_id;
|
||||
|
||||
const unsigned int *ODMMode, *DPPPerSurface;
|
||||
unsigned int odm_mode_array[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0}, dpp_per_surface_array[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0};
|
||||
struct dc_pipe_mapping_scratch scratch;
|
||||
|
||||
if (ctx->config.map_dc_pipes_with_callbacks)
|
||||
return map_dc_pipes_with_callbacks(
|
||||
ctx, state, disp_cfg, mapping, existing_state);
|
||||
|
||||
if (ctx->architecture == dml2_architecture_21) {
|
||||
/*
|
||||
* Extract ODM and DPP outputs from DML2.1 and map them in an array as required for pipe mapping in dml2_map_dc_pipes.
|
||||
* As data cannot be directly extracted in const pointers, assign these arrays to const pointers before proceeding to
|
||||
* maximize the reuse of existing code. Const pointers are required because dml2.0 dml_display_cfg_st is const.
|
||||
*
|
||||
*/
|
||||
ODMMode = (const unsigned int *)odm_mode_array;
|
||||
DPPPerSurface = (const unsigned int *)dpp_per_surface_array;
|
||||
} else {
|
||||
ODMMode = (unsigned int *)disp_cfg->hw.ODMMode;
|
||||
DPPPerSurface = disp_cfg->hw.DPPPerSurface;
|
||||
}
|
||||
ODMMode = (unsigned int *)disp_cfg->hw.ODMMode;
|
||||
DPPPerSurface = disp_cfg->hw.DPPPerSurface;
|
||||
|
||||
for (stream_index = 0; stream_index < state->stream_count; stream_index++) {
|
||||
memset(&scratch, 0, sizeof(struct dc_pipe_mapping_scratch));
|
||||
@ -958,8 +956,8 @@ bool dml2_map_dc_pipes(struct dml2_context *ctx, struct dc_state *state, const s
|
||||
|
||||
for (plane_index = 0; plane_index < state->stream_status[stream_index].plane_count; plane_index++) {
|
||||
// Planes are ordered top to bottom.
|
||||
if (get_plane_id(state, state->stream_status[stream_index].plane_states[plane_index],
|
||||
stream_id, &plane_id)) {
|
||||
if (get_plane_id(ctx, state, state->stream_status[stream_index].plane_states[plane_index],
|
||||
stream_id, plane_index, &plane_id)) {
|
||||
plane_disp_cfg_index = find_disp_cfg_idx_by_plane_id(mapping, plane_id);
|
||||
|
||||
// Setup mpc_info for this plane
|
||||
@ -983,7 +981,8 @@ bool dml2_map_dc_pipes(struct dml2_context *ctx, struct dc_state *state, const s
|
||||
// Clear the pool assignment scratch (which is per plane)
|
||||
memset(&scratch.pipe_pool, 0, sizeof(struct dc_plane_pipe_pool));
|
||||
|
||||
map_pipes_for_plane(ctx, state, state->streams[stream_index], state->stream_status[stream_index].plane_states[plane_index], &scratch, existing_state);
|
||||
map_pipes_for_plane(ctx, state, state->streams[stream_index],
|
||||
state->stream_status[stream_index].plane_states[plane_index], plane_index, &scratch, existing_state);
|
||||
} else {
|
||||
// Plane ID cannot be generated, therefore no DML mapping can be performed.
|
||||
ASSERT(false);
|
||||
|
@ -75,6 +75,8 @@ struct dml2_dml_to_dc_pipe_mapping {
|
||||
bool dml_pipe_idx_to_stream_id_valid[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
|
||||
unsigned int dml_pipe_idx_to_plane_id[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
|
||||
bool dml_pipe_idx_to_plane_id_valid[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
|
||||
unsigned int dml_pipe_idx_to_plane_index[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
|
||||
bool dml_pipe_idx_to_plane_index_valid[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
|
||||
};
|
||||
|
||||
struct dml2_wrapper_scratch {
|
||||
@ -96,6 +98,7 @@ struct dml2_wrapper_scratch {
|
||||
|
||||
struct dml2_dml_to_dc_pipe_mapping dml_to_dc_pipe_mapping;
|
||||
bool enable_flexible_pipe_mapping;
|
||||
bool plane_duplicate_exists;
|
||||
};
|
||||
|
||||
struct dml2_helper_det_policy_scratch {
|
||||
@ -104,7 +107,6 @@ struct dml2_helper_det_policy_scratch {
|
||||
|
||||
enum dml2_architecture {
|
||||
dml2_architecture_20,
|
||||
dml2_architecture_21
|
||||
};
|
||||
|
||||
struct dml2_context {
|
||||
|
@ -231,6 +231,7 @@ void dml2_init_socbb_params(struct dml2_context *dml2, const struct dc *in_dc, s
|
||||
out->num_chans = 4;
|
||||
out->round_trip_ping_latency_dcfclk_cycles = 106;
|
||||
out->smn_latency_us = 2;
|
||||
out->dispclk_dppclk_vco_speed_mhz = 3600;
|
||||
break;
|
||||
|
||||
case dml_project_dcn351:
|
||||
@ -930,10 +931,11 @@ static unsigned int map_stream_to_dml_display_cfg(const struct dml2_context *dml
|
||||
return location;
|
||||
}
|
||||
|
||||
static bool get_plane_id(const struct dc_state *context, const struct dc_plane_state *plane,
|
||||
unsigned int stream_id, unsigned int *plane_id)
|
||||
static bool get_plane_id(struct dml2_context *dml2, const struct dc_state *context, const struct dc_plane_state *plane,
|
||||
unsigned int stream_id, unsigned int plane_index, unsigned int *plane_id)
|
||||
{
|
||||
int i, j;
|
||||
bool is_plane_duplicate = dml2->v20.scratch.plane_duplicate_exists;
|
||||
|
||||
if (!plane_id)
|
||||
return false;
|
||||
@ -941,7 +943,8 @@ static bool get_plane_id(const struct dc_state *context, const struct dc_plane_s
|
||||
for (i = 0; i < context->stream_count; i++) {
|
||||
if (context->streams[i]->stream_id == stream_id) {
|
||||
for (j = 0; j < context->stream_status[i].plane_count; j++) {
|
||||
if (context->stream_status[i].plane_states[j] == plane) {
|
||||
if (context->stream_status[i].plane_states[j] == plane &&
|
||||
(!is_plane_duplicate || (is_plane_duplicate && (j == plane_index)))) {
|
||||
*plane_id = (i << 16) | j;
|
||||
return true;
|
||||
}
|
||||
@ -953,13 +956,13 @@ static bool get_plane_id(const struct dc_state *context, const struct dc_plane_s
|
||||
}
|
||||
|
||||
static unsigned int map_plane_to_dml_display_cfg(const struct dml2_context *dml2, const struct dc_plane_state *plane,
|
||||
const struct dc_state *context, const struct dml_display_cfg_st *dml_dispcfg, unsigned int stream_id)
|
||||
const struct dc_state *context, const struct dml_display_cfg_st *dml_dispcfg, unsigned int stream_id, int plane_index)
|
||||
{
|
||||
unsigned int plane_id;
|
||||
int i = 0;
|
||||
int location = -1;
|
||||
|
||||
if (!get_plane_id(context, plane, stream_id, &plane_id)) {
|
||||
if (!get_plane_id(context->bw_ctx.dml2, context, plane, stream_id, plane_index, &plane_id)) {
|
||||
ASSERT(false);
|
||||
return -1;
|
||||
}
|
||||
@ -990,7 +993,41 @@ static void apply_legacy_svp_drr_settings(struct dml2_context *dml2, const struc
|
||||
}
|
||||
}
|
||||
|
||||
void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, const struct dc_state *context, struct dml_display_cfg_st *dml_dispcfg)
|
||||
static void dml2_populate_pipe_to_plane_index_mapping(struct dml2_context *dml2, struct dc_state *state)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int pipe_index = 0;
|
||||
unsigned int plane_index = 0;
|
||||
struct dml2_dml_to_dc_pipe_mapping *dml_to_dc_pipe_mapping = &dml2->v20.scratch.dml_to_dc_pipe_mapping;
|
||||
|
||||
for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
|
||||
dml_to_dc_pipe_mapping->dml_pipe_idx_to_plane_index_valid[i] = false;
|
||||
dml_to_dc_pipe_mapping->dml_pipe_idx_to_plane_index[i] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
|
||||
struct pipe_ctx *pipe = &state->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (!pipe || !pipe->stream || !pipe->plane_state)
|
||||
continue;
|
||||
|
||||
while (pipe) {
|
||||
pipe_index = pipe->pipe_idx;
|
||||
|
||||
if (pipe->stream && dml_to_dc_pipe_mapping->dml_pipe_idx_to_plane_index_valid[pipe_index] == false) {
|
||||
dml_to_dc_pipe_mapping->dml_pipe_idx_to_plane_index[pipe_index] = plane_index;
|
||||
plane_index++;
|
||||
dml_to_dc_pipe_mapping->dml_pipe_idx_to_plane_index_valid[pipe_index] = true;
|
||||
}
|
||||
|
||||
pipe = pipe->bottom_pipe;
|
||||
}
|
||||
|
||||
plane_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_state *context, struct dml_display_cfg_st *dml_dispcfg)
|
||||
{
|
||||
int i = 0, j = 0;
|
||||
int disp_cfg_stream_location, disp_cfg_plane_location;
|
||||
@ -1007,6 +1044,8 @@ void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, const struct d
|
||||
dml_dispcfg->plane.GPUVMMaxPageTableLevels = 4;
|
||||
dml_dispcfg->plane.HostVMEnable = false;
|
||||
|
||||
dml2_populate_pipe_to_plane_index_mapping(dml2, context);
|
||||
|
||||
for (i = 0; i < context->stream_count; i++) {
|
||||
disp_cfg_stream_location = map_stream_to_dml_display_cfg(dml2, context->streams[i], dml_dispcfg);
|
||||
|
||||
@ -1043,7 +1082,7 @@ void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, const struct d
|
||||
} else {
|
||||
for (j = 0; j < context->stream_status[i].plane_count; j++) {
|
||||
disp_cfg_plane_location = map_plane_to_dml_display_cfg(dml2,
|
||||
context->stream_status[i].plane_states[j], context, dml_dispcfg, context->streams[i]->stream_id);
|
||||
context->stream_status[i].plane_states[j], context, dml_dispcfg, context->streams[i]->stream_id, j);
|
||||
|
||||
if (disp_cfg_plane_location < 0)
|
||||
disp_cfg_plane_location = dml_dispcfg->num_surfaces++;
|
||||
@ -1067,7 +1106,7 @@ void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, const struct d
|
||||
|
||||
dml_dispcfg->plane.BlendingAndTiming[disp_cfg_plane_location] = disp_cfg_stream_location;
|
||||
|
||||
if (get_plane_id(context, context->stream_status[i].plane_states[j], context->streams[i]->stream_id,
|
||||
if (get_plane_id(dml2, context, context->stream_status[i].plane_states[j], context->streams[i]->stream_id, j,
|
||||
&dml2->v20.scratch.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id[disp_cfg_plane_location]))
|
||||
dml2->v20.scratch.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id_valid[disp_cfg_plane_location] = true;
|
||||
|
||||
|
@ -34,7 +34,7 @@ void dml2_init_soc_states(struct dml2_context *dml2, const struct dc *in_dc,
|
||||
void dml2_translate_ip_params(const struct dc *in_dc, struct ip_params_st *out);
|
||||
void dml2_translate_socbb_params(const struct dc *in_dc, struct soc_bounding_box_st *out);
|
||||
void dml2_translate_soc_states(const struct dc *in_dc, struct soc_states_st *out, int num_states);
|
||||
void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, const struct dc_state *context, struct dml_display_cfg_st *dml_dispcfg);
|
||||
void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_state *context, struct dml_display_cfg_st *dml_dispcfg);
|
||||
void dml2_update_pipe_ctx_dchub_regs(struct _vcs_dpi_dml_display_rq_regs_st *rq_regs, struct _vcs_dpi_dml_display_dlg_regs_st *disp_dlg_regs, struct _vcs_dpi_dml_display_ttu_regs_st *disp_ttu_regs, struct pipe_ctx *out);
|
||||
bool is_dp2p0_output_encoder(const struct pipe_ctx *pipe);
|
||||
|
||||
|
@ -209,10 +209,11 @@ static int find_dml_pipe_idx_by_plane_id(struct dml2_context *ctx, unsigned int
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool get_plane_id(const struct dc_state *state, const struct dc_plane_state *plane,
|
||||
unsigned int stream_id, unsigned int *plane_id)
|
||||
static bool get_plane_id(struct dml2_context *dml2, const struct dc_state *state, const struct dc_plane_state *plane,
|
||||
unsigned int stream_id, unsigned int plane_index, unsigned int *plane_id)
|
||||
{
|
||||
int i, j;
|
||||
bool is_plane_duplicate = dml2->v20.scratch.plane_duplicate_exists;
|
||||
|
||||
if (!plane_id)
|
||||
return false;
|
||||
@ -220,7 +221,8 @@ static bool get_plane_id(const struct dc_state *state, const struct dc_plane_sta
|
||||
for (i = 0; i < state->stream_count; i++) {
|
||||
if (state->streams[i]->stream_id == stream_id) {
|
||||
for (j = 0; j < state->stream_status[i].plane_count; j++) {
|
||||
if (state->stream_status[i].plane_states[j] == plane) {
|
||||
if (state->stream_status[i].plane_states[j] == plane &&
|
||||
(!is_plane_duplicate || (is_plane_duplicate && (j == plane_index)))) {
|
||||
*plane_id = (i << 16) | j;
|
||||
return true;
|
||||
}
|
||||
@ -304,8 +306,9 @@ void dml2_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *cont
|
||||
* there is a need to know which DML pipe index maps to which DC pipe. The code below
|
||||
* finds a dml_pipe_index from the plane id if a plane is valid. If a plane is not valid then
|
||||
* it finds a dml_pipe_index from the stream id. */
|
||||
if (get_plane_id(context, context->res_ctx.pipe_ctx[dc_pipe_ctx_index].plane_state,
|
||||
context->res_ctx.pipe_ctx[dc_pipe_ctx_index].stream->stream_id, &plane_id)) {
|
||||
if (get_plane_id(in_ctx, context, context->res_ctx.pipe_ctx[dc_pipe_ctx_index].plane_state,
|
||||
context->res_ctx.pipe_ctx[dc_pipe_ctx_index].stream->stream_id,
|
||||
in_ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_index[context->res_ctx.pipe_ctx[dc_pipe_ctx_index].pipe_idx], &plane_id)) {
|
||||
dml_pipe_idx = find_dml_pipe_idx_by_plane_id(in_ctx, plane_id);
|
||||
} else {
|
||||
dml_pipe_idx = dml2_helper_find_dml_pipe_idx_by_stream_id(in_ctx, context->res_ctx.pipe_ctx[dc_pipe_ctx_index].stream->stream_id);
|
||||
@ -445,8 +448,9 @@ bool dml2_verify_det_buffer_configuration(struct dml2_context *in_ctx, struct dc
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
if (!display_state->res_ctx.pipe_ctx[i].stream)
|
||||
continue;
|
||||
if (get_plane_id(display_state, display_state->res_ctx.pipe_ctx[i].plane_state,
|
||||
display_state->res_ctx.pipe_ctx[i].stream->stream_id, &plane_id))
|
||||
if (get_plane_id(in_ctx, display_state, display_state->res_ctx.pipe_ctx[i].plane_state,
|
||||
display_state->res_ctx.pipe_ctx[i].stream->stream_id,
|
||||
in_ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_index[display_state->res_ctx.pipe_ctx[i].pipe_idx], &plane_id))
|
||||
dml_pipe_idx = find_dml_pipe_idx_by_plane_id(in_ctx, plane_id);
|
||||
else
|
||||
dml_pipe_idx = dml2_helper_find_dml_pipe_idx_by_stream_id(in_ctx, display_state->res_ctx.pipe_ctx[i].stream->stream_id);
|
||||
|
@ -639,7 +639,7 @@ static bool dml2_validate_and_build_resource(const struct dc *in_dc, struct dc_s
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool dml2_validate_only(const struct dc_state *context)
|
||||
static bool dml2_validate_only(struct dc_state *context)
|
||||
{
|
||||
struct dml2_context *dml2 = context->bw_ctx.dml2;
|
||||
unsigned int result = 0;
|
||||
|
@ -512,6 +512,11 @@ static bool intersect_dsc_caps(
|
||||
dsc_sink_caps->slice_caps1.bits.NUM_SLICES_4 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_4;
|
||||
dsc_common_caps->slice_caps.bits.NUM_SLICES_8 =
|
||||
dsc_sink_caps->slice_caps1.bits.NUM_SLICES_8 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_8;
|
||||
dsc_common_caps->slice_caps.bits.NUM_SLICES_12 =
|
||||
dsc_sink_caps->slice_caps1.bits.NUM_SLICES_12 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_12;
|
||||
dsc_common_caps->slice_caps.bits.NUM_SLICES_16 =
|
||||
dsc_sink_caps->slice_caps2.bits.NUM_SLICES_16 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_16;
|
||||
|
||||
if (!dsc_common_caps->slice_caps.raw)
|
||||
return false;
|
||||
|
||||
@ -703,6 +708,12 @@ static int get_available_dsc_slices(union dsc_enc_slice_caps slice_caps, int *av
|
||||
if (slice_caps.bits.NUM_SLICES_8)
|
||||
available_slices[idx++] = 8;
|
||||
|
||||
if (slice_caps.bits.NUM_SLICES_12)
|
||||
available_slices[idx++] = 12;
|
||||
|
||||
if (slice_caps.bits.NUM_SLICES_16)
|
||||
available_slices[idx++] = 16;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
@ -1183,7 +1183,23 @@ struct dce_hwseq_registers {
|
||||
type LONO_FGCG_REP_DIS;\
|
||||
type LONO_DISPCLK_GATE_DISABLE;\
|
||||
type LONO_SOCCLK_GATE_DISABLE;\
|
||||
type LONO_DMCUBCLK_GATE_DISABLE;
|
||||
type LONO_DMCUBCLK_GATE_DISABLE;\
|
||||
type SYMCLKA_FE_GATE_DISABLE;\
|
||||
type SYMCLKB_FE_GATE_DISABLE;\
|
||||
type SYMCLKC_FE_GATE_DISABLE;\
|
||||
type SYMCLKD_FE_GATE_DISABLE;\
|
||||
type SYMCLKE_FE_GATE_DISABLE;\
|
||||
type HDMICHARCLK0_GATE_DISABLE;\
|
||||
type SYMCLKA_GATE_DISABLE;\
|
||||
type SYMCLKB_GATE_DISABLE;\
|
||||
type SYMCLKC_GATE_DISABLE;\
|
||||
type SYMCLKD_GATE_DISABLE;\
|
||||
type SYMCLKE_GATE_DISABLE;\
|
||||
type PHYASYMCLK_ROOT_GATE_DISABLE;\
|
||||
type PHYBSYMCLK_ROOT_GATE_DISABLE;\
|
||||
type PHYCSYMCLK_ROOT_GATE_DISABLE;\
|
||||
type PHYDSYMCLK_ROOT_GATE_DISABLE;\
|
||||
type PHYESYMCLK_ROOT_GATE_DISABLE;
|
||||
|
||||
struct dce_hwseq_shift {
|
||||
HWSEQ_REG_FIELD_LIST(uint8_t)
|
||||
|
@ -615,12 +615,6 @@ void dcn32_update_force_pstate(struct dc *dc, struct dc_state *context)
|
||||
pipe->stream->fpo_in_use)) {
|
||||
if (hubp && hubp->funcs->hubp_update_force_pstate_disallow)
|
||||
hubp->funcs->hubp_update_force_pstate_disallow(hubp, false);
|
||||
}
|
||||
|
||||
/* Today only FPO uses cursor P-State force. Only clear cursor P-State force
|
||||
* if it's not FPO.
|
||||
*/
|
||||
if (!pipe->stream || !pipe->stream->fpo_in_use) {
|
||||
if (hubp && hubp->funcs->hubp_update_force_cursor_pstate_disallow)
|
||||
hubp->funcs->hubp_update_force_cursor_pstate_disallow(hubp, false);
|
||||
}
|
||||
@ -632,17 +626,10 @@ void dcn32_update_force_pstate(struct dc *dc, struct dc_state *context)
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
struct hubp *hubp = pipe->plane_res.hubp;
|
||||
|
||||
if (pipe->stream && pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
|
||||
if (pipe->stream && (pipe->stream->mall_stream_config.type == SUBVP_MAIN ||
|
||||
pipe->stream->fpo_in_use)) {
|
||||
if (hubp && hubp->funcs->hubp_update_force_pstate_disallow)
|
||||
hubp->funcs->hubp_update_force_pstate_disallow(hubp, true);
|
||||
}
|
||||
|
||||
if (pipe->stream && pipe->stream->fpo_in_use) {
|
||||
if (hubp && hubp->funcs->hubp_update_force_pstate_disallow)
|
||||
hubp->funcs->hubp_update_force_pstate_disallow(hubp, true);
|
||||
/* For now only force cursor p-state disallow for FPO
|
||||
* Needs to be added for subvp once FW side gets updated
|
||||
*/
|
||||
if (hubp && hubp->funcs->hubp_update_force_cursor_pstate_disallow)
|
||||
hubp->funcs->hubp_update_force_cursor_pstate_disallow(hubp, true);
|
||||
}
|
||||
|
@ -138,16 +138,25 @@ void dcn35_init_hw(struct dc *dc)
|
||||
if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
|
||||
dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
|
||||
|
||||
REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
|
||||
REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0x3F000000);
|
||||
REG_WRITE(DCCG_GATE_DISABLE_CNTL5, 0x1f7c3fcf);
|
||||
|
||||
//dcn35_set_dmu_fgcg(hws, dc->debug.enable_fine_grain_clock_gating.bits.dmu);
|
||||
|
||||
if (!dcb->funcs->is_accelerated_mode(dcb)) {
|
||||
/*this calls into dmubfw to do the init*/
|
||||
hws->funcs.bios_golden_init(dc);
|
||||
}
|
||||
|
||||
REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
|
||||
REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
|
||||
|
||||
/* Disable gating for PHYASYMCLK. This will be enabled in dccg if needed */
|
||||
REG_UPDATE_5(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, 1,
|
||||
PHYBSYMCLK_ROOT_GATE_DISABLE, 1,
|
||||
PHYCSYMCLK_ROOT_GATE_DISABLE, 1,
|
||||
PHYDSYMCLK_ROOT_GATE_DISABLE, 1,
|
||||
PHYESYMCLK_ROOT_GATE_DISABLE, 1);
|
||||
|
||||
REG_WRITE(DCCG_GATE_DISABLE_CNTL5, 0x1f7c3fcf);
|
||||
|
||||
// Initialize the dccg
|
||||
if (res_pool->dccg->funcs->dccg_init)
|
||||
res_pool->dccg->funcs->dccg_init(res_pool->dccg);
|
||||
@ -274,7 +283,19 @@ void dcn35_init_hw(struct dc *dc)
|
||||
if (!dc->debug.disable_clock_gate) {
|
||||
/* enable all DCN clock gating */
|
||||
REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
|
||||
REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
|
||||
|
||||
REG_UPDATE_5(DCCG_GATE_DISABLE_CNTL2, SYMCLKA_FE_GATE_DISABLE, 0,
|
||||
SYMCLKB_FE_GATE_DISABLE, 0,
|
||||
SYMCLKC_FE_GATE_DISABLE, 0,
|
||||
SYMCLKD_FE_GATE_DISABLE, 0,
|
||||
SYMCLKE_FE_GATE_DISABLE, 0);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, HDMICHARCLK0_GATE_DISABLE, 0);
|
||||
REG_UPDATE_5(DCCG_GATE_DISABLE_CNTL2, SYMCLKA_GATE_DISABLE, 0,
|
||||
SYMCLKB_GATE_DISABLE, 0,
|
||||
SYMCLKC_GATE_DISABLE, 0,
|
||||
SYMCLKD_GATE_DISABLE, 0,
|
||||
SYMCLKE_GATE_DISABLE, 0);
|
||||
|
||||
REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
|
||||
}
|
||||
|
||||
@ -311,6 +332,9 @@ void dcn35_init_hw(struct dc *dc)
|
||||
if (dc->res_pool->pg_cntl) {
|
||||
if (dc->res_pool->pg_cntl->funcs->init_pg_status)
|
||||
dc->res_pool->pg_cntl->funcs->init_pg_status(dc->res_pool->pg_cntl);
|
||||
|
||||
if (dc->res_pool->pg_cntl->funcs->set_force_poweron_domain22)
|
||||
dc->res_pool->pg_cntl->funcs->set_force_poweron_domain22(dc->res_pool->pg_cntl, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,6 +141,11 @@ struct dccg_funcs {
|
||||
enum physymclk_clock_source clk_src,
|
||||
bool force_enable);
|
||||
|
||||
void (*set_physymclk_root_clock_gating)(
|
||||
struct dccg *dccg,
|
||||
int phy_inst,
|
||||
bool enable);
|
||||
|
||||
void (*set_dtbclk_dto)(
|
||||
struct dccg *dccg,
|
||||
const struct dtbclk_dto_params *params);
|
||||
|
@ -76,6 +76,8 @@ union dsc_enc_slice_caps {
|
||||
uint8_t NUM_SLICES_3 : 1; /* This one is not per DSC spec, but our encoder supports it */
|
||||
uint8_t NUM_SLICES_4 : 1;
|
||||
uint8_t NUM_SLICES_8 : 1;
|
||||
uint8_t NUM_SLICES_12 : 1;
|
||||
uint8_t NUM_SLICES_16 : 1;
|
||||
} bits;
|
||||
uint8_t raw;
|
||||
};
|
||||
|
219
drivers/gpu/drm/amd/display/dc/inc/hw/optc.h
Normal file
219
drivers/gpu/drm/amd/display/dc/inc/hw/optc.h
Normal file
@ -0,0 +1,219 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright 2023 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: overview
|
||||
*
|
||||
* Output Pipe Timing Combiner (OPTC) includes two major functional blocks:
|
||||
* Output Data Mapper (ODM) and Output Timing Generator (OTG).
|
||||
*
|
||||
* - ODM: It is Output Data Mapping block. It can combine input data from
|
||||
* multiple OPP data pipes into one single data stream or split data from one
|
||||
* OPP data pipe into multiple data streams or just bypass OPP data to DIO.
|
||||
* - OTG: It is Output Timing Generator. It generates display timing signals to
|
||||
* drive the display output.
|
||||
*/
|
||||
|
||||
#ifndef __DC_OPTC_H__
|
||||
#define __DC_OPTC_H__
|
||||
|
||||
#include "timing_generator.h"
|
||||
|
||||
struct optc {
|
||||
struct timing_generator base;
|
||||
|
||||
const struct dcn_optc_registers *tg_regs;
|
||||
const struct dcn_optc_shift *tg_shift;
|
||||
const struct dcn_optc_mask *tg_mask;
|
||||
|
||||
int opp_count;
|
||||
|
||||
uint32_t max_h_total;
|
||||
uint32_t max_v_total;
|
||||
|
||||
uint32_t min_h_blank;
|
||||
|
||||
uint32_t min_h_sync_width;
|
||||
uint32_t min_v_sync_width;
|
||||
uint32_t min_v_blank;
|
||||
uint32_t min_v_blank_interlace;
|
||||
|
||||
int vstartup_start;
|
||||
int vupdate_offset;
|
||||
int vupdate_width;
|
||||
int vready_offset;
|
||||
struct dc_crtc_timing orginal_patched_timing;
|
||||
enum signal_type signal;
|
||||
};
|
||||
|
||||
struct dcn_otg_state {
|
||||
uint32_t v_blank_start;
|
||||
uint32_t v_blank_end;
|
||||
uint32_t v_sync_a_pol;
|
||||
uint32_t v_total;
|
||||
uint32_t v_total_max;
|
||||
uint32_t v_total_min;
|
||||
uint32_t v_total_min_sel;
|
||||
uint32_t v_total_max_sel;
|
||||
uint32_t v_sync_a_start;
|
||||
uint32_t v_sync_a_end;
|
||||
uint32_t h_blank_start;
|
||||
uint32_t h_blank_end;
|
||||
uint32_t h_sync_a_start;
|
||||
uint32_t h_sync_a_end;
|
||||
uint32_t h_sync_a_pol;
|
||||
uint32_t h_total;
|
||||
uint32_t underflow_occurred_status;
|
||||
uint32_t otg_enabled;
|
||||
uint32_t blank_enabled;
|
||||
uint32_t vertical_interrupt1_en;
|
||||
uint32_t vertical_interrupt1_line;
|
||||
uint32_t vertical_interrupt2_en;
|
||||
uint32_t vertical_interrupt2_line;
|
||||
};
|
||||
|
||||
void optc1_read_otg_state(struct optc *optc1, struct dcn_otg_state *s);
|
||||
|
||||
bool optc1_get_hw_timing(struct timing_generator *tg, struct dc_crtc_timing *hw_crtc_timing);
|
||||
|
||||
bool optc1_validate_timing(struct timing_generator *optc,
|
||||
const struct dc_crtc_timing *timing);
|
||||
|
||||
void optc1_program_timing(struct timing_generator *optc,
|
||||
const struct dc_crtc_timing *dc_crtc_timing,
|
||||
int vready_offset,
|
||||
int vstartup_start,
|
||||
int vupdate_offset,
|
||||
int vupdate_width,
|
||||
const enum signal_type signal,
|
||||
bool use_vbios);
|
||||
|
||||
void optc1_setup_vertical_interrupt0(struct timing_generator *optc,
|
||||
uint32_t start_line,
|
||||
uint32_t end_line);
|
||||
|
||||
void optc1_setup_vertical_interrupt1(struct timing_generator *optc,
|
||||
uint32_t start_line);
|
||||
|
||||
void optc1_setup_vertical_interrupt2(struct timing_generator *optc,
|
||||
uint32_t start_line);
|
||||
|
||||
void optc1_program_global_sync(struct timing_generator *optc,
|
||||
int vready_offset,
|
||||
int vstartup_start,
|
||||
int vupdate_offset,
|
||||
int vupdate_width);
|
||||
|
||||
bool optc1_disable_crtc(struct timing_generator *optc);
|
||||
|
||||
bool optc1_is_counter_moving(struct timing_generator *optc);
|
||||
|
||||
void optc1_get_position(struct timing_generator *optc,
|
||||
struct crtc_position *position);
|
||||
|
||||
uint32_t optc1_get_vblank_counter(struct timing_generator *optc);
|
||||
|
||||
void optc1_get_crtc_scanoutpos(struct timing_generator *optc,
|
||||
uint32_t *v_blank_start,
|
||||
uint32_t *v_blank_end,
|
||||
uint32_t *h_position,
|
||||
uint32_t *v_position);
|
||||
|
||||
void optc1_set_early_control(struct timing_generator *optc,
|
||||
uint32_t early_cntl);
|
||||
|
||||
void optc1_wait_for_state(struct timing_generator *optc,
|
||||
enum crtc_state state);
|
||||
|
||||
void optc1_set_blank(struct timing_generator *optc,
|
||||
bool enable_blanking);
|
||||
|
||||
bool optc1_is_blanked(struct timing_generator *optc);
|
||||
|
||||
void optc1_program_blank_color(struct timing_generator *optc,
|
||||
const struct tg_color *black_color);
|
||||
|
||||
bool optc1_did_triggered_reset_occur(struct timing_generator *optc);
|
||||
|
||||
void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst);
|
||||
|
||||
void optc1_disable_reset_trigger(struct timing_generator *optc);
|
||||
|
||||
void optc1_lock(struct timing_generator *optc);
|
||||
|
||||
void optc1_unlock(struct timing_generator *optc);
|
||||
|
||||
void optc1_enable_optc_clock(struct timing_generator *optc, bool enable);
|
||||
|
||||
void optc1_set_drr(struct timing_generator *optc,
|
||||
const struct drr_params *params);
|
||||
|
||||
void optc1_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max);
|
||||
|
||||
void optc1_set_static_screen_control(struct timing_generator *optc,
|
||||
uint32_t event_triggers,
|
||||
uint32_t num_frames);
|
||||
|
||||
void optc1_program_stereo(struct timing_generator *optc,
|
||||
const struct dc_crtc_timing *timing,
|
||||
struct crtc_stereo_flags *flags);
|
||||
|
||||
bool optc1_is_stereo_left_eye(struct timing_generator *optc);
|
||||
|
||||
void optc1_clear_optc_underflow(struct timing_generator *optc);
|
||||
|
||||
void optc1_tg_init(struct timing_generator *optc);
|
||||
|
||||
bool optc1_is_tg_enabled(struct timing_generator *optc);
|
||||
|
||||
bool optc1_is_optc_underflow_occurred(struct timing_generator *optc);
|
||||
|
||||
void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable);
|
||||
|
||||
void optc1_set_timing_double_buffer(struct timing_generator *optc, bool enable);
|
||||
|
||||
bool optc1_get_otg_active_size(struct timing_generator *optc,
|
||||
uint32_t *otg_active_width,
|
||||
uint32_t *otg_active_height);
|
||||
|
||||
void optc1_enable_crtc_reset(struct timing_generator *optc,
|
||||
int source_tg_inst,
|
||||
struct crtc_trigger_info *crtc_tp);
|
||||
|
||||
bool optc1_configure_crc(struct timing_generator *optc, const struct crc_params *params);
|
||||
|
||||
bool optc1_get_crc(struct timing_generator *optc,
|
||||
uint32_t *r_cr,
|
||||
uint32_t *g_y,
|
||||
uint32_t *b_cb);
|
||||
|
||||
bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing);
|
||||
|
||||
void optc1_set_vtg_params(struct timing_generator *optc,
|
||||
const struct dc_crtc_timing *dc_crtc_timing,
|
||||
bool program_fp2);
|
||||
|
||||
#endif
|
@ -47,6 +47,8 @@ struct pg_cntl_funcs {
|
||||
void (*optc_pg_control)(struct pg_cntl *pg_cntl, unsigned int optc_inst, bool power_on);
|
||||
void (*dwb_pg_control)(struct pg_cntl *pg_cntl, bool power_on);
|
||||
void (*init_pg_status)(struct pg_cntl *pg_cntl);
|
||||
|
||||
void (*set_force_poweron_domain22)(struct pg_cntl *pg_cntl, bool power_on);
|
||||
};
|
||||
|
||||
#endif //__DC_PG_CNTL_H__
|
||||
|
@ -53,6 +53,7 @@ static enum dc_link_rate get_link_rate_from_test_link_rate(uint8_t test_rate)
|
||||
return LINK_RATE_UHBR10;
|
||||
case DP_TEST_LINK_RATE_UHBR20:
|
||||
return LINK_RATE_UHBR20;
|
||||
case DP_TEST_LINK_RATE_UHBR13_5_LEGACY:
|
||||
case DP_TEST_LINK_RATE_UHBR13_5:
|
||||
return LINK_RATE_UHBR13_5;
|
||||
default:
|
||||
@ -119,6 +120,11 @@ static void dp_test_send_link_training(struct dc_link *link)
|
||||
1);
|
||||
link_settings.link_rate = get_link_rate_from_test_link_rate(test_rate);
|
||||
|
||||
if (link_settings.link_rate == LINK_RATE_UNKNOWN) {
|
||||
DC_LOG_ERROR("%s: Invalid test link rate.", __func__);
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
/* Set preferred link settings */
|
||||
link->verified_link_cap.lane_count = link_settings.lane_count;
|
||||
link->verified_link_cap.link_rate = link_settings.link_rate;
|
||||
@ -457,7 +463,7 @@ static void set_crtc_test_pattern(struct dc_link *link,
|
||||
controller_color_space = pipe_ctx->stream_res.test_pattern_params.color_space;
|
||||
|
||||
if (controller_color_space == CONTROLLER_DP_COLOR_SPACE_UDEFINED) {
|
||||
DC_LOG_WARNING("%s: Color space must be defined for test pattern", __func__);
|
||||
DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__);
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
@ -592,6 +598,7 @@ bool dp_set_test_pattern(
|
||||
const unsigned char *p_custom_pattern,
|
||||
unsigned int cust_pattern_size)
|
||||
{
|
||||
const struct link_hwss *link_hwss;
|
||||
struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
|
||||
struct pipe_ctx *pipe_ctx = NULL;
|
||||
unsigned int lane;
|
||||
@ -828,11 +835,9 @@ bool dp_set_test_pattern(
|
||||
|
||||
pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
|
||||
/* update MSA to requested color space */
|
||||
pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(pipe_ctx->stream_res.stream_enc,
|
||||
&pipe_ctx->stream->timing,
|
||||
color_space,
|
||||
pipe_ctx->stream->use_vsc_sdp_for_colorimetry,
|
||||
link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
|
||||
link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
|
||||
pipe_ctx->stream->output_color_space = color_space;
|
||||
link_hwss->setup_stream_attribute(pipe_ctx);
|
||||
|
||||
if (pipe_ctx->stream->use_vsc_sdp_for_colorimetry) {
|
||||
if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
|
||||
|
@ -184,14 +184,17 @@ static bool handle_hpd_irq_psr_sink(struct dc_link *link)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool handle_hpd_irq_replay_sink(struct dc_link *link)
|
||||
static void handle_hpd_irq_replay_sink(struct dc_link *link)
|
||||
{
|
||||
union dpcd_replay_configuration replay_configuration;
|
||||
/*AMD Replay version reuse DP_PSR_ERROR_STATUS for REPLAY_ERROR status.*/
|
||||
union psr_error_status replay_error_status;
|
||||
|
||||
if (link->replay_settings.config.force_disable_desync_error_check)
|
||||
return;
|
||||
|
||||
if (!link->replay_settings.replay_feature_enabled)
|
||||
return false;
|
||||
return;
|
||||
|
||||
dm_helpers_dp_read_dpcd(
|
||||
link->ctx,
|
||||
@ -207,6 +210,9 @@ static bool handle_hpd_irq_replay_sink(struct dc_link *link)
|
||||
&replay_error_status.raw,
|
||||
sizeof(replay_error_status.raw));
|
||||
|
||||
if (replay_configuration.bits.DESYNC_ERROR_STATUS)
|
||||
link->replay_settings.config.received_desync_error_hpd = 1;
|
||||
|
||||
link->replay_settings.config.replay_error_status.bits.LINK_CRC_ERROR =
|
||||
replay_error_status.bits.LINK_CRC_ERROR;
|
||||
link->replay_settings.config.replay_error_status.bits.DESYNC_ERROR =
|
||||
@ -243,7 +249,6 @@ static bool handle_hpd_irq_replay_sink(struct dc_link *link)
|
||||
edp_set_replay_allow_active(link, &allow_active, true, false, NULL);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void dp_handle_link_loss(struct dc_link *link)
|
||||
@ -424,9 +429,7 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
|
||||
/* PSR-related error was detected and handled */
|
||||
return true;
|
||||
|
||||
if (handle_hpd_irq_replay_sink(link))
|
||||
/* Replay-related error was detected and handled */
|
||||
return true;
|
||||
handle_hpd_irq_replay_sink(link);
|
||||
|
||||
/* If PSR-related error handled, Main link may be off,
|
||||
* so do not handle as a normal sink status change interrupt.
|
||||
|
@ -583,6 +583,7 @@ union dmub_fw_boot_status {
|
||||
uint32_t fams_enabled : 1; /**< 1 if VBIOS data is deferred programmed */
|
||||
uint32_t detection_required: 1; /**< if detection need to be triggered by driver */
|
||||
uint32_t hw_power_init_done: 1; /**< 1 if hw power init is completed */
|
||||
uint32_t ono_regions_enabled: 1; /**< 1 if ONO regions are enabled */
|
||||
} bits; /**< status bits */
|
||||
uint32_t all; /**< 32-bit access to status bits */
|
||||
};
|
||||
@ -599,6 +600,7 @@ enum dmub_fw_boot_status_bit {
|
||||
DMUB_FW_BOOT_STATUS_BIT_FAMS_ENABLED = (1 << 5), /**< 1 if FAMS is enabled*/
|
||||
DMUB_FW_BOOT_STATUS_BIT_DETECTION_REQUIRED = (1 << 6), /**< 1 if detection need to be triggered by driver*/
|
||||
DMUB_FW_BOOT_STATUS_BIT_HW_POWER_INIT_DONE = (1 << 7), /**< 1 if hw power init is completed */
|
||||
DMUB_FW_BOOT_STATUS_BIT_ONO_REGIONS_ENABLED = (1 << 8), /**< 1 if ONO regions are enabled */
|
||||
};
|
||||
|
||||
/* Register bit definition for SCRATCH5 */
|
||||
@ -617,9 +619,12 @@ enum dmub_lvtma_status_bit {
|
||||
};
|
||||
|
||||
enum dmub_ips_disable_type {
|
||||
DMUB_IPS_DISABLE_IPS1 = 1,
|
||||
DMUB_IPS_DISABLE_IPS2 = 2,
|
||||
DMUB_IPS_DISABLE_IPS2_Z10 = 3,
|
||||
DMUB_IPS_ENABLE = 0,
|
||||
DMUB_IPS_DISABLE_ALL = 1,
|
||||
DMUB_IPS_DISABLE_IPS1 = 2,
|
||||
DMUB_IPS_DISABLE_IPS2 = 3,
|
||||
DMUB_IPS_DISABLE_IPS2_Z10 = 4,
|
||||
DMUB_IPS_DISABLE_DYNAMIC = 5,
|
||||
};
|
||||
|
||||
#define DMUB_IPS1_ALLOW_MASK 0x00000001
|
||||
@ -653,8 +658,8 @@ union dmub_fw_boot_options {
|
||||
uint32_t disable_clk_ds: 1; /* 1 if disallow dispclk_ds and dppclk_ds*/
|
||||
uint32_t disable_timeout_recovery : 1; /* 1 if timeout recovery should be disabled */
|
||||
uint32_t ips_pg_disable: 1; /* 1 to disable ONO domains power gating*/
|
||||
uint32_t ips_disable: 2; /* options to disable ips support*/
|
||||
uint32_t reserved : 10; /**< reserved */
|
||||
uint32_t ips_disable: 3; /* options to disable ips support*/
|
||||
uint32_t reserved : 9; /**< reserved */
|
||||
} bits; /**< boot bits */
|
||||
uint32_t all; /**< 32-bit access to bits */
|
||||
};
|
||||
@ -2098,7 +2103,7 @@ enum psr_version {
|
||||
/**
|
||||
* PSR not supported.
|
||||
*/
|
||||
PSR_VERSION_UNSUPPORTED = 0xFFFFFFFF,
|
||||
PSR_VERSION_UNSUPPORTED = 0xFF, // psr_version field is only 8 bits wide
|
||||
};
|
||||
|
||||
/**
|
||||
@ -3620,7 +3625,6 @@ struct dmub_cmd_abm_pause_data {
|
||||
uint8_t pad[1];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Definition of a DMUB_CMD__ABM_PAUSE command.
|
||||
*/
|
||||
@ -4046,6 +4050,7 @@ union dmub_rb_cmd {
|
||||
* Definition of a DMUB_CMD__MALL command.
|
||||
*/
|
||||
struct dmub_rb_cmd_mall mall;
|
||||
|
||||
/**
|
||||
* Definition of a DMUB_CMD__CAB command.
|
||||
*/
|
||||
@ -4067,6 +4072,7 @@ union dmub_rb_cmd {
|
||||
* Definition of DMUB_CMD__PANEL_CNTL commands.
|
||||
*/
|
||||
struct dmub_rb_cmd_panel_cntl panel_cntl;
|
||||
|
||||
/**
|
||||
* Definition of a DMUB_CMD__ABM_SET_PIPE command.
|
||||
*/
|
||||
@ -4470,10 +4476,6 @@ static inline void dmub_rb_flush_pending(const struct dmub_rb *rb)
|
||||
uint64_t *data = (uint64_t *)((uint8_t *)(rb->base_address) + rptr);
|
||||
uint8_t i;
|
||||
|
||||
/* Don't remove this.
|
||||
* The contents need to actually be read from the ring buffer
|
||||
* for this function to be effective.
|
||||
*/
|
||||
for (i = 0; i < DMUB_RB_CMD_SIZE / sizeof(uint64_t); i++)
|
||||
(void)READ_ONCE(*data++);
|
||||
|
||||
@ -4522,5 +4524,4 @@ static inline void dmub_rb_get_return_data(struct dmub_rb *rb,
|
||||
//==============================================================================
|
||||
//</DMUB_RB>====================================================================
|
||||
//==============================================================================
|
||||
|
||||
#endif /* _DMUB_CMD_H_ */
|
||||
|
@ -491,7 +491,7 @@ int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors senso
|
||||
int amdgpu_dpm_get_apu_thermal_limit(struct amdgpu_device *adev, uint32_t *limit)
|
||||
{
|
||||
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
||||
int ret = -EINVAL;
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
if (pp_funcs && pp_funcs->get_apu_thermal_limit) {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
@ -505,7 +505,7 @@ int amdgpu_dpm_get_apu_thermal_limit(struct amdgpu_device *adev, uint32_t *limit
|
||||
int amdgpu_dpm_set_apu_thermal_limit(struct amdgpu_device *adev, uint32_t limit)
|
||||
{
|
||||
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
||||
int ret = -EINVAL;
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
if (pp_funcs && pp_funcs->set_apu_thermal_limit) {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
@ -1182,7 +1182,7 @@ int amdgpu_dpm_get_sclk_od(struct amdgpu_device *adev)
|
||||
int ret = 0;
|
||||
|
||||
if (!pp_funcs->get_sclk_od)
|
||||
return 0;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
ret = pp_funcs->get_sclk_od(adev->powerplay.pp_handle);
|
||||
@ -1196,7 +1196,7 @@ int amdgpu_dpm_set_sclk_od(struct amdgpu_device *adev, uint32_t value)
|
||||
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return 0;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
if (pp_funcs->set_sclk_od)
|
||||
@ -1219,7 +1219,7 @@ int amdgpu_dpm_get_mclk_od(struct amdgpu_device *adev)
|
||||
int ret = 0;
|
||||
|
||||
if (!pp_funcs->get_mclk_od)
|
||||
return 0;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
ret = pp_funcs->get_mclk_od(adev->powerplay.pp_handle);
|
||||
@ -1233,7 +1233,7 @@ int amdgpu_dpm_set_mclk_od(struct amdgpu_device *adev, uint32_t value)
|
||||
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return 0;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
if (pp_funcs->set_mclk_od)
|
||||
|
@ -989,12 +989,13 @@ static ssize_t amdgpu_get_pp_features(struct device *dev,
|
||||
* Reading back the files will show you the available power levels within
|
||||
* the power state and the clock information for those levels. If deep sleep is
|
||||
* applied to a clock, the level will be denoted by a special level 'S:'
|
||||
* E.g.,
|
||||
* S: 19Mhz *
|
||||
* 0: 615Mhz
|
||||
* 1: 800Mhz
|
||||
* 2: 888Mhz
|
||||
* 3: 1000Mhz
|
||||
* E.g., ::
|
||||
*
|
||||
* S: 19Mhz *
|
||||
* 0: 615Mhz
|
||||
* 1: 800Mhz
|
||||
* 2: 888Mhz
|
||||
* 3: 1000Mhz
|
||||
*
|
||||
*
|
||||
* To manually adjust these states, first select manual using
|
||||
@ -2197,6 +2198,22 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
|
||||
} else if (DEVICE_ATTR_IS(xgmi_plpd_policy)) {
|
||||
if (amdgpu_dpm_get_xgmi_plpd_mode(adev, NULL) == XGMI_PLPD_NONE)
|
||||
*states = ATTR_STATE_UNSUPPORTED;
|
||||
} else if (DEVICE_ATTR_IS(pp_dpm_mclk_od)) {
|
||||
if (amdgpu_dpm_get_mclk_od(adev) == -EOPNOTSUPP)
|
||||
*states = ATTR_STATE_UNSUPPORTED;
|
||||
} else if (DEVICE_ATTR_IS(pp_dpm_sclk_od)) {
|
||||
if (amdgpu_dpm_get_sclk_od(adev) == -EOPNOTSUPP)
|
||||
*states = ATTR_STATE_UNSUPPORTED;
|
||||
} else if (DEVICE_ATTR_IS(apu_thermal_cap)) {
|
||||
u32 limit;
|
||||
|
||||
if (amdgpu_dpm_get_apu_thermal_limit(adev, &limit) ==
|
||||
-EOPNOTSUPP)
|
||||
*states = ATTR_STATE_UNSUPPORTED;
|
||||
} else if (DEVICE_ATTR_IS(pp_dpm_pcie)) {
|
||||
if (gc_ver == IP_VERSION(9, 4, 2) ||
|
||||
gc_ver == IP_VERSION(9, 4, 3))
|
||||
*states = ATTR_STATE_UNSUPPORTED;
|
||||
}
|
||||
|
||||
switch (gc_ver) {
|
||||
|
@ -1711,6 +1711,7 @@ static int smu_disable_dpms(struct smu_context *smu)
|
||||
}
|
||||
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(9, 4, 2) &&
|
||||
!((adev->flags & AMD_IS_APU) && adev->gfx.imu.funcs) &&
|
||||
!amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs->stop)
|
||||
adev->gfx.rlc.funcs->stop(adev);
|
||||
|
||||
@ -2747,7 +2748,7 @@ unlock:
|
||||
|
||||
static int smu_get_apu_thermal_limit(void *handle, uint32_t *limit)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
int ret = -EOPNOTSUPP;
|
||||
struct smu_context *smu = handle;
|
||||
|
||||
if (smu->ppt_funcs && smu->ppt_funcs->get_apu_thermal_limit)
|
||||
@ -2758,7 +2759,7 @@ static int smu_get_apu_thermal_limit(void *handle, uint32_t *limit)
|
||||
|
||||
static int smu_set_apu_thermal_limit(void *handle, uint32_t limit)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
int ret = -EOPNOTSUPP;
|
||||
struct smu_context *smu = handle;
|
||||
|
||||
if (smu->ppt_funcs && smu->ppt_funcs->set_apu_thermal_limit)
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "smu_cmn.h"
|
||||
#include "mp/mp_13_0_6_offset.h"
|
||||
#include "mp/mp_13_0_6_sh_mask.h"
|
||||
#include "umc_v12_0.h"
|
||||
|
||||
#undef MP1_Public
|
||||
#undef smnMP1_FIRMWARE_FLAGS
|
||||
@ -94,22 +95,11 @@ MODULE_FIRMWARE("amdgpu/smu_13_0_6.bin");
|
||||
#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT 0x5
|
||||
#define LINK_SPEED_MAX 4
|
||||
|
||||
#define SMU_13_0_6_DSCLK_THRESHOLD 100
|
||||
#define SMU_13_0_6_DSCLK_THRESHOLD 140
|
||||
|
||||
#define MCA_BANK_IPID(_ip, _hwid, _type) \
|
||||
[AMDGPU_MCA_IP_##_ip] = { .hwid = _hwid, .mcatype = _type, }
|
||||
|
||||
enum mca_reg_idx {
|
||||
MCA_REG_IDX_CONTROL = 0,
|
||||
MCA_REG_IDX_STATUS = 1,
|
||||
MCA_REG_IDX_ADDR = 2,
|
||||
MCA_REG_IDX_MISC0 = 3,
|
||||
MCA_REG_IDX_CONFIG = 4,
|
||||
MCA_REG_IDX_IPID = 5,
|
||||
MCA_REG_IDX_SYND = 6,
|
||||
MCA_REG_IDX_COUNT = 16,
|
||||
};
|
||||
|
||||
struct mca_bank_ipid {
|
||||
enum amdgpu_mca_ip ip;
|
||||
uint16_t hwid;
|
||||
@ -122,7 +112,9 @@ struct mca_ras_info {
|
||||
int *err_code_array;
|
||||
int err_code_count;
|
||||
int (*get_err_count)(const struct mca_ras_info *mca_ras, struct amdgpu_device *adev,
|
||||
enum amdgpu_mca_error_type type, int idx, uint32_t *count);
|
||||
enum amdgpu_mca_error_type type, struct mca_bank_entry *entry, uint32_t *count);
|
||||
bool (*bank_is_valid)(const struct mca_ras_info *mca_ras, struct amdgpu_device *adev,
|
||||
enum amdgpu_mca_error_type type, struct mca_bank_entry *entry);
|
||||
};
|
||||
|
||||
#define P2S_TABLE_ID_A 0x50325341
|
||||
@ -2305,7 +2297,7 @@ static int smu_v13_0_6_post_init(struct smu_context *smu)
|
||||
struct amdgpu_device *adev = smu->adev;
|
||||
|
||||
if (!amdgpu_sriov_vf(adev) && adev->ras_enabled)
|
||||
return smu_v13_0_6_mca_set_debug_mode(smu, true);
|
||||
return smu_v13_0_6_mca_set_debug_mode(smu, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2387,6 +2379,7 @@ static const struct mca_bank_ipid smu_v13_0_6_mca_ipid_table[AMDGPU_MCA_IP_COUNT
|
||||
MCA_BANK_IPID(UMC, 0x96, 0x0),
|
||||
MCA_BANK_IPID(SMU, 0x01, 0x1),
|
||||
MCA_BANK_IPID(MP5, 0x01, 0x2),
|
||||
MCA_BANK_IPID(PCS_XGMI, 0x50, 0x0),
|
||||
};
|
||||
|
||||
static void mca_bank_entry_info_decode(struct mca_bank_entry *entry, struct mca_bank_info *info)
|
||||
@ -2448,53 +2441,60 @@ static int mca_get_mca_entry(struct amdgpu_device *adev, enum amdgpu_mca_error_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mca_decode_mca_ipid(struct amdgpu_device *adev, enum amdgpu_mca_error_type type, int idx, int *ip)
|
||||
static int mca_decode_ipid_to_hwip(uint64_t val)
|
||||
{
|
||||
const struct mca_bank_ipid *ipid;
|
||||
uint64_t val;
|
||||
uint16_t hwid, mcatype;
|
||||
int i, ret;
|
||||
|
||||
ret = mca_bank_read_reg(adev, type, idx, MCA_REG_IDX_IPID, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
int i;
|
||||
|
||||
hwid = REG_GET_FIELD(val, MCMP1_IPIDT0, HardwareID);
|
||||
mcatype = REG_GET_FIELD(val, MCMP1_IPIDT0, McaType);
|
||||
|
||||
if (hwid) {
|
||||
for (i = 0; i < ARRAY_SIZE(smu_v13_0_6_mca_ipid_table); i++) {
|
||||
ipid = &smu_v13_0_6_mca_ipid_table[i];
|
||||
for (i = 0; i < ARRAY_SIZE(smu_v13_0_6_mca_ipid_table); i++) {
|
||||
ipid = &smu_v13_0_6_mca_ipid_table[i];
|
||||
|
||||
if (!ipid->hwid)
|
||||
continue;
|
||||
if (!ipid->hwid)
|
||||
continue;
|
||||
|
||||
if (ipid->hwid == hwid && ipid->mcatype == mcatype) {
|
||||
*ip = i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (ipid->hwid == hwid && ipid->mcatype == mcatype)
|
||||
return i;
|
||||
}
|
||||
|
||||
*ip = AMDGPU_MCA_IP_UNKNOW;
|
||||
return AMDGPU_MCA_IP_UNKNOW;
|
||||
}
|
||||
|
||||
static int mca_umc_mca_get_err_count(const struct mca_ras_info *mca_ras, struct amdgpu_device *adev,
|
||||
enum amdgpu_mca_error_type type, struct mca_bank_entry *entry, uint32_t *count)
|
||||
{
|
||||
uint64_t status0;
|
||||
|
||||
status0 = entry->regs[MCA_REG_IDX_STATUS];
|
||||
|
||||
if (!REG_GET_FIELD(status0, MCMP1_STATUST0, Val)) {
|
||||
*count = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (type == AMDGPU_MCA_ERROR_TYPE_UE && umc_v12_0_is_uncorrectable_error(status0))
|
||||
*count = 1;
|
||||
else if (type == AMDGPU_MCA_ERROR_TYPE_CE && umc_v12_0_is_correctable_error(status0))
|
||||
*count = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mca_normal_mca_get_err_count(const struct mca_ras_info *mca_ras, struct amdgpu_device *adev,
|
||||
enum amdgpu_mca_error_type type, int idx, uint32_t *count)
|
||||
static int mca_pcs_xgmi_mca_get_err_count(const struct mca_ras_info *mca_ras, struct amdgpu_device *adev,
|
||||
enum amdgpu_mca_error_type type, struct mca_bank_entry *entry,
|
||||
uint32_t *count)
|
||||
{
|
||||
uint64_t status0;
|
||||
int ret;
|
||||
u32 ext_error_code;
|
||||
|
||||
ret = mca_bank_read_reg(adev, type, idx, MCA_REG_IDX_STATUS, &status0);
|
||||
if (ret)
|
||||
return ret;
|
||||
ext_error_code = MCA_REG__STATUS__ERRORCODEEXT(entry->regs[MCA_REG_IDX_STATUS]);
|
||||
|
||||
if (REG_GET_FIELD(status0, MCMP1_STATUST0, Val))
|
||||
if (type == AMDGPU_MCA_ERROR_TYPE_UE && ext_error_code == 0)
|
||||
*count = 1;
|
||||
else if (type == AMDGPU_MCA_ERROR_TYPE_CE && ext_error_code == 6)
|
||||
*count = 1;
|
||||
else
|
||||
*count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2515,70 +2515,41 @@ static bool mca_smu_check_error_code(struct amdgpu_device *adev, const struct mc
|
||||
return false;
|
||||
}
|
||||
|
||||
static int mca_mp5_mca_get_err_count(const struct mca_ras_info *mca_ras, struct amdgpu_device *adev,
|
||||
enum amdgpu_mca_error_type type, int idx, uint32_t *count)
|
||||
static int mca_gfx_mca_get_err_count(const struct mca_ras_info *mca_ras, struct amdgpu_device *adev,
|
||||
enum amdgpu_mca_error_type type, struct mca_bank_entry *entry, uint32_t *count)
|
||||
{
|
||||
uint64_t status0 = 0, misc0 = 0;
|
||||
uint32_t errcode;
|
||||
int ret;
|
||||
|
||||
if (mca_ras->ip != AMDGPU_MCA_IP_MP5)
|
||||
return -EINVAL;
|
||||
|
||||
ret = mca_bank_read_reg(adev, type, idx, MCA_REG_IDX_STATUS, &status0);
|
||||
if (ret)
|
||||
return ret;
|
||||
uint64_t status0, misc0;
|
||||
|
||||
status0 = entry->regs[MCA_REG_IDX_STATUS];
|
||||
if (!REG_GET_FIELD(status0, MCMP1_STATUST0, Val)) {
|
||||
*count = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode = REG_GET_FIELD(status0, MCMP1_STATUST0, ErrorCode);
|
||||
if (!mca_smu_check_error_code(adev, mca_ras, errcode))
|
||||
return 0;
|
||||
|
||||
if (type == AMDGPU_MCA_ERROR_TYPE_UE &&
|
||||
REG_GET_FIELD(status0, MCMP1_STATUST0, UC) == 1 &&
|
||||
REG_GET_FIELD(status0, MCMP1_STATUST0, PCC) == 1) {
|
||||
if (count)
|
||||
*count = 1;
|
||||
*count = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = mca_bank_read_reg(adev, type, idx, MCA_REG_IDX_MISC0, &misc0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (count)
|
||||
} else {
|
||||
misc0 = entry->regs[MCA_REG_IDX_MISC0];
|
||||
*count = REG_GET_FIELD(misc0, MCMP1_MISC0T0, ErrCnt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mca_smu_mca_get_err_count(const struct mca_ras_info *mca_ras, struct amdgpu_device *adev,
|
||||
enum amdgpu_mca_error_type type, int idx, uint32_t *count)
|
||||
enum amdgpu_mca_error_type type, struct mca_bank_entry *entry, uint32_t *count)
|
||||
{
|
||||
uint64_t status0 = 0, misc0 = 0;
|
||||
uint32_t errcode;
|
||||
int ret;
|
||||
|
||||
if (mca_ras->ip != AMDGPU_MCA_IP_SMU)
|
||||
return -EINVAL;
|
||||
|
||||
ret = mca_bank_read_reg(adev, type, idx, MCA_REG_IDX_STATUS, &status0);
|
||||
if (ret)
|
||||
return ret;
|
||||
uint64_t status0, misc0;
|
||||
|
||||
status0 = entry->regs[MCA_REG_IDX_STATUS];
|
||||
if (!REG_GET_FIELD(status0, MCMP1_STATUST0, Val)) {
|
||||
*count = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
errcode = REG_GET_FIELD(status0, MCMP1_STATUST0, ErrorCode);
|
||||
if (!mca_smu_check_error_code(adev, mca_ras, errcode))
|
||||
return 0;
|
||||
|
||||
if (type == AMDGPU_MCA_ERROR_TYPE_UE &&
|
||||
REG_GET_FIELD(status0, MCMP1_STATUST0, UC) == 1 &&
|
||||
REG_GET_FIELD(status0, MCMP1_STATUST0, PCC) == 1) {
|
||||
@ -2587,16 +2558,43 @@ static int mca_smu_mca_get_err_count(const struct mca_ras_info *mca_ras, struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = mca_bank_read_reg(adev, type, idx, MCA_REG_IDX_MISC0, &misc0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (count)
|
||||
*count = REG_GET_FIELD(misc0, MCMP1_MISC0T0, ErrCnt);
|
||||
misc0 = entry->regs[MCA_REG_IDX_MISC0];
|
||||
*count = REG_GET_FIELD(misc0, MCMP1_MISC0T0, ErrCnt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool mca_gfx_smu_bank_is_valid(const struct mca_ras_info *mca_ras, struct amdgpu_device *adev,
|
||||
enum amdgpu_mca_error_type type, struct mca_bank_entry *entry)
|
||||
{
|
||||
uint32_t instlo;
|
||||
|
||||
instlo = REG_GET_FIELD(entry->regs[MCA_REG_IDX_IPID], MCMP1_IPIDT0, InstanceIdLo);
|
||||
switch (instlo) {
|
||||
case 0x36430400: /* SMNAID XCD 0 */
|
||||
case 0x38430400: /* SMNAID XCD 1 */
|
||||
case 0x40430400: /* SMNXCD XCD 0, NOTE: FIXME: fix this error later */
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
static bool mca_smu_bank_is_valid(const struct mca_ras_info *mca_ras, struct amdgpu_device *adev,
|
||||
enum amdgpu_mca_error_type type, struct mca_bank_entry *entry)
|
||||
{
|
||||
uint32_t errcode, instlo;
|
||||
|
||||
instlo = REG_GET_FIELD(entry->regs[MCA_REG_IDX_IPID], MCMP1_IPIDT0, InstanceIdLo);
|
||||
if (instlo != 0x03b30400)
|
||||
return false;
|
||||
|
||||
errcode = REG_GET_FIELD(entry->regs[MCA_REG_IDX_STATUS], MCMP1_STATUST0, ErrorCode);
|
||||
return mca_smu_check_error_code(adev, mca_ras, errcode);
|
||||
}
|
||||
|
||||
static int sdma_err_codes[] = { CODE_SDMA0, CODE_SDMA1, CODE_SDMA2, CODE_SDMA3 };
|
||||
static int mmhub_err_codes[] = {
|
||||
CODE_DAGB0, CODE_DAGB0 + 1, CODE_DAGB0 + 2, CODE_DAGB0 + 3, CODE_DAGB0 + 4, /* DAGB0-4 */
|
||||
@ -2608,23 +2606,30 @@ static const struct mca_ras_info mca_ras_table[] = {
|
||||
{
|
||||
.blkid = AMDGPU_RAS_BLOCK__UMC,
|
||||
.ip = AMDGPU_MCA_IP_UMC,
|
||||
.get_err_count = mca_normal_mca_get_err_count,
|
||||
.get_err_count = mca_umc_mca_get_err_count,
|
||||
}, {
|
||||
.blkid = AMDGPU_RAS_BLOCK__GFX,
|
||||
.ip = AMDGPU_MCA_IP_MP5,
|
||||
.get_err_count = mca_mp5_mca_get_err_count,
|
||||
.ip = AMDGPU_MCA_IP_SMU,
|
||||
.get_err_count = mca_gfx_mca_get_err_count,
|
||||
.bank_is_valid = mca_gfx_smu_bank_is_valid,
|
||||
}, {
|
||||
.blkid = AMDGPU_RAS_BLOCK__SDMA,
|
||||
.ip = AMDGPU_MCA_IP_SMU,
|
||||
.err_code_array = sdma_err_codes,
|
||||
.err_code_count = ARRAY_SIZE(sdma_err_codes),
|
||||
.get_err_count = mca_smu_mca_get_err_count,
|
||||
.bank_is_valid = mca_smu_bank_is_valid,
|
||||
}, {
|
||||
.blkid = AMDGPU_RAS_BLOCK__MMHUB,
|
||||
.ip = AMDGPU_MCA_IP_SMU,
|
||||
.err_code_array = mmhub_err_codes,
|
||||
.err_code_count = ARRAY_SIZE(mmhub_err_codes),
|
||||
.get_err_count = mca_smu_mca_get_err_count,
|
||||
.bank_is_valid = mca_smu_bank_is_valid,
|
||||
}, {
|
||||
.blkid = AMDGPU_RAS_BLOCK__XGMI_WAFL,
|
||||
.ip = AMDGPU_MCA_IP_PCS_XGMI,
|
||||
.get_err_count = mca_pcs_xgmi_mca_get_err_count,
|
||||
},
|
||||
};
|
||||
|
||||
@ -2659,130 +2664,84 @@ static int mca_get_valid_mca_count(struct amdgpu_device *adev, enum amdgpu_mca_e
|
||||
}
|
||||
|
||||
static bool mca_bank_is_valid(struct amdgpu_device *adev, const struct mca_ras_info *mca_ras,
|
||||
enum amdgpu_mca_error_type type, int idx)
|
||||
enum amdgpu_mca_error_type type, struct mca_bank_entry *entry)
|
||||
{
|
||||
int ret, ip = AMDGPU_MCA_IP_UNKNOW;
|
||||
|
||||
ret = mca_decode_mca_ipid(adev, type, idx, &ip);
|
||||
if (ret)
|
||||
if (mca_decode_ipid_to_hwip(entry->regs[MCA_REG_IDX_IPID]) != mca_ras->ip)
|
||||
return false;
|
||||
|
||||
if (ip == AMDGPU_MCA_IP_UNKNOW)
|
||||
return false;
|
||||
if (mca_ras->bank_is_valid)
|
||||
return mca_ras->bank_is_valid(mca_ras, adev, type, entry);
|
||||
|
||||
return ip == mca_ras->ip;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int mca_get_valid_mca_idx(struct amdgpu_device *adev, const struct mca_ras_info *mca_ras,
|
||||
enum amdgpu_mca_error_type type,
|
||||
uint32_t mca_cnt, int *idx_array, int idx_array_size)
|
||||
static int __mca_smu_get_ras_mca_set(struct amdgpu_device *adev, const struct mca_ras_info *mca_ras,
|
||||
enum amdgpu_mca_error_type type, struct mca_bank_set *mca_set)
|
||||
{
|
||||
int i, idx_cnt = 0;
|
||||
|
||||
for (i = 0; i < mca_cnt; i++) {
|
||||
if (!mca_bank_is_valid(adev, mca_ras, type, i))
|
||||
continue;
|
||||
|
||||
if (idx_array) {
|
||||
if (idx_cnt < idx_array_size)
|
||||
idx_array[idx_cnt] = i;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
idx_cnt++;
|
||||
}
|
||||
|
||||
return idx_cnt;
|
||||
}
|
||||
|
||||
static int __mca_smu_get_error_count(struct amdgpu_device *adev, const struct mca_ras_info *mca_ras, enum amdgpu_mca_error_type type, uint32_t *count)
|
||||
{
|
||||
uint32_t result, mca_cnt, total = 0;
|
||||
int idx_array[16];
|
||||
int i, ret, idx_cnt = 0;
|
||||
struct mca_bank_entry entry;
|
||||
uint32_t mca_cnt;
|
||||
int i, ret;
|
||||
|
||||
ret = mca_get_valid_mca_count(adev, type, &mca_cnt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* if valid mca bank count is 0, the driver can return 0 directly */
|
||||
if (!mca_cnt) {
|
||||
if (!mca_cnt)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < mca_cnt; i++) {
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
ret = mca_get_mca_entry(adev, type, i, &entry);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (mca_ras && !mca_bank_is_valid(adev, mca_ras, type, &entry))
|
||||
continue;
|
||||
|
||||
ret = amdgpu_mca_bank_set_add_entry(mca_set, &entry);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mca_smu_get_ras_mca_set(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
|
||||
enum amdgpu_mca_error_type type, struct mca_bank_set *mca_set)
|
||||
{
|
||||
const struct mca_ras_info *mca_ras = NULL;
|
||||
|
||||
if (!mca_set)
|
||||
return -EINVAL;
|
||||
|
||||
if (blk != AMDGPU_RAS_BLOCK_COUNT) {
|
||||
mca_ras = mca_get_mca_ras_info(adev, blk);
|
||||
if (!mca_ras)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return __mca_smu_get_ras_mca_set(adev, mca_ras, type, mca_set);
|
||||
}
|
||||
|
||||
static int mca_smu_parse_mca_error_count(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type,
|
||||
struct mca_bank_entry *entry, uint32_t *count)
|
||||
{
|
||||
const struct mca_ras_info *mca_ras;
|
||||
|
||||
if (!entry || !count)
|
||||
return -EINVAL;
|
||||
|
||||
mca_ras = mca_get_mca_ras_info(adev, blk);
|
||||
if (!mca_ras)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!mca_bank_is_valid(adev, mca_ras, type, entry)) {
|
||||
*count = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!mca_ras->get_err_count)
|
||||
return -EINVAL;
|
||||
|
||||
idx_cnt = mca_get_valid_mca_idx(adev, mca_ras, type, mca_cnt, idx_array, ARRAY_SIZE(idx_array));
|
||||
if (idx_cnt < 0)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < idx_cnt; i++) {
|
||||
result = 0;
|
||||
ret = mca_ras->get_err_count(mca_ras, adev, type, idx_array[i], &result);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
total += result;
|
||||
}
|
||||
|
||||
*count = total;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mca_smu_get_error_count(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
|
||||
enum amdgpu_mca_error_type type, uint32_t *count)
|
||||
{
|
||||
const struct mca_ras_info *mca_ras;
|
||||
|
||||
if (!count)
|
||||
return -EINVAL;
|
||||
|
||||
mca_ras = mca_get_mca_ras_info(adev, blk);
|
||||
if (!mca_ras)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return __mca_smu_get_error_count(adev, mca_ras, type, count);
|
||||
}
|
||||
|
||||
static int __mca_smu_get_ras_mca_idx_array(struct amdgpu_device *adev, const struct mca_ras_info *mca_ras,
|
||||
enum amdgpu_mca_error_type type, int *idx_array, int *idx_array_size)
|
||||
{
|
||||
uint32_t mca_cnt = 0;
|
||||
int ret, idx_cnt = 0;
|
||||
|
||||
ret = mca_get_valid_mca_count(adev, type, &mca_cnt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* if valid mca bank count is 0, the driver can return 0 directly */
|
||||
if (!mca_cnt) {
|
||||
*idx_array_size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
idx_cnt = mca_get_valid_mca_idx(adev, mca_ras, type, mca_cnt, idx_array, *idx_array_size);
|
||||
if (idx_cnt < 0)
|
||||
return -EINVAL;
|
||||
|
||||
*idx_array_size = idx_cnt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mca_smu_get_ras_mca_idx_array(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
|
||||
enum amdgpu_mca_error_type type, int *idx_array, int *idx_array_size)
|
||||
{
|
||||
const struct mca_ras_info *mca_ras;
|
||||
|
||||
mca_ras = mca_get_mca_ras_info(adev, blk);
|
||||
if (!mca_ras)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return __mca_smu_get_ras_mca_idx_array(adev, mca_ras, type, idx_array, idx_array_size);
|
||||
return mca_ras->get_err_count(mca_ras, adev, type, entry, count);
|
||||
}
|
||||
|
||||
static int mca_smu_get_mca_entry(struct amdgpu_device *adev,
|
||||
@ -2801,10 +2760,10 @@ static const struct amdgpu_mca_smu_funcs smu_v13_0_6_mca_smu_funcs = {
|
||||
.max_ue_count = 12,
|
||||
.max_ce_count = 12,
|
||||
.mca_set_debug_mode = mca_smu_set_debug_mode,
|
||||
.mca_get_error_count = mca_smu_get_error_count,
|
||||
.mca_get_ras_mca_set = mca_smu_get_ras_mca_set,
|
||||
.mca_parse_mca_error_count = mca_smu_parse_mca_error_count,
|
||||
.mca_get_mca_entry = mca_smu_get_mca_entry,
|
||||
.mca_get_valid_mca_count = mca_smu_get_valid_mca_count,
|
||||
.mca_get_ras_mca_idx_array = mca_smu_get_ras_mca_idx_array,
|
||||
};
|
||||
|
||||
static int smu_v13_0_6_select_xgmi_plpd_policy(struct smu_context *smu,
|
||||
|
Loading…
Reference in New Issue
Block a user