Merge tag 'amd-drm-next-6.2-2022-11-04' of https://gitlab.freedesktop.org/agd5f/linux into drm-next

amd-drm-next-6.2-2022-11-04:

amdgpu:
- Add TMZ support for GC 11.0.1
- More IP version check conversions
- Mode2 reset fixes for sienna cichlid
- SMU 13.x fixes
- RAS enablement on MP 13.x
- Replace kmap with kmap_local_page()
- Misc Clang warning fixes
- SR-IOV fixes for GC 11.x
- PCI AER fix
- DCN 3.2.x commit sequence rework
- SDMA 4.x doorbell fix
- Expose additional new GC 11.x firmware versions
- Misc code cleanups
- S0i3 fixes
- More DC FPU cleanup
- Add more DC kerneldoc
- Misc spelling and grammer fixes
- DCN 3.1.x fixes
- Plane modifier fix
- MCA RAS enablement
- Secure display locking fix
- RAS TA rework
- RAS EEPROM fixes
- Fail suspend if eviction fails
- Drop AMD specific DSC workarounds in favor of drm EDID quirks
- SR-IOV suspend/resume fixes
- Enable DCN support for ARM
- Enable secure display on DCN 2.1

amdkfd:
- Cache size fixes for GC 10.3.x
- kfd_dev struct cleanup
- GC11.x CWSR trap handler fix
- Userptr fixes
- Warning fixes

radeon:
- Replace kmap with kmap_local_page()

UAPI:
- Expose additional new GC 11.x firmware versions via the existing INFO query

drm:
- Add some new EDID DSC quirks

Signed-off-by: Dave Airlie <airlied@redhat.com>

# Conflicts:
#	drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221104205827.6008-1-alexander.deucher@amd.com
This commit is contained in:
Dave Airlie
2022-11-08 16:32:31 +10:00
164 changed files with 3215 additions and 2377 deletions

View File

@@ -219,10 +219,12 @@ extern int amdgpu_use_xgmi_p2p;
extern int sched_policy; extern int sched_policy;
extern bool debug_evictions; extern bool debug_evictions;
extern bool no_system_mem_limit; extern bool no_system_mem_limit;
extern int halt_if_hws_hang;
#else #else
static const int __maybe_unused sched_policy = KFD_SCHED_POLICY_HWS; static const int __maybe_unused sched_policy = KFD_SCHED_POLICY_HWS;
static const bool __maybe_unused debug_evictions; /* = false */ static const bool __maybe_unused debug_evictions; /* = false */
static const bool __maybe_unused no_system_mem_limit; static const bool __maybe_unused no_system_mem_limit;
static const int __maybe_unused halt_if_hws_hang;
#endif #endif
#ifdef CONFIG_HSA_AMD_P2P #ifdef CONFIG_HSA_AMD_P2P
extern bool pcie_p2p; extern bool pcie_p2p;
@@ -675,7 +677,7 @@ enum amd_hw_ip_block_type {
MAX_HWIP MAX_HWIP
}; };
#define HWIP_MAX_INSTANCE 11 #define HWIP_MAX_INSTANCE 28
#define HW_ID_MAX 300 #define HW_ID_MAX 300
#define IP_VERSION(mj, mn, rv) (((mj) << 16) | ((mn) << 8) | (rv)) #define IP_VERSION(mj, mn, rv) (((mj) << 16) | ((mn) << 8) | (rv))

View File

@@ -195,7 +195,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
} }
adev->kfd.init_complete = kgd2kfd_device_init(adev->kfd.dev, adev->kfd.init_complete = kgd2kfd_device_init(adev->kfd.dev,
adev_to_drm(adev), &gpu_resources); &gpu_resources);
amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size; amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size;
@@ -706,6 +706,13 @@ err:
void amdgpu_amdkfd_set_compute_idle(struct amdgpu_device *adev, bool idle) void amdgpu_amdkfd_set_compute_idle(struct amdgpu_device *adev, bool idle)
{ {
/* Temporary workaround to fix issues observed in some
* compute applications when GFXOFF is enabled on GFX11.
*/
if (IP_VERSION_MAJ(adev->ip_versions[GC_HWIP][0]) == 11) {
pr_debug("GFXOFF is %s\n", idle ? "enabled" : "disabled");
amdgpu_gfx_off_ctrl(adev, idle);
}
amdgpu_dpm_switch_power_profile(adev, amdgpu_dpm_switch_power_profile(adev,
PP_SMC_POWER_PROFILE_COMPUTE, PP_SMC_POWER_PROFILE_COMPUTE,
!idle); !idle);
@@ -753,9 +760,7 @@ bool amdgpu_amdkfd_have_atomics_support(struct amdgpu_device *adev)
void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev, bool reset) void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev, bool reset)
{ {
struct ras_err_data err_data = {0, 0, 0, NULL}; amdgpu_umc_poison_handler(adev, reset);
amdgpu_umc_poison_handler(adev, &err_data, reset);
} }
bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev) bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev)

View File

@@ -353,7 +353,6 @@ int kgd2kfd_init(void);
void kgd2kfd_exit(void); void kgd2kfd_exit(void);
struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf); struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf);
bool kgd2kfd_device_init(struct kfd_dev *kfd, bool kgd2kfd_device_init(struct kfd_dev *kfd,
struct drm_device *ddev,
const struct kgd2kfd_shared_resources *gpu_resources); const struct kgd2kfd_shared_resources *gpu_resources);
void kgd2kfd_device_exit(struct kfd_dev *kfd); void kgd2kfd_device_exit(struct kfd_dev *kfd);
void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm); void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm);
@@ -381,7 +380,7 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
} }
static inline static inline
bool kgd2kfd_device_init(struct kfd_dev *kfd, struct drm_device *ddev, bool kgd2kfd_device_init(struct kfd_dev *kfd,
const struct kgd2kfd_shared_resources *gpu_resources) const struct kgd2kfd_shared_resources *gpu_resources)
{ {
return false; return false;

View File

@@ -787,7 +787,7 @@ void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
for (se_idx = 0; se_idx < se_cnt; se_idx++) { for (se_idx = 0; se_idx < se_cnt; se_idx++) {
for (sh_idx = 0; sh_idx < sh_cnt; sh_idx++) { for (sh_idx = 0; sh_idx < sh_cnt; sh_idx++) {
gfx_v9_0_select_se_sh(adev, se_idx, sh_idx, 0xffffffff); amdgpu_gfx_select_se_sh(adev, se_idx, sh_idx, 0xffffffff);
queue_map = RREG32_SOC15(GC, 0, mmSPI_CSQ_WF_ACTIVE_STATUS); queue_map = RREG32_SOC15(GC, 0, mmSPI_CSQ_WF_ACTIVE_STATUS);
/* /*
@@ -820,7 +820,7 @@ void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
} }
} }
gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
soc15_grbm_select(adev, 0, 0, 0, 0); soc15_grbm_select(adev, 0, 0, 0, 0);
unlock_spi_csq_mutexes(adev); unlock_spi_csq_mutexes(adev);

View File

@@ -418,9 +418,9 @@ static uint64_t get_pte_flags(struct amdgpu_device *adev, struct kgd_mem *mem)
if (mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_EXECUTABLE) if (mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_EXECUTABLE)
mapping_flags |= AMDGPU_VM_PAGE_EXECUTABLE; mapping_flags |= AMDGPU_VM_PAGE_EXECUTABLE;
switch (adev->asic_type) { switch (adev->ip_versions[GC_HWIP][0]) {
case CHIP_ARCTURUS: case IP_VERSION(9, 4, 1):
case CHIP_ALDEBARAN: case IP_VERSION(9, 4, 2):
if (mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { if (mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) {
if (bo_adev == adev) { if (bo_adev == adev) {
if (uncached) if (uncached)
@@ -429,7 +429,7 @@ static uint64_t get_pte_flags(struct amdgpu_device *adev, struct kgd_mem *mem)
mapping_flags |= AMDGPU_VM_MTYPE_CC; mapping_flags |= AMDGPU_VM_MTYPE_CC;
else else
mapping_flags |= AMDGPU_VM_MTYPE_RW; mapping_flags |= AMDGPU_VM_MTYPE_RW;
if (adev->asic_type == CHIP_ALDEBARAN && if ((adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2)) &&
adev->gmc.xgmi.connected_to_cpu) adev->gmc.xgmi.connected_to_cpu)
snoop = true; snoop = true;
} else { } else {
@@ -510,13 +510,13 @@ kfd_mem_dmamap_userptr(struct kgd_mem *mem,
struct ttm_tt *ttm = bo->tbo.ttm; struct ttm_tt *ttm = bo->tbo.ttm;
int ret; int ret;
if (WARN_ON(ttm->num_pages != src_ttm->num_pages))
return -EINVAL;
ttm->sg = kmalloc(sizeof(*ttm->sg), GFP_KERNEL); ttm->sg = kmalloc(sizeof(*ttm->sg), GFP_KERNEL);
if (unlikely(!ttm->sg)) if (unlikely(!ttm->sg))
return -ENOMEM; return -ENOMEM;
if (WARN_ON(ttm->num_pages != src_ttm->num_pages))
return -EINVAL;
/* Same sequence as in amdgpu_ttm_tt_pin_userptr */ /* Same sequence as in amdgpu_ttm_tt_pin_userptr */
ret = sg_alloc_table_from_pages(ttm->sg, src_ttm->pages, ret = sg_alloc_table_from_pages(ttm->sg, src_ttm->pages,
ttm->num_pages, 0, ttm->num_pages, 0,
@@ -1907,16 +1907,6 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
*/ */
mutex_lock(&mem->process_info->lock); mutex_lock(&mem->process_info->lock);
/* Lock mmap-sem. If we find an invalid userptr BO, we can be
* sure that the MMU notifier is no longer running
* concurrently and the queues are actually stopped
*/
if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm)) {
mmap_write_lock(current->mm);
is_invalid_userptr = atomic_read(&mem->invalid);
mmap_write_unlock(current->mm);
}
mutex_lock(&mem->lock); mutex_lock(&mem->lock);
domain = mem->domain; domain = mem->domain;

View File

@@ -326,7 +326,10 @@ static int amdgpu_ctx_init(struct amdgpu_ctx_mgr *mgr, int32_t priority,
if (r) if (r)
return r; return r;
ctx->stable_pstate = current_stable_pstate; if (mgr->adev->pm.stable_pstate_ctx)
ctx->stable_pstate = mgr->adev->pm.stable_pstate_ctx->stable_pstate;
else
ctx->stable_pstate = current_stable_pstate;
return 0; return 0;
} }

View File

@@ -1568,7 +1568,7 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev)
* @pdev: pci dev pointer * @pdev: pci dev pointer
* @state: vga_switcheroo state * @state: vga_switcheroo state
* *
* Callback for the switcheroo driver. Suspends or resumes the * Callback for the switcheroo driver. Suspends or resumes
* the asics before or after it is powered up using ACPI methods. * the asics before or after it is powered up using ACPI methods.
*/ */
static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, static void amdgpu_switcheroo_set_state(struct pci_dev *pdev,
@@ -2397,7 +2397,7 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
adev->ip_blocks[i].status.hw = true; adev->ip_blocks[i].status.hw = true;
/* right after GMC hw init, we create CSA */ /* right after GMC hw init, we create CSA */
if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) { if (amdgpu_mcbp) {
r = amdgpu_allocate_static_csa(adev, &adev->virt.csa_obj, r = amdgpu_allocate_static_csa(adev, &adev->virt.csa_obj,
AMDGPU_GEM_DOMAIN_VRAM, AMDGPU_GEM_DOMAIN_VRAM,
AMDGPU_CSA_SIZE); AMDGPU_CSA_SIZE);
@@ -3210,6 +3210,15 @@ static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev)
return r; return r;
} }
adev->ip_blocks[i].status.hw = true; adev->ip_blocks[i].status.hw = true;
if (adev->in_s0ix && adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
/* disable gfxoff for IP resume. The gfxoff will be re-enabled in
* amdgpu_device_resume() after IP resume.
*/
amdgpu_gfx_off_ctrl(adev, false);
DRM_DEBUG("will disable gfxoff for re-initializing other blocks\n");
}
} }
return 0; return 0;
@@ -4051,15 +4060,18 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
* at suspend time. * at suspend time.
* *
*/ */
static void amdgpu_device_evict_resources(struct amdgpu_device *adev) static int amdgpu_device_evict_resources(struct amdgpu_device *adev)
{ {
int ret;
/* No need to evict vram on APUs for suspend to ram or s2idle */ /* No need to evict vram on APUs for suspend to ram or s2idle */
if ((adev->in_s3 || adev->in_s0ix) && (adev->flags & AMD_IS_APU)) if ((adev->in_s3 || adev->in_s0ix) && (adev->flags & AMD_IS_APU))
return; return 0;
if (amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM)) ret = amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM);
if (ret)
DRM_WARN("evicting device resources failed\n"); DRM_WARN("evicting device resources failed\n");
return ret;
} }
/* /*
@@ -4109,7 +4121,9 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
if (!adev->in_s0ix) if (!adev->in_s0ix)
amdgpu_amdkfd_suspend(adev, adev->in_runpm); amdgpu_amdkfd_suspend(adev, adev->in_runpm);
amdgpu_device_evict_resources(adev); r = amdgpu_device_evict_resources(adev);
if (r)
return r;
amdgpu_fence_driver_hw_fini(adev); amdgpu_fence_driver_hw_fini(adev);
@@ -4183,8 +4197,17 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
} }
/* Make sure IB tests flushed */ /* Make sure IB tests flushed */
if (amdgpu_sriov_vf(adev))
amdgpu_irq_gpu_reset_resume_helper(adev);
flush_delayed_work(&adev->delayed_init_work); flush_delayed_work(&adev->delayed_init_work);
if (adev->in_s0ix) {
/* re-enable gfxoff after IP resume. This re-enables gfxoff after
* it was disabled for IP resume in amdgpu_device_ip_resume_phase2().
*/
amdgpu_gfx_off_ctrl(adev, true);
DRM_DEBUG("will enable gfxoff for the mission mode\n");
}
if (fbcon) if (fbcon)
drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, false); drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, false);
@@ -5381,7 +5404,7 @@ skip_hw_reset:
drm_sched_start(&ring->sched, !tmp_adev->asic_reset_res); drm_sched_start(&ring->sched, !tmp_adev->asic_reset_res);
} }
if (adev->enable_mes) if (adev->enable_mes && adev->ip_versions[GC_HWIP][0] != IP_VERSION(11, 0, 3))
amdgpu_mes_self_test(tmp_adev); amdgpu_mes_self_test(tmp_adev);
if (!drm_drv_uses_atomic_modeset(adev_to_drm(tmp_adev)) && !job_signaled) { if (!drm_drv_uses_atomic_modeset(adev_to_drm(tmp_adev)) && !job_signaled) {

View File

@@ -2201,7 +2201,8 @@ amdgpu_pci_remove(struct pci_dev *pdev)
pm_runtime_forbid(dev->dev); pm_runtime_forbid(dev->dev);
} }
if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2)) { if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2) &&
!amdgpu_sriov_vf(adev)) {
bool need_to_reset_gpu = false; bool need_to_reset_gpu = false;
if (adev->gmc.xgmi.num_physical_nodes > 1) { if (adev->gmc.xgmi.num_physical_nodes > 1) {

View File

@@ -542,6 +542,7 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev)
case IP_VERSION(10, 3, 1): case IP_VERSION(10, 3, 1):
/* YELLOW_CARP*/ /* YELLOW_CARP*/
case IP_VERSION(10, 3, 3): case IP_VERSION(10, 3, 3):
case IP_VERSION(11, 0, 1):
/* Don't enable it by default yet. /* Don't enable it by default yet.
*/ */
if (amdgpu_tmz < 1) { if (amdgpu_tmz < 1) {

View File

@@ -337,11 +337,17 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
fw_info->feature = adev->psp.cap_feature_version; fw_info->feature = adev->psp.cap_feature_version;
break; break;
case AMDGPU_INFO_FW_MES_KIQ: case AMDGPU_INFO_FW_MES_KIQ:
fw_info->ver = adev->mes.ucode_fw_version[0]; fw_info->ver = adev->mes.kiq_version & AMDGPU_MES_VERSION_MASK;
fw_info->feature = 0; fw_info->feature = (adev->mes.kiq_version & AMDGPU_MES_FEAT_VERSION_MASK)
>> AMDGPU_MES_FEAT_VERSION_SHIFT;
break; break;
case AMDGPU_INFO_FW_MES: case AMDGPU_INFO_FW_MES:
fw_info->ver = adev->mes.ucode_fw_version[1]; fw_info->ver = adev->mes.sched_version & AMDGPU_MES_VERSION_MASK;
fw_info->feature = (adev->mes.sched_version & AMDGPU_MES_FEAT_VERSION_MASK)
>> AMDGPU_MES_FEAT_VERSION_SHIFT;
break;
case AMDGPU_INFO_FW_IMU:
fw_info->ver = adev->gfx.imu_fw_version;
fw_info->feature = 0; fw_info->feature = 0;
break; break;
default: default:
@@ -790,7 +796,7 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
dev_info->ids_flags = 0; dev_info->ids_flags = 0;
if (adev->flags & AMD_IS_APU) if (adev->flags & AMD_IS_APU)
dev_info->ids_flags |= AMDGPU_IDS_FLAGS_FUSION; dev_info->ids_flags |= AMDGPU_IDS_FLAGS_FUSION;
if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) if (amdgpu_mcbp)
dev_info->ids_flags |= AMDGPU_IDS_FLAGS_PREEMPTION; dev_info->ids_flags |= AMDGPU_IDS_FLAGS_PREEMPTION;
if (amdgpu_is_tmz(adev)) if (amdgpu_is_tmz(adev))
dev_info->ids_flags |= AMDGPU_IDS_FLAGS_TMZ; dev_info->ids_flags |= AMDGPU_IDS_FLAGS_TMZ;
@@ -1166,7 +1172,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
goto error_vm; goto error_vm;
} }
if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) { if (amdgpu_mcbp) {
uint64_t csa_addr = amdgpu_csa_vaddr(adev) & AMDGPU_GMC_HOLE_MASK; uint64_t csa_addr = amdgpu_csa_vaddr(adev) & AMDGPU_GMC_HOLE_MASK;
r = amdgpu_map_static_csa(adev, &fpriv->vm, adev->virt.csa_obj, r = amdgpu_map_static_csa(adev, &fpriv->vm, adev->virt.csa_obj,
@@ -1230,7 +1236,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
if (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_VCE) != NULL) if (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_VCE) != NULL)
amdgpu_vce_free_handles(adev, file_priv); amdgpu_vce_free_handles(adev, file_priv);
if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) { if (amdgpu_mcbp) {
/* TODO: how to handle reserve failure */ /* TODO: how to handle reserve failure */
BUG_ON(amdgpu_bo_reserve(adev->virt.csa_obj, true)); BUG_ON(amdgpu_bo_reserve(adev->virt.csa_obj, true));
amdgpu_vm_bo_del(adev, fpriv->csa_va); amdgpu_vm_bo_del(adev, fpriv->csa_va);
@@ -1520,6 +1526,15 @@ static int amdgpu_debugfs_firmware_info_show(struct seq_file *m, void *unused)
fw_info.feature, fw_info.ver); fw_info.feature, fw_info.ver);
} }
/* IMU */
query_fw.fw_type = AMDGPU_INFO_FW_IMU;
query_fw.index = 0;
ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
if (ret)
return ret;
seq_printf(m, "IMU feature version: %u, firmware version: 0x%08x\n",
fw_info.feature, fw_info.ver);
/* PSP SOS */ /* PSP SOS */
query_fw.fw_type = AMDGPU_INFO_FW_SOS; query_fw.fw_type = AMDGPU_INFO_FW_SOS;
ret = amdgpu_firmware_info(&fw_info, &query_fw, adev); ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);

View File

@@ -91,14 +91,12 @@ struct amdgpu_mes {
struct amdgpu_bo *ucode_fw_obj[AMDGPU_MAX_MES_PIPES]; struct amdgpu_bo *ucode_fw_obj[AMDGPU_MAX_MES_PIPES];
uint64_t ucode_fw_gpu_addr[AMDGPU_MAX_MES_PIPES]; uint64_t ucode_fw_gpu_addr[AMDGPU_MAX_MES_PIPES];
uint32_t *ucode_fw_ptr[AMDGPU_MAX_MES_PIPES]; uint32_t *ucode_fw_ptr[AMDGPU_MAX_MES_PIPES];
uint32_t ucode_fw_version[AMDGPU_MAX_MES_PIPES];
uint64_t uc_start_addr[AMDGPU_MAX_MES_PIPES]; uint64_t uc_start_addr[AMDGPU_MAX_MES_PIPES];
/* mes ucode data */ /* mes ucode data */
struct amdgpu_bo *data_fw_obj[AMDGPU_MAX_MES_PIPES]; struct amdgpu_bo *data_fw_obj[AMDGPU_MAX_MES_PIPES];
uint64_t data_fw_gpu_addr[AMDGPU_MAX_MES_PIPES]; uint64_t data_fw_gpu_addr[AMDGPU_MAX_MES_PIPES];
uint32_t *data_fw_ptr[AMDGPU_MAX_MES_PIPES]; uint32_t *data_fw_ptr[AMDGPU_MAX_MES_PIPES];
uint32_t data_fw_version[AMDGPU_MAX_MES_PIPES];
uint64_t data_start_addr[AMDGPU_MAX_MES_PIPES]; uint64_t data_start_addr[AMDGPU_MAX_MES_PIPES];
/* eop gpu obj */ /* eop gpu obj */

View File

@@ -988,6 +988,8 @@ int psp_ta_unload(struct psp_context *psp, struct ta_context *context)
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
context->resp_status = cmd->resp.status;
release_psp_cmd_buf(psp); release_psp_cmd_buf(psp);
return ret; return ret;
@@ -1069,42 +1071,6 @@ int psp_ta_init_shared_buf(struct psp_context *psp,
&mem_ctx->shared_buf); &mem_ctx->shared_buf);
} }
static void psp_prep_ta_invoke_indirect_cmd_buf(struct psp_gfx_cmd_resp *cmd,
uint32_t ta_cmd_id,
struct ta_context *context)
{
cmd->cmd_id = GFX_CMD_ID_INVOKE_CMD;
cmd->cmd.cmd_invoke_cmd.session_id = context->session_id;
cmd->cmd.cmd_invoke_cmd.ta_cmd_id = ta_cmd_id;
cmd->cmd.cmd_invoke_cmd.buf.num_desc = 1;
cmd->cmd.cmd_invoke_cmd.buf.total_size = context->mem_context.shared_mem_size;
cmd->cmd.cmd_invoke_cmd.buf.buf_desc[0].buf_size = context->mem_context.shared_mem_size;
cmd->cmd.cmd_invoke_cmd.buf.buf_desc[0].buf_phy_addr_lo =
lower_32_bits(context->mem_context.shared_mc_addr);
cmd->cmd.cmd_invoke_cmd.buf.buf_desc[0].buf_phy_addr_hi =
upper_32_bits(context->mem_context.shared_mc_addr);
}
int psp_ta_invoke_indirect(struct psp_context *psp,
uint32_t ta_cmd_id,
struct ta_context *context)
{
int ret;
struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_invoke_indirect_cmd_buf(cmd, ta_cmd_id, context);
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
context->resp_status = cmd->resp.status;
release_psp_cmd_buf(psp);
return ret;
}
static void psp_prep_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd, static void psp_prep_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd,
uint32_t ta_cmd_id, uint32_t ta_cmd_id,
uint32_t session_id) uint32_t session_id)
@@ -1547,7 +1513,7 @@ int psp_ras_terminate(struct psp_context *psp)
return ret; return ret;
} }
static int psp_ras_initialize(struct psp_context *psp) int psp_ras_initialize(struct psp_context *psp)
{ {
int ret; int ret;
uint32_t boot_cfg = 0xFF; uint32_t boot_cfg = 0xFF;
@@ -1560,6 +1526,11 @@ static int psp_ras_initialize(struct psp_context *psp)
if (amdgpu_sriov_vf(adev)) if (amdgpu_sriov_vf(adev))
return 0; return 0;
if (psp->ras_context.context.initialized) {
dev_warn(adev->dev, "RAS WARN: TA has already been loaded\n");
return 0;
}
if (!adev->psp.ras_context.context.bin_desc.size_bytes || if (!adev->psp.ras_context.context.bin_desc.size_bytes ||
!adev->psp.ras_context.context.bin_desc.start_addr) { !adev->psp.ras_context.context.bin_desc.start_addr) {
dev_info(adev->dev, "RAS: optional ras ta ucode is not available\n"); dev_info(adev->dev, "RAS: optional ras ta ucode is not available\n");
@@ -1610,7 +1581,7 @@ static int psp_ras_initialize(struct psp_context *psp)
psp->ras_context.context.mem_context.shared_mem_size = PSP_RAS_SHARED_MEM_SIZE; psp->ras_context.context.mem_context.shared_mem_size = PSP_RAS_SHARED_MEM_SIZE;
psp->ras_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA; psp->ras_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA;
if (!psp->ras_context.context.initialized) { if (!psp->ras_context.context.mem_context.shared_buf) {
ret = psp_ta_init_shared_buf(psp, &psp->ras_context.context.mem_context); ret = psp_ta_init_shared_buf(psp, &psp->ras_context.context.mem_context);
if (ret) if (ret)
return ret; return ret;
@@ -1631,7 +1602,6 @@ static int psp_ras_initialize(struct psp_context *psp)
else { else {
if (ras_cmd->ras_status) if (ras_cmd->ras_status)
dev_warn(psp->adev->dev, "RAS Init Status: 0x%X\n", ras_cmd->ras_status); dev_warn(psp->adev->dev, "RAS Init Status: 0x%X\n", ras_cmd->ras_status);
amdgpu_ras_fini(psp->adev);
} }
return ret; return ret;
@@ -1938,10 +1908,15 @@ static int psp_securedisplay_initialize(struct psp_context *psp)
} else } else
return ret; return ret;
mutex_lock(&psp->securedisplay_context.mutex);
psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd, psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
TA_SECUREDISPLAY_COMMAND__QUERY_TA); TA_SECUREDISPLAY_COMMAND__QUERY_TA);
ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__QUERY_TA); ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__QUERY_TA);
mutex_unlock(&psp->securedisplay_context.mutex);
if (ret) { if (ret) {
psp_securedisplay_terminate(psp); psp_securedisplay_terminate(psp);
/* free securedisplay shared memory */ /* free securedisplay shared memory */
@@ -1990,12 +1965,8 @@ int psp_securedisplay_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
ta_cmd_id != TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC) ta_cmd_id != TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC)
return -EINVAL; return -EINVAL;
mutex_lock(&psp->securedisplay_context.mutex);
ret = psp_ta_invoke(psp, ta_cmd_id, &psp->securedisplay_context.context); ret = psp_ta_invoke(psp, ta_cmd_id, &psp->securedisplay_context.context);
mutex_unlock(&psp->securedisplay_context.mutex);
return ret; return ret;
} }
/* SECUREDISPLAY end */ /* SECUREDISPLAY end */

View File

@@ -136,6 +136,12 @@ struct psp_funcs
int (*vbflash_stat)(struct psp_context *psp); int (*vbflash_stat)(struct psp_context *psp);
}; };
struct ta_funcs {
int (*fn_ta_initialize)(struct psp_context *psp);
int (*fn_ta_invoke)(struct psp_context *psp, uint32_t ta_cmd_id);
int (*fn_ta_terminate)(struct psp_context *psp);
};
#define AMDGPU_XGMI_MAX_CONNECTED_NODES 64 #define AMDGPU_XGMI_MAX_CONNECTED_NODES 64
struct psp_xgmi_node_info { struct psp_xgmi_node_info {
uint64_t node_id; uint64_t node_id;
@@ -309,6 +315,7 @@ struct psp_context
struct psp_gfx_cmd_resp *cmd; struct psp_gfx_cmd_resp *cmd;
const struct psp_funcs *funcs; const struct psp_funcs *funcs;
const struct ta_funcs *ta_funcs;
/* firmware buffer */ /* firmware buffer */
struct amdgpu_bo *fw_pri_bo; struct amdgpu_bo *fw_pri_bo;
@@ -463,9 +470,6 @@ int psp_ta_load(struct psp_context *psp, struct ta_context *context);
int psp_ta_invoke(struct psp_context *psp, int psp_ta_invoke(struct psp_context *psp,
uint32_t ta_cmd_id, uint32_t ta_cmd_id,
struct ta_context *context); struct ta_context *context);
int psp_ta_invoke_indirect(struct psp_context *psp,
uint32_t ta_cmd_id,
struct ta_context *context);
int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool load_ta); int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool load_ta);
int psp_xgmi_terminate(struct psp_context *psp); int psp_xgmi_terminate(struct psp_context *psp);
@@ -479,7 +483,7 @@ int psp_xgmi_get_topology_info(struct psp_context *psp,
int psp_xgmi_set_topology_info(struct psp_context *psp, int psp_xgmi_set_topology_info(struct psp_context *psp,
int number_devices, int number_devices,
struct psp_xgmi_topology_info *topology); struct psp_xgmi_topology_info *topology);
int psp_ras_initialize(struct psp_context *psp);
int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id); int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id);
int psp_ras_enable_features(struct psp_context *psp, int psp_ras_enable_features(struct psp_context *psp,
union ta_ras_cmd_input *info, bool enable); union ta_ras_cmd_input *info, bool enable);

View File

@@ -41,30 +41,46 @@ static uint32_t get_bin_version(const uint8_t *bin)
return hdr->ucode_version; return hdr->ucode_version;
} }
static void prep_ta_mem_context(struct psp_context *psp, static int prep_ta_mem_context(struct ta_mem_context *mem_context,
struct ta_context *context,
uint8_t *shared_buf, uint8_t *shared_buf,
uint32_t shared_buf_len) uint32_t shared_buf_len)
{ {
context->mem_context.shared_mem_size = PAGE_ALIGN(shared_buf_len); if (mem_context->shared_mem_size < shared_buf_len)
psp_ta_init_shared_buf(psp, &context->mem_context); return -EINVAL;
memset(mem_context->shared_buf, 0, mem_context->shared_mem_size);
memcpy((void *)mem_context->shared_buf, shared_buf, shared_buf_len);
memcpy((void *)context->mem_context.shared_buf, shared_buf, shared_buf_len); return 0;
} }
static bool is_ta_type_valid(enum ta_type_id ta_type) static bool is_ta_type_valid(enum ta_type_id ta_type)
{ {
bool ret = false;
switch (ta_type) { switch (ta_type) {
case TA_TYPE_RAS: case TA_TYPE_RAS:
ret = true; return true;
default:
return false;
}
}
static const struct ta_funcs ras_ta_funcs = {
.fn_ta_initialize = psp_ras_initialize,
.fn_ta_invoke = psp_ras_invoke,
.fn_ta_terminate = psp_ras_terminate
};
static void set_ta_context_funcs(struct psp_context *psp,
enum ta_type_id ta_type,
struct ta_context **pcontext)
{
switch (ta_type) {
case TA_TYPE_RAS:
*pcontext = &psp->ras_context.context;
psp->ta_funcs = &ras_ta_funcs;
break; break;
default: default:
break; break;
} }
return ret;
} }
static const struct file_operations ta_load_debugfs_fops = { static const struct file_operations ta_load_debugfs_fops = {
@@ -85,8 +101,7 @@ static const struct file_operations ta_invoke_debugfs_fops = {
.owner = THIS_MODULE .owner = THIS_MODULE
}; };
/*
/**
* DOC: AMDGPU TA debugfs interfaces * DOC: AMDGPU TA debugfs interfaces
* *
* Three debugfs interfaces can be opened by a program to * Three debugfs interfaces can be opened by a program to
@@ -111,15 +126,18 @@ static const struct file_operations ta_invoke_debugfs_fops = {
* *
* - For TA invoke debugfs interface: * - For TA invoke debugfs interface:
* Transmit buffer: * Transmit buffer:
* - TA type (4bytes)
* - TA ID (4bytes) * - TA ID (4bytes)
* - TA CMD ID (4bytes) * - TA CMD ID (4bytes)
* - TA shard buf length (4bytes) * - TA shard buf length
* (4bytes, value not beyond TA shared memory size)
* - TA shared buf * - TA shared buf
* Receive buffer: * Receive buffer:
* - TA shared buf * - TA shared buf
* *
* - For TA unload debugfs interface: * - For TA unload debugfs interface:
* Transmit buffer: * Transmit buffer:
* - TA type (4bytes)
* - TA ID (4bytes) * - TA ID (4bytes)
*/ */
@@ -131,59 +149,92 @@ static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, size_t
uint32_t copy_pos = 0; uint32_t copy_pos = 0;
int ret = 0; int ret = 0;
struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private;
struct psp_context *psp = &adev->psp; struct psp_context *psp = &adev->psp;
struct ta_context context = {0}; struct ta_context *context = NULL;
if (!buf) if (!buf)
return -EINVAL; return -EINVAL;
ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t)); ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
if (ret || (!is_ta_type_valid(ta_type))) if (ret || (!is_ta_type_valid(ta_type)))
return -EINVAL; return -EFAULT;
copy_pos += sizeof(uint32_t); copy_pos += sizeof(uint32_t);
ret = copy_from_user((void *)&ta_bin_len, &buf[copy_pos], sizeof(uint32_t)); ret = copy_from_user((void *)&ta_bin_len, &buf[copy_pos], sizeof(uint32_t));
if (ret) if (ret)
return -EINVAL; return -EFAULT;
copy_pos += sizeof(uint32_t); copy_pos += sizeof(uint32_t);
ta_bin = kzalloc(ta_bin_len, GFP_KERNEL); ta_bin = kzalloc(ta_bin_len, GFP_KERNEL);
if (!ta_bin) if (!ta_bin)
ret = -ENOMEM; return -ENOMEM;
if (copy_from_user((void *)ta_bin, &buf[copy_pos], ta_bin_len)) { if (copy_from_user((void *)ta_bin, &buf[copy_pos], ta_bin_len)) {
ret = -EFAULT; ret = -EFAULT;
goto err_free_bin; goto err_free_bin;
} }
ret = psp_ras_terminate(psp); /* Set TA context and functions */
if (ret) { set_ta_context_funcs(psp, ta_type, &context);
dev_err(adev->dev, "Failed to unload embedded RAS TA\n");
if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_terminate) {
dev_err(adev->dev, "Unsupported function to terminate TA\n");
ret = -EOPNOTSUPP;
goto err_free_bin; goto err_free_bin;
} }
context.ta_type = ta_type; /*
context.ta_load_type = GFX_CMD_ID_LOAD_TA; * Allocate TA shared buf in case shared buf was freed
context.bin_desc.fw_version = get_bin_version(ta_bin); * due to loading TA failed before.
context.bin_desc.size_bytes = ta_bin_len; */
context.bin_desc.start_addr = ta_bin; if (!context->mem_context.shared_buf) {
ret = psp_ta_init_shared_buf(psp, &context->mem_context);
if (ret) {
ret = -ENOMEM;
goto err_free_bin;
}
}
ret = psp_ta_load(psp, &context); ret = psp_fn_ta_terminate(psp);
if (ret || context->resp_status) {
if (ret || context.resp_status) { dev_err(adev->dev,
dev_err(adev->dev, "TA load via debugfs failed (%d) status %d\n", "Failed to unload embedded TA (%d) and status (0x%X)\n",
ret, context.resp_status); ret, context->resp_status);
if (!ret) if (!ret)
ret = -EINVAL; ret = -EINVAL;
goto err_free_bin; goto err_free_ta_shared_buf;
} }
context.initialized = true; /* Prepare TA context for TA initialization */
if (copy_to_user((char *)buf, (void *)&context.session_id, sizeof(uint32_t))) context->ta_type = ta_type;
context->bin_desc.fw_version = get_bin_version(ta_bin);
context->bin_desc.size_bytes = ta_bin_len;
context->bin_desc.start_addr = ta_bin;
if (!psp->ta_funcs->fn_ta_initialize) {
dev_err(adev->dev, "Unsupported function to initialize TA\n");
ret = -EOPNOTSUPP;
goto err_free_ta_shared_buf;
}
ret = psp_fn_ta_initialize(psp);
if (ret || context->resp_status) {
dev_err(adev->dev, "Failed to load TA via debugfs (%d) and status (0x%X)\n",
ret, context->resp_status);
if (!ret)
ret = -EINVAL;
goto err_free_ta_shared_buf;
}
if (copy_to_user((char *)buf, (void *)&context->session_id, sizeof(uint32_t)))
ret = -EFAULT; ret = -EFAULT;
err_free_ta_shared_buf:
/* Only free TA shared buf when returns error code */
if (ret && context->mem_context.shared_buf)
psp_ta_free_shared_buf(&context->mem_context);
err_free_bin: err_free_bin:
kfree(ta_bin); kfree(ta_bin);
@@ -192,58 +243,85 @@ err_free_bin:
static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off) static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
{ {
uint32_t ta_id = 0; uint32_t ta_type = 0;
int ret = 0; uint32_t ta_id = 0;
uint32_t copy_pos = 0;
int ret = 0;
struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private;
struct psp_context *psp = &adev->psp; struct psp_context *psp = &adev->psp;
struct ta_context context = {0}; struct ta_context *context = NULL;
if (!buf) if (!buf)
return -EINVAL; return -EINVAL;
ret = copy_from_user((void *)&ta_id, buf, sizeof(uint32_t)); ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
if (ret || (!is_ta_type_valid(ta_type)))
return -EFAULT;
copy_pos += sizeof(uint32_t);
ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t));
if (ret) if (ret)
return -EINVAL; return -EFAULT;
context.session_id = ta_id; set_ta_context_funcs(psp, ta_type, &context);
context->session_id = ta_id;
ret = psp_ta_unload(psp, &context); if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_terminate) {
if (!ret) dev_err(adev->dev, "Unsupported function to terminate TA\n");
context.initialized = false; return -EOPNOTSUPP;
}
ret = psp_fn_ta_terminate(psp);
if (ret || context->resp_status) {
dev_err(adev->dev, "Failed to unload TA via debugfs (%d) and status (0x%X)\n",
ret, context->resp_status);
if (!ret)
ret = -EINVAL;
}
if (context->mem_context.shared_buf)
psp_ta_free_shared_buf(&context->mem_context);
return ret; return ret;
} }
static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off) static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
{ {
uint32_t ta_type = 0;
uint32_t ta_id = 0; uint32_t ta_id = 0;
uint32_t cmd_id = 0; uint32_t cmd_id = 0;
uint32_t shared_buf_len = 0; uint32_t shared_buf_len = 0;
uint8_t *shared_buf = NULL; uint8_t *shared_buf = NULL;
uint32_t copy_pos = 0; uint32_t copy_pos = 0;
int ret = 0; int ret = 0;
struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private; struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private;
struct psp_context *psp = &adev->psp; struct psp_context *psp = &adev->psp;
struct ta_context context = {0}; struct ta_context *context = NULL;
if (!buf) if (!buf)
return -EINVAL; return -EINVAL;
ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
if (ret)
return -EFAULT;
copy_pos += sizeof(uint32_t);
ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t)); ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t));
if (ret) if (ret)
return -EINVAL; return -EFAULT;
copy_pos += sizeof(uint32_t); copy_pos += sizeof(uint32_t);
ret = copy_from_user((void *)&cmd_id, &buf[copy_pos], sizeof(uint32_t)); ret = copy_from_user((void *)&cmd_id, &buf[copy_pos], sizeof(uint32_t));
if (ret) if (ret)
return -EINVAL; return -EFAULT;
copy_pos += sizeof(uint32_t); copy_pos += sizeof(uint32_t);
ret = copy_from_user((void *)&shared_buf_len, &buf[copy_pos], sizeof(uint32_t)); ret = copy_from_user((void *)&shared_buf_len, &buf[copy_pos], sizeof(uint32_t));
if (ret) if (ret)
return -EINVAL; return -EFAULT;
copy_pos += sizeof(uint32_t); copy_pos += sizeof(uint32_t);
shared_buf = kzalloc(shared_buf_len, GFP_KERNEL); shared_buf = kzalloc(shared_buf_len, GFP_KERNEL);
@@ -254,25 +332,38 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
goto err_free_shared_buf; goto err_free_shared_buf;
} }
context.session_id = ta_id; set_ta_context_funcs(psp, ta_type, &context);
prep_ta_mem_context(psp, &context, shared_buf, shared_buf_len); if (!context->initialized) {
dev_err(adev->dev, "TA is not initialized\n");
ret = psp_ta_invoke_indirect(psp, cmd_id, &context); ret = -EINVAL;
goto err_free_shared_buf;
if (ret || context.resp_status) {
dev_err(adev->dev, "TA invoke via debugfs failed (%d) status %d\n",
ret, context.resp_status);
if (!ret)
ret = -EINVAL;
goto err_free_ta_shared_buf;
} }
if (copy_to_user((char *)buf, context.mem_context.shared_buf, shared_buf_len)) if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_invoke) {
ret = -EFAULT; dev_err(adev->dev, "Unsupported function to invoke TA\n");
ret = -EOPNOTSUPP;
goto err_free_shared_buf;
}
err_free_ta_shared_buf: context->session_id = ta_id;
psp_ta_free_shared_buf(&context.mem_context);
ret = prep_ta_mem_context(&context->mem_context, shared_buf, shared_buf_len);
if (ret)
goto err_free_shared_buf;
ret = psp_fn_ta_invoke(psp, cmd_id);
if (ret || context->resp_status) {
dev_err(adev->dev, "Failed to invoke TA via debugfs (%d) and status (0x%X)\n",
ret, context->resp_status);
if (!ret) {
ret = -EINVAL;
goto err_free_shared_buf;
}
}
if (copy_to_user((char *)buf, context->mem_context.shared_buf, shared_buf_len))
ret = -EFAULT;
err_free_shared_buf: err_free_shared_buf:
kfree(shared_buf); kfree(shared_buf);

View File

@@ -24,6 +24,11 @@
#ifndef __AMDGPU_PSP_TA_H__ #ifndef __AMDGPU_PSP_TA_H__
#define __AMDGPU_PSP_TA_H__ #define __AMDGPU_PSP_TA_H__
/* Calling set_ta_context_funcs is required before using the following macros */
#define psp_fn_ta_initialize(psp) ((psp)->ta_funcs->fn_ta_initialize((psp)))
#define psp_fn_ta_invoke(psp, ta_cmd_id) ((psp)->ta_funcs->fn_ta_invoke((psp), (ta_cmd_id)))
#define psp_fn_ta_terminate(psp) ((psp)->ta_funcs->fn_ta_terminate((psp)))
void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev); void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev);
#endif #endif

View File

@@ -1561,7 +1561,6 @@ static void amdgpu_ras_interrupt_poison_consumption_handler(struct ras_manager *
{ {
bool poison_stat = false; bool poison_stat = false;
struct amdgpu_device *adev = obj->adev; struct amdgpu_device *adev = obj->adev;
struct ras_err_data err_data = {0, 0, 0, NULL};
struct amdgpu_ras_block_object *block_obj = struct amdgpu_ras_block_object *block_obj =
amdgpu_ras_get_ras_block(adev, obj->head.block, 0); amdgpu_ras_get_ras_block(adev, obj->head.block, 0);
@@ -1584,7 +1583,7 @@ static void amdgpu_ras_interrupt_poison_consumption_handler(struct ras_manager *
} }
if (!adev->gmc.xgmi.connected_to_cpu) if (!adev->gmc.xgmi.connected_to_cpu)
amdgpu_umc_poison_handler(adev, &err_data, false); amdgpu_umc_poison_handler(adev, false);
if (block_obj->hw_ops->handle_poison_consumption) if (block_obj->hw_ops->handle_poison_consumption)
poison_stat = block_obj->hw_ops->handle_poison_consumption(adev); poison_stat = block_obj->hw_ops->handle_poison_consumption(adev);
@@ -2848,7 +2847,6 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb,
struct amdgpu_device *adev = NULL; struct amdgpu_device *adev = NULL;
uint32_t gpu_id = 0; uint32_t gpu_id = 0;
uint32_t umc_inst = 0, ch_inst = 0; uint32_t umc_inst = 0, ch_inst = 0;
struct ras_err_data err_data = {0, 0, 0, NULL};
/* /*
* If the error was generated in UMC_V2, which belongs to GPU UMCs, * If the error was generated in UMC_V2, which belongs to GPU UMCs,
@@ -2887,31 +2885,10 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb,
dev_info(adev->dev, "Uncorrectable error detected in UMC inst: %d, chan_idx: %d", dev_info(adev->dev, "Uncorrectable error detected in UMC inst: %d, chan_idx: %d",
umc_inst, ch_inst); umc_inst, ch_inst);
err_data.err_addr = if (!amdgpu_umc_page_retirement_mca(adev, m->addr, ch_inst, umc_inst))
kcalloc(adev->umc.max_ras_err_cnt_per_query, return NOTIFY_OK;
sizeof(struct eeprom_table_record), GFP_KERNEL); else
if (!err_data.err_addr) {
dev_warn(adev->dev,
"Failed to alloc memory for umc error record in mca notifier!\n");
return NOTIFY_DONE; return NOTIFY_DONE;
}
/*
* Translate UMC channel address to Physical address
*/
if (adev->umc.ras &&
adev->umc.ras->convert_ras_error_address)
adev->umc.ras->convert_ras_error_address(adev,
&err_data, m->addr, ch_inst, umc_inst);
if (amdgpu_bad_page_threshold != 0) {
amdgpu_ras_add_bad_pages(adev, err_data.err_addr,
err_data.err_addr_cnt);
amdgpu_ras_save_bad_pages(adev);
}
kfree(err_data.err_addr);
return NOTIFY_OK;
} }
static struct notifier_block amdgpu_bad_page_nb = { static struct notifier_block amdgpu_bad_page_nb = {

View File

@@ -38,7 +38,7 @@
#define EEPROM_I2C_MADDR_ARCTURUS_D342 0x0 #define EEPROM_I2C_MADDR_ARCTURUS_D342 0x0
#define EEPROM_I2C_MADDR_SIENNA_CICHLID 0x0 #define EEPROM_I2C_MADDR_SIENNA_CICHLID 0x0
#define EEPROM_I2C_MADDR_ALDEBARAN 0x0 #define EEPROM_I2C_MADDR_ALDEBARAN 0x0
#define EEPROM_I2C_MADDR_SMU_13_0_0 (0x54UL << 16) #define EEPROM_I2C_MADDR_54H (0x54UL << 16)
/* /*
* The 2 macros bellow represent the actual size in bytes that * The 2 macros bellow represent the actual size in bytes that
@@ -90,6 +90,16 @@
static bool __is_ras_eeprom_supported(struct amdgpu_device *adev) static bool __is_ras_eeprom_supported(struct amdgpu_device *adev)
{ {
if (adev->asic_type == CHIP_IP_DISCOVERY) {
switch (adev->ip_versions[MP1_HWIP][0]) {
case IP_VERSION(13, 0, 0):
case IP_VERSION(13, 0, 10):
return true;
default:
return false;
}
}
return adev->asic_type == CHIP_VEGA20 || return adev->asic_type == CHIP_VEGA20 ||
adev->asic_type == CHIP_ARCTURUS || adev->asic_type == CHIP_ARCTURUS ||
adev->asic_type == CHIP_SIENNA_CICHLID || adev->asic_type == CHIP_SIENNA_CICHLID ||
@@ -114,6 +124,19 @@ static bool __get_eeprom_i2c_addr_arct(struct amdgpu_device *adev,
return true; return true;
} }
static bool __get_eeprom_i2c_addr_ip_discovery(struct amdgpu_device *adev,
struct amdgpu_ras_eeprom_control *control)
{
switch (adev->ip_versions[MP1_HWIP][0]) {
case IP_VERSION(13, 0, 0):
case IP_VERSION(13, 0, 10):
control->i2c_address = EEPROM_I2C_MADDR_54H;
return true;
default:
return false;
}
}
static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev, static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
struct amdgpu_ras_eeprom_control *control) struct amdgpu_ras_eeprom_control *control)
{ {
@@ -153,13 +176,16 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
control->i2c_address = EEPROM_I2C_MADDR_ALDEBARAN; control->i2c_address = EEPROM_I2C_MADDR_ALDEBARAN;
break; break;
case CHIP_IP_DISCOVERY:
return __get_eeprom_i2c_addr_ip_discovery(adev, control);
default: default:
return false; return false;
} }
switch (adev->ip_versions[MP1_HWIP][0]) { switch (adev->ip_versions[MP1_HWIP][0]) {
case IP_VERSION(13, 0, 0): case IP_VERSION(13, 0, 0):
control->i2c_address = EEPROM_I2C_MADDR_SMU_13_0_0; control->i2c_address = EEPROM_I2C_MADDR_54H;
break; break;
default: default:

View File

@@ -121,6 +121,7 @@ static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __u
switch (op) { switch (op) {
case 1: case 1:
mutex_lock(&psp->securedisplay_context.mutex);
psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd, psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
TA_SECUREDISPLAY_COMMAND__QUERY_TA); TA_SECUREDISPLAY_COMMAND__QUERY_TA);
ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__QUERY_TA); ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__QUERY_TA);
@@ -131,8 +132,10 @@ static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __u
else else
psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status); psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status);
} }
mutex_unlock(&psp->securedisplay_context.mutex);
break; break;
case 2: case 2:
mutex_lock(&psp->securedisplay_context.mutex);
psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd, psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC); TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC);
securedisplay_cmd->securedisplay_in_message.send_roi_crc.phy_id = phy_id; securedisplay_cmd->securedisplay_in_message.send_roi_crc.phy_id = phy_id;
@@ -146,6 +149,7 @@ static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __u
psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status); psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status);
} }
} }
mutex_unlock(&psp->securedisplay_context.mutex);
break; break;
default: default:
dev_err(adev->dev, "Invalid input: %s\n", str); dev_err(adev->dev, "Invalid input: %s\n", str);

View File

@@ -2295,9 +2295,9 @@ static ssize_t amdgpu_iomem_read(struct file *f, char __user *buf,
if (p->mapping != adev->mman.bdev.dev_mapping) if (p->mapping != adev->mman.bdev.dev_mapping)
return -EPERM; return -EPERM;
ptr = kmap(p); ptr = kmap_local_page(p);
r = copy_to_user(buf, ptr + off, bytes); r = copy_to_user(buf, ptr + off, bytes);
kunmap(p); kunmap_local(ptr);
if (r) if (r)
return -EFAULT; return -EFAULT;
@@ -2346,9 +2346,9 @@ static ssize_t amdgpu_iomem_write(struct file *f, const char __user *buf,
if (p->mapping != adev->mman.bdev.dev_mapping) if (p->mapping != adev->mman.bdev.dev_mapping)
return -EPERM; return -EPERM;
ptr = kmap(p); ptr = kmap_local_page(p);
r = copy_from_user(ptr + off, buf, bytes); r = copy_from_user(ptr + off, buf, bytes);
kunmap(p); kunmap_local(ptr);
if (r) if (r)
return -EFAULT; return -EFAULT;

View File

@@ -698,6 +698,7 @@ FW_VERSION_ATTR(rlc_srlg_fw_version, 0444, gfx.rlc_srlg_fw_version);
FW_VERSION_ATTR(rlc_srls_fw_version, 0444, gfx.rlc_srls_fw_version); FW_VERSION_ATTR(rlc_srls_fw_version, 0444, gfx.rlc_srls_fw_version);
FW_VERSION_ATTR(mec_fw_version, 0444, gfx.mec_fw_version); FW_VERSION_ATTR(mec_fw_version, 0444, gfx.mec_fw_version);
FW_VERSION_ATTR(mec2_fw_version, 0444, gfx.mec2_fw_version); FW_VERSION_ATTR(mec2_fw_version, 0444, gfx.mec2_fw_version);
FW_VERSION_ATTR(imu_fw_version, 0444, gfx.imu_fw_version);
FW_VERSION_ATTR(sos_fw_version, 0444, psp.sos.fw_version); FW_VERSION_ATTR(sos_fw_version, 0444, psp.sos.fw_version);
FW_VERSION_ATTR(asd_fw_version, 0444, psp.asd_context.bin_desc.fw_version); FW_VERSION_ATTR(asd_fw_version, 0444, psp.asd_context.bin_desc.fw_version);
FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ras_context.context.bin_desc.fw_version); FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ras_context.context.bin_desc.fw_version);
@@ -719,7 +720,8 @@ static struct attribute *fw_attrs[] = {
&dev_attr_ta_ras_fw_version.attr, &dev_attr_ta_xgmi_fw_version.attr, &dev_attr_ta_ras_fw_version.attr, &dev_attr_ta_xgmi_fw_version.attr,
&dev_attr_smc_fw_version.attr, &dev_attr_sdma_fw_version.attr, &dev_attr_smc_fw_version.attr, &dev_attr_sdma_fw_version.attr,
&dev_attr_sdma2_fw_version.attr, &dev_attr_vcn_fw_version.attr, &dev_attr_sdma2_fw_version.attr, &dev_attr_vcn_fw_version.attr,
&dev_attr_dmcu_fw_version.attr, NULL &dev_attr_dmcu_fw_version.attr, &dev_attr_imu_fw_version.attr,
NULL
}; };
static const struct attribute_group fw_attr_group = { static const struct attribute_group fw_attr_group = {

View File

@@ -125,6 +125,7 @@ enum psp_fw_type {
PSP_FW_TYPE_PSP_INTF_DRV, PSP_FW_TYPE_PSP_INTF_DRV,
PSP_FW_TYPE_PSP_DBG_DRV, PSP_FW_TYPE_PSP_DBG_DRV,
PSP_FW_TYPE_PSP_RAS_DRV, PSP_FW_TYPE_PSP_RAS_DRV,
PSP_FW_TYPE_MAX_INDEX,
}; };
/* version_major=2, version_minor=0 */ /* version_major=2, version_minor=0 */

View File

@@ -22,6 +22,59 @@
*/ */
#include "amdgpu.h" #include "amdgpu.h"
#include "umc_v6_7.h"
static int amdgpu_umc_convert_error_address(struct amdgpu_device *adev,
struct ras_err_data *err_data, uint64_t err_addr,
uint32_t ch_inst, uint32_t umc_inst)
{
switch (adev->ip_versions[UMC_HWIP][0]) {
case IP_VERSION(6, 7, 0):
umc_v6_7_convert_error_address(adev,
err_data, err_addr, ch_inst, umc_inst);
break;
default:
dev_warn(adev->dev,
"UMC address to Physical address translation is not supported\n");
return AMDGPU_RAS_FAIL;
}
return AMDGPU_RAS_SUCCESS;
}
int amdgpu_umc_page_retirement_mca(struct amdgpu_device *adev,
uint64_t err_addr, uint32_t ch_inst, uint32_t umc_inst)
{
struct ras_err_data err_data = {0, 0, 0, NULL};
int ret = AMDGPU_RAS_FAIL;
err_data.err_addr =
kcalloc(adev->umc.max_ras_err_cnt_per_query,
sizeof(struct eeprom_table_record), GFP_KERNEL);
if (!err_data.err_addr) {
dev_warn(adev->dev,
"Failed to alloc memory for umc error record in MCA notifier!\n");
return AMDGPU_RAS_FAIL;
}
/*
* Translate UMC channel address to Physical address
*/
ret = amdgpu_umc_convert_error_address(adev, &err_data, err_addr,
ch_inst, umc_inst);
if (ret)
goto out;
if (amdgpu_bad_page_threshold != 0) {
amdgpu_ras_add_bad_pages(adev, err_data.err_addr,
err_data.err_addr_cnt);
amdgpu_ras_save_bad_pages(adev);
}
out:
kfree(err_data.err_addr);
return ret;
}
static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev, static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
void *ras_error_status, void *ras_error_status,
@@ -112,23 +165,29 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
return AMDGPU_RAS_SUCCESS; return AMDGPU_RAS_SUCCESS;
} }
int amdgpu_umc_poison_handler(struct amdgpu_device *adev, int amdgpu_umc_poison_handler(struct amdgpu_device *adev, bool reset)
void *ras_error_status,
bool reset)
{ {
int ret; int ret = AMDGPU_RAS_SUCCESS;
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
struct ras_common_if head = {
.block = AMDGPU_RAS_BLOCK__UMC,
};
struct ras_manager *obj = amdgpu_ras_find_obj(adev, &head);
ret = if (!adev->gmc.xgmi.connected_to_cpu) {
amdgpu_umc_do_page_retirement(adev, ras_error_status, NULL, reset); struct ras_err_data err_data = {0, 0, 0, NULL};
struct ras_common_if head = {
.block = AMDGPU_RAS_BLOCK__UMC,
};
struct ras_manager *obj = amdgpu_ras_find_obj(adev, &head);
if (ret == AMDGPU_RAS_SUCCESS && obj) { ret = amdgpu_umc_do_page_retirement(adev, &err_data, NULL, reset);
obj->err_data.ue_count += err_data->ue_count;
obj->err_data.ce_count += err_data->ce_count; if (ret == AMDGPU_RAS_SUCCESS && obj) {
obj->err_data.ue_count += err_data.ue_count;
obj->err_data.ce_count += err_data.ce_count;
}
} else if (reset) {
/* MCA poison handler is only responsible for GPU reset,
* let MCA notifier do page retirement.
*/
kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
amdgpu_ras_reset_gpu(adev);
} }
return ret; return ret;

View File

@@ -51,9 +51,6 @@ struct amdgpu_umc_ras {
struct amdgpu_ras_block_object ras_block; struct amdgpu_ras_block_object ras_block;
void (*err_cnt_init)(struct amdgpu_device *adev); void (*err_cnt_init)(struct amdgpu_device *adev);
bool (*query_ras_poison_mode)(struct amdgpu_device *adev); bool (*query_ras_poison_mode)(struct amdgpu_device *adev);
void (*convert_ras_error_address)(struct amdgpu_device *adev,
struct ras_err_data *err_data, uint64_t err_addr,
uint32_t ch_inst, uint32_t umc_inst);
void (*ecc_info_query_ras_error_count)(struct amdgpu_device *adev, void (*ecc_info_query_ras_error_count)(struct amdgpu_device *adev,
void *ras_error_status); void *ras_error_status);
void (*ecc_info_query_ras_error_address)(struct amdgpu_device *adev, void (*ecc_info_query_ras_error_address)(struct amdgpu_device *adev,
@@ -86,9 +83,7 @@ struct amdgpu_umc {
}; };
int amdgpu_umc_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block); int amdgpu_umc_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block);
int amdgpu_umc_poison_handler(struct amdgpu_device *adev, int amdgpu_umc_poison_handler(struct amdgpu_device *adev, bool reset);
void *ras_error_status,
bool reset);
int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev, int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source, struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry); struct amdgpu_iv_entry *entry);
@@ -101,4 +96,6 @@ void amdgpu_umc_fill_error_record(struct ras_err_data *err_data,
int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev, int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev,
void *ras_error_status, void *ras_error_status,
struct amdgpu_iv_entry *entry); struct amdgpu_iv_entry *entry);
int amdgpu_umc_page_retirement_mca(struct amdgpu_device *adev,
uint64_t err_addr, uint32_t ch_inst, uint32_t umc_inst);
#endif #endif

View File

@@ -64,6 +64,10 @@ void amdgpu_virt_init_setting(struct amdgpu_device *adev)
ddev->driver_features &= ~DRIVER_ATOMIC; ddev->driver_features &= ~DRIVER_ATOMIC;
adev->cg_flags = 0; adev->cg_flags = 0;
adev->pg_flags = 0; adev->pg_flags = 0;
/* enable mcbp for sriov asic_type before soc21 */
amdgpu_mcbp = (adev->asic_type < CHIP_IP_DISCOVERY) ? 1 : 0;
} }
void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev, void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev,
@@ -547,6 +551,7 @@ static void amdgpu_virt_populate_vf2pf_ucode_info(struct amdgpu_device *adev)
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_RLC_SRLS, adev->gfx.rlc_srls_fw_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_RLC_SRLS, adev->gfx.rlc_srls_fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC, adev->gfx.mec_fw_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC, adev->gfx.mec_fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC2, adev->gfx.mec2_fw_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC2, adev->gfx.mec2_fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_IMU, adev->gfx.imu_fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SOS, adev->psp.sos.fw_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SOS, adev->psp.sos.fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD, POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD,
adev->psp.asd_context.bin_desc.fw_version); adev->psp.asd_context.bin_desc.fw_version);

View File

@@ -75,6 +75,8 @@ struct amdgpu_vf_error_buffer {
uint64_t data[AMDGPU_VF_ERROR_ENTRY_SIZE]; uint64_t data[AMDGPU_VF_ERROR_ENTRY_SIZE];
}; };
enum idh_request;
/** /**
* struct amdgpu_virt_ops - amdgpu device virt operations * struct amdgpu_virt_ops - amdgpu device virt operations
*/ */
@@ -84,7 +86,8 @@ struct amdgpu_virt_ops {
int (*req_init_data)(struct amdgpu_device *adev); int (*req_init_data)(struct amdgpu_device *adev);
int (*reset_gpu)(struct amdgpu_device *adev); int (*reset_gpu)(struct amdgpu_device *adev);
int (*wait_reset)(struct amdgpu_device *adev); int (*wait_reset)(struct amdgpu_device *adev);
void (*trans_msg)(struct amdgpu_device *adev, u32 req, u32 data1, u32 data2, u32 data3); void (*trans_msg)(struct amdgpu_device *adev, enum idh_request req,
u32 data1, u32 data2, u32 data3);
}; };
/* /*

View File

@@ -498,6 +498,8 @@ static int amdgpu_vkms_sw_init(void *handle)
adev_to_drm(adev)->mode_config.preferred_depth = 24; adev_to_drm(adev)->mode_config.preferred_depth = 24;
adev_to_drm(adev)->mode_config.prefer_shadow = 1; adev_to_drm(adev)->mode_config.prefer_shadow = 1;
adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
r = amdgpu_display_modeset_create_props(adev); r = amdgpu_display_modeset_create_props(adev);
if (r) if (r)
return r; return r;

View File

@@ -70,6 +70,7 @@ enum amd_sriov_ucode_engine_id {
AMD_SRIOV_UCODE_ID_RLC_SRLS, AMD_SRIOV_UCODE_ID_RLC_SRLS,
AMD_SRIOV_UCODE_ID_MEC, AMD_SRIOV_UCODE_ID_MEC,
AMD_SRIOV_UCODE_ID_MEC2, AMD_SRIOV_UCODE_ID_MEC2,
AMD_SRIOV_UCODE_ID_IMU,
AMD_SRIOV_UCODE_ID_SOS, AMD_SRIOV_UCODE_ID_SOS,
AMD_SRIOV_UCODE_ID_ASD, AMD_SRIOV_UCODE_ID_ASD,
AMD_SRIOV_UCODE_ID_TA_RAS, AMD_SRIOV_UCODE_ID_TA_RAS,

View File

@@ -2081,8 +2081,11 @@ amdgpu_atombios_encoder_get_lcd_info(struct amdgpu_encoder *encoder)
} }
} }
record += fake_edid_record->ucFakeEDIDLength ? record += fake_edid_record->ucFakeEDIDLength ?
fake_edid_record->ucFakeEDIDLength + 2 : struct_size(fake_edid_record,
sizeof(ATOM_FAKE_EDID_PATCH_RECORD); ucFakeEDIDString,
fake_edid_record->ucFakeEDIDLength) :
/* empty fake edid record must be 3 bytes long */
sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1;
break; break;
case LCD_PANEL_RESOLUTION_RECORD_TYPE: case LCD_PANEL_RESOLUTION_RECORD_TYPE:
panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record; panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;

View File

@@ -4453,8 +4453,6 @@ static void gfx_v10_0_gpu_early_init(struct amdgpu_device *adev)
{ {
u32 gb_addr_config; u32 gb_addr_config;
adev->gfx.funcs = &gfx_v10_0_gfx_funcs;
switch (adev->ip_versions[GC_HWIP][0]) { switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(10, 1, 10): case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 1): case IP_VERSION(10, 1, 1):
@@ -6911,6 +6909,8 @@ static int gfx_v10_0_kiq_init_queue(struct amdgpu_ring *ring)
mutex_unlock(&adev->srbm_mutex); mutex_unlock(&adev->srbm_mutex);
} else { } else {
memset((void *)mqd, 0, sizeof(*mqd)); memset((void *)mqd, 0, sizeof(*mqd));
if (amdgpu_sriov_vf(adev) && adev->in_suspend)
amdgpu_ring_clear_ring(ring);
mutex_lock(&adev->srbm_mutex); mutex_lock(&adev->srbm_mutex);
nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
amdgpu_ring_init_mqd(ring); amdgpu_ring_init_mqd(ring);
@@ -7593,6 +7593,8 @@ static int gfx_v10_0_early_init(void *handle)
{ {
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
adev->gfx.funcs = &gfx_v10_0_gfx_funcs;
switch (adev->ip_versions[GC_HWIP][0]) { switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(10, 1, 10): case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 1): case IP_VERSION(10, 1, 1):
@@ -8489,7 +8491,7 @@ static void gfx_v10_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
control |= ib->length_dw | (vmid << 24); control |= ib->length_dw | (vmid << 24);
if ((amdgpu_sriov_vf(ring->adev) || amdgpu_mcbp) && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) { if (amdgpu_mcbp && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) {
control |= INDIRECT_BUFFER_PRE_ENB(1); control |= INDIRECT_BUFFER_PRE_ENB(1);
if (flags & AMDGPU_IB_PREEMPTED) if (flags & AMDGPU_IB_PREEMPTED)
@@ -8664,7 +8666,7 @@ static void gfx_v10_0_ring_emit_cntxcntl(struct amdgpu_ring *ring,
{ {
uint32_t dw2 = 0; uint32_t dw2 = 0;
if (amdgpu_mcbp || amdgpu_sriov_vf(ring->adev)) if (amdgpu_mcbp)
gfx_v10_0_ring_emit_ce_meta(ring, gfx_v10_0_ring_emit_ce_meta(ring,
(!amdgpu_sriov_vf(ring->adev) && flags & AMDGPU_IB_PREEMPTED) ? true : false); (!amdgpu_sriov_vf(ring->adev) && flags & AMDGPU_IB_PREEMPTED) ? true : false);

View File

@@ -843,7 +843,6 @@ static const struct amdgpu_gfx_funcs gfx_v11_0_gfx_funcs = {
static int gfx_v11_0_gpu_early_init(struct amdgpu_device *adev) static int gfx_v11_0_gpu_early_init(struct amdgpu_device *adev)
{ {
adev->gfx.funcs = &gfx_v11_0_gfx_funcs;
switch (adev->ip_versions[GC_HWIP][0]) { switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(11, 0, 0): case IP_VERSION(11, 0, 0):
@@ -1626,7 +1625,8 @@ static void gfx_v11_0_constants_init(struct amdgpu_device *adev)
u32 tmp; u32 tmp;
int i; int i;
WREG32_FIELD15_PREREG(GC, 0, GRBM_CNTL, READ_TIMEOUT, 0xff); if (!amdgpu_sriov_vf(adev))
WREG32_FIELD15_PREREG(GC, 0, GRBM_CNTL, READ_TIMEOUT, 0xff);
gfx_v11_0_setup_rb(adev); gfx_v11_0_setup_rb(adev);
gfx_v11_0_get_cu_info(adev, &adev->gfx.cu_info); gfx_v11_0_get_cu_info(adev, &adev->gfx.cu_info);
@@ -4004,6 +4004,8 @@ static int gfx_v11_0_kiq_init_queue(struct amdgpu_ring *ring)
mutex_unlock(&adev->srbm_mutex); mutex_unlock(&adev->srbm_mutex);
} else { } else {
memset((void *)mqd, 0, sizeof(*mqd)); memset((void *)mqd, 0, sizeof(*mqd));
if (amdgpu_sriov_vf(adev) && adev->in_suspend)
amdgpu_ring_clear_ring(ring);
mutex_lock(&adev->srbm_mutex); mutex_lock(&adev->srbm_mutex);
soc21_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); soc21_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
amdgpu_ring_init_mqd(ring); amdgpu_ring_init_mqd(ring);
@@ -4656,6 +4658,8 @@ static int gfx_v11_0_early_init(void *handle)
{ {
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
adev->gfx.funcs = &gfx_v11_0_gfx_funcs;
adev->gfx.num_gfx_rings = GFX11_NUM_GFX_RINGS; adev->gfx.num_gfx_rings = GFX11_NUM_GFX_RINGS;
adev->gfx.num_compute_rings = min(amdgpu_gfx_get_num_kcq(adev), adev->gfx.num_compute_rings = min(amdgpu_gfx_get_num_kcq(adev),
AMDGPU_MAX_COMPUTE_RINGS); AMDGPU_MAX_COMPUTE_RINGS);
@@ -4673,6 +4677,26 @@ static int gfx_v11_0_early_init(void *handle)
return 0; return 0;
} }
static int gfx_v11_0_ras_late_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
struct ras_common_if *gfx_common_if;
int ret;
gfx_common_if = kzalloc(sizeof(struct ras_common_if), GFP_KERNEL);
if (!gfx_common_if)
return -ENOMEM;
gfx_common_if->block = AMDGPU_RAS_BLOCK__GFX;
ret = amdgpu_ras_feature_enable(adev, gfx_common_if, true);
if (ret)
dev_warn(adev->dev, "Failed to enable gfx11 ras feature\n");
kfree(gfx_common_if);
return 0;
}
static int gfx_v11_0_late_init(void *handle) static int gfx_v11_0_late_init(void *handle)
{ {
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -4686,6 +4710,12 @@ static int gfx_v11_0_late_init(void *handle)
if (r) if (r)
return r; return r;
if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(11, 0, 3)) {
r = gfx_v11_0_ras_late_init(handle);
if (r)
return r;
}
return 0; return 0;
} }
@@ -5051,6 +5081,7 @@ static int gfx_v11_0_set_powergating_state(void *handle,
switch (adev->ip_versions[GC_HWIP][0]) { switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(11, 0, 0): case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 2): case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
amdgpu_gfx_off_ctrl(adev, enable); amdgpu_gfx_off_ctrl(adev, enable);
break; break;
case IP_VERSION(11, 0, 1): case IP_VERSION(11, 0, 1):
@@ -5298,7 +5329,7 @@ static void gfx_v11_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
control |= ib->length_dw | (vmid << 24); control |= ib->length_dw | (vmid << 24);
if ((amdgpu_sriov_vf(ring->adev) || amdgpu_mcbp) && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) { if (amdgpu_mcbp && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) {
control |= INDIRECT_BUFFER_PRE_ENB(1); control |= INDIRECT_BUFFER_PRE_ENB(1);
if (flags & AMDGPU_IB_PREEMPTED) if (flags & AMDGPU_IB_PREEMPTED)
@@ -6059,6 +6090,7 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_gfx = {
.align_mask = 0xff, .align_mask = 0xff,
.nop = PACKET3(PACKET3_NOP, 0x3FFF), .nop = PACKET3(PACKET3_NOP, 0x3FFF),
.support_64bit_ptrs = true, .support_64bit_ptrs = true,
.secure_submission_supported = true,
.vmhub = AMDGPU_GFXHUB_0, .vmhub = AMDGPU_GFXHUB_0,
.get_rptr = gfx_v11_0_ring_get_rptr_gfx, .get_rptr = gfx_v11_0_ring_get_rptr_gfx,
.get_wptr = gfx_v11_0_ring_get_wptr_gfx, .get_wptr = gfx_v11_0_ring_get_wptr_gfx,

View File

@@ -4643,6 +4643,8 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring)
memset((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); memset((void *)mqd, 0, sizeof(struct vi_mqd_allocation));
((struct vi_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct vi_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF;
((struct vi_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; ((struct vi_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF;
if (amdgpu_sriov_vf(adev) && adev->in_suspend)
amdgpu_ring_clear_ring(ring);
mutex_lock(&adev->srbm_mutex); mutex_lock(&adev->srbm_mutex);
vi_srbm_select(adev, ring->me, ring->pipe, ring->queue, 0); vi_srbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
gfx_v8_0_mqd_init(ring); gfx_v8_0_mqd_init(ring);

View File

@@ -1564,7 +1564,7 @@ static void gfx_v9_0_init_always_on_cu_mask(struct amdgpu_device *adev)
mask = 1; mask = 1;
cu_bitmap = 0; cu_bitmap = 0;
counter = 0; counter = 0;
gfx_v9_0_select_se_sh(adev, i, j, 0xffffffff); amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff);
for (k = 0; k < adev->gfx.config.max_cu_per_sh; k ++) { for (k = 0; k < adev->gfx.config.max_cu_per_sh; k ++) {
if (cu_info->bitmap[i][j] & mask) { if (cu_info->bitmap[i][j] & mask) {
@@ -1583,7 +1583,7 @@ static void gfx_v9_0_init_always_on_cu_mask(struct amdgpu_device *adev)
cu_info->ao_cu_bitmap[i][j] = cu_bitmap; cu_info->ao_cu_bitmap[i][j] = cu_bitmap;
} }
} }
gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex); mutex_unlock(&adev->grbm_idx_mutex);
} }
@@ -1605,7 +1605,7 @@ static void gfx_v9_0_init_lbpw(struct amdgpu_device *adev)
mutex_lock(&adev->grbm_idx_mutex); mutex_lock(&adev->grbm_idx_mutex);
/* set mmRLC_LB_INIT_CU_MASK thru broadcast mode to enable all SE/SH*/ /* set mmRLC_LB_INIT_CU_MASK thru broadcast mode to enable all SE/SH*/
gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
WREG32_SOC15(GC, 0, mmRLC_LB_INIT_CU_MASK, 0xffffffff); WREG32_SOC15(GC, 0, mmRLC_LB_INIT_CU_MASK, 0xffffffff);
/* set mmRLC_LB_PARAMS = 0x003F_1006 */ /* set mmRLC_LB_PARAMS = 0x003F_1006 */
@@ -1654,7 +1654,7 @@ static void gfx_v9_4_init_lbpw(struct amdgpu_device *adev)
mutex_lock(&adev->grbm_idx_mutex); mutex_lock(&adev->grbm_idx_mutex);
/* set mmRLC_LB_INIT_CU_MASK thru broadcast mode to enable all SE/SH*/ /* set mmRLC_LB_INIT_CU_MASK thru broadcast mode to enable all SE/SH*/
gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
WREG32_SOC15(GC, 0, mmRLC_LB_INIT_CU_MASK, 0xffffffff); WREG32_SOC15(GC, 0, mmRLC_LB_INIT_CU_MASK, 0xffffffff);
/* set mmRLC_LB_PARAMS = 0x003F_1006 */ /* set mmRLC_LB_PARAMS = 0x003F_1006 */
@@ -1919,8 +1919,6 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
u32 gb_addr_config; u32 gb_addr_config;
int err; int err;
adev->gfx.funcs = &gfx_v9_0_gfx_funcs;
switch (adev->ip_versions[GC_HWIP][0]) { switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(9, 0, 1): case IP_VERSION(9, 0, 1):
adev->gfx.config.max_hw_contexts = 8; adev->gfx.config.max_hw_contexts = 8;
@@ -2324,13 +2322,13 @@ static void gfx_v9_0_setup_rb(struct amdgpu_device *adev)
mutex_lock(&adev->grbm_idx_mutex); mutex_lock(&adev->grbm_idx_mutex);
for (i = 0; i < adev->gfx.config.max_shader_engines; i++) { for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) { for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
gfx_v9_0_select_se_sh(adev, i, j, 0xffffffff); amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff);
data = gfx_v9_0_get_rb_active_bitmap(adev); data = gfx_v9_0_get_rb_active_bitmap(adev);
active_rbs |= data << ((i * adev->gfx.config.max_sh_per_se + j) * active_rbs |= data << ((i * adev->gfx.config.max_sh_per_se + j) *
rb_bitmap_width_per_sh); rb_bitmap_width_per_sh);
} }
} }
gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex); mutex_unlock(&adev->grbm_idx_mutex);
adev->gfx.config.backend_enable_mask = active_rbs; adev->gfx.config.backend_enable_mask = active_rbs;
@@ -2467,14 +2465,14 @@ static void gfx_v9_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
mutex_lock(&adev->grbm_idx_mutex); mutex_lock(&adev->grbm_idx_mutex);
for (i = 0; i < adev->gfx.config.max_shader_engines; i++) { for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) { for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
gfx_v9_0_select_se_sh(adev, i, j, 0xffffffff); amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff);
for (k = 0; k < adev->usec_timeout; k++) { for (k = 0; k < adev->usec_timeout; k++) {
if (RREG32_SOC15(GC, 0, mmRLC_SERDES_CU_MASTER_BUSY) == 0) if (RREG32_SOC15(GC, 0, mmRLC_SERDES_CU_MASTER_BUSY) == 0)
break; break;
udelay(1); udelay(1);
} }
if (k == adev->usec_timeout) { if (k == adev->usec_timeout) {
gfx_v9_0_select_se_sh(adev, 0xffffffff, amdgpu_gfx_select_se_sh(adev, 0xffffffff,
0xffffffff, 0xffffffff); 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex); mutex_unlock(&adev->grbm_idx_mutex);
DRM_INFO("Timeout wait for RLC serdes %u,%u\n", DRM_INFO("Timeout wait for RLC serdes %u,%u\n",
@@ -2483,7 +2481,7 @@ static void gfx_v9_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
} }
} }
} }
gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex); mutex_unlock(&adev->grbm_idx_mutex);
mask = RLC_SERDES_NONCU_MASTER_BUSY__SE_MASTER_BUSY_MASK | mask = RLC_SERDES_NONCU_MASTER_BUSY__SE_MASTER_BUSY_MASK |
@@ -3583,6 +3581,8 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring)
memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation)); memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation));
((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF;
((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; ((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF;
if (amdgpu_sriov_vf(adev) && adev->in_suspend)
amdgpu_ring_clear_ring(ring);
mutex_lock(&adev->srbm_mutex); mutex_lock(&adev->srbm_mutex);
soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
gfx_v9_0_mqd_init(ring); gfx_v9_0_mqd_init(ring);
@@ -4539,6 +4539,8 @@ static int gfx_v9_0_early_init(void *handle)
{ {
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
adev->gfx.funcs = &gfx_v9_0_gfx_funcs;
if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1) || if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1) ||
adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2)) adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2))
adev->gfx.num_gfx_rings = 0; adev->gfx.num_gfx_rings = 0;
@@ -6482,7 +6484,7 @@ static void gfx_v9_0_reset_ras_error_count(struct amdgpu_device *adev)
for (i = 0; i < ARRAY_SIZE(gfx_v9_0_edc_counter_regs); i++) { for (i = 0; i < ARRAY_SIZE(gfx_v9_0_edc_counter_regs); i++) {
for (j = 0; j < gfx_v9_0_edc_counter_regs[i].se_num; j++) { for (j = 0; j < gfx_v9_0_edc_counter_regs[i].se_num; j++) {
for (k = 0; k < gfx_v9_0_edc_counter_regs[i].instance; k++) { for (k = 0; k < gfx_v9_0_edc_counter_regs[i].instance; k++) {
gfx_v9_0_select_se_sh(adev, j, 0x0, k); amdgpu_gfx_select_se_sh(adev, j, 0x0, k);
RREG32(SOC15_REG_ENTRY_OFFSET(gfx_v9_0_edc_counter_regs[i])); RREG32(SOC15_REG_ENTRY_OFFSET(gfx_v9_0_edc_counter_regs[i]));
} }
} }
@@ -6544,7 +6546,7 @@ static void gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev,
for (i = 0; i < ARRAY_SIZE(gfx_v9_0_edc_counter_regs); i++) { for (i = 0; i < ARRAY_SIZE(gfx_v9_0_edc_counter_regs); i++) {
for (j = 0; j < gfx_v9_0_edc_counter_regs[i].se_num; j++) { for (j = 0; j < gfx_v9_0_edc_counter_regs[i].se_num; j++) {
for (k = 0; k < gfx_v9_0_edc_counter_regs[i].instance; k++) { for (k = 0; k < gfx_v9_0_edc_counter_regs[i].instance; k++) {
gfx_v9_0_select_se_sh(adev, j, 0, k); amdgpu_gfx_select_se_sh(adev, j, 0, k);
reg_value = reg_value =
RREG32(SOC15_REG_ENTRY_OFFSET(gfx_v9_0_edc_counter_regs[i])); RREG32(SOC15_REG_ENTRY_OFFSET(gfx_v9_0_edc_counter_regs[i]));
if (reg_value) if (reg_value)
@@ -6559,7 +6561,7 @@ static void gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev,
err_data->ce_count += sec_count; err_data->ce_count += sec_count;
err_data->ue_count += ded_count; err_data->ue_count += ded_count;
gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex); mutex_unlock(&adev->grbm_idx_mutex);
gfx_v9_0_query_utc_edc_status(adev, err_data); gfx_v9_0_query_utc_edc_status(adev, err_data);
@@ -6963,7 +6965,7 @@ static int gfx_v9_0_get_cu_info(struct amdgpu_device *adev,
mask = 1; mask = 1;
ao_bitmap = 0; ao_bitmap = 0;
counter = 0; counter = 0;
gfx_v9_0_select_se_sh(adev, i, j, 0xffffffff); amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff);
gfx_v9_0_set_user_cu_inactive_bitmap( gfx_v9_0_set_user_cu_inactive_bitmap(
adev, disable_masks[i * adev->gfx.config.max_sh_per_se + j]); adev, disable_masks[i * adev->gfx.config.max_sh_per_se + j]);
bitmap = gfx_v9_0_get_cu_active_bitmap(adev); bitmap = gfx_v9_0_get_cu_active_bitmap(adev);
@@ -6996,7 +6998,7 @@ static int gfx_v9_0_get_cu_info(struct amdgpu_device *adev,
cu_info->ao_cu_bitmap[i % 4][j + i / 4] = ao_bitmap; cu_info->ao_cu_bitmap[i % 4][j + i / 4] = ao_bitmap;
} }
} }
gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex); mutex_unlock(&adev->grbm_idx_mutex);
cu_info->number = active_cu_number; cu_info->number = active_cu_number;

View File

@@ -397,6 +397,9 @@ static void gfxhub_v2_1_gart_disable(struct amdgpu_device *adev)
ENABLE_ADVANCED_DRIVER_MODEL, 0); ENABLE_ADVANCED_DRIVER_MODEL, 0);
WREG32_SOC15(GC, 0, mmGCMC_VM_MX_L1_TLB_CNTL, tmp); WREG32_SOC15(GC, 0, mmGCMC_VM_MX_L1_TLB_CNTL, tmp);
if (amdgpu_sriov_vf(adev))
return;
/* Setup L2 cache */ /* Setup L2 cache */
WREG32_FIELD15(GC, 0, GCVM_L2_CNTL, ENABLE_L2_CACHE, 0); WREG32_FIELD15(GC, 0, GCVM_L2_CNTL, ENABLE_L2_CACHE, 0);
WREG32_SOC15(GC, 0, mmGCVM_L2_CNTL3, 0); WREG32_SOC15(GC, 0, mmGCVM_L2_CNTL3, 0);

View File

@@ -154,6 +154,9 @@ static void gfxhub_v3_0_3_init_system_aperture_regs(struct amdgpu_device *adev)
{ {
uint64_t value; uint64_t value;
if (amdgpu_sriov_vf(adev))
return;
/* Disable AGP. */ /* Disable AGP. */
WREG32_SOC15(GC, 0, regGCMC_VM_AGP_BASE, 0); WREG32_SOC15(GC, 0, regGCMC_VM_AGP_BASE, 0);
WREG32_SOC15(GC, 0, regGCMC_VM_AGP_TOP, 0); WREG32_SOC15(GC, 0, regGCMC_VM_AGP_TOP, 0);

View File

@@ -121,6 +121,10 @@ static int mes_v10_1_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
if (r < 1) { if (r < 1) {
DRM_ERROR("MES failed to response msg=%d\n", DRM_ERROR("MES failed to response msg=%d\n",
x_pkt->header.opcode); x_pkt->header.opcode);
while (halt_if_hws_hang)
schedule();
return -ETIMEDOUT; return -ETIMEDOUT;
} }
@@ -415,10 +419,6 @@ static int mes_v10_1_init_microcode(struct amdgpu_device *adev,
mes_hdr = (const struct mes_firmware_header_v1_0 *) mes_hdr = (const struct mes_firmware_header_v1_0 *)
adev->mes.fw[pipe]->data; adev->mes.fw[pipe]->data;
adev->mes.ucode_fw_version[pipe] =
le32_to_cpu(mes_hdr->mes_ucode_version);
adev->mes.ucode_fw_version[pipe] =
le32_to_cpu(mes_hdr->mes_ucode_data_version);
adev->mes.uc_start_addr[pipe] = adev->mes.uc_start_addr[pipe] =
le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) | le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) |
((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32); ((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32);

View File

@@ -98,7 +98,14 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
struct amdgpu_device *adev = mes->adev; struct amdgpu_device *adev = mes->adev;
struct amdgpu_ring *ring = &mes->ring; struct amdgpu_ring *ring = &mes->ring;
unsigned long flags; unsigned long flags;
signed long timeout = adev->usec_timeout;
if (amdgpu_emu_mode) {
timeout *= 100;
} else if (amdgpu_sriov_vf(adev)) {
/* Worst case in sriov where all other 15 VF timeout, each VF needs about 600ms */
timeout = 15 * 600 * 1000;
}
BUG_ON(size % 4 != 0); BUG_ON(size % 4 != 0);
spin_lock_irqsave(&mes->ring_lock, flags); spin_lock_irqsave(&mes->ring_lock, flags);
@@ -118,10 +125,14 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
DRM_DEBUG("MES msg=%d was emitted\n", x_pkt->header.opcode); DRM_DEBUG("MES msg=%d was emitted\n", x_pkt->header.opcode);
r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq, r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq,
adev->usec_timeout * (amdgpu_emu_mode ? 100 : 1)); timeout);
if (r < 1) { if (r < 1) {
DRM_ERROR("MES failed to response msg=%d\n", DRM_ERROR("MES failed to response msg=%d\n",
x_pkt->header.opcode); x_pkt->header.opcode);
while (halt_if_hws_hang)
schedule();
return -ETIMEDOUT; return -ETIMEDOUT;
} }
@@ -478,10 +489,6 @@ static int mes_v11_0_init_microcode(struct amdgpu_device *adev,
mes_hdr = (const struct mes_firmware_header_v1_0 *) mes_hdr = (const struct mes_firmware_header_v1_0 *)
adev->mes.fw[pipe]->data; adev->mes.fw[pipe]->data;
adev->mes.ucode_fw_version[pipe] =
le32_to_cpu(mes_hdr->mes_ucode_version);
adev->mes.ucode_fw_version[pipe] =
le32_to_cpu(mes_hdr->mes_ucode_data_version);
adev->mes.uc_start_addr[pipe] = adev->mes.uc_start_addr[pipe] =
le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) | le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) |
((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32); ((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32);

View File

@@ -32,8 +32,6 @@
#include "gc/gc_10_1_0_offset.h" #include "gc/gc_10_1_0_offset.h"
#include "soc15_common.h" #include "soc15_common.h"
#define mmMM_ATC_L2_MISC_CG_Sienna_Cichlid 0x064d
#define mmMM_ATC_L2_MISC_CG_Sienna_Cichlid_BASE_IDX 0
#define mmDAGB0_CNTL_MISC2_Sienna_Cichlid 0x0070 #define mmDAGB0_CNTL_MISC2_Sienna_Cichlid 0x0070
#define mmDAGB0_CNTL_MISC2_Sienna_Cichlid_BASE_IDX 0 #define mmDAGB0_CNTL_MISC2_Sienna_Cichlid_BASE_IDX 0
@@ -574,7 +572,6 @@ static void mmhub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *ad
case IP_VERSION(2, 1, 0): case IP_VERSION(2, 1, 0):
case IP_VERSION(2, 1, 1): case IP_VERSION(2, 1, 1):
case IP_VERSION(2, 1, 2): case IP_VERSION(2, 1, 2):
def = data = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG_Sienna_Cichlid);
def1 = data1 = RREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2_Sienna_Cichlid); def1 = data1 = RREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2_Sienna_Cichlid);
break; break;
default: default:
@@ -608,8 +605,6 @@ static void mmhub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *ad
case IP_VERSION(2, 1, 0): case IP_VERSION(2, 1, 0):
case IP_VERSION(2, 1, 1): case IP_VERSION(2, 1, 1):
case IP_VERSION(2, 1, 2): case IP_VERSION(2, 1, 2):
if (def != data)
WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG_Sienna_Cichlid, data);
if (def1 != data1) if (def1 != data1)
WREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2_Sienna_Cichlid, data1); WREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2_Sienna_Cichlid, data1);
break; break;
@@ -634,8 +629,8 @@ static void mmhub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *ade
case IP_VERSION(2, 1, 0): case IP_VERSION(2, 1, 0):
case IP_VERSION(2, 1, 1): case IP_VERSION(2, 1, 1):
case IP_VERSION(2, 1, 2): case IP_VERSION(2, 1, 2):
def = data = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG_Sienna_Cichlid); /* There is no ATCL2 in MMHUB for 2.1.x */
break; return;
default: default:
def = data = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG); def = data = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG);
break; break;
@@ -646,18 +641,8 @@ static void mmhub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *ade
else else
data &= ~MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK; data &= ~MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK;
if (def != data) { if (def != data)
switch (adev->ip_versions[MMHUB_HWIP][0]) { WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG, data);
case IP_VERSION(2, 1, 0):
case IP_VERSION(2, 1, 1):
case IP_VERSION(2, 1, 2):
WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG_Sienna_Cichlid, data);
break;
default:
WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG, data);
break;
}
}
} }
static int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev, static int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev,
@@ -695,7 +680,10 @@ static void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u64 *flags)
case IP_VERSION(2, 1, 0): case IP_VERSION(2, 1, 0):
case IP_VERSION(2, 1, 1): case IP_VERSION(2, 1, 1):
case IP_VERSION(2, 1, 2): case IP_VERSION(2, 1, 2):
data = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG_Sienna_Cichlid); /* There is no ATCL2 in MMHUB for 2.1.x. Keep the status
* based on DAGB
*/
data = MM_ATC_L2_MISC_CG__ENABLE_MASK;
data1 = RREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2_Sienna_Cichlid); data1 = RREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2_Sienna_Cichlid);
break; break;
default: default:

View File

@@ -455,6 +455,9 @@ static void sdma_v6_0_enable(struct amdgpu_device *adev, bool enable)
sdma_v6_0_rlc_stop(adev); sdma_v6_0_rlc_stop(adev);
} }
if (amdgpu_sriov_vf(adev))
return;
for (i = 0; i < adev->sdma.num_instances; i++) { for (i = 0; i < adev->sdma.num_instances; i++) {
f32_cntl = RREG32_SOC15_IP(GC, sdma_v6_0_get_reg_offset(adev, i, regSDMA0_F32_CNTL)); f32_cntl = RREG32_SOC15_IP(GC, sdma_v6_0_get_reg_offset(adev, i, regSDMA0_F32_CNTL));
f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, enable ? 0 : 1); f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, enable ? 0 : 1);
@@ -1523,6 +1526,7 @@ static const struct amdgpu_ring_funcs sdma_v6_0_ring_funcs = {
.align_mask = 0xf, .align_mask = 0xf,
.nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), .nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP),
.support_64bit_ptrs = true, .support_64bit_ptrs = true,
.secure_submission_supported = true,
.vmhub = AMDGPU_GFXHUB_0, .vmhub = AMDGPU_GFXHUB_0,
.get_rptr = sdma_v6_0_ring_get_rptr, .get_rptr = sdma_v6_0_ring_get_rptr,
.get_wptr = sdma_v6_0_ring_get_wptr, .get_wptr = sdma_v6_0_ring_get_wptr,

View File

@@ -112,14 +112,12 @@ static void si_dma_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
static void si_dma_stop(struct amdgpu_device *adev) static void si_dma_stop(struct amdgpu_device *adev)
{ {
struct amdgpu_ring *ring;
u32 rb_cntl; u32 rb_cntl;
unsigned i; unsigned i;
amdgpu_sdma_unset_buffer_funcs_helper(adev); amdgpu_sdma_unset_buffer_funcs_helper(adev);
for (i = 0; i < adev->sdma.num_instances; i++) { for (i = 0; i < adev->sdma.num_instances; i++) {
ring = &adev->sdma.instance[i].ring;
/* dma0 */ /* dma0 */
rb_cntl = RREG32(DMA_RB_CNTL + sdma_offsets[i]); rb_cntl = RREG32(DMA_RB_CNTL + sdma_offsets[i]);
rb_cntl &= ~DMA_RB_ENABLE; rb_cntl &= ~DMA_RB_ENABLE;

View File

@@ -584,10 +584,6 @@ static int soc21_common_early_init(void *handle)
AMD_PG_SUPPORT_JPEG | AMD_PG_SUPPORT_JPEG |
AMD_PG_SUPPORT_ATHUB | AMD_PG_SUPPORT_ATHUB |
AMD_PG_SUPPORT_MMHUB; AMD_PG_SUPPORT_MMHUB;
if (amdgpu_sriov_vf(adev)) {
adev->cg_flags = 0;
adev->pg_flags = 0;
}
adev->external_rev_id = adev->rev_id + 0x1; // TODO: need update adev->external_rev_id = adev->rev_id + 0x1; // TODO: need update
break; break;
case IP_VERSION(11, 0, 2): case IP_VERSION(11, 0, 2):
@@ -645,11 +641,6 @@ static int soc21_common_early_init(void *handle)
adev->pg_flags = AMD_PG_SUPPORT_VCN | adev->pg_flags = AMD_PG_SUPPORT_VCN |
AMD_PG_SUPPORT_VCN_DPG | AMD_PG_SUPPORT_VCN_DPG |
AMD_PG_SUPPORT_JPEG; AMD_PG_SUPPORT_JPEG;
if (amdgpu_sriov_vf(adev)) {
/* hypervisor control CG and PG enablement */
adev->cg_flags = 0;
adev->pg_flags = 0;
}
adev->external_rev_id = adev->rev_id + 0x20; adev->external_rev_id = adev->rev_id + 0x20;
break; break;
default: default:
@@ -657,6 +648,9 @@ static int soc21_common_early_init(void *handle)
return -EINVAL; return -EINVAL;
} }
if (amdgpu_sriov_vf(adev))
amdgpu_virt_init_setting(adev);
return 0; return 0;
} }

View File

@@ -187,9 +187,9 @@ static void umc_v6_7_ecc_info_query_ras_error_count(struct amdgpu_device *adev,
} }
} }
static void umc_v6_7_convert_error_address(struct amdgpu_device *adev, void umc_v6_7_convert_error_address(struct amdgpu_device *adev,
struct ras_err_data *err_data, uint64_t err_addr, struct ras_err_data *err_data, uint64_t err_addr,
uint32_t ch_inst, uint32_t umc_inst) uint32_t ch_inst, uint32_t umc_inst)
{ {
uint32_t channel_index; uint32_t channel_index;
uint64_t soc_pa, retired_page, column; uint64_t soc_pa, retired_page, column;
@@ -553,5 +553,4 @@ struct amdgpu_umc_ras umc_v6_7_ras = {
.query_ras_poison_mode = umc_v6_7_query_ras_poison_mode, .query_ras_poison_mode = umc_v6_7_query_ras_poison_mode,
.ecc_info_query_ras_error_count = umc_v6_7_ecc_info_query_ras_error_count, .ecc_info_query_ras_error_count = umc_v6_7_ecc_info_query_ras_error_count,
.ecc_info_query_ras_error_address = umc_v6_7_ecc_info_query_ras_error_address, .ecc_info_query_ras_error_address = umc_v6_7_ecc_info_query_ras_error_address,
.convert_ras_error_address = umc_v6_7_convert_error_address,
}; };

View File

@@ -71,5 +71,7 @@ extern const uint32_t
umc_v6_7_channel_idx_tbl_second[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM]; umc_v6_7_channel_idx_tbl_second[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM];
extern const uint32_t extern const uint32_t
umc_v6_7_channel_idx_tbl_first[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM]; umc_v6_7_channel_idx_tbl_first[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM];
void umc_v6_7_convert_error_address(struct amdgpu_device *adev,
struct ras_err_data *err_data, uint64_t err_addr,
uint32_t ch_inst, uint32_t umc_inst);
#endif #endif

View File

@@ -267,7 +267,7 @@ static void vega20_ih_reroute_ih(struct amdgpu_device *adev)
/* vega20 ih reroute will go through psp this /* vega20 ih reroute will go through psp this
* function is used for newer asics starting arcturus * function is used for newer asics starting arcturus
*/ */
if (adev->asic_type >= CHIP_ARCTURUS) { if (adev->ip_versions[OSSSYS_HWIP][0] >= IP_VERSION(4, 2, 1)) {
/* Reroute to IH ring 1 for VMC */ /* Reroute to IH ring 1 for VMC */
WREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_INDEX, 0x12); WREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_INDEX, 0x12);
tmp = RREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_DATA); tmp = RREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_DATA);
@@ -308,7 +308,7 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev)
adev->nbio.funcs->ih_control(adev); adev->nbio.funcs->ih_control(adev);
if (adev->asic_type == CHIP_ARCTURUS && if ((adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 2, 1)) &&
adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) {
ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN); ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN);
if (adev->irq.ih.use_bus_addr) { if (adev->irq.ih.use_bus_addr) {
@@ -321,7 +321,7 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev)
/* psp firmware won't program IH_CHICKEN for aldebaran /* psp firmware won't program IH_CHICKEN for aldebaran
* driver needs to program it properly according to * driver needs to program it properly according to
* MC_SPACE type in IH_RB_CNTL */ * MC_SPACE type in IH_RB_CNTL */
if (adev->asic_type == CHIP_ALDEBARAN) { if (adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 0)) {
ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN_ALDEBARAN); ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN_ALDEBARAN);
if (adev->irq.ih.use_bus_addr) { if (adev->irq.ih.use_bus_addr) {
ih_chicken = REG_SET_FIELD(ih_chicken, IH_CHICKEN, ih_chicken = REG_SET_FIELD(ih_chicken, IH_CHICKEN,

View File

@@ -2495,442 +2495,444 @@ static const uint32_t cwsr_trap_gfx10_hex[] = {
0xbf9f0000, 0x00000000, 0xbf9f0000, 0x00000000,
}; };
static const uint32_t cwsr_trap_gfx11_hex[] = { static const uint32_t cwsr_trap_gfx11_hex[] = {
0xbfa00001, 0xbfa0021e, 0xbfa00001, 0xbfa00221,
0xb0804006, 0xb8f8f802, 0xb0804006, 0xb8f8f802,
0x9178ff78, 0x00020006, 0x9178ff78, 0x00020006,
0xb8fbf803, 0xbf0d9f6d, 0xb8fbf803, 0xbf0d9e6d,
0xbfa20006, 0x8b6eff78, 0xbfa10001, 0xbfbd0000,
0x00002000, 0xbfa10009, 0xbf0d9f6d, 0xbfa20006,
0x8b6eff6d, 0x00ff0000, 0x8b6eff78, 0x00002000,
0xbfa2001e, 0x8b6eff7b, 0xbfa10009, 0x8b6eff6d,
0x00000400, 0xbfa20041, 0x00ff0000, 0xbfa2001e,
0xbf830010, 0xb8fbf803,
0xbfa0fffa, 0x8b6eff7b,
0x00000900, 0xbfa20015,
0x8b6eff7b, 0x000071ff,
0xbfa10008, 0x8b6fff7b,
0x00007080, 0xbfa10001,
0xbeee1287, 0xb8eff801,
0x846e8c6e, 0x8b6e6f6e,
0xbfa2000a, 0x8b6eff6d,
0x00ff0000, 0xbfa20007,
0xb8eef801, 0x8b6eff6e,
0x00000800, 0xbfa20003,
0x8b6eff7b, 0x00000400, 0x8b6eff7b, 0x00000400,
0xbfa20026, 0xbefa4d82, 0xbfa20041, 0xbf830010,
0xbf89fc07, 0x84fa887a, 0xb8fbf803, 0xbfa0fffa,
0xf4005bbd, 0xf8000010, 0x8b6eff7b, 0x00000900,
0xbf89fc07, 0x846e976e, 0xbfa20015, 0x8b6eff7b,
0x9177ff77, 0x00800000, 0x000071ff, 0xbfa10008,
0x8c776e77, 0xf4045bbd, 0x8b6fff7b, 0x00007080,
0xf8000000, 0xbf89fc07, 0xbfa10001, 0xbeee1287,
0xf4045ebd, 0xf8000008, 0xb8eff801, 0x846e8c6e,
0xbf89fc07, 0x8bee6e6e, 0x8b6e6f6e, 0xbfa2000a,
0xbfa10001, 0xbe80486e, 0x8b6eff6d, 0x00ff0000,
0x8b6eff6d, 0x01ff0000, 0xbfa20007, 0xb8eef801,
0xbfa20005, 0x8c78ff78, 0x8b6eff6e, 0x00000800,
0x00002000, 0x80ec886c, 0xbfa20003, 0x8b6eff7b,
0x82ed806d, 0xbfa00005, 0x00000400, 0xbfa20026,
0x8b6eff6d, 0x01000000, 0xbefa4d82, 0xbf89fc07,
0xbfa20002, 0x806c846c, 0x84fa887a, 0xf4005bbd,
0x826d806d, 0x8b6dff6d, 0xf8000010, 0xbf89fc07,
0x0000ffff, 0x8bfe7e7e, 0x846e976e, 0x9177ff77,
0x8bea6a6a, 0xb978f802, 0x00800000, 0x8c776e77,
0xbe804a6c, 0x8b6dff6d, 0xf4045bbd, 0xf8000000,
0x0000ffff, 0xbefa0080, 0xbf89fc07, 0xf4045ebd,
0xb97a0283, 0xbeee007e, 0xf8000008, 0xbf89fc07,
0xbeef007f, 0xbefe0180, 0x8bee6e6e, 0xbfa10001,
0xbefe4d84, 0xbf89fc07, 0xbe80486e, 0x8b6eff6d,
0x8b7aff7f, 0x04000000, 0x01ff0000, 0xbfa20005,
0x847a857a, 0x8c6d7a6d, 0x8c78ff78, 0x00002000,
0xbefa007e, 0x8b7bff7f, 0x80ec886c, 0x82ed806d,
0x0000ffff, 0xbefe00c1, 0xbfa00005, 0x8b6eff6d,
0xbeff00c1, 0xdca6c000, 0x01000000, 0xbfa20002,
0x007a0000, 0x7e000280, 0x806c846c, 0x826d806d,
0xbefe007a, 0xbeff007b, 0x8b6dff6d, 0x0000ffff,
0xb8fb02dc, 0x847b997b, 0x8bfe7e7e, 0x8bea6a6a,
0xb8fa3b05, 0x807a817a, 0xb978f802, 0xbe804a6c,
0xbf0d997b, 0xbfa20002, 0x8b6dff6d, 0x0000ffff,
0x847a897a, 0xbfa00001, 0xbefa0080, 0xb97a0283,
0x847a8a7a, 0xb8fb1e06, 0xbeee007e, 0xbeef007f,
0x847b8a7b, 0x807a7b7a, 0xbefe0180, 0xbefe4d84,
0xbf89fc07, 0x8b7aff7f,
0x04000000, 0x847a857a,
0x8c6d7a6d, 0xbefa007e,
0x8b7bff7f, 0x0000ffff, 0x8b7bff7f, 0x0000ffff,
0x807aff7a, 0x00000200, 0xbefe00c1, 0xbeff00c1,
0x807a7e7a, 0x827b807b, 0xdca6c000, 0x007a0000,
0xd7610000, 0x00010870, 0x7e000280, 0xbefe007a,
0xd7610000, 0x00010a71, 0xbeff007b, 0xb8fb02dc,
0xd7610000, 0x00010c72, 0x847b997b, 0xb8fa3b05,
0xd7610000, 0x00010e73, 0x807a817a, 0xbf0d997b,
0xd7610000, 0x00011074, 0xbfa20002, 0x847a897a,
0xd7610000, 0x00011275, 0xbfa00001, 0x847a8a7a,
0xd7610000, 0x00011476, 0xb8fb1e06, 0x847b8a7b,
0xd7610000, 0x00011677, 0x807a7b7a, 0x8b7bff7f,
0xd7610000, 0x00011a79, 0x0000ffff, 0x807aff7a,
0xd7610000, 0x00011c7e, 0x00000200, 0x807a7e7a,
0xd7610000, 0x00011e7f, 0x827b807b, 0xd7610000,
0xbefe00ff, 0x00003fff, 0x00010870, 0xd7610000,
0xbeff0080, 0xdca6c040, 0x00010a71, 0xd7610000,
0x007a0000, 0xd760007a, 0x00010c72, 0xd7610000,
0x00011d00, 0xd760007b, 0x00010e73, 0xd7610000,
0x00011f00, 0xbefe007a, 0x00011074, 0xd7610000,
0xbeff007b, 0xbef4007e, 0x00011275, 0xd7610000,
0x8b75ff7f, 0x0000ffff, 0x00011476, 0xd7610000,
0x8c75ff75, 0x00040000, 0x00011677, 0xd7610000,
0xbef60080, 0xbef700ff, 0x00011a79, 0xd7610000,
0x10807fac, 0xbef1007d, 0x00011c7e, 0xd7610000,
0xbef00080, 0xb8f302dc, 0x00011e7f, 0xbefe00ff,
0x84739973, 0xbefe00c1, 0x00003fff, 0xbeff0080,
0x857d9973, 0x8b7d817d, 0xdca6c040, 0x007a0000,
0xbf06817d, 0xbfa20002, 0xd760007a, 0x00011d00,
0xbeff0080, 0xbfa00002, 0xd760007b, 0x00011f00,
0xbeff00c1, 0xbfa00009, 0xbefe007a, 0xbeff007b,
0xbef4007e, 0x8b75ff7f,
0x0000ffff, 0x8c75ff75,
0x00040000, 0xbef60080,
0xbef700ff, 0x10807fac,
0xbef1007d, 0xbef00080,
0xb8f302dc, 0x84739973,
0xbefe00c1, 0x857d9973,
0x8b7d817d, 0xbf06817d,
0xbfa20002, 0xbeff0080,
0xbfa00002, 0xbeff00c1,
0xbfa00009, 0xbef600ff,
0x01000000, 0xe0685080,
0x701d0100, 0xe0685100,
0x701d0200, 0xe0685180,
0x701d0300, 0xbfa00008,
0xbef600ff, 0x01000000, 0xbef600ff, 0x01000000,
0xe0685080, 0x701d0100, 0xe0685100, 0x701d0100,
0xe0685100, 0x701d0200, 0xe0685200, 0x701d0200,
0xe0685180, 0x701d0300, 0xe0685300, 0x701d0300,
0xbfa00008, 0xbef600ff,
0x01000000, 0xe0685100,
0x701d0100, 0xe0685200,
0x701d0200, 0xe0685300,
0x701d0300, 0xb8f03b05,
0x80708170, 0xbf0d9973,
0xbfa20002, 0x84708970,
0xbfa00001, 0x84708a70,
0xb8fa1e06, 0x847a8a7a,
0x80707a70, 0x8070ff70,
0x00000200, 0xbef600ff,
0x01000000, 0x7e000280,
0x7e020280, 0x7e040280,
0xbefd0080, 0xd7610002,
0x0000fa71, 0x807d817d,
0xd7610002, 0x0000fa6c,
0x807d817d, 0x917aff6d,
0x80000000, 0xd7610002,
0x0000fa7a, 0x807d817d,
0xd7610002, 0x0000fa6e,
0x807d817d, 0xd7610002,
0x0000fa6f, 0x807d817d,
0xd7610002, 0x0000fa78,
0x807d817d, 0xb8faf803,
0xd7610002, 0x0000fa7a,
0x807d817d, 0xd7610002,
0x0000fa7b, 0x807d817d,
0xb8f1f801, 0xd7610002,
0x0000fa71, 0x807d817d,
0xb8f1f814, 0xd7610002,
0x0000fa71, 0x807d817d,
0xb8f1f815, 0xd7610002,
0x0000fa71, 0x807d817d,
0xbefe00ff, 0x0000ffff,
0xbeff0080, 0xe0685000,
0x701d0200, 0xbefe00c1,
0xb8f03b05, 0x80708170, 0xb8f03b05, 0x80708170,
0xbf0d9973, 0xbfa20002, 0xbf0d9973, 0xbfa20002,
0x84708970, 0xbfa00001, 0x84708970, 0xbfa00001,
0x84708a70, 0xb8fa1e06, 0x84708a70, 0xb8fa1e06,
0x847a8a7a, 0x80707a70, 0x847a8a7a, 0x80707a70,
0x8070ff70, 0x00000200,
0xbef600ff, 0x01000000, 0xbef600ff, 0x01000000,
0xbef90080, 0xbefd0080, 0x7e000280, 0x7e020280,
0xbf800000, 0xbe804100, 0x7e040280, 0xbefd0080,
0xbe824102, 0xbe844104, 0xd7610002, 0x0000fa71,
0xbe864106, 0xbe884108, 0x807d817d, 0xd7610002,
0xbe8a410a, 0xbe8c410c, 0x0000fa6c, 0x807d817d,
0xbe8e410e, 0xd7610002, 0x917aff6d, 0x80000000,
0x0000f200, 0x80798179, 0xd7610002, 0x0000fa7a,
0xd7610002, 0x0000f201, 0x807d817d, 0xd7610002,
0x80798179, 0xd7610002, 0x0000fa6e, 0x807d817d,
0x0000f202, 0x80798179, 0xd7610002, 0x0000fa6f,
0xd7610002, 0x0000f203, 0x807d817d, 0xd7610002,
0x80798179, 0xd7610002, 0x0000fa78, 0x807d817d,
0x0000f204, 0x80798179, 0xb8faf803, 0xd7610002,
0xd7610002, 0x0000f205, 0x0000fa7a, 0x807d817d,
0x80798179, 0xd7610002, 0xd7610002, 0x0000fa7b,
0x0000f206, 0x80798179, 0x807d817d, 0xb8f1f801,
0xd7610002, 0x0000f207, 0xd7610002, 0x0000fa71,
0x80798179, 0xd7610002, 0x807d817d, 0xb8f1f814,
0x0000f208, 0x80798179, 0xd7610002, 0x0000fa71,
0xd7610002, 0x0000f209, 0x807d817d, 0xb8f1f815,
0x80798179, 0xd7610002, 0xd7610002, 0x0000fa71,
0x0000f20a, 0x80798179, 0x807d817d, 0xbefe00ff,
0xd7610002, 0x0000f20b, 0x0000ffff, 0xbeff0080,
0x80798179, 0xd7610002, 0xe0685000, 0x701d0200,
0x0000f20c, 0x80798179, 0xbefe00c1, 0xb8f03b05,
0xd7610002, 0x0000f20d,
0x80798179, 0xd7610002,
0x0000f20e, 0x80798179,
0xd7610002, 0x0000f20f,
0x80798179, 0xbf06a079,
0xbfa10006, 0xe0685000,
0x701d0200, 0x8070ff70,
0x00000080, 0xbef90080,
0x7e040280, 0x807d907d,
0xbf0aff7d, 0x00000060,
0xbfa2ffbc, 0xbe804100,
0xbe824102, 0xbe844104,
0xbe864106, 0xbe884108,
0xbe8a410a, 0xd7610002,
0x0000f200, 0x80798179,
0xd7610002, 0x0000f201,
0x80798179, 0xd7610002,
0x0000f202, 0x80798179,
0xd7610002, 0x0000f203,
0x80798179, 0xd7610002,
0x0000f204, 0x80798179,
0xd7610002, 0x0000f205,
0x80798179, 0xd7610002,
0x0000f206, 0x80798179,
0xd7610002, 0x0000f207,
0x80798179, 0xd7610002,
0x0000f208, 0x80798179,
0xd7610002, 0x0000f209,
0x80798179, 0xd7610002,
0x0000f20a, 0x80798179,
0xd7610002, 0x0000f20b,
0x80798179, 0xe0685000,
0x701d0200, 0xbefe00c1,
0x857d9973, 0x8b7d817d,
0xbf06817d, 0xbfa20002,
0xbeff0080, 0xbfa00001,
0xbeff00c1, 0xb8fb4306,
0x8b7bc17b, 0xbfa10044,
0xbfbd0000, 0x8b7aff6d,
0x80000000, 0xbfa10040,
0x847b867b, 0x847b827b,
0xbef6007b, 0xb8f03b05,
0x80708170, 0xbf0d9973, 0x80708170, 0xbf0d9973,
0xbfa20002, 0x84708970, 0xbfa20002, 0x84708970,
0xbfa00001, 0x84708a70, 0xbfa00001, 0x84708a70,
0xb8fa1e06, 0x847a8a7a, 0xb8fa1e06, 0x847a8a7a,
0x80707a70, 0x8070ff70, 0x80707a70, 0xbef600ff,
0x00000200, 0x8070ff70, 0x01000000, 0xbef90080,
0x00000080, 0xbef600ff, 0xbefd0080, 0xbf800000,
0x01000000, 0xd71f0000, 0xbe804100, 0xbe824102,
0x000100c1, 0xd7200000, 0xbe844104, 0xbe864106,
0x000200c1, 0x16000084, 0xbe884108, 0xbe8a410a,
0x857d9973, 0x8b7d817d, 0xbe8c410c, 0xbe8e410e,
0xbf06817d, 0xbefd0080, 0xd7610002, 0x0000f200,
0xbfa20012, 0xbe8300ff, 0x80798179, 0xd7610002,
0x00000080, 0xbf800000, 0x0000f201, 0x80798179,
0xbf800000, 0xbf800000, 0xd7610002, 0x0000f202,
0xd8d80000, 0x01000000, 0x80798179, 0xd7610002,
0xbf890000, 0xe0685000, 0x0000f203, 0x80798179,
0x701d0100, 0x807d037d, 0xd7610002, 0x0000f204,
0x80700370, 0xd5250000, 0x80798179, 0xd7610002,
0x0001ff00, 0x00000080, 0x0000f205, 0x80798179,
0xbf0a7b7d, 0xbfa2fff4, 0xd7610002, 0x0000f206,
0xbfa00011, 0xbe8300ff, 0x80798179, 0xd7610002,
0x00000100, 0xbf800000, 0x0000f207, 0x80798179,
0xbf800000, 0xbf800000, 0xd7610002, 0x0000f208,
0xd8d80000, 0x01000000, 0x80798179, 0xd7610002,
0xbf890000, 0xe0685000, 0x0000f209, 0x80798179,
0x701d0100, 0x807d037d, 0xd7610002, 0x0000f20a,
0x80700370, 0xd5250000, 0x80798179, 0xd7610002,
0x0001ff00, 0x00000100, 0x0000f20b, 0x80798179,
0xbf0a7b7d, 0xbfa2fff4, 0xd7610002, 0x0000f20c,
0x80798179, 0xd7610002,
0x0000f20d, 0x80798179,
0xd7610002, 0x0000f20e,
0x80798179, 0xd7610002,
0x0000f20f, 0x80798179,
0xbf06a079, 0xbfa10006,
0xe0685000, 0x701d0200,
0x8070ff70, 0x00000080,
0xbef90080, 0x7e040280,
0x807d907d, 0xbf0aff7d,
0x00000060, 0xbfa2ffbc,
0xbe804100, 0xbe824102,
0xbe844104, 0xbe864106,
0xbe884108, 0xbe8a410a,
0xd7610002, 0x0000f200,
0x80798179, 0xd7610002,
0x0000f201, 0x80798179,
0xd7610002, 0x0000f202,
0x80798179, 0xd7610002,
0x0000f203, 0x80798179,
0xd7610002, 0x0000f204,
0x80798179, 0xd7610002,
0x0000f205, 0x80798179,
0xd7610002, 0x0000f206,
0x80798179, 0xd7610002,
0x0000f207, 0x80798179,
0xd7610002, 0x0000f208,
0x80798179, 0xd7610002,
0x0000f209, 0x80798179,
0xd7610002, 0x0000f20a,
0x80798179, 0xd7610002,
0x0000f20b, 0x80798179,
0xe0685000, 0x701d0200,
0xbefe00c1, 0x857d9973, 0xbefe00c1, 0x857d9973,
0x8b7d817d, 0xbf06817d, 0x8b7d817d, 0xbf06817d,
0xbfa20004, 0xbef000ff, 0xbfa20002, 0xbeff0080,
0x00000200, 0xbeff0080, 0xbfa00001, 0xbeff00c1,
0xbfa00003, 0xbef000ff, 0xb8fb4306, 0x8b7bc17b,
0x00000400, 0xbeff00c1, 0xbfa10044, 0xbfbd0000,
0xb8fb3b05, 0x807b817b, 0x8b7aff6d, 0x80000000,
0x847b827b, 0x857d9973, 0xbfa10040, 0x847b867b,
0x847b827b, 0xbef6007b,
0xb8f03b05, 0x80708170,
0xbf0d9973, 0xbfa20002,
0x84708970, 0xbfa00001,
0x84708a70, 0xb8fa1e06,
0x847a8a7a, 0x80707a70,
0x8070ff70, 0x00000200,
0x8070ff70, 0x00000080,
0xbef600ff, 0x01000000,
0xd71f0000, 0x000100c1,
0xd7200000, 0x000200c1,
0x16000084, 0x857d9973,
0x8b7d817d, 0xbf06817d, 0x8b7d817d, 0xbf06817d,
0xbfa20017, 0xbef600ff, 0xbefd0080, 0xbfa20012,
0xbe8300ff, 0x00000080,
0xbf800000, 0xbf800000,
0xbf800000, 0xd8d80000,
0x01000000, 0xbf890000,
0xe0685000, 0x701d0100,
0x807d037d, 0x80700370,
0xd5250000, 0x0001ff00,
0x00000080, 0xbf0a7b7d,
0xbfa2fff4, 0xbfa00011,
0xbe8300ff, 0x00000100,
0xbf800000, 0xbf800000,
0xbf800000, 0xd8d80000,
0x01000000, 0xbf890000,
0xe0685000, 0x701d0100,
0x807d037d, 0x80700370,
0xd5250000, 0x0001ff00,
0x00000100, 0xbf0a7b7d,
0xbfa2fff4, 0xbefe00c1,
0x857d9973, 0x8b7d817d,
0xbf06817d, 0xbfa20004,
0xbef000ff, 0x00000200,
0xbeff0080, 0xbfa00003,
0xbef000ff, 0x00000400,
0xbeff00c1, 0xb8fb3b05,
0x807b817b, 0x847b827b,
0x857d9973, 0x8b7d817d,
0xbf06817d, 0xbfa20017,
0xbef600ff, 0x01000000,
0xbefd0084, 0xbf0a7b7d,
0xbfa10037, 0x7e008700,
0x7e028701, 0x7e048702,
0x7e068703, 0xe0685000,
0x701d0000, 0xe0685080,
0x701d0100, 0xe0685100,
0x701d0200, 0xe0685180,
0x701d0300, 0x807d847d,
0x8070ff70, 0x00000200,
0xbf0a7b7d, 0xbfa2ffef,
0xbfa00025, 0xbef600ff,
0x01000000, 0xbefd0084, 0x01000000, 0xbefd0084,
0xbf0a7b7d, 0xbfa10037, 0xbf0a7b7d, 0xbfa10011,
0x7e008700, 0x7e028701, 0x7e008700, 0x7e028701,
0x7e048702, 0x7e068703, 0x7e048702, 0x7e068703,
0xe0685000, 0x701d0000, 0xe0685000, 0x701d0000,
0xe0685080, 0x701d0100, 0xe0685100, 0x701d0100,
0xe0685100, 0x701d0200, 0xe0685200, 0x701d0200,
0xe0685180, 0x701d0300, 0xe0685300, 0x701d0300,
0x807d847d, 0x8070ff70, 0x807d847d, 0x8070ff70,
0x00000200, 0xbf0a7b7d, 0x00000400, 0xbf0a7b7d,
0xbfa2ffef, 0xbfa00025, 0xbfa2ffef, 0xb8fb1e06,
0xbef600ff, 0x01000000, 0x8b7bc17b, 0xbfa1000c,
0xbefd0084, 0xbf0a7b7d, 0x847b837b, 0x807b7d7b,
0xbfa10011, 0x7e008700, 0xbefe00c1, 0xbeff0080,
0x7e028701, 0x7e048702, 0x7e008700, 0xe0685000,
0x7e068703, 0xe0685000, 0x701d0000, 0x807d817d,
0x701d0000, 0xe0685100, 0x8070ff70, 0x00000080,
0x701d0100, 0xe0685200, 0xbf0a7b7d, 0xbfa2fff8,
0x701d0200, 0xe0685300, 0xbfa00146, 0xbef4007e,
0x701d0300, 0x807d847d, 0x8b75ff7f, 0x0000ffff,
0x8070ff70, 0x00000400, 0x8c75ff75, 0x00040000,
0xbf0a7b7d, 0xbfa2ffef, 0xbef60080, 0xbef700ff,
0xb8fb1e06, 0x8b7bc17b, 0x10807fac, 0xb8f202dc,
0xbfa1000c, 0x847b837b, 0x84729972, 0x8b6eff7f,
0x807b7d7b, 0xbefe00c1, 0x04000000, 0xbfa1003a,
0xbeff0080, 0x7e008700,
0xe0685000, 0x701d0000,
0x807d817d, 0x8070ff70,
0x00000080, 0xbf0a7b7d,
0xbfa2fff8, 0xbfa00146,
0xbef4007e, 0x8b75ff7f,
0x0000ffff, 0x8c75ff75,
0x00040000, 0xbef60080,
0xbef700ff, 0x10807fac,
0xb8f202dc, 0x84729972,
0x8b6eff7f, 0x04000000,
0xbfa1003a, 0xbefe00c1,
0x857d9972, 0x8b7d817d,
0xbf06817d, 0xbfa20002,
0xbeff0080, 0xbfa00001,
0xbeff00c1, 0xb8ef4306,
0x8b6fc16f, 0xbfa1002f,
0x846f866f, 0x846f826f,
0xbef6006f, 0xb8f83b05,
0x80788178, 0xbf0d9972,
0xbfa20002, 0x84788978,
0xbfa00001, 0x84788a78,
0xb8ee1e06, 0x846e8a6e,
0x80786e78, 0x8078ff78,
0x00000200, 0x8078ff78,
0x00000080, 0xbef600ff,
0x01000000, 0x857d9972,
0x8b7d817d, 0xbf06817d,
0xbefd0080, 0xbfa2000c,
0xe0500000, 0x781d0000,
0xbf8903f7, 0xdac00000,
0x00000000, 0x807dff7d,
0x00000080, 0x8078ff78,
0x00000080, 0xbf0a6f7d,
0xbfa2fff5, 0xbfa0000b,
0xe0500000, 0x781d0000,
0xbf8903f7, 0xdac00000,
0x00000000, 0x807dff7d,
0x00000100, 0x8078ff78,
0x00000100, 0xbf0a6f7d,
0xbfa2fff5, 0xbef80080,
0xbefe00c1, 0x857d9972, 0xbefe00c1, 0x857d9972,
0x8b7d817d, 0xbf06817d, 0x8b7d817d, 0xbf06817d,
0xbfa20002, 0xbeff0080, 0xbfa20002, 0xbeff0080,
0xbfa00001, 0xbeff00c1, 0xbfa00001, 0xbeff00c1,
0xb8ef3b05, 0x806f816f, 0xb8ef4306, 0x8b6fc16f,
0x846f826f, 0x857d9972, 0xbfa1002f, 0x846f866f,
0x8b7d817d, 0xbf06817d, 0x846f826f, 0xbef6006f,
0xbfa20024, 0xbef600ff,
0x01000000, 0xbeee0078,
0x8078ff78, 0x00000200,
0xbefd0084, 0xbf0a6f7d,
0xbfa10050, 0xe0505000,
0x781d0000, 0xe0505080,
0x781d0100, 0xe0505100,
0x781d0200, 0xe0505180,
0x781d0300, 0xbf8903f7,
0x7e008500, 0x7e028501,
0x7e048502, 0x7e068503,
0x807d847d, 0x8078ff78,
0x00000200, 0xbf0a6f7d,
0xbfa2ffee, 0xe0505000,
0x6e1d0000, 0xe0505080,
0x6e1d0100, 0xe0505100,
0x6e1d0200, 0xe0505180,
0x6e1d0300, 0xbf8903f7,
0xbfa00034, 0xbef600ff,
0x01000000, 0xbeee0078,
0x8078ff78, 0x00000400,
0xbefd0084, 0xbf0a6f7d,
0xbfa10012, 0xe0505000,
0x781d0000, 0xe0505100,
0x781d0100, 0xe0505200,
0x781d0200, 0xe0505300,
0x781d0300, 0xbf8903f7,
0x7e008500, 0x7e028501,
0x7e048502, 0x7e068503,
0x807d847d, 0x8078ff78,
0x00000400, 0xbf0a6f7d,
0xbfa2ffee, 0xb8ef1e06,
0x8b6fc16f, 0xbfa1000e,
0x846f836f, 0x806f7d6f,
0xbefe00c1, 0xbeff0080,
0xe0505000, 0x781d0000,
0xbf8903f7, 0x7e008500,
0x807d817d, 0x8078ff78,
0x00000080, 0xbf0a6f7d,
0xbfa2fff7, 0xbeff00c1,
0xe0505000, 0x6e1d0000,
0xe0505100, 0x6e1d0100,
0xe0505200, 0x6e1d0200,
0xe0505300, 0x6e1d0300,
0xbf8903f7, 0xb8f83b05,
0x80788178, 0xbf0d9972,
0xbfa20002, 0x84788978,
0xbfa00001, 0x84788a78,
0xb8ee1e06, 0x846e8a6e,
0x80786e78, 0x8078ff78,
0x00000200, 0x80f8ff78,
0x00000050, 0xbef600ff,
0x01000000, 0xbefd00ff,
0x0000006c, 0x80f89078,
0xf428403a, 0xf0000000,
0xbf89fc07, 0x80fd847d,
0xbf800000, 0xbe804300,
0xbe824302, 0x80f8a078,
0xf42c403a, 0xf0000000,
0xbf89fc07, 0x80fd887d,
0xbf800000, 0xbe804300,
0xbe824302, 0xbe844304,
0xbe864306, 0x80f8c078,
0xf430403a, 0xf0000000,
0xbf89fc07, 0x80fd907d,
0xbf800000, 0xbe804300,
0xbe824302, 0xbe844304,
0xbe864306, 0xbe884308,
0xbe8a430a, 0xbe8c430c,
0xbe8e430e, 0xbf06807d,
0xbfa1fff0, 0xb980f801,
0x00000000, 0xbfbd0000,
0xb8f83b05, 0x80788178, 0xb8f83b05, 0x80788178,
0xbf0d9972, 0xbfa20002, 0xbf0d9972, 0xbfa20002,
0x84788978, 0xbfa00001, 0x84788978, 0xbfa00001,
0x84788a78, 0xb8ee1e06, 0x84788a78, 0xb8ee1e06,
0x846e8a6e, 0x80786e78, 0x846e8a6e, 0x80786e78,
0x8078ff78, 0x00000200, 0x8078ff78, 0x00000200,
0x8078ff78, 0x00000080,
0xbef600ff, 0x01000000, 0xbef600ff, 0x01000000,
0xf4205bfa, 0xf0000000, 0x857d9972, 0x8b7d817d,
0x80788478, 0xf4205b3a, 0xbf06817d, 0xbefd0080,
0xbfa2000c, 0xe0500000,
0x781d0000, 0xbf8903f7,
0xdac00000, 0x00000000,
0x807dff7d, 0x00000080,
0x8078ff78, 0x00000080,
0xbf0a6f7d, 0xbfa2fff5,
0xbfa0000b, 0xe0500000,
0x781d0000, 0xbf8903f7,
0xdac00000, 0x00000000,
0x807dff7d, 0x00000100,
0x8078ff78, 0x00000100,
0xbf0a6f7d, 0xbfa2fff5,
0xbef80080, 0xbefe00c1,
0x857d9972, 0x8b7d817d,
0xbf06817d, 0xbfa20002,
0xbeff0080, 0xbfa00001,
0xbeff00c1, 0xb8ef3b05,
0x806f816f, 0x846f826f,
0x857d9972, 0x8b7d817d,
0xbf06817d, 0xbfa20024,
0xbef600ff, 0x01000000,
0xbeee0078, 0x8078ff78,
0x00000200, 0xbefd0084,
0xbf0a6f7d, 0xbfa10050,
0xe0505000, 0x781d0000,
0xe0505080, 0x781d0100,
0xe0505100, 0x781d0200,
0xe0505180, 0x781d0300,
0xbf8903f7, 0x7e008500,
0x7e028501, 0x7e048502,
0x7e068503, 0x807d847d,
0x8078ff78, 0x00000200,
0xbf0a6f7d, 0xbfa2ffee,
0xe0505000, 0x6e1d0000,
0xe0505080, 0x6e1d0100,
0xe0505100, 0x6e1d0200,
0xe0505180, 0x6e1d0300,
0xbf8903f7, 0xbfa00034,
0xbef600ff, 0x01000000,
0xbeee0078, 0x8078ff78,
0x00000400, 0xbefd0084,
0xbf0a6f7d, 0xbfa10012,
0xe0505000, 0x781d0000,
0xe0505100, 0x781d0100,
0xe0505200, 0x781d0200,
0xe0505300, 0x781d0300,
0xbf8903f7, 0x7e008500,
0x7e028501, 0x7e048502,
0x7e068503, 0x807d847d,
0x8078ff78, 0x00000400,
0xbf0a6f7d, 0xbfa2ffee,
0xb8ef1e06, 0x8b6fc16f,
0xbfa1000e, 0x846f836f,
0x806f7d6f, 0xbefe00c1,
0xbeff0080, 0xe0505000,
0x781d0000, 0xbf8903f7,
0x7e008500, 0x807d817d,
0x8078ff78, 0x00000080,
0xbf0a6f7d, 0xbfa2fff7,
0xbeff00c1, 0xe0505000,
0x6e1d0000, 0xe0505100,
0x6e1d0100, 0xe0505200,
0x6e1d0200, 0xe0505300,
0x6e1d0300, 0xbf8903f7,
0xb8f83b05, 0x80788178,
0xbf0d9972, 0xbfa20002,
0x84788978, 0xbfa00001,
0x84788a78, 0xb8ee1e06,
0x846e8a6e, 0x80786e78,
0x8078ff78, 0x00000200,
0x80f8ff78, 0x00000050,
0xbef600ff, 0x01000000,
0xbefd00ff, 0x0000006c,
0x80f89078, 0xf428403a,
0xf0000000, 0xbf89fc07,
0x80fd847d, 0xbf800000,
0xbe804300, 0xbe824302,
0x80f8a078, 0xf42c403a,
0xf0000000, 0xbf89fc07,
0x80fd887d, 0xbf800000,
0xbe804300, 0xbe824302,
0xbe844304, 0xbe864306,
0x80f8c078, 0xf430403a,
0xf0000000, 0xbf89fc07,
0x80fd907d, 0xbf800000,
0xbe804300, 0xbe824302,
0xbe844304, 0xbe864306,
0xbe884308, 0xbe8a430a,
0xbe8c430c, 0xbe8e430e,
0xbf06807d, 0xbfa1fff0,
0xb980f801, 0x00000000,
0xbfbd0000, 0xb8f83b05,
0x80788178, 0xbf0d9972,
0xbfa20002, 0x84788978,
0xbfa00001, 0x84788a78,
0xb8ee1e06, 0x846e8a6e,
0x80786e78, 0x8078ff78,
0x00000200, 0xbef600ff,
0x01000000, 0xf4205bfa,
0xf0000000, 0x80788478, 0xf0000000, 0x80788478,
0xf4205b7a, 0xf0000000, 0xf4205b3a, 0xf0000000,
0x80788478, 0xf4205c3a, 0x80788478, 0xf4205b7a,
0xf0000000, 0x80788478, 0xf0000000, 0x80788478,
0xf4205c7a, 0xf0000000, 0xf4205c3a, 0xf0000000,
0x80788478, 0xf4205eba, 0x80788478, 0xf4205c7a,
0xf0000000, 0x80788478, 0xf0000000, 0x80788478,
0xf4205efa, 0xf0000000, 0xf4205eba, 0xf0000000,
0x80788478, 0xf4205e7a, 0x80788478, 0xf4205efa,
0xf0000000, 0x80788478, 0xf0000000, 0x80788478,
0xf4205cfa, 0xf0000000, 0xf4205e7a, 0xf0000000,
0x80788478, 0xf4205bba, 0x80788478, 0xf4205cfa,
0xf0000000, 0x80788478, 0xf0000000, 0x80788478,
0xbf89fc07, 0xb96ef814,
0xf4205bba, 0xf0000000, 0xf4205bba, 0xf0000000,
0x80788478, 0xbf89fc07, 0x80788478, 0xbf89fc07,
0xb96ef815, 0xbefd006f, 0xb96ef814, 0xf4205bba,
0xbefe0070, 0xbeff0071, 0xf0000000, 0x80788478,
0x8b6f7bff, 0x000003ff, 0xbf89fc07, 0xb96ef815,
0xb96f4803, 0x8b6f7bff, 0xbefd006f, 0xbefe0070,
0xfffff800, 0x856f8b6f, 0xbeff0071, 0x8b6f7bff,
0xb96fa2c3, 0xb973f801, 0x000003ff, 0xb96f4803,
0xb8ee3b05, 0x806e816e, 0x8b6f7bff, 0xfffff800,
0xbf0d9972, 0xbfa20002, 0x856f8b6f, 0xb96fa2c3,
0x846e896e, 0xbfa00001, 0xb973f801, 0xb8ee3b05,
0x846e8a6e, 0xb8ef1e06, 0x806e816e, 0xbf0d9972,
0x846f8a6f, 0x806e6f6e, 0xbfa20002, 0x846e896e,
0x806eff6e, 0x00000200, 0xbfa00001, 0x846e8a6e,
0x806e746e, 0x826f8075, 0xb8ef1e06, 0x846f8a6f,
0x8b6fff6f, 0x0000ffff, 0x806e6f6e, 0x806eff6e,
0xf4085c37, 0xf8000050, 0x00000200, 0x806e746e,
0xf4085d37, 0xf8000060, 0x826f8075, 0x8b6fff6f,
0xf4005e77, 0xf8000074, 0x0000ffff, 0xf4085c37,
0xbf89fc07, 0x8b6dff6d, 0xf8000050, 0xf4085d37,
0x0000ffff, 0x8bfe7e7e, 0xf8000060, 0xf4005e77,
0x8bea6a6a, 0xb8eef802, 0xf8000074, 0xbf89fc07,
0xbf0d866e, 0xbfa20002, 0x8b6dff6d, 0x0000ffff,
0xb97af802, 0xbe80486c, 0x8bfe7e7e, 0x8bea6a6a,
0xb97af802, 0xbe804a6c, 0xb8eef802, 0xbf0d866e,
0xbfb00000, 0xbf9f0000, 0xbfa20002, 0xb97af802,
0xbe80486c, 0xb97af802,
0xbe804a6c, 0xbfb00000,
0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000,
0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000,
0xbf9f0000, 0x00000000,
}; };

View File

@@ -186,6 +186,12 @@ L_SKIP_RESTORE:
s_getreg_b32 s_save_trapsts, hwreg(HW_REG_TRAPSTS) s_getreg_b32 s_save_trapsts, hwreg(HW_REG_TRAPSTS)
#if SW_SA_TRAP #if SW_SA_TRAP
// If ttmp1[30] is set then issue s_barrier to unblock dependent waves.
s_bitcmp1_b32 s_save_pc_hi, 30
s_cbranch_scc0 L_TRAP_NO_BARRIER
s_barrier
L_TRAP_NO_BARRIER:
// If ttmp1[31] is set then trap may occur early. // If ttmp1[31] is set then trap may occur early.
// Spin wait until SAVECTX exception is raised. // Spin wait until SAVECTX exception is raised.
s_bitcmp1_b32 s_save_pc_hi, 31 s_bitcmp1_b32 s_save_pc_hi, 31

View File

@@ -50,16 +50,6 @@ static inline unsigned int get_and_inc_gpu_processor_id(
return current_id; return current_id;
} }
/* Static table to describe GPU Cache information */
struct kfd_gpu_cache_info {
uint32_t cache_size;
uint32_t cache_level;
uint32_t flags;
/* Indicates how many Compute Units share this cache
* within a SA. Value = 1 indicates the cache is not shared
*/
uint32_t num_cu_shared;
};
static struct kfd_gpu_cache_info kaveri_cache_info[] = { static struct kfd_gpu_cache_info kaveri_cache_info[] = {
{ {
@@ -795,6 +785,150 @@ static struct kfd_gpu_cache_info yellow_carp_cache_info[] = {
}, },
}; };
static struct kfd_gpu_cache_info gfx1037_cache_info[] = {
{
/* TCP L1 Cache per CU */
.cache_size = 16,
.cache_level = 1,
.flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE),
.num_cu_shared = 1,
},
{
/* Scalar L1 Instruction Cache per SQC */
.cache_size = 32,
.cache_level = 1,
.flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_INST_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE),
.num_cu_shared = 2,
},
{
/* Scalar L1 Data Cache per SQC */
.cache_size = 16,
.cache_level = 1,
.flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE),
.num_cu_shared = 2,
},
{
/* GL1 Data Cache per SA */
.cache_size = 128,
.cache_level = 1,
.flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE),
.num_cu_shared = 2,
},
{
/* L2 Data Cache per GPU (Total Tex Cache) */
.cache_size = 256,
.cache_level = 2,
.flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE),
.num_cu_shared = 2,
},
};
static struct kfd_gpu_cache_info gc_10_3_6_cache_info[] = {
{
/* TCP L1 Cache per CU */
.cache_size = 16,
.cache_level = 1,
.flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE),
.num_cu_shared = 1,
},
{
/* Scalar L1 Instruction Cache per SQC */
.cache_size = 32,
.cache_level = 1,
.flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_INST_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE),
.num_cu_shared = 2,
},
{
/* Scalar L1 Data Cache per SQC */
.cache_size = 16,
.cache_level = 1,
.flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE),
.num_cu_shared = 2,
},
{
/* GL1 Data Cache per SA */
.cache_size = 128,
.cache_level = 1,
.flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE),
.num_cu_shared = 2,
},
{
/* L2 Data Cache per GPU (Total Tex Cache) */
.cache_size = 256,
.cache_level = 2,
.flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE),
.num_cu_shared = 2,
},
};
static struct kfd_gpu_cache_info dummy_cache_info[] = {
{
/* TCP L1 Cache per CU */
.cache_size = 16,
.cache_level = 1,
.flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE),
.num_cu_shared = 1,
},
{
/* Scalar L1 Instruction Cache per SQC */
.cache_size = 32,
.cache_level = 1,
.flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_INST_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE),
.num_cu_shared = 2,
},
{
/* Scalar L1 Data Cache per SQC */
.cache_size = 16,
.cache_level = 1,
.flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE),
.num_cu_shared = 2,
},
{
/* GL1 Data Cache per SA */
.cache_size = 128,
.cache_level = 1,
.flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE),
.num_cu_shared = 6,
},
{
/* L2 Data Cache per GPU (Total Tex Cache) */
.cache_size = 2048,
.cache_level = 2,
.flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE),
.num_cu_shared = 6,
},
};
static void kfd_populated_cu_info_cpu(struct kfd_topology_device *dev, static void kfd_populated_cu_info_cpu(struct kfd_topology_device *dev,
struct crat_subtype_computeunit *cu) struct crat_subtype_computeunit *cu)
{ {
@@ -975,9 +1109,13 @@ static int kfd_parse_subtype_cache(struct crat_subtype_cache *cache,
props->cachelines_per_tag = cache->lines_per_tag; props->cachelines_per_tag = cache->lines_per_tag;
props->cache_assoc = cache->associativity; props->cache_assoc = cache->associativity;
props->cache_latency = cache->cache_latency; props->cache_latency = cache->cache_latency;
memcpy(props->sibling_map, cache->sibling_map, memcpy(props->sibling_map, cache->sibling_map,
sizeof(props->sibling_map)); sizeof(props->sibling_map));
/* set the sibling_map_size as 32 for CRAT from ACPI */
props->sibling_map_size = CRAT_SIBLINGMAP_SIZE;
if (cache->flags & CRAT_CACHE_FLAGS_DATA_CACHE) if (cache->flags & CRAT_CACHE_FLAGS_DATA_CACHE)
props->cache_type |= HSA_CACHE_TYPE_DATA; props->cache_type |= HSA_CACHE_TYPE_DATA;
if (cache->flags & CRAT_CACHE_FLAGS_INST_CACHE) if (cache->flags & CRAT_CACHE_FLAGS_INST_CACHE)
@@ -987,7 +1125,6 @@ static int kfd_parse_subtype_cache(struct crat_subtype_cache *cache,
if (cache->flags & CRAT_CACHE_FLAGS_SIMD_CACHE) if (cache->flags & CRAT_CACHE_FLAGS_SIMD_CACHE)
props->cache_type |= HSA_CACHE_TYPE_HSACU; props->cache_type |= HSA_CACHE_TYPE_HSACU;
dev->cache_count++;
dev->node_props.caches_count++; dev->node_props.caches_count++;
list_add_tail(&props->list, &dev->cache_props); list_add_tail(&props->list, &dev->cache_props);
@@ -1195,125 +1332,6 @@ err:
return ret; return ret;
} }
/* Helper function. See kfd_fill_gpu_cache_info for parameter description */
static int fill_in_l1_pcache(struct crat_subtype_cache *pcache,
struct kfd_gpu_cache_info *pcache_info,
struct kfd_cu_info *cu_info,
int mem_available,
int cu_bitmask,
int cache_type, unsigned int cu_processor_id,
int cu_block)
{
unsigned int cu_sibling_map_mask;
int first_active_cu;
/* First check if enough memory is available */
if (sizeof(struct crat_subtype_cache) > mem_available)
return -ENOMEM;
cu_sibling_map_mask = cu_bitmask;
cu_sibling_map_mask >>= cu_block;
cu_sibling_map_mask &=
((1 << pcache_info[cache_type].num_cu_shared) - 1);
first_active_cu = ffs(cu_sibling_map_mask);
/* CU could be inactive. In case of shared cache find the first active
* CU. and incase of non-shared cache check if the CU is inactive. If
* inactive active skip it
*/
if (first_active_cu) {
memset(pcache, 0, sizeof(struct crat_subtype_cache));
pcache->type = CRAT_SUBTYPE_CACHE_AFFINITY;
pcache->length = sizeof(struct crat_subtype_cache);
pcache->flags = pcache_info[cache_type].flags;
pcache->processor_id_low = cu_processor_id
+ (first_active_cu - 1);
pcache->cache_level = pcache_info[cache_type].cache_level;
pcache->cache_size = pcache_info[cache_type].cache_size;
/* Sibling map is w.r.t processor_id_low, so shift out
* inactive CU
*/
cu_sibling_map_mask =
cu_sibling_map_mask >> (first_active_cu - 1);
pcache->sibling_map[0] = (uint8_t)(cu_sibling_map_mask & 0xFF);
pcache->sibling_map[1] =
(uint8_t)((cu_sibling_map_mask >> 8) & 0xFF);
pcache->sibling_map[2] =
(uint8_t)((cu_sibling_map_mask >> 16) & 0xFF);
pcache->sibling_map[3] =
(uint8_t)((cu_sibling_map_mask >> 24) & 0xFF);
return 0;
}
return 1;
}
/* Helper function. See kfd_fill_gpu_cache_info for parameter description */
static int fill_in_l2_l3_pcache(struct crat_subtype_cache *pcache,
struct kfd_gpu_cache_info *pcache_info,
struct kfd_cu_info *cu_info,
int mem_available,
int cache_type, unsigned int cu_processor_id)
{
unsigned int cu_sibling_map_mask;
int first_active_cu;
int i, j, k;
/* First check if enough memory is available */
if (sizeof(struct crat_subtype_cache) > mem_available)
return -ENOMEM;
cu_sibling_map_mask = cu_info->cu_bitmap[0][0];
cu_sibling_map_mask &=
((1 << pcache_info[cache_type].num_cu_shared) - 1);
first_active_cu = ffs(cu_sibling_map_mask);
/* CU could be inactive. In case of shared cache find the first active
* CU. and incase of non-shared cache check if the CU is inactive. If
* inactive active skip it
*/
if (first_active_cu) {
memset(pcache, 0, sizeof(struct crat_subtype_cache));
pcache->type = CRAT_SUBTYPE_CACHE_AFFINITY;
pcache->length = sizeof(struct crat_subtype_cache);
pcache->flags = pcache_info[cache_type].flags;
pcache->processor_id_low = cu_processor_id
+ (first_active_cu - 1);
pcache->cache_level = pcache_info[cache_type].cache_level;
pcache->cache_size = pcache_info[cache_type].cache_size;
/* Sibling map is w.r.t processor_id_low, so shift out
* inactive CU
*/
cu_sibling_map_mask =
cu_sibling_map_mask >> (first_active_cu - 1);
k = 0;
for (i = 0; i < cu_info->num_shader_engines; i++) {
for (j = 0; j < cu_info->num_shader_arrays_per_engine;
j++) {
pcache->sibling_map[k] =
(uint8_t)(cu_sibling_map_mask & 0xFF);
pcache->sibling_map[k+1] =
(uint8_t)((cu_sibling_map_mask >> 8) & 0xFF);
pcache->sibling_map[k+2] =
(uint8_t)((cu_sibling_map_mask >> 16) & 0xFF);
pcache->sibling_map[k+3] =
(uint8_t)((cu_sibling_map_mask >> 24) & 0xFF);
k += 4;
cu_sibling_map_mask =
cu_info->cu_bitmap[i % 4][j + i / 4];
cu_sibling_map_mask &= (
(1 << pcache_info[cache_type].num_cu_shared)
- 1);
}
}
return 0;
}
return 1;
}
#define KFD_MAX_CACHE_TYPES 6
static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev, static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
struct kfd_gpu_cache_info *pcache_info) struct kfd_gpu_cache_info *pcache_info)
@@ -1387,222 +1405,133 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
return i; return i;
} }
/* kfd_fill_gpu_cache_info - Fill GPU cache info using kfd_gpu_cache_info int kfd_get_gpu_cache_info(struct kfd_dev *kdev, struct kfd_gpu_cache_info **pcache_info)
* tables
*
* @kdev - [IN] GPU device
* @gpu_processor_id - [IN] GPU processor ID to which these caches
* associate
* @available_size - [IN] Amount of memory available in pcache
* @cu_info - [IN] Compute Unit info obtained from KGD
* @pcache - [OUT] memory into which cache data is to be filled in.
* @size_filled - [OUT] amount of data used up in pcache.
* @num_of_entries - [OUT] number of caches added
*/
static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev,
int gpu_processor_id,
int available_size,
struct kfd_cu_info *cu_info,
struct crat_subtype_cache *pcache,
int *size_filled,
int *num_of_entries)
{ {
struct kfd_gpu_cache_info *pcache_info;
struct kfd_gpu_cache_info cache_info[KFD_MAX_CACHE_TYPES];
int num_of_cache_types = 0; int num_of_cache_types = 0;
int i, j, k;
int ct = 0;
int mem_available = available_size;
unsigned int cu_processor_id;
int ret;
unsigned int num_cu_shared;
switch (kdev->adev->asic_type) { switch (kdev->adev->asic_type) {
case CHIP_KAVERI: case CHIP_KAVERI:
pcache_info = kaveri_cache_info; *pcache_info = kaveri_cache_info;
num_of_cache_types = ARRAY_SIZE(kaveri_cache_info); num_of_cache_types = ARRAY_SIZE(kaveri_cache_info);
break; break;
case CHIP_HAWAII: case CHIP_HAWAII:
pcache_info = hawaii_cache_info; *pcache_info = hawaii_cache_info;
num_of_cache_types = ARRAY_SIZE(hawaii_cache_info); num_of_cache_types = ARRAY_SIZE(hawaii_cache_info);
break; break;
case CHIP_CARRIZO: case CHIP_CARRIZO:
pcache_info = carrizo_cache_info; *pcache_info = carrizo_cache_info;
num_of_cache_types = ARRAY_SIZE(carrizo_cache_info); num_of_cache_types = ARRAY_SIZE(carrizo_cache_info);
break; break;
case CHIP_TONGA: case CHIP_TONGA:
pcache_info = tonga_cache_info; *pcache_info = tonga_cache_info;
num_of_cache_types = ARRAY_SIZE(tonga_cache_info); num_of_cache_types = ARRAY_SIZE(tonga_cache_info);
break; break;
case CHIP_FIJI: case CHIP_FIJI:
pcache_info = fiji_cache_info; *pcache_info = fiji_cache_info;
num_of_cache_types = ARRAY_SIZE(fiji_cache_info); num_of_cache_types = ARRAY_SIZE(fiji_cache_info);
break; break;
case CHIP_POLARIS10: case CHIP_POLARIS10:
pcache_info = polaris10_cache_info; *pcache_info = polaris10_cache_info;
num_of_cache_types = ARRAY_SIZE(polaris10_cache_info); num_of_cache_types = ARRAY_SIZE(polaris10_cache_info);
break; break;
case CHIP_POLARIS11: case CHIP_POLARIS11:
pcache_info = polaris11_cache_info; *pcache_info = polaris11_cache_info;
num_of_cache_types = ARRAY_SIZE(polaris11_cache_info); num_of_cache_types = ARRAY_SIZE(polaris11_cache_info);
break; break;
case CHIP_POLARIS12: case CHIP_POLARIS12:
pcache_info = polaris12_cache_info; *pcache_info = polaris12_cache_info;
num_of_cache_types = ARRAY_SIZE(polaris12_cache_info); num_of_cache_types = ARRAY_SIZE(polaris12_cache_info);
break; break;
case CHIP_VEGAM: case CHIP_VEGAM:
pcache_info = vegam_cache_info; *pcache_info = vegam_cache_info;
num_of_cache_types = ARRAY_SIZE(vegam_cache_info); num_of_cache_types = ARRAY_SIZE(vegam_cache_info);
break; break;
default: default:
switch (KFD_GC_VERSION(kdev)) { switch (KFD_GC_VERSION(kdev)) {
case IP_VERSION(9, 0, 1): case IP_VERSION(9, 0, 1):
pcache_info = vega10_cache_info; *pcache_info = vega10_cache_info;
num_of_cache_types = ARRAY_SIZE(vega10_cache_info); num_of_cache_types = ARRAY_SIZE(vega10_cache_info);
break; break;
case IP_VERSION(9, 2, 1): case IP_VERSION(9, 2, 1):
pcache_info = vega12_cache_info; *pcache_info = vega12_cache_info;
num_of_cache_types = ARRAY_SIZE(vega12_cache_info); num_of_cache_types = ARRAY_SIZE(vega12_cache_info);
break; break;
case IP_VERSION(9, 4, 0): case IP_VERSION(9, 4, 0):
case IP_VERSION(9, 4, 1): case IP_VERSION(9, 4, 1):
pcache_info = vega20_cache_info; *pcache_info = vega20_cache_info;
num_of_cache_types = ARRAY_SIZE(vega20_cache_info); num_of_cache_types = ARRAY_SIZE(vega20_cache_info);
break; break;
case IP_VERSION(9, 4, 2): case IP_VERSION(9, 4, 2):
pcache_info = aldebaran_cache_info; *pcache_info = aldebaran_cache_info;
num_of_cache_types = ARRAY_SIZE(aldebaran_cache_info); num_of_cache_types = ARRAY_SIZE(aldebaran_cache_info);
break; break;
case IP_VERSION(9, 1, 0): case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 2): case IP_VERSION(9, 2, 2):
pcache_info = raven_cache_info; *pcache_info = raven_cache_info;
num_of_cache_types = ARRAY_SIZE(raven_cache_info); num_of_cache_types = ARRAY_SIZE(raven_cache_info);
break; break;
case IP_VERSION(9, 3, 0): case IP_VERSION(9, 3, 0):
pcache_info = renoir_cache_info; *pcache_info = renoir_cache_info;
num_of_cache_types = ARRAY_SIZE(renoir_cache_info); num_of_cache_types = ARRAY_SIZE(renoir_cache_info);
break; break;
case IP_VERSION(10, 1, 10): case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 2): case IP_VERSION(10, 1, 2):
case IP_VERSION(10, 1, 3): case IP_VERSION(10, 1, 3):
case IP_VERSION(10, 1, 4): case IP_VERSION(10, 1, 4):
pcache_info = navi10_cache_info; *pcache_info = navi10_cache_info;
num_of_cache_types = ARRAY_SIZE(navi10_cache_info); num_of_cache_types = ARRAY_SIZE(navi10_cache_info);
break; break;
case IP_VERSION(10, 1, 1): case IP_VERSION(10, 1, 1):
pcache_info = navi14_cache_info; *pcache_info = navi14_cache_info;
num_of_cache_types = ARRAY_SIZE(navi14_cache_info); num_of_cache_types = ARRAY_SIZE(navi14_cache_info);
break; break;
case IP_VERSION(10, 3, 0): case IP_VERSION(10, 3, 0):
pcache_info = sienna_cichlid_cache_info; *pcache_info = sienna_cichlid_cache_info;
num_of_cache_types = ARRAY_SIZE(sienna_cichlid_cache_info); num_of_cache_types = ARRAY_SIZE(sienna_cichlid_cache_info);
break; break;
case IP_VERSION(10, 3, 2): case IP_VERSION(10, 3, 2):
pcache_info = navy_flounder_cache_info; *pcache_info = navy_flounder_cache_info;
num_of_cache_types = ARRAY_SIZE(navy_flounder_cache_info); num_of_cache_types = ARRAY_SIZE(navy_flounder_cache_info);
break; break;
case IP_VERSION(10, 3, 4): case IP_VERSION(10, 3, 4):
pcache_info = dimgrey_cavefish_cache_info; *pcache_info = dimgrey_cavefish_cache_info;
num_of_cache_types = ARRAY_SIZE(dimgrey_cavefish_cache_info); num_of_cache_types = ARRAY_SIZE(dimgrey_cavefish_cache_info);
break; break;
case IP_VERSION(10, 3, 1): case IP_VERSION(10, 3, 1):
pcache_info = vangogh_cache_info; *pcache_info = vangogh_cache_info;
num_of_cache_types = ARRAY_SIZE(vangogh_cache_info); num_of_cache_types = ARRAY_SIZE(vangogh_cache_info);
break; break;
case IP_VERSION(10, 3, 5): case IP_VERSION(10, 3, 5):
pcache_info = beige_goby_cache_info; *pcache_info = beige_goby_cache_info;
num_of_cache_types = ARRAY_SIZE(beige_goby_cache_info); num_of_cache_types = ARRAY_SIZE(beige_goby_cache_info);
break; break;
case IP_VERSION(10, 3, 3): case IP_VERSION(10, 3, 3):
case IP_VERSION(10, 3, 6): /* TODO: Double check these on production silicon */ *pcache_info = yellow_carp_cache_info;
case IP_VERSION(10, 3, 7): /* TODO: Double check these on production silicon */
pcache_info = yellow_carp_cache_info;
num_of_cache_types = ARRAY_SIZE(yellow_carp_cache_info); num_of_cache_types = ARRAY_SIZE(yellow_carp_cache_info);
break; break;
case IP_VERSION(10, 3, 6):
*pcache_info = gc_10_3_6_cache_info;
num_of_cache_types = ARRAY_SIZE(gc_10_3_6_cache_info);
break;
case IP_VERSION(10, 3, 7):
*pcache_info = gfx1037_cache_info;
num_of_cache_types = ARRAY_SIZE(gfx1037_cache_info);
break;
case IP_VERSION(11, 0, 0): case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 1): case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 2): case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3): case IP_VERSION(11, 0, 3):
pcache_info = cache_info;
num_of_cache_types = num_of_cache_types =
kfd_fill_gpu_cache_info_from_gfx_config(kdev, pcache_info); kfd_fill_gpu_cache_info_from_gfx_config(kdev, *pcache_info);
break; break;
default: default:
return -EINVAL; *pcache_info = dummy_cache_info;
} num_of_cache_types = ARRAY_SIZE(dummy_cache_info);
} pr_warn("dummy cache info is used temporarily and real cache info need update later.\n");
*size_filled = 0;
*num_of_entries = 0;
/* For each type of cache listed in the kfd_gpu_cache_info table,
* go through all available Compute Units.
* The [i,j,k] loop will
* if kfd_gpu_cache_info.num_cu_shared = 1
* will parse through all available CU
* If (kfd_gpu_cache_info.num_cu_shared != 1)
* then it will consider only one CU from
* the shared unit
*/
for (ct = 0; ct < num_of_cache_types; ct++) {
cu_processor_id = gpu_processor_id;
if (pcache_info[ct].cache_level == 1) {
for (i = 0; i < cu_info->num_shader_engines; i++) {
for (j = 0; j < cu_info->num_shader_arrays_per_engine; j++) {
for (k = 0; k < cu_info->num_cu_per_sh;
k += pcache_info[ct].num_cu_shared) {
ret = fill_in_l1_pcache(pcache,
pcache_info,
cu_info,
mem_available,
cu_info->cu_bitmap[i % 4][j + i / 4],
ct,
cu_processor_id,
k);
if (ret < 0)
break; break;
if (!ret) {
pcache++;
(*num_of_entries)++;
mem_available -= sizeof(*pcache);
(*size_filled) += sizeof(*pcache);
}
/* Move to next CU block */
num_cu_shared = ((k + pcache_info[ct].num_cu_shared) <=
cu_info->num_cu_per_sh) ?
pcache_info[ct].num_cu_shared :
(cu_info->num_cu_per_sh - k);
cu_processor_id += num_cu_shared;
} }
}
}
} else {
ret = fill_in_l2_l3_pcache(pcache,
pcache_info,
cu_info,
mem_available,
ct,
cu_processor_id);
if (ret < 0)
break;
if (!ret) {
pcache++;
(*num_of_entries)++;
mem_available -= sizeof(*pcache);
(*size_filled) += sizeof(*pcache);
}
}
} }
return num_of_cache_types;
pr_debug("Added [%d] GPU cache entries\n", *num_of_entries);
return 0;
} }
static bool kfd_ignore_crat(void) static bool kfd_ignore_crat(void)
@@ -1961,8 +1890,8 @@ static void kfd_find_numa_node_in_srat(struct kfd_dev *kdev)
struct acpi_table_header *table_header = NULL; struct acpi_table_header *table_header = NULL;
struct acpi_subtable_header *sub_header = NULL; struct acpi_subtable_header *sub_header = NULL;
unsigned long table_end, subtable_len; unsigned long table_end, subtable_len;
u32 pci_id = pci_domain_nr(kdev->pdev->bus) << 16 | u32 pci_id = pci_domain_nr(kdev->adev->pdev->bus) << 16 |
pci_dev_id(kdev->pdev); pci_dev_id(kdev->adev->pdev);
u32 bdf; u32 bdf;
acpi_status status; acpi_status status;
struct acpi_srat_cpu_affinity *cpu; struct acpi_srat_cpu_affinity *cpu;
@@ -2037,7 +1966,7 @@ static void kfd_find_numa_node_in_srat(struct kfd_dev *kdev)
numa_node = 0; numa_node = 0;
if (numa_node != NUMA_NO_NODE) if (numa_node != NUMA_NO_NODE)
set_dev_node(&kdev->pdev->dev, numa_node); set_dev_node(&kdev->adev->pdev->dev, numa_node);
} }
#endif #endif
@@ -2098,14 +2027,14 @@ static int kfd_fill_gpu_direct_io_link_to_cpu(int *avail_size,
sub_type_hdr->proximity_domain_from = proximity_domain; sub_type_hdr->proximity_domain_from = proximity_domain;
#ifdef CONFIG_ACPI_NUMA #ifdef CONFIG_ACPI_NUMA
if (kdev->pdev->dev.numa_node == NUMA_NO_NODE) if (kdev->adev->pdev->dev.numa_node == NUMA_NO_NODE)
kfd_find_numa_node_in_srat(kdev); kfd_find_numa_node_in_srat(kdev);
#endif #endif
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
if (kdev->pdev->dev.numa_node == NUMA_NO_NODE) if (kdev->adev->pdev->dev.numa_node == NUMA_NO_NODE)
sub_type_hdr->proximity_domain_to = 0; sub_type_hdr->proximity_domain_to = 0;
else else
sub_type_hdr->proximity_domain_to = kdev->pdev->dev.numa_node; sub_type_hdr->proximity_domain_to = kdev->adev->pdev->dev.numa_node;
#else #else
sub_type_hdr->proximity_domain_to = 0; sub_type_hdr->proximity_domain_to = 0;
#endif #endif
@@ -2161,8 +2090,6 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
struct kfd_cu_info cu_info; struct kfd_cu_info cu_info;
int avail_size = *size; int avail_size = *size;
uint32_t total_num_of_cu; uint32_t total_num_of_cu;
int num_of_cache_entries = 0;
int cache_mem_filled = 0;
uint32_t nid = 0; uint32_t nid = 0;
int ret = 0; int ret = 0;
@@ -2263,31 +2190,12 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
crat_table->length += sizeof(struct crat_subtype_memory); crat_table->length += sizeof(struct crat_subtype_memory);
crat_table->total_entries++; crat_table->total_entries++;
/* TODO: Fill in cache information. This information is NOT readily
* available in KGD
*/
sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +
sub_type_hdr->length);
ret = kfd_fill_gpu_cache_info(kdev, cu->processor_id_low,
avail_size,
&cu_info,
(struct crat_subtype_cache *)sub_type_hdr,
&cache_mem_filled,
&num_of_cache_entries);
if (ret < 0)
return ret;
crat_table->length += cache_mem_filled;
crat_table->total_entries += num_of_cache_entries;
avail_size -= cache_mem_filled;
/* Fill in Subtype: IO_LINKS /* Fill in Subtype: IO_LINKS
* Only direct links are added here which is Link from GPU to * Only direct links are added here which is Link from GPU to
* its NUMA node. Indirect links are added by userspace. * its NUMA node. Indirect links are added by userspace.
*/ */
sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr + sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +
cache_mem_filled); sub_type_hdr->length);
ret = kfd_fill_gpu_direct_io_link_to_cpu(&avail_size, kdev, ret = kfd_fill_gpu_direct_io_link_to_cpu(&avail_size, kdev,
(struct crat_subtype_iolink *)sub_type_hdr, proximity_domain); (struct crat_subtype_iolink *)sub_type_hdr, proximity_domain);

View File

@@ -29,11 +29,10 @@
#pragma pack(1) #pragma pack(1)
/* /*
* 4CC signature values for the CRAT and CDIT ACPI tables * 4CC signature value for the CRAT ACPI table
*/ */
#define CRAT_SIGNATURE "CRAT" #define CRAT_SIGNATURE "CRAT"
#define CDIT_SIGNATURE "CDIT"
/* /*
* Component Resource Association Table (CRAT) * Component Resource Association Table (CRAT)
@@ -292,31 +291,22 @@ struct crat_subtype_generic {
uint32_t flags; uint32_t flags;
}; };
/*
* Component Locality Distance Information Table (CDIT)
*/
#define CDIT_OEMID_LENGTH 6
#define CDIT_OEMTABLEID_LENGTH 8
struct cdit_header {
uint32_t signature;
uint32_t length;
uint8_t revision;
uint8_t checksum;
uint8_t oem_id[CDIT_OEMID_LENGTH];
uint8_t oem_table_id[CDIT_OEMTABLEID_LENGTH];
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_revision;
uint32_t total_entries;
uint16_t num_domains;
uint8_t entry[1];
};
#pragma pack() #pragma pack()
struct kfd_dev; struct kfd_dev;
/* Static table to describe GPU Cache information */
struct kfd_gpu_cache_info {
uint32_t cache_size;
uint32_t cache_level;
uint32_t flags;
/* Indicates how many Compute Units share this cache
* within a SA. Value = 1 indicates the cache is not shared
*/
uint32_t num_cu_shared;
};
int kfd_get_gpu_cache_info(struct kfd_dev *kdev, struct kfd_gpu_cache_info **pcache_info);
int kfd_create_crat_image_acpi(void **crat_image, size_t *size); int kfd_create_crat_image_acpi(void **crat_image, size_t *size);
void kfd_destroy_crat_image(void *crat_image); void kfd_destroy_crat_image(void *crat_image);
int kfd_parse_crat_table(void *crat_image, struct list_head *device_list, int kfd_parse_crat_table(void *crat_image, struct list_head *device_list,

View File

@@ -227,7 +227,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
{ {
struct kfd_dev *kfd = NULL; struct kfd_dev *kfd = NULL;
const struct kfd2kgd_calls *f2g = NULL; const struct kfd2kgd_calls *f2g = NULL;
struct pci_dev *pdev = adev->pdev;
uint32_t gfx_target_version = 0; uint32_t gfx_target_version = 0;
switch (adev->asic_type) { switch (adev->asic_type) {
@@ -429,7 +428,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
kfd->adev = adev; kfd->adev = adev;
kfd_device_info_init(kfd, vf, gfx_target_version); kfd_device_info_init(kfd, vf, gfx_target_version);
kfd->pdev = pdev;
kfd->init_complete = false; kfd->init_complete = false;
kfd->kfd2kgd = f2g; kfd->kfd2kgd = f2g;
atomic_set(&kfd->compute_profile, 0); atomic_set(&kfd->compute_profile, 0);
@@ -511,12 +509,10 @@ static void kfd_smi_init(struct kfd_dev *dev)
} }
bool kgd2kfd_device_init(struct kfd_dev *kfd, bool kgd2kfd_device_init(struct kfd_dev *kfd,
struct drm_device *ddev,
const struct kgd2kfd_shared_resources *gpu_resources) const struct kgd2kfd_shared_resources *gpu_resources)
{ {
unsigned int size, map_process_packet_size; unsigned int size, map_process_packet_size;
kfd->ddev = ddev;
kfd->mec_fw_version = amdgpu_amdkfd_get_fw_version(kfd->adev, kfd->mec_fw_version = amdgpu_amdkfd_get_fw_version(kfd->adev,
KGD_ENGINE_MEC1); KGD_ENGINE_MEC1);
kfd->mec2_fw_version = amdgpu_amdkfd_get_fw_version(kfd->adev, kfd->mec2_fw_version = amdgpu_amdkfd_get_fw_version(kfd->adev,
@@ -541,7 +537,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
kfd->mec_fw_version < kfd->device_info.no_atomic_fw_version)) { kfd->mec_fw_version < kfd->device_info.no_atomic_fw_version)) {
dev_info(kfd_device, dev_info(kfd_device,
"skipped device %x:%x, PCI rejects atomics %d<%d\n", "skipped device %x:%x, PCI rejects atomics %d<%d\n",
kfd->pdev->vendor, kfd->pdev->device, kfd->adev->pdev->vendor, kfd->adev->pdev->device,
kfd->mec_fw_version, kfd->mec_fw_version,
kfd->device_info.no_atomic_fw_version); kfd->device_info.no_atomic_fw_version);
return false; return false;
@@ -650,8 +646,8 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
kfd_smi_init(kfd); kfd_smi_init(kfd);
kfd->init_complete = true; kfd->init_complete = true;
dev_info(kfd_device, "added device %x:%x\n", kfd->pdev->vendor, dev_info(kfd_device, "added device %x:%x\n", kfd->adev->pdev->vendor,
kfd->pdev->device); kfd->adev->pdev->device);
pr_debug("Starting kfd with the following scheduling policy %d\n", pr_debug("Starting kfd with the following scheduling policy %d\n",
kfd->dqm->sched_policy); kfd->dqm->sched_policy);
@@ -676,7 +672,7 @@ alloc_gtt_mem_failure:
amdgpu_amdkfd_free_gws(kfd->adev, kfd->gws); amdgpu_amdkfd_free_gws(kfd->adev, kfd->gws);
dev_err(kfd_device, dev_err(kfd_device,
"device %x:%x NOT added due to errors\n", "device %x:%x NOT added due to errors\n",
kfd->pdev->vendor, kfd->pdev->device); kfd->adev->pdev->vendor, kfd->adev->pdev->device);
out: out:
return kfd->init_complete; return kfd->init_complete;
} }
@@ -789,7 +785,7 @@ int kgd2kfd_resume_iommu(struct kfd_dev *kfd)
if (err) if (err)
dev_err(kfd_device, dev_err(kfd_device,
"Failed to resume IOMMU for device %x:%x\n", "Failed to resume IOMMU for device %x:%x\n",
kfd->pdev->vendor, kfd->pdev->device); kfd->adev->pdev->vendor, kfd->adev->pdev->device);
return err; return err;
} }
@@ -801,7 +797,7 @@ static int kfd_resume(struct kfd_dev *kfd)
if (err) if (err)
dev_err(kfd_device, dev_err(kfd_device,
"Error starting queue manager for device %x:%x\n", "Error starting queue manager for device %x:%x\n",
kfd->pdev->vendor, kfd->pdev->device); kfd->adev->pdev->vendor, kfd->adev->pdev->device);
return err; return err;
} }

View File

@@ -49,7 +49,7 @@ int kfd_iommu_check_device(struct kfd_dev *kfd)
return -ENODEV; return -ENODEV;
iommu_info.flags = 0; iommu_info.flags = 0;
err = amd_iommu_device_info(kfd->pdev, &iommu_info); err = amd_iommu_device_info(kfd->adev->pdev, &iommu_info);
if (err) if (err)
return err; return err;
@@ -71,7 +71,7 @@ int kfd_iommu_device_init(struct kfd_dev *kfd)
return 0; return 0;
iommu_info.flags = 0; iommu_info.flags = 0;
err = amd_iommu_device_info(kfd->pdev, &iommu_info); err = amd_iommu_device_info(kfd->adev->pdev, &iommu_info);
if (err < 0) { if (err < 0) {
dev_err(kfd_device, dev_err(kfd_device,
"error getting iommu info. is the iommu enabled?\n"); "error getting iommu info. is the iommu enabled?\n");
@@ -121,7 +121,7 @@ int kfd_iommu_bind_process_to_device(struct kfd_process_device *pdd)
return -EINVAL; return -EINVAL;
} }
err = amd_iommu_bind_pasid(dev->pdev, p->pasid, p->lead_thread); err = amd_iommu_bind_pasid(dev->adev->pdev, p->pasid, p->lead_thread);
if (!err) if (!err)
pdd->bound = PDD_BOUND; pdd->bound = PDD_BOUND;
@@ -139,7 +139,8 @@ void kfd_iommu_unbind_process(struct kfd_process *p)
for (i = 0; i < p->n_pdds; i++) for (i = 0; i < p->n_pdds; i++)
if (p->pdds[i]->bound == PDD_BOUND) if (p->pdds[i]->bound == PDD_BOUND)
amd_iommu_unbind_pasid(p->pdds[i]->dev->pdev, p->pasid); amd_iommu_unbind_pasid(p->pdds[i]->dev->adev->pdev,
p->pasid);
} }
/* Callback for process shutdown invoked by the IOMMU driver */ /* Callback for process shutdown invoked by the IOMMU driver */
@@ -222,7 +223,7 @@ static int kfd_bind_processes_to_device(struct kfd_dev *kfd)
continue; continue;
} }
err = amd_iommu_bind_pasid(kfd->pdev, p->pasid, err = amd_iommu_bind_pasid(kfd->adev->pdev, p->pasid,
p->lead_thread); p->lead_thread);
if (err < 0) { if (err < 0) {
pr_err("Unexpected pasid 0x%x binding failure\n", pr_err("Unexpected pasid 0x%x binding failure\n",
@@ -282,9 +283,9 @@ void kfd_iommu_suspend(struct kfd_dev *kfd)
kfd_unbind_processes_from_device(kfd); kfd_unbind_processes_from_device(kfd);
amd_iommu_set_invalidate_ctx_cb(kfd->pdev, NULL); amd_iommu_set_invalidate_ctx_cb(kfd->adev->pdev, NULL);
amd_iommu_set_invalid_ppr_cb(kfd->pdev, NULL); amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev, NULL);
amd_iommu_free_device(kfd->pdev); amd_iommu_free_device(kfd->adev->pdev);
} }
/** kfd_iommu_resume - Restore IOMMU after resume /** kfd_iommu_resume - Restore IOMMU after resume
@@ -302,20 +303,20 @@ int kfd_iommu_resume(struct kfd_dev *kfd)
pasid_limit = kfd_get_pasid_limit(); pasid_limit = kfd_get_pasid_limit();
err = amd_iommu_init_device(kfd->pdev, pasid_limit); err = amd_iommu_init_device(kfd->adev->pdev, pasid_limit);
if (err) if (err)
return -ENXIO; return -ENXIO;
amd_iommu_set_invalidate_ctx_cb(kfd->pdev, amd_iommu_set_invalidate_ctx_cb(kfd->adev->pdev,
iommu_pasid_shutdown_callback); iommu_pasid_shutdown_callback);
amd_iommu_set_invalid_ppr_cb(kfd->pdev, amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev,
iommu_invalid_ppr_cb); iommu_invalid_ppr_cb);
err = kfd_bind_processes_to_device(kfd); err = kfd_bind_processes_to_device(kfd);
if (err) { if (err) {
amd_iommu_set_invalidate_ctx_cb(kfd->pdev, NULL); amd_iommu_set_invalidate_ctx_cb(kfd->adev->pdev, NULL);
amd_iommu_set_invalid_ppr_cb(kfd->pdev, NULL); amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev, NULL);
amd_iommu_free_device(kfd->pdev); amd_iommu_free_device(kfd->adev->pdev);
return err; return err;
} }

View File

@@ -529,8 +529,8 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
for (addr = start; addr < end;) { for (addr = start; addr < end;) {
unsigned long next; unsigned long next;
vma = find_vma(mm, addr); vma = vma_lookup(mm, addr);
if (!vma || addr < vma->vm_start) if (!vma)
break; break;
next = min(vma->vm_end, end); next = min(vma->vm_end, end);
@@ -798,8 +798,8 @@ int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm,
for (addr = start; addr < end;) { for (addr = start; addr < end;) {
unsigned long next; unsigned long next;
vma = find_vma(mm, addr); vma = vma_lookup(mm, addr);
if (!vma || addr < vma->vm_start) { if (!vma) {
pr_debug("failed to find vma for prange %p\n", prange); pr_debug("failed to find vma for prange %p\n", prange);
r = -EFAULT; r = -EFAULT;
break; break;
@@ -973,12 +973,10 @@ out_unlock_prange:
out_unlock_svms: out_unlock_svms:
mutex_unlock(&p->svms.lock); mutex_unlock(&p->svms.lock);
out_unref_process: out_unref_process:
pr_debug("CPU fault svms 0x%p address 0x%lx done\n", &p->svms, addr);
kfd_unref_process(p); kfd_unref_process(p);
out_mmput: out_mmput:
mmput(mm); mmput(mm);
pr_debug("CPU fault svms 0x%p address 0x%lx done\n", &p->svms, addr);
return r ? VM_FAULT_SIGBUS : 0; return r ? VM_FAULT_SIGBUS : 0;
} }

View File

@@ -1,291 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/*
* Copyright 2014-2022 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.
*
*/
#ifndef KFD_PM4_HEADERS_DIQ_H_
#define KFD_PM4_HEADERS_DIQ_H_
/*--------------------_INDIRECT_BUFFER-------------------- */
#ifndef _PM4__INDIRECT_BUFFER_DEFINED
#define _PM4__INDIRECT_BUFFER_DEFINED
enum _INDIRECT_BUFFER_cache_policy_enum {
cache_policy___indirect_buffer__lru = 0,
cache_policy___indirect_buffer__stream = 1,
cache_policy___indirect_buffer__bypass = 2
};
enum {
IT_INDIRECT_BUFFER_PASID = 0x5C
};
struct pm4__indirect_buffer_pasid {
union {
union PM4_MES_TYPE_3_HEADER header; /* header */
unsigned int ordinal1;
};
union {
struct {
unsigned int reserved1:2;
unsigned int ib_base_lo:30;
} bitfields2;
unsigned int ordinal2;
};
union {
struct {
unsigned int ib_base_hi:16;
unsigned int reserved2:16;
} bitfields3;
unsigned int ordinal3;
};
union {
unsigned int control;
unsigned int ordinal4;
};
union {
struct {
unsigned int pasid:10;
unsigned int reserved4:22;
} bitfields5;
unsigned int ordinal5;
};
};
#endif
/*--------------------_RELEASE_MEM-------------------- */
#ifndef _PM4__RELEASE_MEM_DEFINED
#define _PM4__RELEASE_MEM_DEFINED
enum _RELEASE_MEM_event_index_enum {
event_index___release_mem__end_of_pipe = 5,
event_index___release_mem__shader_done = 6
};
enum _RELEASE_MEM_cache_policy_enum {
cache_policy___release_mem__lru = 0,
cache_policy___release_mem__stream = 1,
cache_policy___release_mem__bypass = 2
};
enum _RELEASE_MEM_dst_sel_enum {
dst_sel___release_mem__memory_controller = 0,
dst_sel___release_mem__tc_l2 = 1,
dst_sel___release_mem__queue_write_pointer_register = 2,
dst_sel___release_mem__queue_write_pointer_poll_mask_bit = 3
};
enum _RELEASE_MEM_int_sel_enum {
int_sel___release_mem__none = 0,
int_sel___release_mem__send_interrupt_only = 1,
int_sel___release_mem__send_interrupt_after_write_confirm = 2,
int_sel___release_mem__send_data_after_write_confirm = 3
};
enum _RELEASE_MEM_data_sel_enum {
data_sel___release_mem__none = 0,
data_sel___release_mem__send_32_bit_low = 1,
data_sel___release_mem__send_64_bit_data = 2,
data_sel___release_mem__send_gpu_clock_counter = 3,
data_sel___release_mem__send_cp_perfcounter_hi_lo = 4,
data_sel___release_mem__store_gds_data_to_memory = 5
};
struct pm4__release_mem {
union {
union PM4_MES_TYPE_3_HEADER header; /*header */
unsigned int ordinal1;
};
union {
struct {
unsigned int event_type:6;
unsigned int reserved1:2;
enum _RELEASE_MEM_event_index_enum event_index:4;
unsigned int tcl1_vol_action_ena:1;
unsigned int tc_vol_action_ena:1;
unsigned int reserved2:1;
unsigned int tc_wb_action_ena:1;
unsigned int tcl1_action_ena:1;
unsigned int tc_action_ena:1;
unsigned int reserved3:6;
unsigned int atc:1;
enum _RELEASE_MEM_cache_policy_enum cache_policy:2;
unsigned int reserved4:5;
} bitfields2;
unsigned int ordinal2;
};
union {
struct {
unsigned int reserved5:16;
enum _RELEASE_MEM_dst_sel_enum dst_sel:2;
unsigned int reserved6:6;
enum _RELEASE_MEM_int_sel_enum int_sel:3;
unsigned int reserved7:2;
enum _RELEASE_MEM_data_sel_enum data_sel:3;
} bitfields3;
unsigned int ordinal3;
};
union {
struct {
unsigned int reserved8:2;
unsigned int address_lo_32b:30;
} bitfields4;
struct {
unsigned int reserved9:3;
unsigned int address_lo_64b:29;
} bitfields5;
unsigned int ordinal4;
};
unsigned int address_hi;
unsigned int data_lo;
unsigned int data_hi;
};
#endif
/*--------------------_SET_CONFIG_REG-------------------- */
#ifndef _PM4__SET_CONFIG_REG_DEFINED
#define _PM4__SET_CONFIG_REG_DEFINED
struct pm4__set_config_reg {
union {
union PM4_MES_TYPE_3_HEADER header; /*header */
unsigned int ordinal1;
};
union {
struct {
unsigned int reg_offset:16;
unsigned int reserved1:7;
unsigned int vmid_shift:5;
unsigned int insert_vmid:1;
unsigned int reserved2:3;
} bitfields2;
unsigned int ordinal2;
};
unsigned int reg_data[1]; /*1..N of these fields */
};
#endif
/*--------------------_WAIT_REG_MEM-------------------- */
#ifndef _PM4__WAIT_REG_MEM_DEFINED
#define _PM4__WAIT_REG_MEM_DEFINED
enum _WAIT_REG_MEM_function_enum {
function___wait_reg_mem__always_pass = 0,
function___wait_reg_mem__less_than_ref_value = 1,
function___wait_reg_mem__less_than_equal_to_the_ref_value = 2,
function___wait_reg_mem__equal_to_the_reference_value = 3,
function___wait_reg_mem__not_equal_reference_value = 4,
function___wait_reg_mem__greater_than_or_equal_reference_value = 5,
function___wait_reg_mem__greater_than_reference_value = 6,
function___wait_reg_mem__reserved = 7
};
enum _WAIT_REG_MEM_mem_space_enum {
mem_space___wait_reg_mem__register_space = 0,
mem_space___wait_reg_mem__memory_space = 1
};
enum _WAIT_REG_MEM_operation_enum {
operation___wait_reg_mem__wait_reg_mem = 0,
operation___wait_reg_mem__wr_wait_wr_reg = 1
};
struct pm4__wait_reg_mem {
union {
union PM4_MES_TYPE_3_HEADER header; /*header */
unsigned int ordinal1;
};
union {
struct {
enum _WAIT_REG_MEM_function_enum function:3;
unsigned int reserved1:1;
enum _WAIT_REG_MEM_mem_space_enum mem_space:2;
enum _WAIT_REG_MEM_operation_enum operation:2;
unsigned int reserved2:24;
} bitfields2;
unsigned int ordinal2;
};
union {
struct {
unsigned int reserved3:2;
unsigned int memory_poll_addr_lo:30;
} bitfields3;
struct {
unsigned int register_poll_addr:16;
unsigned int reserved4:16;
} bitfields4;
struct {
unsigned int register_write_addr:16;
unsigned int reserved5:16;
} bitfields5;
unsigned int ordinal3;
};
union {
struct {
unsigned int poll_address_hi:16;
unsigned int reserved6:16;
} bitfields6;
struct {
unsigned int register_write_addr:16;
unsigned int reserved7:16;
} bitfields7;
unsigned int ordinal4;
};
unsigned int reference;
unsigned int mask;
union {
struct {
unsigned int poll_interval:16;
unsigned int reserved8:16;
} bitfields8;
unsigned int ordinal7;
};
};
#endif
#endif /* KFD_PM4_HEADERS_DIQ_H_ */

View File

@@ -254,8 +254,6 @@ struct kfd_dev {
struct amdgpu_device *adev; struct amdgpu_device *adev;
struct kfd_device_info device_info; struct kfd_device_info device_info;
struct pci_dev *pdev;
struct drm_device *ddev;
unsigned int id; /* topology stub index */ unsigned int id; /* topology stub index */
@@ -1365,7 +1363,7 @@ void kfd_dec_compute_active(struct kfd_dev *dev);
static inline int kfd_devcgroup_check_permission(struct kfd_dev *kfd) static inline int kfd_devcgroup_check_permission(struct kfd_dev *kfd)
{ {
#if defined(CONFIG_CGROUP_DEVICE) || defined(CONFIG_CGROUP_BPF) #if defined(CONFIG_CGROUP_DEVICE) || defined(CONFIG_CGROUP_BPF)
struct drm_device *ddev = kfd->ddev; struct drm_device *ddev = adev_to_drm(kfd->adev);
return devcgroup_check_permission(DEVCG_DEV_CHAR, DRM_MAJOR, return devcgroup_check_permission(DEVCG_DEV_CHAR, DRM_MAJOR,
ddev->render->index, ddev->render->index,

View File

@@ -1050,8 +1050,8 @@ static void kfd_process_destroy_pdds(struct kfd_process *p)
* for auto suspend * for auto suspend
*/ */
if (pdd->runtime_inuse) { if (pdd->runtime_inuse) {
pm_runtime_mark_last_busy(pdd->dev->ddev->dev); pm_runtime_mark_last_busy(adev_to_drm(pdd->dev->adev)->dev);
pm_runtime_put_autosuspend(pdd->dev->ddev->dev); pm_runtime_put_autosuspend(adev_to_drm(pdd->dev->adev)->dev);
pdd->runtime_inuse = false; pdd->runtime_inuse = false;
} }
@@ -1633,9 +1633,9 @@ struct kfd_process_device *kfd_bind_process_to_device(struct kfd_dev *dev,
* pdd is destroyed. * pdd is destroyed.
*/ */
if (!pdd->runtime_inuse) { if (!pdd->runtime_inuse) {
err = pm_runtime_get_sync(dev->ddev->dev); err = pm_runtime_get_sync(adev_to_drm(dev->adev)->dev);
if (err < 0) { if (err < 0) {
pm_runtime_put_autosuspend(dev->ddev->dev); pm_runtime_put_autosuspend(adev_to_drm(dev->adev)->dev);
return ERR_PTR(err); return ERR_PTR(err);
} }
} }
@@ -1655,8 +1655,8 @@ struct kfd_process_device *kfd_bind_process_to_device(struct kfd_dev *dev,
out: out:
/* balance runpm reference count and exit with error */ /* balance runpm reference count and exit with error */
if (!pdd->runtime_inuse) { if (!pdd->runtime_inuse) {
pm_runtime_mark_last_busy(dev->ddev->dev); pm_runtime_mark_last_busy(adev_to_drm(dev->adev)->dev);
pm_runtime_put_autosuspend(dev->ddev->dev); pm_runtime_put_autosuspend(adev_to_drm(dev->adev)->dev);
} }
return ERR_PTR(err); return ERR_PTR(err);

View File

@@ -259,7 +259,7 @@ void svm_range_free_dma_mappings(struct svm_range *prange)
pr_debug("failed to find device idx %d\n", gpuidx); pr_debug("failed to find device idx %d\n", gpuidx);
continue; continue;
} }
dev = &pdd->dev->pdev->dev; dev = &pdd->dev->adev->pdev->dev;
svm_range_dma_unmap(dev, dma_addr, 0, prange->npages); svm_range_dma_unmap(dev, dma_addr, 0, prange->npages);
kvfree(dma_addr); kvfree(dma_addr);
prange->dma_addr[gpuidx] = NULL; prange->dma_addr[gpuidx] = NULL;
@@ -1586,8 +1586,8 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
unsigned long npages; unsigned long npages;
bool readonly; bool readonly;
vma = find_vma(mm, addr); vma = vma_lookup(mm, addr);
if (!vma || addr < vma->vm_start) { if (!vma) {
r = -EFAULT; r = -EFAULT;
goto unreserve_out; goto unreserve_out;
} }
@@ -2542,8 +2542,8 @@ svm_range_get_range_boundaries(struct kfd_process *p, int64_t addr,
struct interval_tree_node *node; struct interval_tree_node *node;
unsigned long start_limit, end_limit; unsigned long start_limit, end_limit;
vma = find_vma(p->mm, addr << PAGE_SHIFT); vma = vma_lookup(p->mm, addr << PAGE_SHIFT);
if (!vma || (addr << PAGE_SHIFT) < vma->vm_start) { if (!vma) {
pr_debug("VMA does not exist in address [0x%llx]\n", addr); pr_debug("VMA does not exist in address [0x%llx]\n", addr);
return -EFAULT; return -EFAULT;
} }
@@ -2871,8 +2871,8 @@ retry_write_locked:
/* __do_munmap removed VMA, return success as we are handling stale /* __do_munmap removed VMA, return success as we are handling stale
* retry fault. * retry fault.
*/ */
vma = find_vma(mm, addr << PAGE_SHIFT); vma = vma_lookup(mm, addr << PAGE_SHIFT);
if (!vma || (addr << PAGE_SHIFT) < vma->vm_start) { if (!vma) {
pr_debug("address 0x%llx VMA is removed\n", addr); pr_debug("address 0x%llx VMA is removed\n", addr);
r = 0; r = 0;
goto out_unlock_range; goto out_unlock_range;
@@ -3152,9 +3152,8 @@ svm_range_is_valid(struct kfd_process *p, uint64_t start, uint64_t size)
start <<= PAGE_SHIFT; start <<= PAGE_SHIFT;
end = start + (size << PAGE_SHIFT); end = start + (size << PAGE_SHIFT);
do { do {
vma = find_vma(p->mm, start); vma = vma_lookup(p->mm, start);
if (!vma || start < vma->vm_start || if (!vma || (vma->vm_flags & device_vma))
(vma->vm_flags & device_vma))
return -EFAULT; return -EFAULT;
start = min(end, vma->vm_end); start = min(end, vma->vm_end);
} while (start < end); } while (start < end);

View File

@@ -115,7 +115,7 @@ struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev)
down_read(&topology_lock); down_read(&topology_lock);
list_for_each_entry(top_dev, &topology_device_list, list) list_for_each_entry(top_dev, &topology_device_list, list)
if (top_dev->gpu && top_dev->gpu->pdev == pdev) { if (top_dev->gpu && top_dev->gpu->adev->pdev == pdev) {
device = top_dev->gpu; device = top_dev->gpu;
break; break;
} }
@@ -364,7 +364,6 @@ static ssize_t kfd_cache_show(struct kobject *kobj, struct attribute *attr,
/* Making sure that the buffer is an empty string */ /* Making sure that the buffer is an empty string */
buffer[0] = 0; buffer[0] = 0;
cache = container_of(attr, struct kfd_cache_properties, attr); cache = container_of(attr, struct kfd_cache_properties, attr);
if (cache->gpu && kfd_devcgroup_check_permission(cache->gpu)) if (cache->gpu && kfd_devcgroup_check_permission(cache->gpu))
return -EPERM; return -EPERM;
@@ -379,12 +378,13 @@ static ssize_t kfd_cache_show(struct kobject *kobj, struct attribute *attr,
sysfs_show_32bit_prop(buffer, offs, "association", cache->cache_assoc); sysfs_show_32bit_prop(buffer, offs, "association", cache->cache_assoc);
sysfs_show_32bit_prop(buffer, offs, "latency", cache->cache_latency); sysfs_show_32bit_prop(buffer, offs, "latency", cache->cache_latency);
sysfs_show_32bit_prop(buffer, offs, "type", cache->cache_type); sysfs_show_32bit_prop(buffer, offs, "type", cache->cache_type);
offs += snprintf(buffer+offs, PAGE_SIZE-offs, "sibling_map "); offs += snprintf(buffer+offs, PAGE_SIZE-offs, "sibling_map ");
for (i = 0; i < CRAT_SIBLINGMAP_SIZE; i++) for (i = 0; i < cache->sibling_map_size; i++)
for (j = 0; j < sizeof(cache->sibling_map[0])*8; j++) for (j = 0; j < sizeof(cache->sibling_map[0])*8; j++)
/* Check each bit */ /* Check each bit */
offs += snprintf(buffer+offs, PAGE_SIZE-offs, "%d,", offs += snprintf(buffer+offs, PAGE_SIZE-offs, "%d,",
(cache->sibling_map[i] >> j) & 1); (cache->sibling_map[i] >> j) & 1);
/* Replace the last "," with end of line */ /* Replace the last "," with end of line */
buffer[offs-1] = '\n'; buffer[offs-1] = '\n';
@@ -1169,13 +1169,12 @@ static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu)
local_mem_size = gpu->local_mem_info.local_mem_size_private + local_mem_size = gpu->local_mem_info.local_mem_size_private +
gpu->local_mem_info.local_mem_size_public; gpu->local_mem_info.local_mem_size_public;
buf[0] = gpu->adev->pdev->devfn;
buf[0] = gpu->pdev->devfn; buf[1] = gpu->adev->pdev->subsystem_vendor |
buf[1] = gpu->pdev->subsystem_vendor | (gpu->adev->pdev->subsystem_device << 16);
(gpu->pdev->subsystem_device << 16); buf[2] = pci_domain_nr(gpu->adev->pdev->bus);
buf[2] = pci_domain_nr(gpu->pdev->bus); buf[3] = gpu->adev->pdev->device;
buf[3] = gpu->pdev->device; buf[4] = gpu->adev->pdev->bus->number;
buf[4] = gpu->pdev->bus->number;
buf[5] = lower_32_bits(local_mem_size); buf[5] = lower_32_bits(local_mem_size);
buf[6] = upper_32_bits(local_mem_size); buf[6] = upper_32_bits(local_mem_size);
@@ -1198,7 +1197,6 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
struct kfd_iolink_properties *iolink; struct kfd_iolink_properties *iolink;
struct kfd_iolink_properties *p2plink; struct kfd_iolink_properties *p2plink;
down_write(&topology_lock);
list_for_each_entry(dev, &topology_device_list, list) { list_for_each_entry(dev, &topology_device_list, list) {
/* Discrete GPUs need their own topology device list /* Discrete GPUs need their own topology device list
* entries. Don't assign them to CPU/APU nodes. * entries. Don't assign them to CPU/APU nodes.
@@ -1222,7 +1220,6 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
break; break;
} }
} }
up_write(&topology_lock);
return out_dev; return out_dev;
} }
@@ -1269,7 +1266,7 @@ static void kfd_set_iolink_no_atomics(struct kfd_topology_device *dev,
if (target_gpu_dev) { if (target_gpu_dev) {
uint32_t cap; uint32_t cap;
pcie_capability_read_dword(target_gpu_dev->gpu->pdev, pcie_capability_read_dword(target_gpu_dev->gpu->adev->pdev,
PCI_EXP_DEVCAP2, &cap); PCI_EXP_DEVCAP2, &cap);
if (!(cap & (PCI_EXP_DEVCAP2_ATOMIC_COMP32 | if (!(cap & (PCI_EXP_DEVCAP2_ATOMIC_COMP32 |
@@ -1593,6 +1590,221 @@ out:
return ret; return ret;
} }
/* Helper function. See kfd_fill_gpu_cache_info for parameter description */
static int fill_in_l1_pcache(struct kfd_cache_properties **props_ext,
struct kfd_gpu_cache_info *pcache_info,
struct kfd_cu_info *cu_info,
int cu_bitmask,
int cache_type, unsigned int cu_processor_id,
int cu_block)
{
unsigned int cu_sibling_map_mask;
int first_active_cu;
struct kfd_cache_properties *pcache = NULL;
cu_sibling_map_mask = cu_bitmask;
cu_sibling_map_mask >>= cu_block;
cu_sibling_map_mask &= ((1 << pcache_info[cache_type].num_cu_shared) - 1);
first_active_cu = ffs(cu_sibling_map_mask);
/* CU could be inactive. In case of shared cache find the first active
* CU. and incase of non-shared cache check if the CU is inactive. If
* inactive active skip it
*/
if (first_active_cu) {
pcache = kfd_alloc_struct(pcache);
if (!pcache)
return -ENOMEM;
memset(pcache, 0, sizeof(struct kfd_cache_properties));
pcache->processor_id_low = cu_processor_id + (first_active_cu - 1);
pcache->cache_level = pcache_info[cache_type].cache_level;
pcache->cache_size = pcache_info[cache_type].cache_size;
if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_DATA_CACHE)
pcache->cache_type |= HSA_CACHE_TYPE_DATA;
if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_INST_CACHE)
pcache->cache_type |= HSA_CACHE_TYPE_INSTRUCTION;
if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_CPU_CACHE)
pcache->cache_type |= HSA_CACHE_TYPE_CPU;
if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_SIMD_CACHE)
pcache->cache_type |= HSA_CACHE_TYPE_HSACU;
/* Sibling map is w.r.t processor_id_low, so shift out
* inactive CU
*/
cu_sibling_map_mask =
cu_sibling_map_mask >> (first_active_cu - 1);
pcache->sibling_map[0] = (uint8_t)(cu_sibling_map_mask & 0xFF);
pcache->sibling_map[1] =
(uint8_t)((cu_sibling_map_mask >> 8) & 0xFF);
pcache->sibling_map[2] =
(uint8_t)((cu_sibling_map_mask >> 16) & 0xFF);
pcache->sibling_map[3] =
(uint8_t)((cu_sibling_map_mask >> 24) & 0xFF);
pcache->sibling_map_size = 4;
*props_ext = pcache;
return 0;
}
return 1;
}
/* Helper function. See kfd_fill_gpu_cache_info for parameter description */
static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext,
struct kfd_gpu_cache_info *pcache_info,
struct kfd_cu_info *cu_info,
int cache_type, unsigned int cu_processor_id)
{
unsigned int cu_sibling_map_mask;
int first_active_cu;
int i, j, k;
struct kfd_cache_properties *pcache = NULL;
cu_sibling_map_mask = cu_info->cu_bitmap[0][0];
cu_sibling_map_mask &=
((1 << pcache_info[cache_type].num_cu_shared) - 1);
first_active_cu = ffs(cu_sibling_map_mask);
/* CU could be inactive. In case of shared cache find the first active
* CU. and incase of non-shared cache check if the CU is inactive. If
* inactive active skip it
*/
if (first_active_cu) {
pcache = kfd_alloc_struct(pcache);
if (!pcache)
return -ENOMEM;
memset(pcache, 0, sizeof(struct kfd_cache_properties));
pcache->processor_id_low = cu_processor_id
+ (first_active_cu - 1);
pcache->cache_level = pcache_info[cache_type].cache_level;
pcache->cache_size = pcache_info[cache_type].cache_size;
if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_DATA_CACHE)
pcache->cache_type |= HSA_CACHE_TYPE_DATA;
if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_INST_CACHE)
pcache->cache_type |= HSA_CACHE_TYPE_INSTRUCTION;
if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_CPU_CACHE)
pcache->cache_type |= HSA_CACHE_TYPE_CPU;
if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_SIMD_CACHE)
pcache->cache_type |= HSA_CACHE_TYPE_HSACU;
/* Sibling map is w.r.t processor_id_low, so shift out
* inactive CU
*/
cu_sibling_map_mask = cu_sibling_map_mask >> (first_active_cu - 1);
k = 0;
for (i = 0; i < cu_info->num_shader_engines; i++) {
for (j = 0; j < cu_info->num_shader_arrays_per_engine; j++) {
pcache->sibling_map[k] = (uint8_t)(cu_sibling_map_mask & 0xFF);
pcache->sibling_map[k+1] = (uint8_t)((cu_sibling_map_mask >> 8) & 0xFF);
pcache->sibling_map[k+2] = (uint8_t)((cu_sibling_map_mask >> 16) & 0xFF);
pcache->sibling_map[k+3] = (uint8_t)((cu_sibling_map_mask >> 24) & 0xFF);
k += 4;
cu_sibling_map_mask = cu_info->cu_bitmap[i % 4][j + i / 4];
cu_sibling_map_mask &= ((1 << pcache_info[cache_type].num_cu_shared) - 1);
}
}
pcache->sibling_map_size = k;
*props_ext = pcache;
return 0;
}
return 1;
}
#define KFD_MAX_CACHE_TYPES 6
/* kfd_fill_cache_non_crat_info - Fill GPU cache info using kfd_gpu_cache_info
* tables
*/
void kfd_fill_cache_non_crat_info(struct kfd_topology_device *dev, struct kfd_dev *kdev)
{
struct kfd_gpu_cache_info *pcache_info = NULL;
int i, j, k;
int ct = 0;
unsigned int cu_processor_id;
int ret;
unsigned int num_cu_shared;
struct kfd_cu_info cu_info;
struct kfd_cu_info *pcu_info;
int gpu_processor_id;
struct kfd_cache_properties *props_ext;
int num_of_entries = 0;
int num_of_cache_types = 0;
struct kfd_gpu_cache_info cache_info[KFD_MAX_CACHE_TYPES];
amdgpu_amdkfd_get_cu_info(kdev->adev, &cu_info);
pcu_info = &cu_info;
gpu_processor_id = dev->node_props.simd_id_base;
pcache_info = cache_info;
num_of_cache_types = kfd_get_gpu_cache_info(kdev, &pcache_info);
if (!num_of_cache_types) {
pr_warn("no cache info found\n");
return;
}
/* For each type of cache listed in the kfd_gpu_cache_info table,
* go through all available Compute Units.
* The [i,j,k] loop will
* if kfd_gpu_cache_info.num_cu_shared = 1
* will parse through all available CU
* If (kfd_gpu_cache_info.num_cu_shared != 1)
* then it will consider only one CU from
* the shared unit
*/
for (ct = 0; ct < num_of_cache_types; ct++) {
cu_processor_id = gpu_processor_id;
if (pcache_info[ct].cache_level == 1) {
for (i = 0; i < pcu_info->num_shader_engines; i++) {
for (j = 0; j < pcu_info->num_shader_arrays_per_engine; j++) {
for (k = 0; k < pcu_info->num_cu_per_sh; k += pcache_info[ct].num_cu_shared) {
ret = fill_in_l1_pcache(&props_ext, pcache_info, pcu_info,
pcu_info->cu_bitmap[i % 4][j + i / 4], ct,
cu_processor_id, k);
if (ret < 0)
break;
if (!ret) {
num_of_entries++;
list_add_tail(&props_ext->list, &dev->cache_props);
}
/* Move to next CU block */
num_cu_shared = ((k + pcache_info[ct].num_cu_shared) <=
pcu_info->num_cu_per_sh) ?
pcache_info[ct].num_cu_shared :
(pcu_info->num_cu_per_sh - k);
cu_processor_id += num_cu_shared;
}
}
}
} else {
ret = fill_in_l2_l3_pcache(&props_ext, pcache_info,
pcu_info, ct, cu_processor_id);
if (ret < 0)
break;
if (!ret) {
num_of_entries++;
list_add_tail(&props_ext->list, &dev->cache_props);
}
}
}
dev->node_props.caches_count += num_of_entries;
pr_debug("Added [%d] GPU cache entries\n", num_of_entries);
}
int kfd_topology_add_device(struct kfd_dev *gpu) int kfd_topology_add_device(struct kfd_dev *gpu)
{ {
uint32_t gpu_id; uint32_t gpu_id;
@@ -1617,9 +1829,9 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
* CRAT to create a new topology device. Once created assign the gpu to * CRAT to create a new topology device. Once created assign the gpu to
* that topology device * that topology device
*/ */
down_write(&topology_lock);
dev = kfd_assign_gpu(gpu); dev = kfd_assign_gpu(gpu);
if (!dev) { if (!dev) {
down_write(&topology_lock);
proximity_domain = ++topology_crat_proximity_domain; proximity_domain = ++topology_crat_proximity_domain;
res = kfd_create_crat_image_virtual(&crat_image, &image_size, res = kfd_create_crat_image_virtual(&crat_image, &image_size,
@@ -1631,6 +1843,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
topology_crat_proximity_domain--; topology_crat_proximity_domain--;
return res; return res;
} }
res = kfd_parse_crat_table(crat_image, res = kfd_parse_crat_table(crat_image,
&temp_topology_device_list, &temp_topology_device_list,
proximity_domain); proximity_domain);
@@ -1644,23 +1857,28 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
kfd_topology_update_device_list(&temp_topology_device_list, kfd_topology_update_device_list(&temp_topology_device_list,
&topology_device_list); &topology_device_list);
/* Update the SYSFS tree, since we added another topology
* device
*/
res = kfd_topology_update_sysfs();
up_write(&topology_lock);
if (!res)
sys_props.generation_count++;
else
pr_err("Failed to update GPU (ID: 0x%x) to sysfs topology. res=%d\n",
gpu_id, res);
dev = kfd_assign_gpu(gpu); dev = kfd_assign_gpu(gpu);
if (WARN_ON(!dev)) { if (WARN_ON(!dev)) {
res = -ENODEV; res = -ENODEV;
goto err; goto err;
} }
/* Fill the cache affinity information here for the GPUs
* using VCRAT
*/
kfd_fill_cache_non_crat_info(dev, gpu);
/* Update the SYSFS tree, since we added another topology
* device
*/
res = kfd_topology_update_sysfs();
if (!res)
sys_props.generation_count++;
else
pr_err("Failed to update GPU (ID: 0x%x) to sysfs topology. res=%d\n",
gpu_id, res);
} }
up_write(&topology_lock);
dev->gpu_id = gpu_id; dev->gpu_id = gpu_id;
gpu->id = gpu_id; gpu->id = gpu_id;
@@ -1688,13 +1906,13 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
cu_info.num_shader_arrays_per_engine; cu_info.num_shader_arrays_per_engine;
dev->node_props.gfx_target_version = gpu->device_info.gfx_target_version; dev->node_props.gfx_target_version = gpu->device_info.gfx_target_version;
dev->node_props.vendor_id = gpu->pdev->vendor; dev->node_props.vendor_id = gpu->adev->pdev->vendor;
dev->node_props.device_id = gpu->pdev->device; dev->node_props.device_id = gpu->adev->pdev->device;
dev->node_props.capability |= dev->node_props.capability |=
((dev->gpu->adev->rev_id << HSA_CAP_ASIC_REVISION_SHIFT) & ((dev->gpu->adev->rev_id << HSA_CAP_ASIC_REVISION_SHIFT) &
HSA_CAP_ASIC_REVISION_MASK); HSA_CAP_ASIC_REVISION_MASK);
dev->node_props.location_id = pci_dev_id(gpu->pdev); dev->node_props.location_id = pci_dev_id(gpu->adev->pdev);
dev->node_props.domain = pci_domain_nr(gpu->pdev->bus); dev->node_props.domain = pci_domain_nr(gpu->adev->pdev->bus);
dev->node_props.max_engine_clk_fcompute = dev->node_props.max_engine_clk_fcompute =
amdgpu_amdkfd_get_max_engine_clock_in_mhz(dev->gpu->adev); amdgpu_amdkfd_get_max_engine_clock_in_mhz(dev->gpu->adev);
dev->node_props.max_engine_clk_ccompute = dev->node_props.max_engine_clk_ccompute =

View File

@@ -80,6 +80,8 @@ struct kfd_mem_properties {
struct attribute attr; struct attribute attr;
}; };
#define CACHE_SIBLINGMAP_SIZE 64
struct kfd_cache_properties { struct kfd_cache_properties {
struct list_head list; struct list_head list;
uint32_t processor_id_low; uint32_t processor_id_low;
@@ -90,10 +92,11 @@ struct kfd_cache_properties {
uint32_t cache_assoc; uint32_t cache_assoc;
uint32_t cache_latency; uint32_t cache_latency;
uint32_t cache_type; uint32_t cache_type;
uint8_t sibling_map[CRAT_SIBLINGMAP_SIZE]; uint8_t sibling_map[CACHE_SIBLINGMAP_SIZE];
struct kfd_dev *gpu; struct kfd_dev *gpu;
struct kobject *kobj; struct kobject *kobj;
struct attribute attr; struct attribute attr;
uint32_t sibling_map_size;
}; };
struct kfd_iolink_properties { struct kfd_iolink_properties {
@@ -128,7 +131,6 @@ struct kfd_topology_device {
uint32_t proximity_domain; uint32_t proximity_domain;
struct kfd_node_properties node_props; struct kfd_node_properties node_props;
struct list_head mem_props; struct list_head mem_props;
uint32_t cache_count;
struct list_head cache_props; struct list_head cache_props;
struct list_head io_link_props; struct list_head io_link_props;
struct list_head p2p_link_props; struct list_head p2p_link_props;

View File

@@ -6,7 +6,8 @@ config DRM_AMD_DC
bool "AMD DC - Enable new display engine" bool "AMD DC - Enable new display engine"
default y default y
select SND_HDA_COMPONENT if SND_HDA_CORE select SND_HDA_COMPONENT if SND_HDA_CORE
select DRM_AMD_DC_DCN if (X86 || PPC_LONG_DOUBLE_128) # !CC_IS_CLANG: https://github.com/ClangBuiltLinux/linux/issues/1752
select DRM_AMD_DC_DCN if (X86 || PPC_LONG_DOUBLE_128 || (ARM64 && KERNEL_MODE_NEON && !CC_IS_CLANG))
help help
Choose this option if you want to use the new display engine Choose this option if you want to use the new display engine
support for AMDGPU. This adds required support for Vega and support for AMDGPU. This adds required support for Vega and

View File

@@ -1399,7 +1399,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
mutex_init(&adev->dm.dc_lock); mutex_init(&adev->dm.dc_lock);
mutex_init(&adev->dm.audio_lock); mutex_init(&adev->dm.audio_lock);
spin_lock_init(&adev->dm.vblank_lock);
if(amdgpu_dm_irq_init(adev)) { if(amdgpu_dm_irq_init(adev)) {
DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n"); DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n");
@@ -1549,6 +1548,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
adev->dm.dc->debug.visual_confirm = amdgpu_dc_visual_confirm; adev->dm.dc->debug.visual_confirm = amdgpu_dc_visual_confirm;
/* TODO: Remove after DP2 receiver gets proper support of Cable ID feature */
adev->dm.dc->debug.ignore_cable_id = true;
r = dm_dmub_hw_init(adev); r = dm_dmub_hw_init(adev);
if (r) { if (r) {
DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r); DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r);
@@ -5602,16 +5604,14 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector,
{ {
struct drm_connector *drm_connector = &aconnector->base; struct drm_connector *drm_connector = &aconnector->base;
uint32_t link_bandwidth_kbps; uint32_t link_bandwidth_kbps;
uint32_t max_dsc_target_bpp_limit_override = 0;
struct dc *dc = sink->ctx->dc; struct dc *dc = sink->ctx->dc;
uint32_t max_supported_bw_in_kbps, timing_bw_in_kbps; uint32_t max_supported_bw_in_kbps, timing_bw_in_kbps;
uint32_t dsc_max_supported_bw_in_kbps; uint32_t dsc_max_supported_bw_in_kbps;
uint32_t max_dsc_target_bpp_limit_override =
drm_connector->display_info.max_dsc_bpp;
link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link,
dc_link_get_link_cap(aconnector->dc_link)); dc_link_get_link_cap(aconnector->dc_link));
if (stream->link && stream->link->local_sink)
max_dsc_target_bpp_limit_override =
stream->link->local_sink->edid_caps.panel_patch.max_dsc_target_bpp_limit;
/* Set DSC policy according to dsc_clock_en */ /* Set DSC policy according to dsc_clock_en */
dc_dsc_policy_set_enable_dsc_when_not_needed( dc_dsc_policy_set_enable_dsc_when_not_needed(
@@ -5692,6 +5692,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false; bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false;
int mode_refresh; int mode_refresh;
int preferred_refresh = 0; int preferred_refresh = 0;
enum color_transfer_func tf = TRANSFER_FUNC_UNKNOWN;
#if defined(CONFIG_DRM_AMD_DC_DCN) #if defined(CONFIG_DRM_AMD_DC_DCN)
struct dsc_dec_dpcd_caps dsc_caps; struct dsc_dec_dpcd_caps dsc_caps;
#endif #endif
@@ -5815,7 +5816,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
if (stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) if (stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED)
stream->use_vsc_sdp_for_colorimetry = true; stream->use_vsc_sdp_for_colorimetry = true;
} }
mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space); if (stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22)
tf = TRANSFER_FUNC_GAMMA_22;
mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space, tf);
aconnector->psr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY; aconnector->psr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY;
} }
@@ -6145,6 +6148,70 @@ static void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector)
create_eml_sink(aconnector); create_eml_sink(aconnector);
} }
static enum dc_status dm_validate_stream_and_context(struct dc *dc,
struct dc_stream_state *stream)
{
enum dc_status dc_result = DC_ERROR_UNEXPECTED;
struct dc_plane_state *dc_plane_state = NULL;
struct dc_state *dc_state = NULL;
if (!stream)
goto cleanup;
dc_plane_state = dc_create_plane_state(dc);
if (!dc_plane_state)
goto cleanup;
dc_state = dc_create_state(dc);
if (!dc_state)
goto cleanup;
/* populate stream to plane */
dc_plane_state->src_rect.height = stream->src.height;
dc_plane_state->src_rect.width = stream->src.width;
dc_plane_state->dst_rect.height = stream->src.height;
dc_plane_state->dst_rect.width = stream->src.width;
dc_plane_state->clip_rect.height = stream->src.height;
dc_plane_state->clip_rect.width = stream->src.width;
dc_plane_state->plane_size.surface_pitch = ((stream->src.width + 255) / 256) * 256;
dc_plane_state->plane_size.surface_size.height = stream->src.height;
dc_plane_state->plane_size.surface_size.width = stream->src.width;
dc_plane_state->plane_size.chroma_size.height = stream->src.height;
dc_plane_state->plane_size.chroma_size.width = stream->src.width;
dc_plane_state->tiling_info.gfx9.swizzle = DC_SW_UNKNOWN;
dc_plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888;
dc_plane_state->tiling_info.gfx9.swizzle = DC_SW_UNKNOWN;
dc_plane_state->rotation = ROTATION_ANGLE_0;
dc_plane_state->is_tiling_rotated = false;
dc_plane_state->tiling_info.gfx8.array_mode = DC_ARRAY_LINEAR_GENERAL;
dc_result = dc_validate_stream(dc, stream);
if (dc_result == DC_OK)
dc_result = dc_validate_plane(dc, dc_plane_state);
if (dc_result == DC_OK)
dc_result = dc_add_stream_to_ctx(dc, dc_state, stream);
if (dc_result == DC_OK && !dc_add_plane_to_context(
dc,
stream,
dc_plane_state,
dc_state))
dc_result = DC_FAIL_ATTACH_SURFACES;
if (dc_result == DC_OK)
dc_result = dc_validate_global_state(dc, dc_state, true);
cleanup:
if (dc_state)
dc_release_state(dc_state);
if (dc_plane_state)
dc_plane_state_release(dc_plane_state);
return dc_result;
}
struct dc_stream_state * struct dc_stream_state *
create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
const struct drm_display_mode *drm_mode, const struct drm_display_mode *drm_mode,
@@ -6171,6 +6238,9 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
if (dc_result == DC_OK && stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) if (dc_result == DC_OK && stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
dc_result = dm_dp_mst_is_port_support_mode(aconnector, stream); dc_result = dm_dp_mst_is_port_support_mode(aconnector, stream);
if (dc_result == DC_OK)
dc_result = dm_validate_stream_and_context(adev->dm.dc, stream);
if (dc_result != DC_OK) { if (dc_result != DC_OK) {
DRM_DEBUG_KMS("Mode %dx%d (clk %d) failed DC validation with error %d (%s)\n", DRM_DEBUG_KMS("Mode %dx%d (clk %d) failed DC validation with error %d (%s)\n",
drm_mode->hdisplay, drm_mode->hdisplay,
@@ -7832,6 +7902,9 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
*/ */
if (acrtc_state->stream->link->psr_settings.psr_version >= DC_PSR_VERSION_SU_1 && if (acrtc_state->stream->link->psr_settings.psr_version >= DC_PSR_VERSION_SU_1 &&
acrtc_attach->dm_irq_params.allow_psr_entry && acrtc_attach->dm_irq_params.allow_psr_entry &&
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
!amdgpu_dm_crc_window_is_activated(acrtc_state->base.crtc) &&
#endif
!acrtc_state->stream->link->psr_settings.psr_allow_active) !acrtc_state->stream->link->psr_settings.psr_allow_active)
amdgpu_dm_psr_enable(acrtc_state->stream); amdgpu_dm_psr_enable(acrtc_state->stream);
} else { } else {
@@ -8293,8 +8366,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
if (amdgpu_dm_crc_window_is_activated(crtc)) { if (amdgpu_dm_crc_window_is_activated(crtc)) {
spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
acrtc->dm_irq_params.crc_window.update_win = true; acrtc->dm_irq_params.window_param.update_win = true;
acrtc->dm_irq_params.crc_window.skip_frame_cnt = 2; acrtc->dm_irq_params.window_param.skip_frame_cnt = 2;
spin_lock_irq(&crc_rd_wrk->crc_rd_work_lock); spin_lock_irq(&crc_rd_wrk->crc_rd_work_lock);
crc_rd_wrk->crtc = crtc; crc_rd_wrk->crtc = crtc;
spin_unlock_irq(&crc_rd_wrk->crc_rd_work_lock); spin_unlock_irq(&crc_rd_wrk->crc_rd_work_lock);

View File

@@ -365,13 +365,6 @@ struct amdgpu_display_manager {
*/ */
struct mutex audio_lock; struct mutex audio_lock;
/**
* @vblank_lock:
*
* Guards access to deferred vblank work state.
*/
spinlock_t vblank_lock;
/** /**
* @audio_component: * @audio_component:
* *

View File

@@ -89,13 +89,13 @@ static void amdgpu_dm_set_crc_window_default(struct drm_crtc *crtc)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock); spin_lock_irq(&drm_dev->event_lock);
acrtc->dm_irq_params.crc_window.x_start = 0; acrtc->dm_irq_params.window_param.x_start = 0;
acrtc->dm_irq_params.crc_window.y_start = 0; acrtc->dm_irq_params.window_param.y_start = 0;
acrtc->dm_irq_params.crc_window.x_end = 0; acrtc->dm_irq_params.window_param.x_end = 0;
acrtc->dm_irq_params.crc_window.y_end = 0; acrtc->dm_irq_params.window_param.y_end = 0;
acrtc->dm_irq_params.crc_window.activated = false; acrtc->dm_irq_params.window_param.activated = false;
acrtc->dm_irq_params.crc_window.update_win = false; acrtc->dm_irq_params.window_param.update_win = false;
acrtc->dm_irq_params.crc_window.skip_frame_cnt = 0; acrtc->dm_irq_params.window_param.skip_frame_cnt = 0;
spin_unlock_irq(&drm_dev->event_lock); spin_unlock_irq(&drm_dev->event_lock);
} }
@@ -123,6 +123,8 @@ static void amdgpu_dm_crtc_notify_ta_to_read(struct work_struct *work)
phy_id = crc_rd_wrk->phy_inst; phy_id = crc_rd_wrk->phy_inst;
spin_unlock_irq(&crc_rd_wrk->crc_rd_work_lock); spin_unlock_irq(&crc_rd_wrk->crc_rd_work_lock);
mutex_lock(&psp->securedisplay_context.mutex);
psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd, psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC); TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC);
securedisplay_cmd->securedisplay_in_message.send_roi_crc.phy_id = securedisplay_cmd->securedisplay_in_message.send_roi_crc.phy_id =
@@ -133,6 +135,24 @@ static void amdgpu_dm_crtc_notify_ta_to_read(struct work_struct *work)
psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status); psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status);
} }
} }
mutex_unlock(&psp->securedisplay_context.mutex);
}
static void
amdgpu_dm_forward_crc_window(struct work_struct *work)
{
struct crc_fw_work *crc_fw_wrk;
struct amdgpu_display_manager *dm;
crc_fw_wrk = container_of(work, struct crc_fw_work, forward_roi_work);
dm = crc_fw_wrk->dm;
mutex_lock(&dm->dc_lock);
dc_stream_forward_crc_window(dm->dc, &crc_fw_wrk->rect, crc_fw_wrk->stream, crc_fw_wrk->is_stop_cmd);
mutex_unlock(&dm->dc_lock);
kfree(crc_fw_wrk);
} }
bool amdgpu_dm_crc_window_is_activated(struct drm_crtc *crtc) bool amdgpu_dm_crc_window_is_activated(struct drm_crtc *crtc)
@@ -142,7 +162,7 @@ bool amdgpu_dm_crc_window_is_activated(struct drm_crtc *crtc)
bool ret = false; bool ret = false;
spin_lock_irq(&drm_dev->event_lock); spin_lock_irq(&drm_dev->event_lock);
ret = acrtc->dm_irq_params.crc_window.activated; ret = acrtc->dm_irq_params.window_param.activated;
spin_unlock_irq(&drm_dev->event_lock); spin_unlock_irq(&drm_dev->event_lock);
return ret; return ret;
@@ -187,9 +207,11 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
if (adev->dm.crc_rd_wrk) { if (adev->dm.crc_rd_wrk) {
flush_work(&adev->dm.crc_rd_wrk->notify_ta_work); flush_work(&adev->dm.crc_rd_wrk->notify_ta_work);
spin_lock_irq(&adev->dm.crc_rd_wrk->crc_rd_work_lock); spin_lock_irq(&adev->dm.crc_rd_wrk->crc_rd_work_lock);
if (adev->dm.crc_rd_wrk->crtc == crtc) { if (adev->dm.crc_rd_wrk->crtc == crtc) {
dc_stream_stop_dmcu_crc_win_update(stream_state->ctx->dc, /* stop ROI update on this crtc */
dm_crtc_state->stream); dc_stream_forward_crc_window(stream_state->ctx->dc,
NULL, stream_state, true);
adev->dm.crc_rd_wrk->crtc = NULL; adev->dm.crc_rd_wrk->crtc = NULL;
} }
spin_unlock_irq(&adev->dm.crc_rd_wrk->crc_rd_work_lock); spin_unlock_irq(&adev->dm.crc_rd_wrk->crc_rd_work_lock);
@@ -439,14 +461,9 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
enum amdgpu_dm_pipe_crc_source cur_crc_src; enum amdgpu_dm_pipe_crc_source cur_crc_src;
struct amdgpu_crtc *acrtc = NULL; struct amdgpu_crtc *acrtc = NULL;
struct amdgpu_device *adev = NULL; struct amdgpu_device *adev = NULL;
struct crc_rd_work *crc_rd_wrk = NULL; struct crc_rd_work *crc_rd_wrk;
struct crc_params *crc_window = NULL, tmp_window; struct crc_fw_work *crc_fw_wrk;
unsigned long flags1, flags2; unsigned long flags1, flags2;
struct crtc_position position;
uint32_t v_blank;
uint32_t v_back_porch;
uint32_t crc_window_latch_up_line;
struct dc_crtc_timing *timing_out;
if (crtc == NULL) if (crtc == NULL)
return; return;
@@ -458,74 +475,54 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
spin_lock_irqsave(&drm_dev->event_lock, flags1); spin_lock_irqsave(&drm_dev->event_lock, flags1);
stream_state = acrtc->dm_irq_params.stream; stream_state = acrtc->dm_irq_params.stream;
cur_crc_src = acrtc->dm_irq_params.crc_src; cur_crc_src = acrtc->dm_irq_params.crc_src;
timing_out = &stream_state->timing;
/* Early return if CRC capture is not enabled. */ /* Early return if CRC capture is not enabled. */
if (!amdgpu_dm_is_valid_crc_source(cur_crc_src)) if (!amdgpu_dm_is_valid_crc_source(cur_crc_src))
goto cleanup; goto cleanup;
if (dm_is_crc_source_crtc(cur_crc_src)) { if (!dm_is_crc_source_crtc(cur_crc_src))
if (acrtc->dm_irq_params.crc_window.activated) { goto cleanup;
if (acrtc->dm_irq_params.crc_window.update_win) {
if (acrtc->dm_irq_params.crc_window.skip_frame_cnt) {
acrtc->dm_irq_params.crc_window.skip_frame_cnt -= 1;
goto cleanup;
}
crc_window = &tmp_window;
tmp_window.windowa_x_start = if (!acrtc->dm_irq_params.window_param.activated)
acrtc->dm_irq_params.crc_window.x_start; goto cleanup;
tmp_window.windowa_y_start =
acrtc->dm_irq_params.crc_window.y_start;
tmp_window.windowa_x_end =
acrtc->dm_irq_params.crc_window.x_end;
tmp_window.windowa_y_end =
acrtc->dm_irq_params.crc_window.y_end;
tmp_window.windowb_x_start =
acrtc->dm_irq_params.crc_window.x_start;
tmp_window.windowb_y_start =
acrtc->dm_irq_params.crc_window.y_start;
tmp_window.windowb_x_end =
acrtc->dm_irq_params.crc_window.x_end;
tmp_window.windowb_y_end =
acrtc->dm_irq_params.crc_window.y_end;
dc_stream_forward_dmcu_crc_window(stream_state->ctx->dc, if (acrtc->dm_irq_params.window_param.update_win) {
stream_state, crc_window); if (acrtc->dm_irq_params.window_param.skip_frame_cnt) {
acrtc->dm_irq_params.window_param.skip_frame_cnt -= 1;
goto cleanup;
}
acrtc->dm_irq_params.crc_window.update_win = false; /* prepare work for dmub to update ROI */
crc_fw_wrk = kzalloc(sizeof(*crc_fw_wrk), GFP_ATOMIC);
if (!crc_fw_wrk)
goto cleanup;
dc_stream_get_crtc_position(stream_state->ctx->dc, &stream_state, 1, INIT_WORK(&crc_fw_wrk->forward_roi_work, amdgpu_dm_forward_crc_window);
&position.vertical_count, crc_fw_wrk->dm = &adev->dm;
&position.nominal_vcount); crc_fw_wrk->stream = stream_state;
crc_fw_wrk->rect.x = acrtc->dm_irq_params.window_param.x_start;
crc_fw_wrk->rect.y = acrtc->dm_irq_params.window_param.y_start;
crc_fw_wrk->rect.width = acrtc->dm_irq_params.window_param.x_end -
acrtc->dm_irq_params.window_param.x_start;
crc_fw_wrk->rect.height = acrtc->dm_irq_params.window_param.y_end -
acrtc->dm_irq_params.window_param.y_start;
schedule_work(&crc_fw_wrk->forward_roi_work);
v_blank = timing_out->v_total - timing_out->v_border_top - acrtc->dm_irq_params.window_param.update_win = false;
timing_out->v_addressable - timing_out->v_border_bottom; acrtc->dm_irq_params.window_param.skip_frame_cnt = 1;
v_back_porch = v_blank - timing_out->v_front_porch - } else {
timing_out->v_sync_width; if (acrtc->dm_irq_params.window_param.skip_frame_cnt) {
acrtc->dm_irq_params.window_param.skip_frame_cnt -= 1;
goto cleanup;
}
crc_window_latch_up_line = v_back_porch + timing_out->v_sync_width; if (adev->dm.crc_rd_wrk) {
crc_rd_wrk = adev->dm.crc_rd_wrk;
/* take 3 lines margin*/ spin_lock_irqsave(&crc_rd_wrk->crc_rd_work_lock, flags2);
if ((position.vertical_count + 3) >= crc_window_latch_up_line) crc_rd_wrk->phy_inst = stream_state->link->link_enc_hw_inst;
acrtc->dm_irq_params.crc_window.skip_frame_cnt = 1; spin_unlock_irqrestore(&crc_rd_wrk->crc_rd_work_lock, flags2);
else schedule_work(&crc_rd_wrk->notify_ta_work);
acrtc->dm_irq_params.crc_window.skip_frame_cnt = 0;
} else {
if (acrtc->dm_irq_params.crc_window.skip_frame_cnt == 0) {
if (adev->dm.crc_rd_wrk) {
crc_rd_wrk = adev->dm.crc_rd_wrk;
spin_lock_irqsave(&crc_rd_wrk->crc_rd_work_lock, flags2);
crc_rd_wrk->phy_inst =
stream_state->link->link_enc_hw_inst;
spin_unlock_irqrestore(&crc_rd_wrk->crc_rd_work_lock, flags2);
schedule_work(&crc_rd_wrk->notify_ta_work);
}
} else {
acrtc->dm_irq_params.crc_window.skip_frame_cnt -= 1;
}
}
} }
} }

View File

@@ -40,7 +40,7 @@ enum amdgpu_dm_pipe_crc_source {
}; };
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY #ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
struct crc_window_parm { struct crc_window_param {
uint16_t x_start; uint16_t x_start;
uint16_t y_start; uint16_t y_start;
uint16_t x_end; uint16_t x_end;
@@ -53,6 +53,7 @@ struct crc_window_parm {
int skip_frame_cnt; int skip_frame_cnt;
}; };
/* read_work for driver to call PSP to read */
struct crc_rd_work { struct crc_rd_work {
struct work_struct notify_ta_work; struct work_struct notify_ta_work;
/* To protect crc_rd_work carried fields*/ /* To protect crc_rd_work carried fields*/
@@ -60,6 +61,15 @@ struct crc_rd_work {
struct drm_crtc *crtc; struct drm_crtc *crtc;
uint8_t phy_inst; uint8_t phy_inst;
}; };
/* forward_work for driver to forward ROI to dmu */
struct crc_fw_work {
struct work_struct forward_roi_work;
struct amdgpu_display_manager *dm;
struct dc_stream_state *stream;
struct rect rect;
bool is_stop_cmd;
};
#endif #endif
static inline bool amdgpu_dm_is_valid_crc_source(enum amdgpu_dm_pipe_crc_source source) static inline bool amdgpu_dm_is_valid_crc_source(enum amdgpu_dm_pipe_crc_source source)

View File

@@ -127,6 +127,9 @@ static void vblank_control_worker(struct work_struct *work)
amdgpu_dm_psr_disable(vblank_work->stream); amdgpu_dm_psr_disable(vblank_work->stream);
} else if (vblank_work->stream->link->psr_settings.psr_feature_enabled && } else if (vblank_work->stream->link->psr_settings.psr_feature_enabled &&
!vblank_work->stream->link->psr_settings.psr_allow_active && !vblank_work->stream->link->psr_settings.psr_allow_active &&
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
!amdgpu_dm_crc_window_is_activated(&vblank_work->acrtc->base) &&
#endif
vblank_work->acrtc->dm_irq_params.allow_psr_entry) { vblank_work->acrtc->dm_irq_params.allow_psr_entry) {
amdgpu_dm_psr_enable(vblank_work->stream); amdgpu_dm_psr_enable(vblank_work->stream);
} }

View File

@@ -38,6 +38,10 @@
#include "link_hwss.h" #include "link_hwss.h"
#include "dc/dc_dmub_srv.h" #include "dc/dc_dmub_srv.h"
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
#include "amdgpu_dm_psr.h"
#endif
struct dmub_debugfs_trace_header { struct dmub_debugfs_trace_header {
uint32_t entry_count; uint32_t entry_count;
uint32_t reserved[3]; uint32_t reserved[3];
@@ -299,6 +303,8 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
case LINK_RATE_HIGH2: case LINK_RATE_HIGH2:
case LINK_RATE_HIGH3: case LINK_RATE_HIGH3:
case LINK_RATE_UHBR10: case LINK_RATE_UHBR10:
case LINK_RATE_UHBR13_5:
case LINK_RATE_UHBR20:
break; break;
default: default:
valid_input = false; valid_input = false;
@@ -3079,8 +3085,8 @@ static int crc_win_x_start_set(void *data, u64 val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock); spin_lock_irq(&drm_dev->event_lock);
acrtc->dm_irq_params.crc_window.x_start = (uint16_t) val; acrtc->dm_irq_params.window_param.x_start = (uint16_t) val;
acrtc->dm_irq_params.crc_window.update_win = false; acrtc->dm_irq_params.window_param.update_win = false;
spin_unlock_irq(&drm_dev->event_lock); spin_unlock_irq(&drm_dev->event_lock);
return 0; return 0;
@@ -3096,7 +3102,7 @@ static int crc_win_x_start_get(void *data, u64 *val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock); spin_lock_irq(&drm_dev->event_lock);
*val = acrtc->dm_irq_params.crc_window.x_start; *val = acrtc->dm_irq_params.window_param.x_start;
spin_unlock_irq(&drm_dev->event_lock); spin_unlock_irq(&drm_dev->event_lock);
return 0; return 0;
@@ -3116,8 +3122,8 @@ static int crc_win_y_start_set(void *data, u64 val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock); spin_lock_irq(&drm_dev->event_lock);
acrtc->dm_irq_params.crc_window.y_start = (uint16_t) val; acrtc->dm_irq_params.window_param.y_start = (uint16_t) val;
acrtc->dm_irq_params.crc_window.update_win = false; acrtc->dm_irq_params.window_param.update_win = false;
spin_unlock_irq(&drm_dev->event_lock); spin_unlock_irq(&drm_dev->event_lock);
return 0; return 0;
@@ -3133,7 +3139,7 @@ static int crc_win_y_start_get(void *data, u64 *val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock); spin_lock_irq(&drm_dev->event_lock);
*val = acrtc->dm_irq_params.crc_window.y_start; *val = acrtc->dm_irq_params.window_param.y_start;
spin_unlock_irq(&drm_dev->event_lock); spin_unlock_irq(&drm_dev->event_lock);
return 0; return 0;
@@ -3152,8 +3158,8 @@ static int crc_win_x_end_set(void *data, u64 val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock); spin_lock_irq(&drm_dev->event_lock);
acrtc->dm_irq_params.crc_window.x_end = (uint16_t) val; acrtc->dm_irq_params.window_param.x_end = (uint16_t) val;
acrtc->dm_irq_params.crc_window.update_win = false; acrtc->dm_irq_params.window_param.update_win = false;
spin_unlock_irq(&drm_dev->event_lock); spin_unlock_irq(&drm_dev->event_lock);
return 0; return 0;
@@ -3169,7 +3175,7 @@ static int crc_win_x_end_get(void *data, u64 *val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock); spin_lock_irq(&drm_dev->event_lock);
*val = acrtc->dm_irq_params.crc_window.x_end; *val = acrtc->dm_irq_params.window_param.x_end;
spin_unlock_irq(&drm_dev->event_lock); spin_unlock_irq(&drm_dev->event_lock);
return 0; return 0;
@@ -3188,8 +3194,8 @@ static int crc_win_y_end_set(void *data, u64 val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock); spin_lock_irq(&drm_dev->event_lock);
acrtc->dm_irq_params.crc_window.y_end = (uint16_t) val; acrtc->dm_irq_params.window_param.y_end = (uint16_t) val;
acrtc->dm_irq_params.crc_window.update_win = false; acrtc->dm_irq_params.window_param.update_win = false;
spin_unlock_irq(&drm_dev->event_lock); spin_unlock_irq(&drm_dev->event_lock);
return 0; return 0;
@@ -3205,7 +3211,7 @@ static int crc_win_y_end_get(void *data, u64 *val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock); spin_lock_irq(&drm_dev->event_lock);
*val = acrtc->dm_irq_params.crc_window.y_end; *val = acrtc->dm_irq_params.window_param.y_end;
spin_unlock_irq(&drm_dev->event_lock); spin_unlock_irq(&drm_dev->event_lock);
return 0; return 0;
@@ -3228,31 +3234,38 @@ static int crc_win_update_set(void *data, u64 val)
return 0; return 0;
if (val) { if (val) {
new_acrtc = to_amdgpu_crtc(new_crtc);
mutex_lock(&adev->dm.dc_lock);
/* PSR may write to OTG CRC window control register,
* so close it before starting secure_display.
*/
amdgpu_dm_psr_disable(new_acrtc->dm_irq_params.stream);
spin_lock_irq(&adev_to_drm(adev)->event_lock); spin_lock_irq(&adev_to_drm(adev)->event_lock);
spin_lock_irq(&crc_rd_wrk->crc_rd_work_lock); spin_lock_irq(&crc_rd_wrk->crc_rd_work_lock);
if (crc_rd_wrk->crtc) { if (crc_rd_wrk->crtc) {
old_crtc = crc_rd_wrk->crtc; old_crtc = crc_rd_wrk->crtc;
old_acrtc = to_amdgpu_crtc(old_crtc); old_acrtc = to_amdgpu_crtc(old_crtc);
} }
new_acrtc = to_amdgpu_crtc(new_crtc);
if (old_crtc && old_crtc != new_crtc) { if (old_crtc && old_crtc != new_crtc) {
old_acrtc->dm_irq_params.crc_window.activated = false; old_acrtc->dm_irq_params.window_param.activated = false;
old_acrtc->dm_irq_params.crc_window.update_win = false; old_acrtc->dm_irq_params.window_param.update_win = false;
old_acrtc->dm_irq_params.crc_window.skip_frame_cnt = 0; old_acrtc->dm_irq_params.window_param.skip_frame_cnt = 0;
new_acrtc->dm_irq_params.crc_window.activated = true; new_acrtc->dm_irq_params.window_param.activated = true;
new_acrtc->dm_irq_params.crc_window.update_win = true; new_acrtc->dm_irq_params.window_param.update_win = true;
new_acrtc->dm_irq_params.crc_window.skip_frame_cnt = 0; new_acrtc->dm_irq_params.window_param.skip_frame_cnt = 0;
crc_rd_wrk->crtc = new_crtc; crc_rd_wrk->crtc = new_crtc;
} else { } else {
new_acrtc->dm_irq_params.crc_window.activated = true; new_acrtc->dm_irq_params.window_param.activated = true;
new_acrtc->dm_irq_params.crc_window.update_win = true; new_acrtc->dm_irq_params.window_param.update_win = true;
new_acrtc->dm_irq_params.crc_window.skip_frame_cnt = 0; new_acrtc->dm_irq_params.window_param.skip_frame_cnt = 0;
crc_rd_wrk->crtc = new_crtc; crc_rd_wrk->crtc = new_crtc;
} }
spin_unlock_irq(&crc_rd_wrk->crc_rd_work_lock); spin_unlock_irq(&crc_rd_wrk->crc_rd_work_lock);
spin_unlock_irq(&adev_to_drm(adev)->event_lock); spin_unlock_irq(&adev_to_drm(adev)->event_lock);
mutex_unlock(&adev->dm.dc_lock);
} }
return 0; return 0;

View File

@@ -495,7 +495,7 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)
link->dp.mst_enabled = config->mst_enabled; link->dp.mst_enabled = config->mst_enabled;
link->dp.usb4_enabled = config->usb4_enabled; link->dp.usb4_enabled = config->usb4_enabled;
display->adjust.disable = MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION; display->adjust.disable = MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION;
link->adjust.auth_delay = 3; link->adjust.auth_delay = 0;
link->adjust.hdcp1.disable = 0; link->adjust.hdcp1.disable = 0;
conn_state = aconnector->base.state; conn_state = aconnector->base.state;

View File

@@ -42,39 +42,6 @@
#include "dm_helpers.h" #include "dm_helpers.h"
#include "ddc_service_types.h" #include "ddc_service_types.h"
struct monitor_patch_info {
unsigned int manufacturer_id;
unsigned int product_id;
void (*patch_func)(struct dc_edid_caps *edid_caps, unsigned int param);
unsigned int patch_param;
};
static void set_max_dsc_bpp_limit(struct dc_edid_caps *edid_caps, unsigned int param);
static const struct monitor_patch_info monitor_patch_table[] = {
{0x6D1E, 0x5BBF, set_max_dsc_bpp_limit, 15},
{0x6D1E, 0x5B9A, set_max_dsc_bpp_limit, 15},
};
static void set_max_dsc_bpp_limit(struct dc_edid_caps *edid_caps, unsigned int param)
{
if (edid_caps)
edid_caps->panel_patch.max_dsc_target_bpp_limit = param;
}
static int amdgpu_dm_patch_edid_caps(struct dc_edid_caps *edid_caps)
{
int i, ret = 0;
for (i = 0; i < ARRAY_SIZE(monitor_patch_table); i++)
if ((edid_caps->manufacturer_id == monitor_patch_table[i].manufacturer_id)
&& (edid_caps->product_id == monitor_patch_table[i].product_id)) {
monitor_patch_table[i].patch_func(edid_caps, monitor_patch_table[i].patch_param);
ret++;
}
return ret;
}
/* dm_helpers_parse_edid_caps /* dm_helpers_parse_edid_caps
* *
* Parse edid caps * Parse edid caps
@@ -149,8 +116,6 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
kfree(sads); kfree(sads);
kfree(sadb); kfree(sadb);
amdgpu_dm_patch_edid_caps(edid_caps);
return result; return result;
} }

View File

@@ -39,7 +39,7 @@ struct dm_irq_params {
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
enum amdgpu_dm_pipe_crc_source crc_src; enum amdgpu_dm_pipe_crc_source crc_src;
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY #ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
struct crc_window_parm crc_window; struct crc_window_param window_param;
#endif #endif
#endif #endif
}; };

View File

@@ -642,15 +642,18 @@ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *p
int count, int count,
int k) int k)
{ {
struct drm_connector *drm_connector;
int i; int i;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
drm_connector = &params[i].aconnector->base;
memset(&params[i].timing->dsc_cfg, 0, sizeof(params[i].timing->dsc_cfg)); memset(&params[i].timing->dsc_cfg, 0, sizeof(params[i].timing->dsc_cfg));
if (vars[i + k].dsc_enabled && dc_dsc_compute_config( if (vars[i + k].dsc_enabled && dc_dsc_compute_config(
params[i].sink->ctx->dc->res_pool->dscs[0], params[i].sink->ctx->dc->res_pool->dscs[0],
&params[i].sink->dsc_caps.dsc_dec_caps, &params[i].sink->dsc_caps.dsc_dec_caps,
params[i].sink->ctx->dc->debug.dsc_min_slice_height_override, params[i].sink->ctx->dc->debug.dsc_min_slice_height_override,
params[i].sink->edid_caps.panel_patch.max_dsc_target_bpp_limit, drm_connector->display_info.max_dsc_bpp,
0, 0,
params[i].timing, params[i].timing,
&params[i].timing->dsc_cfg)) { &params[i].timing->dsc_cfg)) {
@@ -692,12 +695,16 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
struct dc_dsc_config dsc_config; struct dc_dsc_config dsc_config;
u64 kbps; u64 kbps;
struct drm_connector *drm_connector = &param.aconnector->base;
uint32_t max_dsc_target_bpp_limit_override =
drm_connector->display_info.max_dsc_bpp;
kbps = div_u64((u64)pbn * 994 * 8 * 54, 64); kbps = div_u64((u64)pbn * 994 * 8 * 54, 64);
dc_dsc_compute_config( dc_dsc_compute_config(
param.sink->ctx->dc->res_pool->dscs[0], param.sink->ctx->dc->res_pool->dscs[0],
&param.sink->dsc_caps.dsc_dec_caps, &param.sink->dsc_caps.dsc_dec_caps,
param.sink->ctx->dc->debug.dsc_min_slice_height_override, param.sink->ctx->dc->debug.dsc_min_slice_height_override,
param.sink->edid_caps.panel_patch.max_dsc_target_bpp_limit, max_dsc_target_bpp_limit_override,
(int) kbps, param.timing, &dsc_config); (int) kbps, param.timing, &dsc_config);
return dsc_config.bits_per_pixel; return dsc_config.bits_per_pixel;

View File

@@ -1369,7 +1369,7 @@ static bool dm_plane_format_mod_supported(struct drm_plane *plane,
{ {
struct amdgpu_device *adev = drm_to_adev(plane->dev); struct amdgpu_device *adev = drm_to_adev(plane->dev);
const struct drm_format_info *info = drm_format_info(format); const struct drm_format_info *info = drm_format_info(format);
struct hw_asic_id asic_id = adev->dm.dc->ctx->asic_id; int i;
enum dm_micro_swizzle microtile = modifier_gfx9_swizzle_mode(modifier) & 3; enum dm_micro_swizzle microtile = modifier_gfx9_swizzle_mode(modifier) & 3;
@@ -1386,49 +1386,13 @@ static bool dm_plane_format_mod_supported(struct drm_plane *plane,
return true; return true;
} }
/* check if swizzle mode is supported by this version of DCN */ /* Check that the modifier is on the list of the plane's supported modifiers. */
switch (asic_id.chip_family) { for (i = 0; i < plane->modifier_count; i++) {
case FAMILY_SI: if (modifier == plane->modifiers[i])
case FAMILY_CI: break;
case FAMILY_KV:
case FAMILY_CZ:
case FAMILY_VI:
/* asics before AI does not have modifier support */
return false;
case FAMILY_AI:
case FAMILY_RV:
case FAMILY_NV:
case FAMILY_VGH:
case FAMILY_YELLOW_CARP:
case AMDGPU_FAMILY_GC_10_3_6:
case AMDGPU_FAMILY_GC_10_3_7:
switch (AMD_FMT_MOD_GET(TILE, modifier)) {
case AMD_FMT_MOD_TILE_GFX9_64K_R_X:
case AMD_FMT_MOD_TILE_GFX9_64K_D_X:
case AMD_FMT_MOD_TILE_GFX9_64K_S_X:
case AMD_FMT_MOD_TILE_GFX9_64K_D:
return true;
default:
return false;
}
break;
case AMDGPU_FAMILY_GC_11_0_0:
case AMDGPU_FAMILY_GC_11_0_1:
switch (AMD_FMT_MOD_GET(TILE, modifier)) {
case AMD_FMT_MOD_TILE_GFX11_256K_R_X:
case AMD_FMT_MOD_TILE_GFX9_64K_R_X:
case AMD_FMT_MOD_TILE_GFX9_64K_D_X:
case AMD_FMT_MOD_TILE_GFX9_64K_S_X:
case AMD_FMT_MOD_TILE_GFX9_64K_D:
return true;
default:
return false;
}
break;
default:
ASSERT(0); /* Unknown asic */
break;
} }
if (i == plane->modifier_count)
return false;
/* /*
* For D swizzle the canonical modifier depends on the bpp, so check * For D swizzle the canonical modifier depends on the bpp, so check

View File

@@ -37,6 +37,7 @@
#include <drm/drm_framebuffer.h> #include <drm/drm_framebuffer.h>
#include <drm/drm_encoder.h> #include <drm/drm_encoder.h>
#include <drm/drm_atomic.h> #include <drm/drm_atomic.h>
#include "dcn10/dcn10_optc.h"
#include "dc/inc/core_types.h" #include "dc/inc/core_types.h"
@@ -662,6 +663,69 @@ TRACE_EVENT(dcn_fpu,
) )
); );
TRACE_EVENT(dcn_optc_lock_unlock_state,
TP_PROTO(const struct optc *optc_state, int instance, bool lock, const char *function, const int line),
TP_ARGS(optc_state, instance, lock, function, line),
TP_STRUCT__entry(
__field(const char *, function)
__field(int, instance)
__field(bool, lock)
__field(int, line)
__field(int, opp_count)
__field(int, max_h_total)
__field(int, max_v_total)
__field(int, min_h_blank)
__field(int, min_h_sync_width)
__field(int, min_v_sync_width)
__field(int, min_v_blank)
__field(int, min_v_blank_interlace)
__field(int, vstartup_start)
__field(int, vupdate_offset)
__field(int, vupdate_width)
__field(int, vready_offset)
),
TP_fast_assign(
__entry->function = function;
__entry->instance = instance;
__entry->lock = lock;
__entry->line = line;
__entry->opp_count = optc_state->opp_count;
__entry->max_h_total = optc_state->max_h_total;
__entry->max_v_total = optc_state->max_v_total;
__entry->min_h_blank = optc_state->min_h_blank;
__entry->min_h_sync_width = optc_state->min_h_sync_width;
__entry->min_v_sync_width = optc_state->min_v_sync_width;
__entry->min_v_blank = optc_state->min_v_blank;
__entry->min_v_blank_interlace = optc_state->min_v_blank_interlace;
__entry->vstartup_start = optc_state->vstartup_start;
__entry->vupdate_offset = optc_state->vupdate_offset;
__entry->vupdate_width = optc_state->vupdate_width;
__entry->vready_offset = optc_state->vupdate_offset;
),
TP_printk("%s: %s()+%d: optc_instance=%d opp_count=%d max_h_total=%d max_v_total=%d "
"min_h_blank=%d min_h_sync_width=%d min_v_sync_width=%d min_v_blank=%d "
"min_v_blank_interlace=%d vstartup_start=%d vupdate_offset=%d vupdate_width=%d "
"vready_offset=%d",
__entry->lock ? "Lock" : "Unlock",
__entry->function,
__entry->line,
__entry->instance,
__entry->opp_count,
__entry->max_h_total,
__entry->max_v_total,
__entry->min_h_blank,
__entry->min_h_sync_width,
__entry->min_v_sync_width,
__entry->min_v_blank,
__entry->min_v_blank_interlace,
__entry->vstartup_start,
__entry->vupdate_offset,
__entry->vupdate_width,
__entry->vready_offset
)
);
#endif /* _AMDGPU_DM_TRACE_H_ */ #endif /* _AMDGPU_DM_TRACE_H_ */
#undef TRACE_INCLUDE_PATH #undef TRACE_INCLUDE_PATH

View File

@@ -31,6 +31,8 @@
#elif defined(CONFIG_PPC64) #elif defined(CONFIG_PPC64)
#include <asm/switch_to.h> #include <asm/switch_to.h>
#include <asm/cputable.h> #include <asm/cputable.h>
#elif defined(CONFIG_ARM64)
#include <asm/neon.h>
#endif #endif
/** /**
@@ -99,6 +101,8 @@ void dc_fpu_begin(const char *function_name, const int line)
preempt_disable(); preempt_disable();
enable_kernel_fp(); enable_kernel_fp();
} }
#elif defined(CONFIG_ARM64)
kernel_neon_begin();
#endif #endif
} }
@@ -136,6 +140,8 @@ void dc_fpu_end(const char *function_name, const int line)
disable_kernel_fp(); disable_kernel_fp();
preempt_enable(); preempt_enable();
} }
#elif defined(CONFIG_ARM64)
kernel_neon_end();
#endif #endif
} }

View File

@@ -26,6 +26,8 @@
#ifndef DAL_DC_RN_CLK_MGR_VBIOS_SMU_H_ #ifndef DAL_DC_RN_CLK_MGR_VBIOS_SMU_H_
#define DAL_DC_RN_CLK_MGR_VBIOS_SMU_H_ #define DAL_DC_RN_CLK_MGR_VBIOS_SMU_H_
enum dcn_pwr_state;
int rn_vbios_smu_get_smu_version(struct clk_mgr_internal *clk_mgr); int rn_vbios_smu_get_smu_version(struct clk_mgr_internal *clk_mgr);
int rn_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz); int rn_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz);
int rn_vbios_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr); int rn_vbios_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr);
@@ -33,7 +35,7 @@ int rn_vbios_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int reque
int rn_vbios_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz); int rn_vbios_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz);
void rn_vbios_smu_set_phyclk(struct clk_mgr_internal *clk_mgr, int requested_phyclk_khz); void rn_vbios_smu_set_phyclk(struct clk_mgr_internal *clk_mgr, int requested_phyclk_khz);
int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz); int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz);
void rn_vbios_smu_set_dcn_low_power_state(struct clk_mgr_internal *clk_mgr, int display_count); void rn_vbios_smu_set_dcn_low_power_state(struct clk_mgr_internal *clk_mgr, enum dcn_pwr_state);
void rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable); void rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable);
void rn_vbios_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr); void rn_vbios_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr);
int rn_vbios_smu_is_periodic_retraining_disabled(struct clk_mgr_internal *clk_mgr); int rn_vbios_smu_is_periodic_retraining_disabled(struct clk_mgr_internal *clk_mgr);

View File

@@ -458,19 +458,6 @@ static void dcn315_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr,
dcn315_smu_transfer_dpm_table_smu_2_dram(clk_mgr); dcn315_smu_transfer_dpm_table_smu_2_dram(clk_mgr);
} }
static uint32_t find_max_clk_value(const uint32_t clocks[], uint32_t num_clocks)
{
uint32_t max = 0;
int i;
for (i = 0; i < num_clocks; ++i) {
if (clocks[i] > max)
max = clocks[i];
}
return max;
}
static void dcn315_clk_mgr_helper_populate_bw_params( static void dcn315_clk_mgr_helper_populate_bw_params(
struct clk_mgr_internal *clk_mgr, struct clk_mgr_internal *clk_mgr,
struct integrated_info *bios_info, struct integrated_info *bios_info,
@@ -478,29 +465,21 @@ static void dcn315_clk_mgr_helper_populate_bw_params(
{ {
int i; int i;
struct clk_bw_params *bw_params = clk_mgr->base.bw_params; struct clk_bw_params *bw_params = clk_mgr->base.bw_params;
uint32_t max_pstate = 0, max_fclk = 0, min_pstate = 0; uint32_t max_pstate = clock_table->NumDfPstatesEnabled - 1;
struct clk_limit_table_entry def_max = bw_params->clk_table.entries[bw_params->clk_table.num_entries - 1]; struct clk_limit_table_entry def_max = bw_params->clk_table.entries[bw_params->clk_table.num_entries - 1];
/* Find highest fclk pstate */
for (i = 0; i < clock_table->NumDfPstatesEnabled; i++) {
if (clock_table->DfPstateTable[i].FClk > max_fclk) {
max_fclk = clock_table->DfPstateTable[i].FClk;
max_pstate = i;
}
}
/* For 315 we want to base clock table on dcfclk, need at least one entry regardless of pmfw table */ /* For 315 we want to base clock table on dcfclk, need at least one entry regardless of pmfw table */
for (i = 0; i < clock_table->NumDcfClkLevelsEnabled; i++) { for (i = 0; i < clock_table->NumDcfClkLevelsEnabled; i++) {
int j; int j;
uint32_t min_fclk = clock_table->DfPstateTable[0].FClk;
for (j = 1; j < clock_table->NumDfPstatesEnabled; j++) { /* DF table is sorted with clocks decreasing */
if (clock_table->DfPstateTable[j].Voltage <= clock_table->SocVoltage[i] for (j = clock_table->NumDfPstatesEnabled - 2; j >= 0; j--) {
&& clock_table->DfPstateTable[j].FClk < min_fclk) { if (clock_table->DfPstateTable[j].Voltage <= clock_table->SocVoltage[i])
min_fclk = clock_table->DfPstateTable[j].FClk; max_pstate = j;
min_pstate = j;
}
} }
/* Max DCFCLK should match up with max pstate */
if (i == clock_table->NumDcfClkLevelsEnabled - 1)
max_pstate = 0;
/* First search defaults for the clocks we don't read using closest lower or equal default dcfclk */ /* First search defaults for the clocks we don't read using closest lower or equal default dcfclk */
for (j = bw_params->clk_table.num_entries - 1; j > 0; j--) for (j = bw_params->clk_table.num_entries - 1; j > 0; j--)
@@ -511,9 +490,9 @@ static void dcn315_clk_mgr_helper_populate_bw_params(
bw_params->clk_table.entries[i].dtbclk_mhz = bw_params->clk_table.entries[j].dtbclk_mhz; bw_params->clk_table.entries[i].dtbclk_mhz = bw_params->clk_table.entries[j].dtbclk_mhz;
/* Now update clocks we do read */ /* Now update clocks we do read */
bw_params->clk_table.entries[i].fclk_mhz = min_fclk; bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[max_pstate].FClk;
bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[min_pstate].MemClk; bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[max_pstate].MemClk;
bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[min_pstate].Voltage; bw_params->clk_table.entries[i].voltage = clock_table->SocVoltage[i];
bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[i]; bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[i];
bw_params->clk_table.entries[i].socclk_mhz = clock_table->SocClocks[i]; bw_params->clk_table.entries[i].socclk_mhz = clock_table->SocClocks[i];
bw_params->clk_table.entries[i].dispclk_mhz = clock_table->DispClocks[i]; bw_params->clk_table.entries[i].dispclk_mhz = clock_table->DispClocks[i];
@@ -521,25 +500,16 @@ static void dcn315_clk_mgr_helper_populate_bw_params(
bw_params->clk_table.entries[i].wck_ratio = 1; bw_params->clk_table.entries[i].wck_ratio = 1;
} }
/* Make sure to include at least one entry and highest pstate */ /* Make sure to include at least one entry */
if (max_pstate != min_pstate || i == 0) { if (i == 0) {
bw_params->clk_table.entries[i].fclk_mhz = max_fclk; bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[0].FClk;
bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[max_pstate].MemClk; bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[0].MemClk;
bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[max_pstate].Voltage; bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[0].Voltage;
bw_params->clk_table.entries[i].dcfclk_mhz = find_max_clk_value(clock_table->DcfClocks, NUM_DCFCLK_DPM_LEVELS); bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[0];
bw_params->clk_table.entries[i].wck_ratio = 1; bw_params->clk_table.entries[i].wck_ratio = 1;
i++; i++;
} }
bw_params->clk_table.num_entries = i--; bw_params->clk_table.num_entries = i;
/* Make sure all highest clocks are included*/
bw_params->clk_table.entries[i].socclk_mhz = find_max_clk_value(clock_table->SocClocks, NUM_SOCCLK_DPM_LEVELS);
bw_params->clk_table.entries[i].dispclk_mhz = find_max_clk_value(clock_table->DispClocks, NUM_DISPCLK_DPM_LEVELS);
bw_params->clk_table.entries[i].dppclk_mhz = find_max_clk_value(clock_table->DppClocks, NUM_DPPCLK_DPM_LEVELS);
ASSERT(clock_table->DcfClocks[i] == find_max_clk_value(clock_table->DcfClocks, NUM_DCFCLK_DPM_LEVELS));
bw_params->clk_table.entries[i].phyclk_mhz = def_max.phyclk_mhz;
bw_params->clk_table.entries[i].phyclk_d18_mhz = def_max.phyclk_d18_mhz;
bw_params->clk_table.entries[i].dtbclk_mhz = def_max.dtbclk_mhz;
/* Set any 0 clocks to max default setting. Not an issue for /* Set any 0 clocks to max default setting. Not an issue for
* power since we aren't doing switching in such case anyway * power since we aren't doing switching in such case anyway
@@ -565,6 +535,11 @@ static void dcn315_clk_mgr_helper_populate_bw_params(
if (!bw_params->clk_table.entries[i].dtbclk_mhz) if (!bw_params->clk_table.entries[i].dtbclk_mhz)
bw_params->clk_table.entries[i].dtbclk_mhz = def_max.dtbclk_mhz; bw_params->clk_table.entries[i].dtbclk_mhz = def_max.dtbclk_mhz;
} }
/* Make sure all highest default clocks are included*/
ASSERT(bw_params->clk_table.entries[i-1].phyclk_mhz == def_max.phyclk_mhz);
ASSERT(bw_params->clk_table.entries[i-1].phyclk_d18_mhz == def_max.phyclk_d18_mhz);
ASSERT(bw_params->clk_table.entries[i-1].dtbclk_mhz == def_max.dtbclk_mhz);
ASSERT(bw_params->clk_table.entries[i-1].dcfclk_mhz); ASSERT(bw_params->clk_table.entries[i-1].dcfclk_mhz);
bw_params->vram_type = bios_info->memory_type; bw_params->vram_type = bios_info->memory_type;
bw_params->num_channels = bios_info->ma_channel_number; bw_params->num_channels = bios_info->ma_channel_number;

View File

@@ -157,6 +157,7 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
unsigned int num_levels; unsigned int num_levels;
struct clk_limit_num_entries *num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk; struct clk_limit_num_entries *num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk;
unsigned int i;
memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks)); memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks));
clk_mgr_base->clks.p_state_change_support = true; clk_mgr_base->clks.p_state_change_support = true;
@@ -205,18 +206,17 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
clk_mgr->dpm_present = true; clk_mgr->dpm_present = true;
if (clk_mgr_base->ctx->dc->debug.min_disp_clk_khz) { if (clk_mgr_base->ctx->dc->debug.min_disp_clk_khz) {
unsigned int i;
for (i = 0; i < num_levels; i++) for (i = 0; i < num_levels; i++)
if (clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz if (clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz
< khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_disp_clk_khz)) < khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_disp_clk_khz))
clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz
= khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_disp_clk_khz); = khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_disp_clk_khz);
} }
for (i = 0; i < num_levels; i++)
if (clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz > 1950)
clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz = 1950;
if (clk_mgr_base->ctx->dc->debug.min_dpp_clk_khz) { if (clk_mgr_base->ctx->dc->debug.min_dpp_clk_khz) {
unsigned int i;
for (i = 0; i < num_levels; i++) for (i = 0; i < num_levels; i++)
if (clk_mgr_base->bw_params->clk_table.entries[i].dppclk_mhz if (clk_mgr_base->bw_params->clk_table.entries[i].dppclk_mhz
< khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_dpp_clk_khz)) < khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_dpp_clk_khz))
@@ -669,6 +669,9 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
&clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz, &clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz,
&num_entries_per_clk->num_memclk_levels); &num_entries_per_clk->num_memclk_levels);
/* memclk must have at least one level */
num_entries_per_clk->num_memclk_levels = num_entries_per_clk->num_memclk_levels ? num_entries_per_clk->num_memclk_levels : 1;
dcn32_init_single_clock(clk_mgr, PPCLK_FCLK, dcn32_init_single_clock(clk_mgr, PPCLK_FCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz, &clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz,
&num_entries_per_clk->num_fclk_levels); &num_entries_per_clk->num_fclk_levels);

View File

@@ -135,9 +135,7 @@ static const char DC_BUILD_ID[] = "production-build";
* one or two (in the pipe-split case). * one or two (in the pipe-split case).
*/ */
/******************************************************************************* /* Private functions */
* Private functions
******************************************************************************/
static inline void elevate_update_type(enum surface_update_type *original, enum surface_update_type new) static inline void elevate_update_type(enum surface_update_type *original, enum surface_update_type new)
{ {
@@ -401,9 +399,6 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
{ {
int i; int i;
if (memcmp(adjust, &stream->adjust, sizeof(struct dc_crtc_timing_adjust)) == 0)
return true;
stream->adjust.v_total_max = adjust->v_total_max; stream->adjust.v_total_max = adjust->v_total_max;
stream->adjust.v_total_mid = adjust->v_total_mid; stream->adjust.v_total_mid = adjust->v_total_mid;
stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num; stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num;
@@ -424,18 +419,14 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
} }
/** /**
***************************************************************************** * dc_stream_get_last_used_drr_vtotal - dc_stream_get_last_vrr_vtotal
* Function: dc_stream_get_last_vrr_vtotal
* *
* @brief * @dc: [in] dc reference
* Looks up the pipe context of dc_stream_state and gets the * @stream: [in] Initial dc stream state
* last VTOTAL used by DRR (Dynamic Refresh Rate) * @adjust: [in] Updated parameters for vertical_total_min and
* *
* @param [in] dc: dc reference * Looks up the pipe context of dc_stream_state and gets the last VTOTAL used
* @param [in] stream: Initial dc stream state * by DRR (Dynamic Refresh Rate)
* @param [in] adjust: Updated parameters for vertical_total_min and
* vertical_total_max
*****************************************************************************
*/ */
bool dc_stream_get_last_used_drr_vtotal(struct dc *dc, bool dc_stream_get_last_used_drr_vtotal(struct dc *dc,
struct dc_stream_state *stream, struct dc_stream_state *stream,
@@ -491,86 +482,79 @@ bool dc_stream_get_crtc_position(struct dc *dc,
} }
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
bool dc_stream_forward_dmcu_crc_window(struct dc *dc, struct dc_stream_state *stream, static inline void
struct crc_params *crc_window) dc_stream_forward_dmub_crc_window(struct dc_dmub_srv *dmub_srv,
struct rect *rect, struct otg_phy_mux *mux_mapping, bool is_stop)
{ {
int i; union dmub_rb_cmd cmd = {0};
struct dmcu *dmcu = dc->res_pool->dmcu;
struct pipe_ctx *pipe;
struct crc_region tmp_win, *crc_win;
struct otg_phy_mux mapping_tmp, *mux_mapping;
/*crc window can't be null*/ cmd.secure_display.roi_info.phy_id = mux_mapping->phy_output_num;
if (!crc_window) cmd.secure_display.roi_info.otg_id = mux_mapping->otg_output_num;
return false;
if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu))) { if (is_stop) {
crc_win = &tmp_win; cmd.secure_display.header.type = DMUB_CMD__SECURE_DISPLAY;
mux_mapping = &mapping_tmp; cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_CRC_STOP_UPDATE;
/*set crc window*/
tmp_win.x_start = crc_window->windowa_x_start;
tmp_win.y_start = crc_window->windowa_y_start;
tmp_win.x_end = crc_window->windowa_x_end;
tmp_win.y_end = crc_window->windowa_y_end;
for (i = 0; i < MAX_PIPES; i++) {
pipe = &dc->current_state->res_ctx.pipe_ctx[i];
if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe)
break;
}
/* Stream not found */
if (i == MAX_PIPES)
return false;
/*set mux routing info*/
mapping_tmp.phy_output_num = stream->link->link_enc_hw_inst;
mapping_tmp.otg_output_num = pipe->stream_res.tg->inst;
dmcu->funcs->forward_crc_window(dmcu, crc_win, mux_mapping);
} else { } else {
DC_LOG_DC("dmcu is not initialized"); cmd.secure_display.header.type = DMUB_CMD__SECURE_DISPLAY;
return false; cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_CRC_WIN_NOTIFY;
cmd.secure_display.roi_info.x_start = rect->x;
cmd.secure_display.roi_info.y_start = rect->y;
cmd.secure_display.roi_info.x_end = rect->x + rect->width;
cmd.secure_display.roi_info.y_end = rect->y + rect->height;
} }
return true; dc_dmub_srv_cmd_queue(dmub_srv, &cmd);
dc_dmub_srv_cmd_execute(dmub_srv);
} }
bool dc_stream_stop_dmcu_crc_win_update(struct dc *dc, struct dc_stream_state *stream) static inline void
dc_stream_forward_dmcu_crc_window(struct dmcu *dmcu,
struct rect *rect, struct otg_phy_mux *mux_mapping, bool is_stop)
{ {
int i; if (is_stop)
struct dmcu *dmcu = dc->res_pool->dmcu;
struct pipe_ctx *pipe;
struct otg_phy_mux mapping_tmp, *mux_mapping;
if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu))) {
mux_mapping = &mapping_tmp;
for (i = 0; i < MAX_PIPES; i++) {
pipe = &dc->current_state->res_ctx.pipe_ctx[i];
if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe)
break;
}
/* Stream not found */
if (i == MAX_PIPES)
return false;
/*set mux routing info*/
mapping_tmp.phy_output_num = stream->link->link_enc_hw_inst;
mapping_tmp.otg_output_num = pipe->stream_res.tg->inst;
dmcu->funcs->stop_crc_win_update(dmcu, mux_mapping); dmcu->funcs->stop_crc_win_update(dmcu, mux_mapping);
} else { else
DC_LOG_DC("dmcu is not initialized"); dmcu->funcs->forward_crc_window(dmcu, rect, mux_mapping);
return false; }
bool
dc_stream_forward_crc_window(struct dc *dc,
struct rect *rect, struct dc_stream_state *stream, bool is_stop)
{
struct dmcu *dmcu;
struct dc_dmub_srv *dmub_srv;
struct otg_phy_mux mux_mapping;
struct pipe_ctx *pipe;
int i;
for (i = 0; i < MAX_PIPES; i++) {
pipe = &dc->current_state->res_ctx.pipe_ctx[i];
if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe)
break;
} }
/* Stream not found */
if (i == MAX_PIPES)
return false;
mux_mapping.phy_output_num = stream->link->link_enc_hw_inst;
mux_mapping.otg_output_num = pipe->stream_res.tg->inst;
dmcu = dc->res_pool->dmcu;
dmub_srv = dc->ctx->dmub_srv;
/* forward to dmub */
if (dmub_srv)
dc_stream_forward_dmub_crc_window(dmub_srv, rect, &mux_mapping, is_stop);
/* forward to dmcu */
else if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu))
dc_stream_forward_dmcu_crc_window(dmcu, rect, &mux_mapping, is_stop);
else
return false;
return true; return true;
} }
#endif #endif /* CONFIG_DRM_AMD_SECURE_DISPLAY */
/** /**
* dc_stream_configure_crc() - Configure CRC capture for the given stream. * dc_stream_configure_crc() - Configure CRC capture for the given stream.
@@ -1219,9 +1203,7 @@ static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context)
PERF_TRACE(); PERF_TRACE();
} }
/******************************************************************************* /* Public functions */
* Public functions
******************************************************************************/
struct dc *dc_create(const struct dc_init_data *init_params) struct dc *dc_create(const struct dc_init_data *init_params)
{ {
@@ -1488,17 +1470,19 @@ static void program_timing_sync(
} }
} }
static bool context_changed( static bool streams_changed(struct dc *dc,
struct dc *dc, struct dc_stream_state *streams[],
struct dc_state *context) uint8_t stream_count)
{ {
uint8_t i; uint8_t i;
if (context->stream_count != dc->current_state->stream_count) if (stream_count != dc->current_state->stream_count)
return true; return true;
for (i = 0; i < dc->current_state->stream_count; i++) { for (i = 0; i < dc->current_state->stream_count; i++) {
if (dc->current_state->streams[i] != context->streams[i]) if (dc->current_state->streams[i] != streams[i])
return true;
if (!streams[i]->link->link_state_valid)
return true; return true;
} }
@@ -1722,8 +1706,13 @@ void dc_z10_save_init(struct dc *dc)
dc->hwss.z10_save_init(dc); dc->hwss.z10_save_init(dc);
} }
/* /**
* Applies given context to HW and copy it into current context. * dc_commit_state_no_check - Apply context to the hardware
*
* @dc: DC object with the current status to be updated
* @context: New state that will become the current status at the end of this function
*
* Applies given context to the hardware and copy it into current context.
* It's up to the user to release the src context afterwards. * It's up to the user to release the src context afterwards.
*/ */
static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *context) static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *context)
@@ -1888,12 +1877,108 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
return result; return result;
} }
/**
* dc_commit_streams - Commit current stream state
*
* @dc: DC object with the commit state to be configured in the hardware
* @streams: Array with a list of stream state
* @stream_count: Total of streams
*
* Function responsible for commit streams change to the hardware.
*
* Return:
* Return DC_OK if everything work as expected, otherwise, return a dc_status
* code.
*/
enum dc_status dc_commit_streams(struct dc *dc,
struct dc_stream_state *streams[],
uint8_t stream_count)
{
int i, j;
struct dc_state *context;
enum dc_status res = DC_OK;
struct dc_validation_set set[MAX_STREAMS] = {0};
if (dc->ctx->dce_environment == DCE_ENV_VIRTUAL_HW)
return res;
if (!streams_changed(dc, streams, stream_count))
return res;
DC_LOG_DC("%s: %d streams\n", __func__, stream_count);
for (i = 0; i < stream_count; i++) {
struct dc_stream_state *stream = streams[i];
struct dc_stream_status *status = dc_stream_get_status(stream);
dc_stream_log(dc, stream);
set[i].stream = stream;
if (status) {
set[i].plane_count = status->plane_count;
for (j = 0; j < status->plane_count; j++)
set[i].plane_states[j] = status->plane_states[j];
}
}
context = dc_create_state(dc);
if (!context)
goto context_alloc_fail;
dc_resource_state_copy_construct_current(dc, context);
res = dc_validate_with_context(dc, set, stream_count, context, false);
if (res != DC_OK) {
BREAK_TO_DEBUGGER();
goto fail;
}
res = dc_commit_state_no_check(dc, context);
for (i = 0; i < stream_count; i++) {
for (j = 0; j < context->stream_count; j++) {
if (streams[i]->stream_id == context->streams[j]->stream_id)
streams[i]->out.otg_offset = context->stream_status[j].primary_otg_inst;
if (dc_is_embedded_signal(streams[i]->signal)) {
struct dc_stream_status *status = dc_stream_get_status_from_state(context, streams[i]);
if (dc->hwss.is_abm_supported)
status->is_abm_supported = dc->hwss.is_abm_supported(dc, context, streams[i]);
else
status->is_abm_supported = true;
}
}
}
fail:
dc_release_state(context);
context_alloc_fail:
DC_LOG_DC("%s Finished.\n", __func__);
return (res == DC_OK);
}
/* TODO: When the transition to the new commit sequence is done, remove this
* function in favor of dc_commit_streams. */
bool dc_commit_state(struct dc *dc, struct dc_state *context) bool dc_commit_state(struct dc *dc, struct dc_state *context)
{ {
enum dc_status result = DC_ERROR_UNEXPECTED; enum dc_status result = DC_ERROR_UNEXPECTED;
int i; int i;
if (!context_changed(dc, context)) /* TODO: Since change commit sequence can have a huge impact,
* we decided to only enable it for DCN3x. However, as soon as
* we get more confident about this change we'll need to enable
* the new sequence for all ASICs. */
if (dc->ctx->dce_version >= DCN_VERSION_3_2) {
result = dc_commit_streams(dc, context->streams, context->stream_count);
return result == DC_OK;
}
if (!streams_changed(dc, context->streams, context->stream_count))
return DC_OK; return DC_OK;
DC_LOG_DC("%s: %d streams\n", DC_LOG_DC("%s: %d streams\n",
@@ -3563,10 +3648,24 @@ static void commit_planes_for_stream(struct dc *dc,
} }
} }
/* Determines if the incoming context requires a applying transition state with unnecessary /**
* pipe splitting and ODM disabled, due to hardware limitations. In a case where * could_mpcc_tree_change_for_active_pipes - Check if an OPP associated with MPCC might change
* the OPP associated with an MPCC might change due to plane additions, this function *
* @dc: Used to get the current state status
* @stream: Target stream, which we want to remove the attached planes
* @surface_count: Number of surface update
* @is_plane_addition: [in] Fill out with true if it is a plane addition case
*
* DCN32x and newer support a feature named Dynamic ODM which can conflict with
* the MPO if used simultaneously in some specific configurations (e.g.,
* 4k@144). This function checks if the incoming context requires applying a
* transition state with unnecessary pipe splitting and ODM disabled to
* circumvent our hardware limitations to prevent this edge case. If the OPP
* associated with an MPCC might change due to plane additions, this function
* returns true. * returns true.
*
* Return:
* Return true if OPP and MPCC might change, otherwise, return false.
*/ */
static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc, static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc,
struct dc_stream_state *stream, struct dc_stream_state *stream,
@@ -3641,6 +3740,24 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc,
return force_minimal_pipe_splitting; return force_minimal_pipe_splitting;
} }
/**
* commit_minimal_transition_state - Create a transition pipe split state
*
* @dc: Used to get the current state status
* @transition_base_context: New transition state
*
* In some specific configurations, such as pipe split on multi-display with
* MPO and/or Dynamic ODM, removing a plane may cause unsupported pipe
* programming when moving to new planes. To mitigate those types of problems,
* this function adds a transition state that minimizes pipe usage before
* programming the new configuration. When adding a new plane, the current
* state requires the least pipes, so it is applied without splitting. When
* removing a plane, the new state requires the least pipes, so it is applied
* without splitting.
*
* Return:
* Return false if something is wrong in the transition state.
*/
static bool commit_minimal_transition_state(struct dc *dc, static bool commit_minimal_transition_state(struct dc *dc,
struct dc_state *transition_base_context) struct dc_state *transition_base_context)
{ {
@@ -3650,9 +3767,35 @@ static bool commit_minimal_transition_state(struct dc *dc,
bool temp_subvp_policy; bool temp_subvp_policy;
enum dc_status ret = DC_ERROR_UNEXPECTED; enum dc_status ret = DC_ERROR_UNEXPECTED;
unsigned int i, j; unsigned int i, j;
unsigned int pipe_in_use = 0;
if (!transition_context) if (!transition_context)
return false; return false;
/* Setup:
* Store the current ODM and MPC config in some temp variables to be
* restored after we commit the transition state.
*/
/* check current pipes in use*/
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &transition_base_context->res_ctx.pipe_ctx[i];
if (pipe->plane_state)
pipe_in_use++;
}
/* When the OS add a new surface if we have been used all of pipes with odm combine
* and mpc split feature, it need use commit_minimal_transition_state to transition safely.
* After OS exit MPO, it will back to use odm and mpc split with all of pipes, we need
* call it again. Otherwise return true to skip.
*
* Reduce the scenarios to use dc_commit_state_no_check in the stage of flip. Especially
* enter/exit MPO when DCN still have enough resources.
*/
if (pipe_in_use != dc->res_pool->pipe_count) {
dc_release_state(transition_context);
return true;
}
if (!dc->config.is_vmin_only_asic) { if (!dc->config.is_vmin_only_asic) {
tmp_mpc_policy = dc->debug.pipe_split_policy; tmp_mpc_policy = dc->debug.pipe_split_policy;
@@ -3667,7 +3810,7 @@ static bool commit_minimal_transition_state(struct dc *dc,
dc_resource_state_copy_construct(transition_base_context, transition_context); dc_resource_state_copy_construct(transition_base_context, transition_context);
//commit minimal state /* commit minimal state */
if (dc->res_pool->funcs->validate_bandwidth(dc, transition_context, false)) { if (dc->res_pool->funcs->validate_bandwidth(dc, transition_context, false)) {
for (i = 0; i < transition_context->stream_count; i++) { for (i = 0; i < transition_context->stream_count; i++) {
struct dc_stream_status *stream_status = &transition_context->stream_status[i]; struct dc_stream_status *stream_status = &transition_context->stream_status[i];
@@ -3685,10 +3828,12 @@ static bool commit_minimal_transition_state(struct dc *dc,
ret = dc_commit_state_no_check(dc, transition_context); ret = dc_commit_state_no_check(dc, transition_context);
} }
/*always release as dc_commit_state_no_check retains in good case*/ /* always release as dc_commit_state_no_check retains in good case */
dc_release_state(transition_context); dc_release_state(transition_context);
/*restore previous pipe split and odm policy*/ /* TearDown:
* Restore original configuration for ODM and MPO.
*/
if (!dc->config.is_vmin_only_asic) if (!dc->config.is_vmin_only_asic)
dc->debug.pipe_split_policy = tmp_mpc_policy; dc->debug.pipe_split_policy = tmp_mpc_policy;
@@ -3696,12 +3841,12 @@ static bool commit_minimal_transition_state(struct dc *dc,
dc->debug.force_disable_subvp = temp_subvp_policy; dc->debug.force_disable_subvp = temp_subvp_policy;
if (ret != DC_OK) { if (ret != DC_OK) {
/*this should never happen*/ /* this should never happen */
BREAK_TO_DEBUGGER(); BREAK_TO_DEBUGGER();
return false; return false;
} }
/*force full surface update*/ /* force full surface update */
for (i = 0; i < dc->current_state->stream_count; i++) { for (i = 0; i < dc->current_state->stream_count; i++) {
for (j = 0; j < dc->current_state->stream_status[i].plane_count; j++) { for (j = 0; j < dc->current_state->stream_status[i].plane_count; j++) {
dc->current_state->stream_status[i].plane_states[j]->update_flags.raw = 0xFFFFFFFF; dc->current_state->stream_status[i].plane_states[j]->update_flags.raw = 0xFFFFFFFF;
@@ -3806,6 +3951,18 @@ void dc_commit_updates_for_stream(struct dc *dc,
struct dc_context *dc_ctx = dc->ctx; struct dc_context *dc_ctx = dc->ctx;
int i, j; int i, j;
/* TODO: Since change commit sequence can have a huge impact,
* we decided to only enable it for DCN3x. However, as soon as
* we get more confident about this change we'll need to enable
* the new sequence for all ASICs.
*/
if (dc->ctx->dce_version >= DCN_VERSION_3_2) {
dc_update_planes_and_stream(dc, srf_updates,
surface_count, stream,
stream_update);
return;
}
stream_status = dc_stream_get_status(stream); stream_status = dc_stream_get_status(stream);
context = dc->current_state; context = dc->current_state;
@@ -4387,21 +4544,17 @@ void dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(struct dc *dc)
dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching_shut_down = true; dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching_shut_down = true;
} }
/* /**
***************************************************************************** * dc_is_dmub_outbox_supported - Check if DMUB firmware support outbox notification
* Function: dc_is_dmub_outbox_supported -
* *
* @brief * @dc: [in] dc structure
* Checks whether DMUB FW supports outbox notifications, if supported
* DM should register outbox interrupt prior to actually enabling interrupts
* via dc_enable_dmub_outbox
* *
* @param * Checks whether DMUB FW supports outbox notifications, if supported DM
* [in] dc: dc structure * should register outbox interrupt prior to actually enabling interrupts
* via dc_enable_dmub_outbox
* *
* @return * Return:
* True if DMUB FW supports outbox notifications, False otherwise * True if DMUB FW supports outbox notifications, False otherwise
*****************************************************************************
*/ */
bool dc_is_dmub_outbox_supported(struct dc *dc) bool dc_is_dmub_outbox_supported(struct dc *dc)
{ {
@@ -4419,21 +4572,17 @@ bool dc_is_dmub_outbox_supported(struct dc *dc)
return dc->debug.enable_dmub_aux_for_legacy_ddc; return dc->debug.enable_dmub_aux_for_legacy_ddc;
} }
/* /**
***************************************************************************** * dc_enable_dmub_notifications - Check if dmub fw supports outbox
* Function: dc_enable_dmub_notifications
* *
* @brief * @dc: [in] dc structure
* Calls dc_is_dmub_outbox_supported to check if dmub fw supports outbox
* notifications. All DMs shall switch to dc_is_dmub_outbox_supported.
* This API shall be removed after switching.
* *
* @param * Calls dc_is_dmub_outbox_supported to check if dmub fw supports outbox
* [in] dc: dc structure * notifications. All DMs shall switch to dc_is_dmub_outbox_supported. This
* API shall be removed after switching.
* *
* @return * Return:
* True if DMUB FW supports outbox notifications, False otherwise * True if DMUB FW supports outbox notifications, False otherwise
*****************************************************************************
*/ */
bool dc_enable_dmub_notifications(struct dc *dc) bool dc_enable_dmub_notifications(struct dc *dc)
{ {
@@ -4441,18 +4590,11 @@ bool dc_enable_dmub_notifications(struct dc *dc)
} }
/** /**
***************************************************************************** * dc_enable_dmub_outbox - Enables DMUB unsolicited notification
* Function: dc_enable_dmub_outbox
* *
* @brief * dc: [in] dc structure
* Enables DMUB unsolicited notifications to x86 via outbox
* *
* @param * Enables DMUB unsolicited notifications to x86 via outbox.
* [in] dc: dc structure
*
* @return
* None
*****************************************************************************
*/ */
void dc_enable_dmub_outbox(struct dc *dc) void dc_enable_dmub_outbox(struct dc *dc)
{ {
@@ -4553,21 +4695,17 @@ uint8_t get_link_index_from_dpia_port_index(const struct dc *dc,
} }
/** /**
***************************************************************************** * dc_process_dmub_set_config_async - Submits set_config command
* Function: dc_process_dmub_set_config_async
* *
* @brief * @dc: [in] dc structure
* Submits set_config command to dmub via inbox message * @link_index: [in] link_index: link index
* @payload: [in] aux payload
* @notify: [out] set_config immediate reply
* *
* @param * Submits set_config command to dmub via inbox message.
* [in] dc: dc structure
* [in] link_index: link index
* [in] payload: aux payload
* [out] notify: set_config immediate reply
* *
* @return * Return:
* True if successful, False if failure * True if successful, False if failure
*****************************************************************************
*/ */
bool dc_process_dmub_set_config_async(struct dc *dc, bool dc_process_dmub_set_config_async(struct dc *dc,
uint32_t link_index, uint32_t link_index,
@@ -4603,21 +4741,17 @@ bool dc_process_dmub_set_config_async(struct dc *dc,
} }
/** /**
***************************************************************************** * dc_process_dmub_set_mst_slots - Submits MST solt allocation
* Function: dc_process_dmub_set_mst_slots
* *
* @brief * @dc: [in] dc structure
* Submits mst slot allocation command to dmub via inbox message * @link_index: [in] link index
* @mst_alloc_slots: [in] mst slots to be allotted
* @mst_slots_in_use: [out] mst slots in use returned in failure case
* *
* @param * Submits mst slot allocation command to dmub via inbox message
* [in] dc: dc structure
* [in] link_index: link index
* [in] mst_alloc_slots: mst slots to be allotted
* [out] mst_slots_in_use: mst slots in use returned in failure case
* *
* @return * Return:
* DC_OK if successful, DC_ERROR if failure * DC_OK if successful, DC_ERROR if failure
*****************************************************************************
*/ */
enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc, enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
uint32_t link_index, uint32_t link_index,
@@ -4657,19 +4791,12 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
} }
/** /**
***************************************************************************** * dc_process_dmub_dpia_hpd_int_enable - Submits DPIA DPD interruption
* Function: dc_process_dmub_dpia_hpd_int_enable
* *
* @brief * @dc [in]: dc structure
* Submits dpia hpd int enable command to dmub via inbox message * @hpd_int_enable [in]: 1 for hpd int enable, 0 to disable
* *
* @param * Submits dpia hpd int enable command to dmub via inbox message
* [in] dc: dc structure
* [in] hpd_int_enable: 1 for hpd int enable, 0 to disable
*
* @return
* None
*****************************************************************************
*/ */
void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc, void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc,
uint32_t hpd_int_enable) uint32_t hpd_int_enable)
@@ -4698,16 +4825,13 @@ void dc_disable_accelerated_mode(struct dc *dc)
/** /**
***************************************************************************** * dc_notify_vsync_int_state - notifies vsync enable/disable state
* dc_notify_vsync_int_state() - notifies vsync enable/disable state
* @dc: dc structure * @dc: dc structure
* @stream: stream where vsync int state changed * @stream: stream where vsync int state changed
* @enable: whether vsync is enabled or disabled * @enable: whether vsync is enabled or disabled
* *
* Called when vsync is enabled/disabled * Called when vsync is enabled/disabled Will notify DMUB to start/stop ABM
* Will notify DMUB to start/stop ABM interrupts after steady state is reached * interrupts after steady state is reached.
*
*****************************************************************************
*/ */
void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable) void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable)
{ {
@@ -4749,14 +4873,18 @@ void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bo
if (pipe->stream_res.abm && pipe->stream_res.abm->funcs->set_abm_pause) if (pipe->stream_res.abm && pipe->stream_res.abm->funcs->set_abm_pause)
pipe->stream_res.abm->funcs->set_abm_pause(pipe->stream_res.abm, !enable, i, pipe->stream_res.tg->inst); pipe->stream_res.abm->funcs->set_abm_pause(pipe->stream_res.abm, !enable, i, pipe->stream_res.tg->inst);
} }
/*
* dc_extended_blank_supported: Decide whether extended blank is supported /**
* dc_extended_blank_supported 0 Decide whether extended blank is supported
* *
* Extended blank is a freesync optimization feature to be enabled in the future. * @dc: [in] Current DC state
* During the extra vblank period gained from freesync, we have the ability to enter z9/z10.
* *
* @param [in] dc: Current DC state * Extended blank is a freesync optimization feature to be enabled in the
* @return: Indicate whether extended blank is supported (true or false) * future. During the extra vblank period gained from freesync, we have the
* ability to enter z9/z10.
*
* Return:
* Indicate whether extended blank is supported (true or false)
*/ */
bool dc_extended_blank_supported(struct dc *dc) bool dc_extended_blank_supported(struct dc *dc)
{ {

View File

@@ -366,6 +366,7 @@ void get_hdr_visual_confirm_color(
struct tg_color *color) struct tg_color *color)
{ {
uint32_t color_value = MAX_TG_COLOR_VALUE; uint32_t color_value = MAX_TG_COLOR_VALUE;
bool is_sdr = false;
/* Determine the overscan color based on the top-most (desktop) plane's context */ /* Determine the overscan color based on the top-most (desktop) plane's context */
struct pipe_ctx *top_pipe_ctx = pipe_ctx; struct pipe_ctx *top_pipe_ctx = pipe_ctx;
@@ -382,7 +383,8 @@ void get_hdr_visual_confirm_color(
/* FreeSync 2 ARGB2101010 - set border color to pink */ /* FreeSync 2 ARGB2101010 - set border color to pink */
color->color_r_cr = color_value; color->color_r_cr = color_value;
color->color_b_cb = color_value; color->color_b_cb = color_value;
} } else
is_sdr = true;
break; break;
case PIXEL_FORMAT_FP16: case PIXEL_FORMAT_FP16:
if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_PQ) { if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_PQ) {
@@ -391,14 +393,19 @@ void get_hdr_visual_confirm_color(
} else if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) { } else if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) {
/* FreeSync 2 HDR - set border color to green */ /* FreeSync 2 HDR - set border color to green */
color->color_g_y = color_value; color->color_g_y = color_value;
} } else
is_sdr = true;
break; break;
default: default:
is_sdr = true;
break;
}
if (is_sdr) {
/* SDR - set border color to Gray */ /* SDR - set border color to Gray */
color->color_r_cr = color_value/2; color->color_r_cr = color_value/2;
color->color_b_cb = color_value/2; color->color_b_cb = color_value/2;
color->color_g_y = color_value/2; color->color_g_y = color_value/2;
break;
} }
} }

View File

@@ -4229,6 +4229,7 @@ static void fpga_dp_hpo_enable_link_and_stream(struct dc_state *state, struct pi
link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp);
dc->hwss.unblank_stream(pipe_ctx, &stream->link->cur_link_settings); dc->hwss.unblank_stream(pipe_ctx, &stream->link->cur_link_settings);
dc->hwss.enable_audio_stream(pipe_ctx);
} }
void core_link_enable_stream( void core_link_enable_stream(
@@ -4308,10 +4309,7 @@ void core_link_enable_stream(
/* Still enable stream features & audio on seamless boot for DP external displays */ /* Still enable stream features & audio on seamless boot for DP external displays */
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT) { if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT) {
enable_stream_features(pipe_ctx); enable_stream_features(pipe_ctx);
if (pipe_ctx->stream_res.audio != NULL) { dc->hwss.enable_audio_stream(pipe_ctx);
pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
dc->hwss.enable_audio_stream(pipe_ctx);
}
} }
#if defined(CONFIG_DRM_AMD_DC_HDCP) #if defined(CONFIG_DRM_AMD_DC_HDCP)

View File

@@ -5031,7 +5031,7 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link)
return true; return true;
} }
bool dp_retrieve_lttpr_cap(struct dc_link *link) enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link)
{ {
uint8_t lttpr_dpcd_data[8]; uint8_t lttpr_dpcd_data[8];
enum dc_status status = DC_ERROR_UNEXPECTED; enum dc_status status = DC_ERROR_UNEXPECTED;
@@ -5099,7 +5099,7 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link)
CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: "); CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: ");
DC_LOG_DC("is_lttpr_present = %d\n", is_lttpr_present); DC_LOG_DC("is_lttpr_present = %d\n", is_lttpr_present);
return is_lttpr_present; return status;
} }
bool dp_is_lttpr_present(struct dc_link *link) bool dp_is_lttpr_present(struct dc_link *link)
@@ -5227,122 +5227,11 @@ static void retrieve_cable_id(struct dc_link *link)
&link->dpcd_caps.cable_id, &usbc_cable_id); &link->dpcd_caps.cable_id, &usbc_cable_id);
} }
/* DPRX may take some time to respond to AUX messages after HPD asserted. static enum dc_status wake_up_aux_channel(struct dc_link *link)
* If AUX read unsuccessful, try to wake unresponsive DPRX by toggling DPCD SET_POWER (0x600).
*/
static enum dc_status wa_try_to_wake_dprx(struct dc_link *link, uint64_t timeout_ms)
{ {
enum dc_status status = DC_ERROR_UNEXPECTED; enum dc_status status = DC_ERROR_UNEXPECTED;
uint8_t dpcd_data = 0;
uint64_t start_ts = 0;
uint64_t current_ts = 0;
uint64_t time_taken_ms = 0;
enum dc_connection_type type = dc_connection_none;
bool lttpr_present;
bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
lttpr_present = dp_is_lttpr_present(link) ||
(!vbios_lttpr_interop || !link->dc->caps.extended_aux_timeout_support);
DC_LOG_DC("lttpr_present = %d.\n", lttpr_present ? 1 : 0);
/* Issue an AUX read to test DPRX responsiveness. If LTTPR is supported the first read is expected to
* be to determine LTTPR capabilities. Otherwise trying to read power state should be an innocuous AUX read.
*/
if (lttpr_present)
status = core_link_read_dpcd(
link,
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
&dpcd_data,
sizeof(dpcd_data));
else
status = core_link_read_dpcd(
link,
DP_SET_POWER,
&dpcd_data,
sizeof(dpcd_data));
if (status != DC_OK) {
DC_LOG_WARNING("%s: Read DPCD LTTPR_CAP failed - try to toggle DPCD SET_POWER for %lld ms.",
__func__,
timeout_ms);
start_ts = dm_get_timestamp(link->ctx);
do {
if (!dc_link_detect_sink(link, &type) || type == dc_connection_none)
break;
dpcd_data = DP_SET_POWER_D3;
status = core_link_write_dpcd(
link,
DP_SET_POWER,
&dpcd_data,
sizeof(dpcd_data));
dpcd_data = DP_SET_POWER_D0;
status = core_link_write_dpcd(
link,
DP_SET_POWER,
&dpcd_data,
sizeof(dpcd_data));
current_ts = dm_get_timestamp(link->ctx);
time_taken_ms = div_u64(dm_get_elapse_time_in_ns(link->ctx, current_ts, start_ts), 1000000);
} while (status != DC_OK && time_taken_ms < timeout_ms);
DC_LOG_WARNING("%s: DPCD SET_POWER %s after %lld ms%s",
__func__,
(status == DC_OK) ? "succeeded" : "failed",
time_taken_ms,
(type == dc_connection_none) ? ". Unplugged." : ".");
}
return status;
}
static bool retrieve_link_cap(struct dc_link *link)
{
/* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16,
* which means size 16 will be good for both of those DPCD register block reads
*/
uint8_t dpcd_data[16];
/*Only need to read 1 byte starting from DP_DPRX_FEATURE_ENUMERATION_LIST.
*/
uint8_t dpcd_dprx_data = '\0';
uint8_t dpcd_power_state = '\0';
struct dp_device_vendor_id sink_id;
union down_stream_port_count down_strm_port_count;
union edp_configuration_cap edp_config_cap;
union dp_downstream_port_present ds_port = { 0 };
enum dc_status status = DC_ERROR_UNEXPECTED;
uint32_t read_dpcd_retry_cnt = 3;
uint32_t aux_channel_retry_cnt = 0; uint32_t aux_channel_retry_cnt = 0;
int i; uint8_t dpcd_power_state = '\0';
struct dp_sink_hw_fw_revision dp_hw_fw_revision;
const uint32_t post_oui_delay = 30; // 30ms
bool is_lttpr_present = false;
memset(dpcd_data, '\0', sizeof(dpcd_data));
memset(&down_strm_port_count,
'\0', sizeof(union down_stream_port_count));
memset(&edp_config_cap, '\0',
sizeof(union edp_configuration_cap));
/* if extended timeout is supported in hardware,
* default to LTTPR timeout (3.2ms) first as a W/A for DP link layer
* CTS 4.2.1.1 regression introduced by CTS specs requirement update.
*/
dc_link_aux_try_to_configure_timeout(link->ddc,
LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD);
/* Try to ensure AUX channel active before proceeding. */
if (link->dc->debug.aux_wake_wa.bits.enable_wa) {
uint64_t timeout_ms = link->dc->debug.aux_wake_wa.bits.timeout_ms;
if (link->dc->debug.aux_wake_wa.bits.use_default_timeout)
timeout_ms = LINK_AUX_WAKE_TIMEOUT_MS;
status = wa_try_to_wake_dprx(link, timeout_ms);
}
while (status != DC_OK && aux_channel_retry_cnt < 10) { while (status != DC_OK && aux_channel_retry_cnt < 10) {
status = core_link_read_dpcd(link, DP_SET_POWER, status = core_link_read_dpcd(link, DP_SET_POWER,
@@ -5359,7 +5248,6 @@ static bool retrieve_link_cap(struct dc_link *link)
} }
} }
/* If aux channel is not active, return false and trigger another detect*/
if (status != DC_OK) { if (status != DC_OK) {
dpcd_power_state = DP_SET_POWER_D0; dpcd_power_state = DP_SET_POWER_D0;
status = core_link_write_dpcd( status = core_link_write_dpcd(
@@ -5374,12 +5262,56 @@ static bool retrieve_link_cap(struct dc_link *link)
DP_SET_POWER, DP_SET_POWER,
&dpcd_power_state, &dpcd_power_state,
sizeof(dpcd_power_state)); sizeof(dpcd_power_state));
return false; return DC_ERROR_UNEXPECTED;
} }
is_lttpr_present = dp_retrieve_lttpr_cap(link); return DC_OK;
}
if (is_lttpr_present) static bool retrieve_link_cap(struct dc_link *link)
{
/* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16,
* which means size 16 will be good for both of those DPCD register block reads
*/
uint8_t dpcd_data[16];
/*Only need to read 1 byte starting from DP_DPRX_FEATURE_ENUMERATION_LIST.
*/
uint8_t dpcd_dprx_data = '\0';
struct dp_device_vendor_id sink_id;
union down_stream_port_count down_strm_port_count;
union edp_configuration_cap edp_config_cap;
union dp_downstream_port_present ds_port = { 0 };
enum dc_status status = DC_ERROR_UNEXPECTED;
uint32_t read_dpcd_retry_cnt = 3;
int i;
struct dp_sink_hw_fw_revision dp_hw_fw_revision;
const uint32_t post_oui_delay = 30; // 30ms
memset(dpcd_data, '\0', sizeof(dpcd_data));
memset(&down_strm_port_count,
'\0', sizeof(union down_stream_port_count));
memset(&edp_config_cap, '\0',
sizeof(union edp_configuration_cap));
/* if extended timeout is supported in hardware,
* default to LTTPR timeout (3.2ms) first as a W/A for DP link layer
* CTS 4.2.1.1 regression introduced by CTS specs requirement update.
*/
dc_link_aux_try_to_configure_timeout(link->ddc,
LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD);
status = dp_retrieve_lttpr_cap(link);
if (status != DC_OK) {
status = wake_up_aux_channel(link);
if (status == DC_OK)
dp_retrieve_lttpr_cap(link);
else
return false;
}
if (dp_is_lttpr_present(link))
configure_lttpr_mode_transparent(link); configure_lttpr_mode_transparent(link);
/* Read DP tunneling information. */ /* Read DP tunneling information. */
@@ -5406,7 +5338,7 @@ static bool retrieve_link_cap(struct dc_link *link)
return false; return false;
} }
if (!is_lttpr_present) if (!dp_is_lttpr_present(link))
dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD); dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD);
{ {
@@ -7339,19 +7271,7 @@ void dp_retrain_link_dp_test(struct dc_link *link,
link->dc->hwss.unblank_stream(&pipes[i], link->dc->hwss.unblank_stream(&pipes[i],
link_setting); link_setting);
if (pipes[i].stream_res.audio) { link->dc->hwss.enable_audio_stream(&pipes[i]);
/* notify audio driver for
* audio modes of monitor */
pipes[i].stream_res.audio->funcs->az_enable(
pipes[i].stream_res.audio);
/* un-mute audio */
/* TODO: audio should be per stream rather than
* per link */
pipes[i].stream_res.stream_enc->funcs->
audio_mute_control(
pipes[i].stream_res.stream_enc, false);
}
} }
} }
} }

View File

@@ -1768,6 +1768,17 @@ bool dc_remove_plane_from_context(
return true; return true;
} }
/**
* dc_rem_all_planes_for_stream - Remove planes attached to the target stream.
*
* @dc: Current dc state.
* @stream: Target stream, which we want to remove the attached plans.
* @context: New context.
*
* Return:
* Return true if DC was able to remove all planes from the target
* stream, otherwise, return false.
*/
bool dc_rem_all_planes_for_stream( bool dc_rem_all_planes_for_stream(
const struct dc *dc, const struct dc *dc,
struct dc_stream_state *stream, struct dc_stream_state *stream,
@@ -2562,9 +2573,12 @@ enum dc_status resource_map_pool_resources(
/** /**
* dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state * dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state
* Is a shallow copy. Increments refcounts on existing streams and planes. *
* @dc: copy out of dc->current_state * @dc: copy out of dc->current_state
* @dst_ctx: copy into this * @dst_ctx: copy into this
*
* This function makes a shallow copy of the current DC state and increments
* refcounts on existing streams and planes.
*/ */
void dc_resource_state_copy_construct_current( void dc_resource_state_copy_construct_current(
const struct dc *dc, const struct dc *dc,
@@ -2593,15 +2607,241 @@ bool dc_resource_is_dsc_encoding_supported(const struct dc *dc)
return dc->res_pool->res_cap->num_dsc > 0; return dc->res_pool->res_cap->num_dsc > 0;
} }
static bool planes_changed_for_existing_stream(struct dc_state *context,
struct dc_stream_state *stream,
const struct dc_validation_set set[],
int set_count)
{
int i, j;
struct dc_stream_status *stream_status = NULL;
for (i = 0; i < context->stream_count; i++) {
if (context->streams[i] == stream) {
stream_status = &context->stream_status[i];
break;
}
}
if (!stream_status)
ASSERT(0);
for (i = 0; i < set_count; i++)
if (set[i].stream == stream)
break;
if (i == set_count)
ASSERT(0);
if (set[i].plane_count != stream_status->plane_count)
return true;
for (j = 0; j < set[i].plane_count; j++)
if (set[i].plane_states[j] != stream_status->plane_states[j])
return true;
return false;
}
/** /**
* dc_validate_global_state() - Determine if HW can support a given state * dc_validate_with_context - Validate and update the potential new stream in the context object
* Checks HW resource availability and bandwidth requirement. *
* @dc: Used to get the current state status
* @set: An array of dc_validation_set with all the current streams reference
* @set_count: Total of streams
* @context: New context
* @fast_validate: Enable or disable fast validation
*
* This function updates the potential new stream in the context object. It
* creates multiple lists for the add, remove, and unchanged streams. In
* particular, if the unchanged streams have a plane that changed, it is
* necessary to remove all planes from the unchanged streams. In summary, this
* function is responsible for validating the new context.
*
* Return:
* In case of success, return DC_OK (1), otherwise, return a DC error.
*/
enum dc_status dc_validate_with_context(struct dc *dc,
const struct dc_validation_set set[],
int set_count,
struct dc_state *context,
bool fast_validate)
{
struct dc_stream_state *unchanged_streams[MAX_PIPES] = { 0 };
struct dc_stream_state *del_streams[MAX_PIPES] = { 0 };
struct dc_stream_state *add_streams[MAX_PIPES] = { 0 };
int old_stream_count = context->stream_count;
enum dc_status res = DC_ERROR_UNEXPECTED;
int unchanged_streams_count = 0;
int del_streams_count = 0;
int add_streams_count = 0;
bool found = false;
int i, j, k;
DC_LOGGER_INIT(dc->ctx->logger);
/* First build a list of streams to be remove from current context */
for (i = 0; i < old_stream_count; i++) {
struct dc_stream_state *stream = context->streams[i];
for (j = 0; j < set_count; j++) {
if (stream == set[j].stream) {
found = true;
break;
}
}
if (!found)
del_streams[del_streams_count++] = stream;
found = false;
}
/* Second, build a list of new streams */
for (i = 0; i < set_count; i++) {
struct dc_stream_state *stream = set[i].stream;
for (j = 0; j < old_stream_count; j++) {
if (stream == context->streams[j]) {
found = true;
break;
}
}
if (!found)
add_streams[add_streams_count++] = stream;
found = false;
}
/* Build a list of unchanged streams which is necessary for handling
* planes change such as added, removed, and updated.
*/
for (i = 0; i < set_count; i++) {
/* Check if stream is part of the delete list */
for (j = 0; j < del_streams_count; j++) {
if (set[i].stream == del_streams[j]) {
found = true;
break;
}
}
if (!found) {
/* Check if stream is part of the add list */
for (j = 0; j < add_streams_count; j++) {
if (set[i].stream == add_streams[j]) {
found = true;
break;
}
}
}
if (!found)
unchanged_streams[unchanged_streams_count++] = set[i].stream;
found = false;
}
/* Remove all planes for unchanged streams if planes changed */
for (i = 0; i < unchanged_streams_count; i++) {
if (planes_changed_for_existing_stream(context,
unchanged_streams[i],
set,
set_count)) {
if (!dc_rem_all_planes_for_stream(dc,
unchanged_streams[i],
context)) {
res = DC_FAIL_DETACH_SURFACES;
goto fail;
}
}
}
/* Remove all planes for removed streams and then remove the streams */
for (i = 0; i < del_streams_count; i++) {
/* Need to cpy the dwb data from the old stream in order to efc to work */
if (del_streams[i]->num_wb_info > 0) {
for (j = 0; j < add_streams_count; j++) {
if (del_streams[i]->sink == add_streams[j]->sink) {
add_streams[j]->num_wb_info = del_streams[i]->num_wb_info;
for (k = 0; k < del_streams[i]->num_wb_info; k++)
add_streams[j]->writeback_info[k] = del_streams[i]->writeback_info[k];
}
}
}
if (!dc_rem_all_planes_for_stream(dc, del_streams[i], context)) {
res = DC_FAIL_DETACH_SURFACES;
goto fail;
}
res = dc_remove_stream_from_ctx(dc, context, del_streams[i]);
if (res != DC_OK)
goto fail;
}
/* Swap seamless boot stream to pipe 0 (if needed) to ensure pipe_ctx
* matches. This may change in the future if seamless_boot_stream can be
* multiple.
*/
for (i = 0; i < add_streams_count; i++) {
mark_seamless_boot_stream(dc, add_streams[i]);
if (add_streams[i]->apply_seamless_boot_optimization && i != 0) {
struct dc_stream_state *temp = add_streams[0];
add_streams[0] = add_streams[i];
add_streams[i] = temp;
break;
}
}
/* Add new streams and then add all planes for the new stream */
for (i = 0; i < add_streams_count; i++) {
calculate_phy_pix_clks(add_streams[i]);
res = dc_add_stream_to_ctx(dc, context, add_streams[i]);
if (res != DC_OK)
goto fail;
if (!add_all_planes_for_stream(dc, add_streams[i], set, set_count, context)) {
res = DC_FAIL_ATTACH_SURFACES;
goto fail;
}
}
/* Add all planes for unchanged streams if planes changed */
for (i = 0; i < unchanged_streams_count; i++) {
if (planes_changed_for_existing_stream(context,
unchanged_streams[i],
set,
set_count)) {
if (!add_all_planes_for_stream(dc, unchanged_streams[i], set, set_count, context)) {
res = DC_FAIL_ATTACH_SURFACES;
goto fail;
}
}
}
res = dc_validate_global_state(dc, context, fast_validate);
fail:
if (res != DC_OK)
DC_LOG_WARNING("%s:resource validation failed, dc_status:%d\n",
__func__,
res);
return res;
}
/**
* dc_validate_global_state() - Determine if hardware can support a given state
*
* @dc: dc struct for this driver * @dc: dc struct for this driver
* @new_ctx: state to be validated * @new_ctx: state to be validated
* @fast_validate: set to true if only yes/no to support matters * @fast_validate: set to true if only yes/no to support matters
* *
* Return: DC_OK if the result can be programmed. Otherwise, an error code. * Checks hardware resource availability and bandwidth requirement.
*
* Return:
* DC_OK if the result can be programmed. Otherwise, an error code.
*/ */
enum dc_status dc_validate_global_state( enum dc_status dc_validate_global_state(
struct dc *dc, struct dc *dc,
@@ -2789,6 +3029,12 @@ static void set_avi_info_frame(
hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED;
} }
if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR &&
stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) {
hdmi_info.bits.EC0_EC2 = 0;
hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709;
}
/* TODO: un-hardcode aspect ratio */ /* TODO: un-hardcode aspect ratio */
aspect = stream->timing.aspect_ratio; aspect = stream->timing.aspect_ratio;
@@ -3734,4 +3980,4 @@ bool dc_resource_acquire_secondary_pipe_for_mpc_odm(
} }
return true; return true;
} }

View File

@@ -47,7 +47,7 @@ struct aux_payload;
struct set_config_cmd_payload; struct set_config_cmd_payload;
struct dmub_notification; struct dmub_notification;
#define DC_VER "3.2.207" #define DC_VER "3.2.210"
#define MAX_SURFACES 3 #define MAX_SURFACES 3
#define MAX_PLANES 6 #define MAX_PLANES 6
@@ -56,9 +56,7 @@ struct dmub_notification;
#define MIN_VIEWPORT_SIZE 12 #define MIN_VIEWPORT_SIZE 12
#define MAX_NUM_EDP 2 #define MAX_NUM_EDP 2
/******************************************************************************* /* Display Core Interfaces */
* Display Core Interfaces
******************************************************************************/
struct dc_versions { struct dc_versions {
const char *dc_ver; const char *dc_ver;
struct dmcu_version dmcu_version; struct dmcu_version dmcu_version;
@@ -395,6 +393,7 @@ struct dc_config {
bool disable_dmcu; bool disable_dmcu;
bool enable_4to1MPC; bool enable_4to1MPC;
bool enable_windowed_mpo_odm; bool enable_windowed_mpo_odm;
bool forceHBR2CP2520; // Used for switching between test patterns TPS4 and CP2520
uint32_t allow_edp_hotplug_detection; uint32_t allow_edp_hotplug_detection;
bool clamp_min_dcfclk; bool clamp_min_dcfclk;
uint64_t vblank_alignment_dto_params; uint64_t vblank_alignment_dto_params;
@@ -494,9 +493,12 @@ enum dcn_zstate_support_state {
DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY, DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY,
DCN_ZSTATE_SUPPORT_DISALLOW, DCN_ZSTATE_SUPPORT_DISALLOW,
}; };
/*
* For any clocks that may differ per pipe /**
* only the max is stored in this structure * dc_clocks - DC pipe clocks
*
* For any clocks that may differ per pipe only the max is stored in this
* structure
*/ */
struct dc_clocks { struct dc_clocks {
int dispclk_khz; int dispclk_khz;
@@ -523,6 +525,16 @@ struct dc_clocks {
bool prev_p_state_change_support; bool prev_p_state_change_support;
bool fclk_prev_p_state_change_support; bool fclk_prev_p_state_change_support;
int num_ways; int num_ways;
/**
* @fw_based_mclk_switching
*
* DC has a mechanism that leverage the variable refresh rate to switch
* memory clock in cases that we have a large latency to achieve the
* memory clock change and a short vblank window. DC has some
* requirements to enable this feature, and this field describes if the
* system support or not such a feature.
*/
bool fw_based_mclk_switching; bool fw_based_mclk_switching;
bool fw_based_mclk_switching_shut_down; bool fw_based_mclk_switching_shut_down;
int prev_num_ways; int prev_num_ways;
@@ -764,7 +776,6 @@ struct dc_debug_options {
bool disable_mem_low_power; bool disable_mem_low_power;
bool pstate_enabled; bool pstate_enabled;
bool disable_dmcu; bool disable_dmcu;
bool disable_psr;
bool force_abm_enable; bool force_abm_enable;
bool disable_stereo_support; bool disable_stereo_support;
bool vsr_support; bool vsr_support;
@@ -852,6 +863,7 @@ struct dc_debug_options {
bool enable_double_buffered_dsc_pg_support; bool enable_double_buffered_dsc_pg_support;
bool enable_dp_dig_pixel_rate_div_policy; bool enable_dp_dig_pixel_rate_div_policy;
enum lttpr_mode lttpr_mode_override; enum lttpr_mode lttpr_mode_override;
unsigned int dsc_delay_factor_wa_x1000;
}; };
struct gpu_info_soc_bounding_box_v1_0; struct gpu_info_soc_bounding_box_v1_0;
@@ -988,9 +1000,7 @@ void dc_init_callbacks(struct dc *dc,
void dc_deinit_callbacks(struct dc *dc); void dc_deinit_callbacks(struct dc *dc);
void dc_destroy(struct dc **dc); void dc_destroy(struct dc **dc);
/******************************************************************************* /* Surface Interfaces */
* Surface Interfaces
******************************************************************************/
enum { enum {
TRANSFER_FUNC_POINTS = 1025 TRANSFER_FUNC_POINTS = 1025
@@ -1269,12 +1279,23 @@ void dc_post_update_surfaces_to_stream(
#include "dc_stream.h" #include "dc_stream.h"
/* /**
* Structure to store surface/stream associations for validation * struct dc_validation_set - Struct to store surface/stream associations for validation
*/ */
struct dc_validation_set { struct dc_validation_set {
/**
* @stream: Stream state properties
*/
struct dc_stream_state *stream; struct dc_stream_state *stream;
/**
* @plane_state: Surface state
*/
struct dc_plane_state *plane_states[MAX_SURFACES]; struct dc_plane_state *plane_states[MAX_SURFACES];
/**
* @plane_count: Total of active planes
*/
uint8_t plane_count; uint8_t plane_count;
}; };
@@ -1286,6 +1307,12 @@ enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *pla
void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info); void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info);
enum dc_status dc_validate_with_context(struct dc *dc,
const struct dc_validation_set set[],
int set_count,
struct dc_state *context,
bool fast_validate);
bool dc_set_generic_gpio_for_stereo(bool enable, bool dc_set_generic_gpio_for_stereo(bool enable,
struct gpio_service *gpio_service); struct gpio_service *gpio_service);
@@ -1321,15 +1348,12 @@ void dc_resource_state_destruct(struct dc_state *context);
bool dc_resource_is_dsc_encoding_supported(const struct dc *dc); bool dc_resource_is_dsc_encoding_supported(const struct dc *dc);
/* enum dc_status dc_commit_streams(struct dc *dc,
* TODO update to make it about validation sets struct dc_stream_state *streams[],
* Set up streams and links associated to drive sinks uint8_t stream_count);
* The streams parameter is an absolute set of all active streams.
* /* TODO: When the transition to the new commit sequence is done, remove this
* After this call: * function in favor of dc_commit_streams. */
* Phy, Encoder, Timing Generator are programmed and enabled.
* New streams are enabled with blank stream; no memory read.
*/
bool dc_commit_state(struct dc *dc, struct dc_state *context); bool dc_commit_state(struct dc *dc, struct dc_state *context);
struct dc_state *dc_create_state(struct dc *dc); struct dc_state *dc_create_state(struct dc *dc);
@@ -1337,9 +1361,7 @@ struct dc_state *dc_copy_state(struct dc_state *src_ctx);
void dc_retain_state(struct dc_state *context); void dc_retain_state(struct dc_state *context);
void dc_release_state(struct dc_state *context); void dc_release_state(struct dc_state *context);
/******************************************************************************* /* Link Interfaces */
* Link Interfaces
******************************************************************************/
struct dpcd_caps { struct dpcd_caps {
union dpcd_rev dpcd_rev; union dpcd_rev dpcd_rev;
@@ -1441,9 +1463,7 @@ struct hdcp_caps {
uint32_t dc_get_opp_for_plane(struct dc *dc, struct dc_plane_state *plane); uint32_t dc_get_opp_for_plane(struct dc *dc, struct dc_plane_state *plane);
/******************************************************************************* /* Sink Interfaces - A sink corresponds to a display output device */
* Sink Interfaces - A sink corresponds to a display output device
******************************************************************************/
struct dc_container_id { struct dc_container_id {
// 128bit GUID in binary form // 128bit GUID in binary form
@@ -1526,9 +1546,7 @@ struct dc_cursor {
}; };
/******************************************************************************* /* Interrupt interfaces */
* Interrupt interfaces
******************************************************************************/
enum dc_irq_source dc_interrupt_to_irq_source( enum dc_irq_source dc_interrupt_to_irq_source(
struct dc *dc, struct dc *dc,
uint32_t src_id, uint32_t src_id,
@@ -1540,9 +1558,7 @@ enum dc_irq_source dc_get_hpd_irq_source_at_index(
void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable); void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable);
/******************************************************************************* /* Power Interfaces */
* Power Interfaces
******************************************************************************/
void dc_set_power_state( void dc_set_power_state(
struct dc *dc, struct dc *dc,
@@ -1615,14 +1631,10 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc, void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc,
uint32_t hpd_int_enable); uint32_t hpd_int_enable);
/******************************************************************************* /* DSC Interfaces */
* DSC Interfaces
******************************************************************************/
#include "dc_dsc.h" #include "dc_dsc.h"
/******************************************************************************* /* Disable acc mode Interfaces */
* Disable acc mode Interfaces
******************************************************************************/
void dc_disable_accelerated_mode(struct dc *dc); void dc_disable_accelerated_mode(struct dc *dc);
#endif /* DC_INTERFACE_H_ */ #endif /* DC_INTERFACE_H_ */

View File

@@ -423,25 +423,20 @@ void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pi
#ifdef CONFIG_DRM_AMD_DC_DCN #ifdef CONFIG_DRM_AMD_DC_DCN
/** /**
* *********************************************************************************************** * populate_subvp_cmd_drr_info - Helper to populate DRR pipe info for the DMCUB subvp command
* populate_subvp_cmd_drr_info: Helper to populate DRR pipe info for the DMCUB subvp command
* *
* Populate the DMCUB SubVP command with DRR pipe info. All the information required for calculating * @dc: [in] current dc state
* the SubVP + DRR microschedule is populated here. * @subvp_pipe: [in] pipe_ctx for the SubVP pipe
* @vblank_pipe: [in] pipe_ctx for the DRR pipe
* @pipe_data: [in] Pipe data which stores the VBLANK/DRR info
*
* Populate the DMCUB SubVP command with DRR pipe info. All the information
* required for calculating the SubVP + DRR microschedule is populated here.
* *
* High level algorithm: * High level algorithm:
* 1. Get timing for SubVP pipe, phantom pipe, and DRR pipe * 1. Get timing for SubVP pipe, phantom pipe, and DRR pipe
* 2. Calculate the min and max vtotal which supports SubVP + DRR microschedule * 2. Calculate the min and max vtotal which supports SubVP + DRR microschedule
* 3. Populate the drr_info with the min and max supported vtotal values * 3. Populate the drr_info with the min and max supported vtotal values
*
* @param [in] dc: current dc state
* @param [in] subvp_pipe: pipe_ctx for the SubVP pipe
* @param [in] vblank_pipe: pipe_ctx for the DRR pipe
* @param [in] pipe_data: Pipe data which stores the VBLANK/DRR info
*
* @return: void
*
* ***********************************************************************************************
*/ */
static void populate_subvp_cmd_drr_info(struct dc *dc, static void populate_subvp_cmd_drr_info(struct dc *dc,
struct pipe_ctx *subvp_pipe, struct pipe_ctx *subvp_pipe,
@@ -493,22 +488,18 @@ static void populate_subvp_cmd_drr_info(struct dc *dc,
} }
/** /**
* *********************************************************************************************** * populate_subvp_cmd_vblank_pipe_info - Helper to populate VBLANK pipe info for the DMUB subvp command
* populate_subvp_cmd_vblank_pipe_info: Helper to populate VBLANK pipe info for the DMUB subvp command
* *
* Populate the DMCUB SubVP command with VBLANK pipe info. All the information required to calculate * @dc: [in] current dc state
* the microschedule for SubVP + VBLANK case is stored in the pipe_data (subvp_data and vblank_data). * @context: [in] new dc state
* Also check if the VBLANK pipe is a DRR display -- if it is make a call to populate drr_info. * @cmd: [in] DMUB cmd to be populated with SubVP info
* @vblank_pipe: [in] pipe_ctx for the VBLANK pipe
* @cmd_pipe_index: [in] index for the pipe array in DMCUB SubVP cmd
* *
* @param [in] dc: current dc state * Populate the DMCUB SubVP command with VBLANK pipe info. All the information
* @param [in] context: new dc state * required to calculate the microschedule for SubVP + VBLANK case is stored in
* @param [in] cmd: DMUB cmd to be populated with SubVP info * the pipe_data (subvp_data and vblank_data). Also check if the VBLANK pipe
* @param [in] vblank_pipe: pipe_ctx for the VBLANK pipe * is a DRR display -- if it is make a call to populate drr_info.
* @param [in] cmd_pipe_index: index for the pipe array in DMCUB SubVP cmd
*
* @return: void
*
* ***********************************************************************************************
*/ */
static void populate_subvp_cmd_vblank_pipe_info(struct dc *dc, static void populate_subvp_cmd_vblank_pipe_info(struct dc *dc,
struct dc_state *context, struct dc_state *context,
@@ -551,22 +542,18 @@ static void populate_subvp_cmd_vblank_pipe_info(struct dc *dc,
} }
/** /**
* *********************************************************************************************** * update_subvp_prefetch_end_to_mall_start - Helper for SubVP + SubVP case
* update_subvp_prefetch_end_to_mall_start: Helper for SubVP + SubVP case
* *
* For SubVP + SubVP, we use a single vertical interrupt to start the microschedule for both * @dc: [in] current dc state
* SubVP pipes. In order for this to work correctly, the MALL REGION of both SubVP pipes must * @context: [in] new dc state
* start at the same time. This function lengthens the prefetch end to mall start delay of the * @cmd: [in] DMUB cmd to be populated with SubVP info
* SubVP pipe that has the shorter prefetch so that both MALL REGION's will start at the same time. * @subvp_pipes: [in] Array of SubVP pipes (should always be length 2)
* *
* @param [in] dc: current dc state * For SubVP + SubVP, we use a single vertical interrupt to start the
* @param [in] context: new dc state * microschedule for both SubVP pipes. In order for this to work correctly, the
* @param [in] cmd: DMUB cmd to be populated with SubVP info * MALL REGION of both SubVP pipes must start at the same time. This function
* @param [in] subvp_pipes: Array of SubVP pipes (should always be length 2) * lengthens the prefetch end to mall start delay of the SubVP pipe that has
* * the shorter prefetch so that both MALL REGION's will start at the same time.
* @return: void
*
* ***********************************************************************************************
*/ */
static void update_subvp_prefetch_end_to_mall_start(struct dc *dc, static void update_subvp_prefetch_end_to_mall_start(struct dc *dc,
struct dc_state *context, struct dc_state *context,
@@ -608,22 +595,17 @@ static void update_subvp_prefetch_end_to_mall_start(struct dc *dc,
} }
/** /**
* *************************************************************************************** * populate_subvp_cmd_pipe_info - Helper to populate the SubVP pipe info for the DMUB subvp command
* setup_subvp_dmub_command: Helper to populate the SubVP pipe info for the DMUB subvp command
* *
* Populate the DMCUB SubVP command with SubVP pipe info. All the information required to * @dc: [in] current dc state
* calculate the microschedule for the SubVP pipe is stored in the pipe_data of the DMCUB * @context: [in] new dc state
* SubVP command. * @cmd: [in] DMUB cmd to be populated with SubVP info
* @subvp_pipe: [in] pipe_ctx for the SubVP pipe
* @cmd_pipe_index: [in] index for the pipe array in DMCUB SubVP cmd
* *
* @param [in] dc: current dc state * Populate the DMCUB SubVP command with SubVP pipe info. All the information
* @param [in] context: new dc state * required to calculate the microschedule for the SubVP pipe is stored in the
* @param [in] cmd: DMUB cmd to be populated with SubVP info * pipe_data of the DMCUB SubVP command.
* @param [in] subvp_pipe: pipe_ctx for the SubVP pipe
* @param [in] cmd_pipe_index: index for the pipe array in DMCUB SubVP cmd
*
* @return: void
*
* ***************************************************************************************
*/ */
static void populate_subvp_cmd_pipe_info(struct dc *dc, static void populate_subvp_cmd_pipe_info(struct dc *dc,
struct dc_state *context, struct dc_state *context,
@@ -703,19 +685,14 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc,
} }
/** /**
* *************************************************************************************** * dc_dmub_setup_subvp_dmub_command - Populate the DMCUB SubVP command
* dc_dmub_setup_subvp_dmub_command: Populate the DMCUB SubVP command
* *
* This function loops through each pipe and populates the DMUB * @dc: [in] current dc state
* SubVP CMD info based on the pipe (e.g. SubVP, VBLANK). * @context: [in] new dc state
* @cmd: [in] DMUB cmd to be populated with SubVP info
* *
* @param [in] dc: current dc state * This function loops through each pipe and populates the DMUB SubVP CMD info
* @param [in] context: new dc state * based on the pipe (e.g. SubVP, VBLANK).
* @param [in] cmd: DMUB cmd to be populated with SubVP info
*
* @return: void
*
* ***************************************************************************************
*/ */
void dc_dmub_setup_subvp_dmub_command(struct dc *dc, void dc_dmub_setup_subvp_dmub_command(struct dc *dc,
struct dc_state *context, struct dc_state *context,
@@ -962,19 +939,14 @@ static void dc_build_cursor_attribute_update_payload1(
} }
/** /**
* *************************************************************************************** * dc_send_update_cursor_info_to_dmu - Populate the DMCUB Cursor update info command
* dc_send_update_cursor_info_to_dmu: Populate the DMCUB Cursor update info command
* *
* This function would store the cursor related information and pass it into dmub * @pCtx: [in] pipe context
* @pipe_idx: [in] pipe index
* *
* @param [in] pCtx: pipe context * This function would store the cursor related information and pass it into
* @param [in] pipe_idx: pipe index * dmub
*
* @return: void
*
* ***************************************************************************************
*/ */
void dc_send_update_cursor_info_to_dmu( void dc_send_update_cursor_info_to_dmu(
struct pipe_ctx *pCtx, uint8_t pipe_idx) struct pipe_ctx *pCtx, uint8_t pipe_idx)
{ {

View File

@@ -117,7 +117,7 @@ struct psr_settings {
* Add a struct dc_panel_config under dc_link * Add a struct dc_panel_config under dc_link
*/ */
struct dc_panel_config { struct dc_panel_config {
// extra panel power sequence parameters /* extra panel power sequence parameters */
struct pps { struct pps {
unsigned int extra_t3_ms; unsigned int extra_t3_ms;
unsigned int extra_t7_ms; unsigned int extra_t7_ms;
@@ -127,13 +127,21 @@ struct dc_panel_config {
unsigned int extra_t12_ms; unsigned int extra_t12_ms;
unsigned int extra_post_OUI_ms; unsigned int extra_post_OUI_ms;
} pps; } pps;
// ABM /* PSR */
struct psr {
bool disable_psr;
bool disallow_psrsu;
bool rc_disable;
bool rc_allow_static_screen;
bool rc_allow_fullscreen_VPB;
} psr;
/* ABM */
struct varib { struct varib {
unsigned int varibright_feature_enable; unsigned int varibright_feature_enable;
unsigned int def_varibright_level; unsigned int def_varibright_level;
unsigned int abm_config_setting; unsigned int abm_config_setting;
} varib; } varib;
// edp DSC /* edp DSC */
struct dsc { struct dsc {
bool disable_dsc_edp; bool disable_dsc_edp;
unsigned int force_dsc_edp_policy; unsigned int force_dsc_edp_policy;
@@ -158,6 +166,14 @@ struct dc_link {
enum dc_irq_source irq_source_hpd_rx;/* aka DP Short Pulse */ enum dc_irq_source irq_source_hpd_rx;/* aka DP Short Pulse */
bool is_hpd_filter_disabled; bool is_hpd_filter_disabled;
bool dp_ss_off; bool dp_ss_off;
/**
* @link_state_valid:
*
* If there is no link and local sink, this variable should be set to
* false. Otherwise, it should be set to true; usually, the function
* core_link_enable_stream sets this field to true.
*/
bool link_state_valid; bool link_state_valid;
bool aux_access_disabled; bool aux_access_disabled;
bool sync_lt_in_progress; bool sync_lt_in_progress;

View File

@@ -41,6 +41,10 @@ struct timing_sync_info {
struct dc_stream_status { struct dc_stream_status {
int primary_otg_inst; int primary_otg_inst;
int stream_enc_inst; int stream_enc_inst;
/**
* @plane_count: Total of planes attached to a single stream
*/
int plane_count; int plane_count;
int audio_inst; int audio_inst;
struct timing_sync_info timing_sync_info; struct timing_sync_info timing_sync_info;
@@ -197,7 +201,18 @@ struct dc_stream_state {
bool use_vsc_sdp_for_colorimetry; bool use_vsc_sdp_for_colorimetry;
bool ignore_msa_timing_param; bool ignore_msa_timing_param;
/**
* @allow_freesync:
*
* It say if Freesync is enabled or not.
*/
bool allow_freesync; bool allow_freesync;
/**
* @vrr_active_variable:
*
* It describes if VRR is in use.
*/
bool vrr_active_variable; bool vrr_active_variable;
bool freesync_on_desktop; bool freesync_on_desktop;
@@ -517,10 +532,10 @@ bool dc_stream_get_crtc_position(struct dc *dc,
unsigned int *nom_v_pos); unsigned int *nom_v_pos);
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
bool dc_stream_forward_dmcu_crc_window(struct dc *dc, struct dc_stream_state *stream, bool dc_stream_forward_crc_window(struct dc *dc,
struct crc_params *crc_window); struct rect *rect,
bool dc_stream_stop_dmcu_crc_win_update(struct dc *dc, struct dc_stream_state *stream,
struct dc_stream_state *stream); bool is_stop);
#endif #endif
bool dc_stream_configure_crc(struct dc *dc, bool dc_stream_configure_crc(struct dc *dc,

View File

@@ -40,3 +40,5 @@
#define TRACE_DCN_FPU(begin, function, line, ref_count) \ #define TRACE_DCN_FPU(begin, function, line, ref_count) \
trace_dcn_fpu(begin, function, line, ref_count) trace_dcn_fpu(begin, function, line, ref_count)
#define TRACE_OPTC_LOCK_UNLOCK_STATE(optc, inst, lock) \
trace_dcn_optc_lock_unlock_state(optc, inst, lock, __func__, __LINE__)

View File

@@ -993,4 +993,11 @@ struct display_endpoint_id {
enum display_endpoint_type ep_type; enum display_endpoint_type ep_type;
}; };
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
struct otg_phy_mux {
uint8_t phy_output_num;
uint8_t otg_output_num;
};
#endif
#endif /* DC_TYPES_H_ */ #endif /* DC_TYPES_H_ */

View File

@@ -927,19 +927,20 @@ static bool dcn10_recv_edid_cea_ack(struct dmcu *dmcu, int *offset)
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
static void dcn10_forward_crc_window(struct dmcu *dmcu, static void dcn10_forward_crc_window(struct dmcu *dmcu,
struct crc_region *crc_win, struct rect *rect,
struct otg_phy_mux *mux_mapping) struct otg_phy_mux *mux_mapping)
{ {
struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
unsigned int dmcu_max_retry_on_wait_reg_ready = 801; unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
unsigned int dmcu_wait_reg_ready_interval = 100; unsigned int dmcu_wait_reg_ready_interval = 100;
unsigned int crc_start = 0, crc_end = 0, otg_phy_mux = 0; unsigned int crc_start = 0, crc_end = 0, otg_phy_mux = 0;
int x_start, y_start, x_end, y_end;
/* If microcontroller is not running, do nothing */ /* If microcontroller is not running, do nothing */
if (dmcu->dmcu_state != DMCU_RUNNING) if (dmcu->dmcu_state != DMCU_RUNNING)
return; return;
if (!crc_win) if (!rect)
return; return;
/* waitDMCUReadyForCmd */ /* waitDMCUReadyForCmd */
@@ -947,9 +948,14 @@ static void dcn10_forward_crc_window(struct dmcu *dmcu,
dmcu_wait_reg_ready_interval, dmcu_wait_reg_ready_interval,
dmcu_max_retry_on_wait_reg_ready); dmcu_max_retry_on_wait_reg_ready);
x_start = rect->x;
y_start = rect->y;
x_end = x_start + rect->width;
y_end = y_start + rect->height;
/* build up nitification data */ /* build up nitification data */
crc_start = (((unsigned int) crc_win->x_start) << 16) | crc_win->y_start; crc_start = (((unsigned int) x_start) << 16) | y_start;
crc_end = (((unsigned int) crc_win->x_end) << 16) | crc_win->y_end; crc_end = (((unsigned int) x_end) << 16) | y_end;
otg_phy_mux = otg_phy_mux =
(((unsigned int) mux_mapping->otg_output_num) << 16) | mux_mapping->phy_output_num; (((unsigned int) mux_mapping->otg_output_num) << 16) | mux_mapping->phy_output_num;

View File

@@ -399,7 +399,11 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
link->psr_settings.force_ffu_mode = 0; link->psr_settings.force_ffu_mode = 0;
copy_settings_data->force_ffu_mode = link->psr_settings.force_ffu_mode; copy_settings_data->force_ffu_mode = link->psr_settings.force_ffu_mode;
if (link->fec_state == dc_link_fec_enabled && if (((link->dpcd_caps.fec_cap.bits.FEC_CAPABLE &&
!link->dc->debug.disable_fec) &&
(link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT &&
!link->panel_config.dsc.disable_dsc_edp &&
link->dc->caps.edp_dsc_support)) &&
link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_38EC11 && link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_38EC11 &&
(!memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_1, (!memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_1,
sizeof(DP_SINK_DEVICE_STR_ID_1)) || sizeof(DP_SINK_DEVICE_STR_ID_1)) ||

View File

@@ -688,16 +688,6 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
early_control = lane_count; early_control = lane_count;
tg->funcs->set_early_control(tg, early_control); tg->funcs->set_early_control(tg, early_control);
/* enable audio only within mode set */
if (pipe_ctx->stream_res.audio != NULL) {
if (dc_is_dp_signal(pipe_ctx->stream->signal))
pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
}
} }
static enum bp_result link_transmitter_control( static enum bp_result link_transmitter_control(
@@ -1081,12 +1071,14 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
struct dc *dc; struct dc *dc;
struct clk_mgr *clk_mgr; struct clk_mgr *clk_mgr;
unsigned int i, num_audio = 1; unsigned int i, num_audio = 1;
const struct link_hwss *link_hwss;
if (!pipe_ctx->stream) if (!pipe_ctx->stream)
return; return;
dc = pipe_ctx->stream->ctx->dc; dc = pipe_ctx->stream->ctx->dc;
clk_mgr = dc->clk_mgr; clk_mgr = dc->clk_mgr;
link_hwss = get_link_hwss(pipe_ctx->stream->link, &pipe_ctx->link_res);
if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == true) if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == true)
return; return;
@@ -1103,56 +1095,35 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
if (num_audio >= 1 && clk_mgr->funcs->enable_pme_wa) if (num_audio >= 1 && clk_mgr->funcs->enable_pme_wa)
/*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
clk_mgr->funcs->enable_pme_wa(clk_mgr); clk_mgr->funcs->enable_pme_wa(clk_mgr);
/* un-mute audio */
/* TODO: audio should be per stream rather than per link */ link_hwss->enable_audio_packet(pipe_ctx);
if (is_dp_128b_132b_signal(pipe_ctx))
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->audio_mute_control(
pipe_ctx->stream_res.hpo_dp_stream_enc, false);
else
pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
pipe_ctx->stream_res.stream_enc, false);
if (pipe_ctx->stream_res.audio) if (pipe_ctx->stream_res.audio)
pipe_ctx->stream_res.audio->enabled = true; pipe_ctx->stream_res.audio->enabled = true;
} }
if (dc_is_dp_signal(pipe_ctx->stream->signal))
dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_ENABLE_AUDIO_STREAM);
} }
void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx) void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx)
{ {
struct dc *dc; struct dc *dc;
struct clk_mgr *clk_mgr; struct clk_mgr *clk_mgr;
const struct link_hwss *link_hwss;
if (!pipe_ctx || !pipe_ctx->stream) if (!pipe_ctx || !pipe_ctx->stream)
return; return;
dc = pipe_ctx->stream->ctx->dc; dc = pipe_ctx->stream->ctx->dc;
clk_mgr = dc->clk_mgr; clk_mgr = dc->clk_mgr;
link_hwss = get_link_hwss(pipe_ctx->stream->link, &pipe_ctx->link_res);
if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == false) if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == false)
return; return;
if (is_dp_128b_132b_signal(pipe_ctx)) link_hwss->disable_audio_packet(pipe_ctx);
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->audio_mute_control(
pipe_ctx->stream_res.hpo_dp_stream_enc, true);
else
pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
pipe_ctx->stream_res.stream_enc, true);
if (pipe_ctx->stream_res.audio) { if (pipe_ctx->stream_res.audio) {
pipe_ctx->stream_res.audio->enabled = false; pipe_ctx->stream_res.audio->enabled = false;
if (dc_is_dp_signal(pipe_ctx->stream->signal))
if (is_dp_128b_132b_signal(pipe_ctx))
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_disable(
pipe_ctx->stream_res.hpo_dp_stream_enc);
else
pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable(
pipe_ctx->stream_res.stream_enc);
else
pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable(
pipe_ctx->stream_res.stream_enc);
if (clk_mgr->funcs->enable_pme_wa) if (clk_mgr->funcs->enable_pme_wa)
/*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
clk_mgr->funcs->enable_pme_wa(clk_mgr); clk_mgr->funcs->enable_pme_wa(clk_mgr);
@@ -1163,9 +1134,6 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx)
* stream->stream_engine_id); * stream->stream_engine_id);
*/ */
} }
if (dc_is_dp_signal(pipe_ctx->stream->signal))
dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_DISABLE_AUDIO_STREAM);
} }
void dce110_disable_stream(struct pipe_ctx *pipe_ctx) void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
@@ -1487,6 +1455,9 @@ static enum dc_status apply_single_controller_ctx_to_hw(
unsigned int event_triggers = 0; unsigned int event_triggers = 0;
struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe; struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
struct dce_hwseq *hws = dc->hwseq; struct dce_hwseq *hws = dc->hwseq;
const struct link_hwss *link_hwss = get_link_hwss(
link, &pipe_ctx->link_res);
if (hws->funcs.disable_stream_gating) { if (hws->funcs.disable_stream_gating) {
hws->funcs.disable_stream_gating(dc, pipe_ctx); hws->funcs.disable_stream_gating(dc, pipe_ctx);
@@ -1497,23 +1468,8 @@ static enum dc_status apply_single_controller_ctx_to_hw(
build_audio_output(context, pipe_ctx, &audio_output); build_audio_output(context, pipe_ctx, &audio_output);
if (dc_is_dp_signal(pipe_ctx->stream->signal)) link_hwss->setup_audio_output(pipe_ctx, &audio_output,
if (is_dp_128b_132b_signal(pipe_ctx)) pipe_ctx->stream_res.audio->inst);
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_setup(
pipe_ctx->stream_res.hpo_dp_stream_enc,
pipe_ctx->stream_res.audio->inst,
&pipe_ctx->stream->audio_info);
else
pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup(
pipe_ctx->stream_res.stream_enc,
pipe_ctx->stream_res.audio->inst,
&pipe_ctx->stream->audio_info);
else
pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup(
pipe_ctx->stream_res.stream_enc,
pipe_ctx->stream_res.audio->inst,
&pipe_ctx->stream->audio_info,
&audio_output.crtc_info);
pipe_ctx->stream_res.audio->funcs->az_configure( pipe_ctx->stream_res.audio->funcs->az_configure(
pipe_ctx->stream_res.audio, pipe_ctx->stream_res.audio,

View File

@@ -1128,6 +1128,7 @@ struct resource_pool *dce60_create_resource_pool(
if (dce60_construct(num_virtual_links, dc, pool)) if (dce60_construct(num_virtual_links, dc, pool))
return &pool->base; return &pool->base;
kfree(pool);
BREAK_TO_DEBUGGER(); BREAK_TO_DEBUGGER();
return NULL; return NULL;
} }
@@ -1325,6 +1326,7 @@ struct resource_pool *dce61_create_resource_pool(
if (dce61_construct(num_virtual_links, dc, pool)) if (dce61_construct(num_virtual_links, dc, pool))
return &pool->base; return &pool->base;
kfree(pool);
BREAK_TO_DEBUGGER(); BREAK_TO_DEBUGGER();
return NULL; return NULL;
} }
@@ -1518,6 +1520,7 @@ struct resource_pool *dce64_create_resource_pool(
if (dce64_construct(num_virtual_links, dc, pool)) if (dce64_construct(num_virtual_links, dc, pool))
return &pool->base; return &pool->base;
kfree(pool);
BREAK_TO_DEBUGGER(); BREAK_TO_DEBUGGER();
return NULL; return NULL;
} }

View File

@@ -1137,6 +1137,7 @@ struct resource_pool *dce80_create_resource_pool(
if (dce80_construct(num_virtual_links, dc, pool)) if (dce80_construct(num_virtual_links, dc, pool))
return &pool->base; return &pool->base;
kfree(pool);
BREAK_TO_DEBUGGER(); BREAK_TO_DEBUGGER();
return NULL; return NULL;
} }
@@ -1336,6 +1337,7 @@ struct resource_pool *dce81_create_resource_pool(
if (dce81_construct(num_virtual_links, dc, pool)) if (dce81_construct(num_virtual_links, dc, pool))
return &pool->base; return &pool->base;
kfree(pool);
BREAK_TO_DEBUGGER(); BREAK_TO_DEBUGGER();
return NULL; return NULL;
} }

View File

@@ -27,6 +27,7 @@
#include "reg_helper.h" #include "reg_helper.h"
#include "dcn10_optc.h" #include "dcn10_optc.h"
#include "dc.h" #include "dc.h"
#include "dc_trace.h"
#define REG(reg)\ #define REG(reg)\
optc1->tg_regs->reg optc1->tg_regs->reg
@@ -657,6 +658,8 @@ void optc1_lock(struct timing_generator *optc)
REG_WAIT(OTG_MASTER_UPDATE_LOCK, REG_WAIT(OTG_MASTER_UPDATE_LOCK,
UPDATE_LOCK_STATUS, 1, UPDATE_LOCK_STATUS, 1,
1, 10); 1, 10);
TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true);
} }
void optc1_unlock(struct timing_generator *optc) void optc1_unlock(struct timing_generator *optc)
@@ -665,6 +668,8 @@ void optc1_unlock(struct timing_generator *optc)
REG_SET(OTG_MASTER_UPDATE_LOCK, 0, REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
OTG_MASTER_UPDATE_LOCK, 0); OTG_MASTER_UPDATE_LOCK, 0);
TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, false);
} }
void optc1_get_position(struct timing_generator *optc, void optc1_get_position(struct timing_generator *optc,

View File

@@ -1295,47 +1295,6 @@ static uint32_t read_pipe_fuses(struct dc_context *ctx)
return value; return value;
} }
/*
* Some architectures don't support soft-float (e.g. aarch64), on those
* this function has to be called with hardfloat enabled, make sure not
* to inline it so whatever fp stuff is done stays inside
*/
static noinline void dcn10_resource_construct_fp(
struct dc *dc)
{
if (dc->ctx->dce_version == DCN_VERSION_1_01) {
struct dcn_soc_bounding_box *dcn_soc = dc->dcn_soc;
struct dcn_ip_params *dcn_ip = dc->dcn_ip;
struct display_mode_lib *dml = &dc->dml;
dml->ip.max_num_dpp = 3;
/* TODO how to handle 23.84? */
dcn_soc->dram_clock_change_latency = 23;
dcn_ip->max_num_dpp = 3;
}
if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) {
dc->dcn_soc->urgent_latency = 3;
dc->debug.disable_dmcu = true;
dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 41.60f;
}
dc->dcn_soc->number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width;
ASSERT(dc->dcn_soc->number_of_channels < 3);
if (dc->dcn_soc->number_of_channels == 0)/*old sbios bug*/
dc->dcn_soc->number_of_channels = 2;
if (dc->dcn_soc->number_of_channels == 1) {
dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 19.2f;
dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 = 17.066f;
dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = 14.933f;
dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = 12.8f;
if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) {
dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 20.80f;
}
}
}
static bool verify_clock_values(struct dm_pp_clock_levels_with_voltage *clks) static bool verify_clock_values(struct dm_pp_clock_levels_with_voltage *clks)
{ {
int i; int i;
@@ -1510,8 +1469,9 @@ static bool dcn10_resource_construct(
memcpy(dc->dcn_ip, &dcn10_ip_defaults, sizeof(dcn10_ip_defaults)); memcpy(dc->dcn_ip, &dcn10_ip_defaults, sizeof(dcn10_ip_defaults));
memcpy(dc->dcn_soc, &dcn10_soc_defaults, sizeof(dcn10_soc_defaults)); memcpy(dc->dcn_soc, &dcn10_soc_defaults, sizeof(dcn10_soc_defaults));
/* Other architectures we build for build this with soft-float */ DC_FP_START();
dcn10_resource_construct_fp(dc); dcn10_resource_construct_fp(dc);
DC_FP_END();
if (!dc->config.is_vmin_only_asic) if (!dc->config.is_vmin_only_asic)
if (ASICREV_IS_RAVEN2(dc->ctx->asic_id.hw_internal_rev)) if (ASICREV_IS_RAVEN2(dc->ctx->asic_id.hw_internal_rev))

View File

@@ -623,6 +623,10 @@ void hubp2_cursor_set_attributes(
hubp->att.size.bits.width = attr->width; hubp->att.size.bits.width = attr->width;
hubp->att.size.bits.height = attr->height; hubp->att.size.bits.height = attr->height;
hubp->att.cur_ctl.bits.mode = attr->color_format; hubp->att.cur_ctl.bits.mode = attr->color_format;
hubp->cur_rect.w = attr->width;
hubp->cur_rect.h = attr->height;
hubp->att.cur_ctl.bits.pitch = hw_pitch; hubp->att.cur_ctl.bits.pitch = hw_pitch;
hubp->att.cur_ctl.bits.line_per_chunk = lpc; hubp->att.cur_ctl.bits.line_per_chunk = lpc;
hubp->att.cur_ctl.bits.cur_2x_magnify = attr->attribute_flags.bits.ENABLE_MAGNIFICATION; hubp->att.cur_ctl.bits.cur_2x_magnify = attr->attribute_flags.bits.ENABLE_MAGNIFICATION;

View File

@@ -1079,6 +1079,29 @@ void dcn20_blank_pixel_data(
0); 0);
} }
if (!blank && dc->debug.enable_single_display_2to1_odm_policy) {
/* when exiting dynamic ODM need to reinit DPG state for unused pipes */
struct pipe_ctx *old_odm_pipe = dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx].next_odm_pipe;
odm_pipe = pipe_ctx->next_odm_pipe;
while (old_odm_pipe) {
if (!odm_pipe || old_odm_pipe->pipe_idx != odm_pipe->pipe_idx)
dc->hwss.set_disp_pattern_generator(dc,
old_odm_pipe,
CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
CONTROLLER_DP_COLOR_SPACE_UDEFINED,
COLOR_DEPTH_888,
NULL,
0,
0,
0);
old_odm_pipe = old_odm_pipe->next_odm_pipe;
if (odm_pipe)
odm_pipe = odm_pipe->next_odm_pipe;
}
}
if (!blank) if (!blank)
if (stream_res->abm) { if (stream_res->abm) {
dc->hwss.set_pipe(pipe_ctx); dc->hwss.set_pipe(pipe_ctx);
@@ -1270,16 +1293,6 @@ void dcn20_pipe_control_lock(
lock, lock,
&hw_locks, &hw_locks,
&inst_flags); &inst_flags);
} else if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
hw_lock_cmd.bits.lock_pipe = 1;
hw_lock_cmd.bits.otg_inst = pipe->stream_res.tg->inst;
hw_lock_cmd.bits.lock = lock;
if (!lock)
hw_lock_cmd.bits.should_release = 1;
dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd);
} else if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) { } else if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) {
if (lock) if (lock)
pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg); pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg);
@@ -1650,10 +1663,7 @@ static void dcn20_program_pipe(
pipe_ctx->pipe_dlg_param.vupdate_width); pipe_ctx->pipe_dlg_param.vupdate_width);
if (pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) { if (pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) {
pipe_ctx->stream_res.tg->funcs->wait_for_state( pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK);
pipe_ctx->stream_res.tg->funcs->wait_for_state(
pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
} }
pipe_ctx->stream_res.tg->funcs->set_vtg_params( pipe_ctx->stream_res.tg->funcs->set_vtg_params(
@@ -1856,7 +1866,7 @@ void dcn20_post_unlock_program_front_end(
for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS*1000 for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS*1000
&& hubp->funcs->hubp_is_flip_pending(hubp); j++) && hubp->funcs->hubp_is_flip_pending(hubp); j++)
mdelay(1); udelay(1);
} }
} }
@@ -2611,14 +2621,6 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
if (dc->hwseq->funcs.set_pixels_per_cycle) if (dc->hwseq->funcs.set_pixels_per_cycle)
dc->hwseq->funcs.set_pixels_per_cycle(pipe_ctx); dc->hwseq->funcs.set_pixels_per_cycle(pipe_ctx);
/* enable audio only within mode set */
if (pipe_ctx->stream_res.audio != NULL) {
if (is_dp_128b_132b_signal(pipe_ctx))
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.hpo_dp_stream_enc);
else if (dc_is_dp_signal(pipe_ctx->stream->signal))
pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
}
} }
void dcn20_program_dmdata_engine(struct pipe_ctx *pipe_ctx) void dcn20_program_dmdata_engine(struct pipe_ctx *pipe_ctx)

View File

@@ -1454,6 +1454,22 @@ enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_
return result; return result;
} }
/**
* dcn20_split_stream_for_odm - Check if stream can be splited for ODM
*
* @dc: DC object with resource pool info required for pipe split
* @res_ctx: Persistent state of resources
* @prev_odm_pipe: Reference to the previous ODM pipe
* @next_odm_pipe: Reference to the next ODM pipe
*
* This function takes a logically active pipe and a logically free pipe and
* halves all the scaling parameters that need to be halved while populating
* the free pipe with the required resources and configuring the next/previous
* ODM pipe pointers.
*
* Return:
* Return true if split stream for ODM is possible, otherwise, return false.
*/
bool dcn20_split_stream_for_odm( bool dcn20_split_stream_for_odm(
const struct dc *dc, const struct dc *dc,
struct resource_context *res_ctx, struct resource_context *res_ctx,

View File

@@ -671,12 +671,15 @@ static const struct dc_debug_options debug_defaults_diags = {
.disable_pplib_wm_range = true, .disable_pplib_wm_range = true,
.disable_stutter = true, .disable_stutter = true,
.disable_48mhz_pwrdwn = true, .disable_48mhz_pwrdwn = true,
.disable_psr = true,
.enable_tri_buf = true, .enable_tri_buf = true,
.use_max_lb = true .use_max_lb = true
}; };
static const struct dc_panel_config panel_config_defaults = { static const struct dc_panel_config panel_config_defaults = {
.psr = {
.disable_psr = false,
.disallow_psrsu = false,
},
.ilr = { .ilr = {
.optimize_edp_link_rate = true, .optimize_edp_link_rate = true,
}, },

View File

@@ -30,6 +30,7 @@
#include "dc_dmub_srv.h" #include "dc_dmub_srv.h"
#include "dml/dcn30/dcn30_fpu.h" #include "dml/dcn30/dcn30_fpu.h"
#include "dc_trace.h"
#define REG(reg)\ #define REG(reg)\
optc1->tg_regs->reg optc1->tg_regs->reg
@@ -58,6 +59,8 @@ void optc3_triplebuffer_lock(struct timing_generator *optc)
REG_WAIT(OTG_MASTER_UPDATE_LOCK, REG_WAIT(OTG_MASTER_UPDATE_LOCK,
UPDATE_LOCK_STATUS, 1, UPDATE_LOCK_STATUS, 1,
1, 10); 1, 10);
TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true);
} }
void optc3_lock_doublebuffer_enable(struct timing_generator *optc) void optc3_lock_doublebuffer_enable(struct timing_generator *optc)
@@ -93,6 +96,8 @@ void optc3_lock_doublebuffer_enable(struct timing_generator *optc)
MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, 0, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, 0,
MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, 100, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, 100,
OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1);
TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true);
} }
void optc3_lock_doublebuffer_disable(struct timing_generator *optc) void optc3_lock_doublebuffer_disable(struct timing_generator *optc)
@@ -108,6 +113,8 @@ void optc3_lock_doublebuffer_disable(struct timing_generator *optc)
REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 0); REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 0);
REG_UPDATE(OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, 0); REG_UPDATE(OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, 0);
TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true);
} }
void optc3_lock(struct timing_generator *optc) void optc3_lock(struct timing_generator *optc)
@@ -122,6 +129,8 @@ void optc3_lock(struct timing_generator *optc)
REG_WAIT(OTG_MASTER_UPDATE_LOCK, REG_WAIT(OTG_MASTER_UPDATE_LOCK,
UPDATE_LOCK_STATUS, 1, UPDATE_LOCK_STATUS, 1,
1, 10); 1, 10);
TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true);
} }
void optc3_set_out_mux(struct timing_generator *optc, enum otg_out_mux_dest dest) void optc3_set_out_mux(struct timing_generator *optc, enum otg_out_mux_dest dest)

View File

@@ -723,7 +723,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.underflow_assert_delay_us = 0xFFFFFFFF, .underflow_assert_delay_us = 0xFFFFFFFF,
.dwb_fi_phase = -1, // -1 = disable, .dwb_fi_phase = -1, // -1 = disable,
.dmub_command_table = true, .dmub_command_table = true,
.disable_psr = false,
.use_max_lb = true, .use_max_lb = true,
.exit_idle_opt_for_cursor_updates = true .exit_idle_opt_for_cursor_updates = true
}; };
@@ -742,11 +741,17 @@ static const struct dc_debug_options debug_defaults_diags = {
.scl_reset_length10 = true, .scl_reset_length10 = true,
.dwb_fi_phase = -1, // -1 = disable .dwb_fi_phase = -1, // -1 = disable
.dmub_command_table = true, .dmub_command_table = true,
.disable_psr = true,
.enable_tri_buf = true, .enable_tri_buf = true,
.use_max_lb = true .use_max_lb = true
}; };
static const struct dc_panel_config panel_config_defaults = {
.psr = {
.disable_psr = false,
.disallow_psrsu = false,
},
};
static void dcn30_dpp_destroy(struct dpp **dpp) static void dcn30_dpp_destroy(struct dpp **dpp)
{ {
kfree(TO_DCN20_DPP(*dpp)); kfree(TO_DCN20_DPP(*dpp));
@@ -2212,6 +2217,11 @@ void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params
} }
} }
static void dcn30_get_panel_config_defaults(struct dc_panel_config *panel_config)
{
*panel_config = panel_config_defaults;
}
static const struct resource_funcs dcn30_res_pool_funcs = { static const struct resource_funcs dcn30_res_pool_funcs = {
.destroy = dcn30_destroy_resource_pool, .destroy = dcn30_destroy_resource_pool,
.link_enc_create = dcn30_link_encoder_create, .link_enc_create = dcn30_link_encoder_create,
@@ -2231,6 +2241,7 @@ static const struct resource_funcs dcn30_res_pool_funcs = {
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut, .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn30_update_bw_bounding_box, .update_bw_bounding_box = dcn30_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state, .patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn30_get_panel_config_defaults,
}; };
#define CTX ctx #define CTX ctx

View File

@@ -112,10 +112,16 @@ static const struct dc_debug_options debug_defaults_diags = {
.dwb_fi_phase = -1, // -1 = disable .dwb_fi_phase = -1, // -1 = disable
.dmub_command_table = true, .dmub_command_table = true,
.enable_tri_buf = true, .enable_tri_buf = true,
.disable_psr = true,
.use_max_lb = true .use_max_lb = true
}; };
static const struct dc_panel_config panel_config_defaults = {
.psr = {
.disable_psr = false,
.disallow_psrsu = false,
},
};
enum dcn302_clk_src_array_id { enum dcn302_clk_src_array_id {
DCN302_CLK_SRC_PLL0, DCN302_CLK_SRC_PLL0,
DCN302_CLK_SRC_PLL1, DCN302_CLK_SRC_PLL1,
@@ -1132,6 +1138,11 @@ void dcn302_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
DC_FP_END(); DC_FP_END();
} }
static void dcn302_get_panel_config_defaults(struct dc_panel_config *panel_config)
{
*panel_config = panel_config_defaults;
}
static struct resource_funcs dcn302_res_pool_funcs = { static struct resource_funcs dcn302_res_pool_funcs = {
.destroy = dcn302_destroy_resource_pool, .destroy = dcn302_destroy_resource_pool,
.link_enc_create = dcn302_link_encoder_create, .link_enc_create = dcn302_link_encoder_create,
@@ -1151,6 +1162,7 @@ static struct resource_funcs dcn302_res_pool_funcs = {
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut, .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn302_update_bw_bounding_box, .update_bw_bounding_box = dcn302_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state, .patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn302_get_panel_config_defaults,
}; };
static struct dc_cap_funcs cap_funcs = { static struct dc_cap_funcs cap_funcs = {

View File

@@ -96,7 +96,13 @@ static const struct dc_debug_options debug_defaults_diags = {
.dwb_fi_phase = -1, // -1 = disable .dwb_fi_phase = -1, // -1 = disable
.dmub_command_table = true, .dmub_command_table = true,
.enable_tri_buf = true, .enable_tri_buf = true,
.disable_psr = true, };
static const struct dc_panel_config panel_config_defaults = {
.psr = {
.disable_psr = false,
.disallow_psrsu = false,
},
}; };
enum dcn303_clk_src_array_id { enum dcn303_clk_src_array_id {
@@ -1055,6 +1061,10 @@ static void dcn303_destroy_resource_pool(struct resource_pool **pool)
*pool = NULL; *pool = NULL;
} }
static void dcn303_get_panel_config_defaults(struct dc_panel_config *panel_config)
{
*panel_config = panel_config_defaults;
}
void dcn303_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) void dcn303_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
{ {
@@ -1082,6 +1092,7 @@ static struct resource_funcs dcn303_res_pool_funcs = {
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut, .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn303_update_bw_bounding_box, .update_bw_bounding_box = dcn303_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state, .patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn303_get_panel_config_defaults,
}; };
static struct dc_cap_funcs cap_funcs = { static struct dc_cap_funcs cap_funcs = {

View File

@@ -134,23 +134,10 @@ static void apg31_se_audio_setup(
/* Disable forced mem power off */ /* Disable forced mem power off */
REG_UPDATE(APG_MEM_PWR, APG_MEM_PWR_FORCE, 0); REG_UPDATE(APG_MEM_PWR, APG_MEM_PWR_FORCE, 0);
apg31_enable(apg);
}
static void apg31_audio_mute_control(
struct apg *apg,
bool mute)
{
if (mute)
apg31_disable(apg);
else
apg31_enable(apg);
} }
static struct apg_funcs dcn31_apg_funcs = { static struct apg_funcs dcn31_apg_funcs = {
.se_audio_setup = apg31_se_audio_setup, .se_audio_setup = apg31_se_audio_setup,
.audio_mute_control = apg31_audio_mute_control,
.enable_apg = apg31_enable, .enable_apg = apg31_enable,
.disable_apg = apg31_disable, .disable_apg = apg31_disable,
}; };

Some files were not shown because too many files have changed in this diff Show More