mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
Merge tag 'amd-drm-next-5.14-2021-07-01' of https://gitlab.freedesktop.org/agd5f/linux into drm-next
amd-drm-next-5.14-2021-07-01: amdgpu: - Misc Navi fixes - Powergating fix - Yellow Carp updates - Beige Goby updates - S0ix fix - Revert overlay validation fix - GPU reset fix for DC - PPC64 fix - Add new dimgrey cavefish DID - RAS fix amdkfd: - SVM fixes radeon: - Fix missing drm_gem_object_put in error path Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20210701042241.25449-1-alexander.deucher@amd.com
This commit is contained in:
commit
0d3a1b37ab
@ -1369,6 +1369,38 @@ def_value:
|
|||||||
adev->pm.smu_prv_buffer_size = 0;
|
adev->pm.smu_prv_buffer_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int amdgpu_device_init_apu_flags(struct amdgpu_device *adev)
|
||||||
|
{
|
||||||
|
if (!(adev->flags & AMD_IS_APU) ||
|
||||||
|
adev->asic_type < CHIP_RAVEN)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (adev->asic_type) {
|
||||||
|
case CHIP_RAVEN:
|
||||||
|
if (adev->pdev->device == 0x15dd)
|
||||||
|
adev->apu_flags |= AMD_APU_IS_RAVEN;
|
||||||
|
if (adev->pdev->device == 0x15d8)
|
||||||
|
adev->apu_flags |= AMD_APU_IS_PICASSO;
|
||||||
|
break;
|
||||||
|
case CHIP_RENOIR:
|
||||||
|
if ((adev->pdev->device == 0x1636) ||
|
||||||
|
(adev->pdev->device == 0x164c))
|
||||||
|
adev->apu_flags |= AMD_APU_IS_RENOIR;
|
||||||
|
else
|
||||||
|
adev->apu_flags |= AMD_APU_IS_GREEN_SARDINE;
|
||||||
|
break;
|
||||||
|
case CHIP_VANGOGH:
|
||||||
|
adev->apu_flags |= AMD_APU_IS_VANGOGH;
|
||||||
|
break;
|
||||||
|
case CHIP_YELLOW_CARP:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* amdgpu_device_check_arguments - validate module params
|
* amdgpu_device_check_arguments - validate module params
|
||||||
*
|
*
|
||||||
@ -3386,6 +3418,10 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||||||
mutex_init(&adev->psp.mutex);
|
mutex_init(&adev->psp.mutex);
|
||||||
mutex_init(&adev->notifier_lock);
|
mutex_init(&adev->notifier_lock);
|
||||||
|
|
||||||
|
r = amdgpu_device_init_apu_flags(adev);
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
|
||||||
r = amdgpu_device_check_arguments(adev);
|
r = amdgpu_device_check_arguments(adev);
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
@ -4304,6 +4340,7 @@ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev)
|
|||||||
case CHIP_SIENNA_CICHLID:
|
case CHIP_SIENNA_CICHLID:
|
||||||
case CHIP_NAVY_FLOUNDER:
|
case CHIP_NAVY_FLOUNDER:
|
||||||
case CHIP_DIMGREY_CAVEFISH:
|
case CHIP_DIMGREY_CAVEFISH:
|
||||||
|
case CHIP_BEIGE_GOBY:
|
||||||
case CHIP_VANGOGH:
|
case CHIP_VANGOGH:
|
||||||
case CHIP_ALDEBARAN:
|
case CHIP_ALDEBARAN:
|
||||||
break;
|
break;
|
||||||
|
@ -160,6 +160,7 @@ int amdgpu_smu_pptable_id = -1;
|
|||||||
* highest. That helps saving some idle power.
|
* highest. That helps saving some idle power.
|
||||||
* DISABLE_FRACTIONAL_PWM (bit 2) disabled by default
|
* DISABLE_FRACTIONAL_PWM (bit 2) disabled by default
|
||||||
* PSR (bit 3) disabled by default
|
* PSR (bit 3) disabled by default
|
||||||
|
* EDP NO POWER SEQUENCING (bit 4) disabled by default
|
||||||
*/
|
*/
|
||||||
uint amdgpu_dc_feature_mask = 2;
|
uint amdgpu_dc_feature_mask = 2;
|
||||||
uint amdgpu_dc_debug_mask;
|
uint amdgpu_dc_debug_mask;
|
||||||
@ -1198,6 +1199,7 @@ static const struct pci_device_id pciidlist[] = {
|
|||||||
{0x1002, 0x73E0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
|
{0x1002, 0x73E0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
|
||||||
{0x1002, 0x73E1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
|
{0x1002, 0x73E1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
|
||||||
{0x1002, 0x73E2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
|
{0x1002, 0x73E2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
|
||||||
|
{0x1002, 0x73E3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
|
||||||
{0x1002, 0x73FF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
|
{0x1002, 0x73FF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
|
||||||
|
|
||||||
/* Aldebaran */
|
/* Aldebaran */
|
||||||
|
@ -562,6 +562,7 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev)
|
|||||||
case CHIP_NAVI14:
|
case CHIP_NAVI14:
|
||||||
case CHIP_NAVI12:
|
case CHIP_NAVI12:
|
||||||
case CHIP_VANGOGH:
|
case CHIP_VANGOGH:
|
||||||
|
case CHIP_YELLOW_CARP:
|
||||||
/* Don't enable it by default yet.
|
/* Don't enable it by default yet.
|
||||||
*/
|
*/
|
||||||
if (amdgpu_tmz < 1) {
|
if (amdgpu_tmz < 1) {
|
||||||
|
@ -160,7 +160,7 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
|
|||||||
struct mm_struct *mm, struct page **pages,
|
struct mm_struct *mm, struct page **pages,
|
||||||
uint64_t start, uint64_t npages,
|
uint64_t start, uint64_t npages,
|
||||||
struct hmm_range **phmm_range, bool readonly,
|
struct hmm_range **phmm_range, bool readonly,
|
||||||
bool mmap_locked)
|
bool mmap_locked, void *owner)
|
||||||
{
|
{
|
||||||
struct hmm_range *hmm_range;
|
struct hmm_range *hmm_range;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
@ -185,6 +185,7 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
|
|||||||
hmm_range->hmm_pfns = pfns;
|
hmm_range->hmm_pfns = pfns;
|
||||||
hmm_range->start = start;
|
hmm_range->start = start;
|
||||||
hmm_range->end = start + npages * PAGE_SIZE;
|
hmm_range->end = start + npages * PAGE_SIZE;
|
||||||
|
hmm_range->dev_private_owner = owner;
|
||||||
|
|
||||||
/* Assuming 512MB takes maxmium 1 second to fault page address */
|
/* Assuming 512MB takes maxmium 1 second to fault page address */
|
||||||
timeout = max(npages >> 17, 1ULL) * HMM_RANGE_DEFAULT_TIMEOUT;
|
timeout = max(npages >> 17, 1ULL) * HMM_RANGE_DEFAULT_TIMEOUT;
|
||||||
|
@ -34,7 +34,7 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
|
|||||||
struct mm_struct *mm, struct page **pages,
|
struct mm_struct *mm, struct page **pages,
|
||||||
uint64_t start, uint64_t npages,
|
uint64_t start, uint64_t npages,
|
||||||
struct hmm_range **phmm_range, bool readonly,
|
struct hmm_range **phmm_range, bool readonly,
|
||||||
bool mmap_locked);
|
bool mmap_locked, void *owner);
|
||||||
int amdgpu_hmm_range_get_pages_done(struct hmm_range *hmm_range);
|
int amdgpu_hmm_range_get_pages_done(struct hmm_range *hmm_range);
|
||||||
|
|
||||||
#if defined(CONFIG_HMM_MIRROR)
|
#if defined(CONFIG_HMM_MIRROR)
|
||||||
|
@ -93,6 +93,8 @@ struct amdgpu_nbio_funcs {
|
|||||||
void (*enable_aspm)(struct amdgpu_device *adev,
|
void (*enable_aspm)(struct amdgpu_device *adev,
|
||||||
bool enable);
|
bool enable);
|
||||||
void (*program_aspm)(struct amdgpu_device *adev);
|
void (*program_aspm)(struct amdgpu_device *adev);
|
||||||
|
void (*apply_lc_spc_mode_wa)(struct amdgpu_device *adev);
|
||||||
|
void (*apply_l1_link_width_reconfig_wa)(struct amdgpu_device *adev);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct amdgpu_nbio {
|
struct amdgpu_nbio {
|
||||||
|
@ -590,10 +590,6 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_device *bdev,
|
|||||||
|
|
||||||
mem->bus.offset += adev->gmc.aper_base;
|
mem->bus.offset += adev->gmc.aper_base;
|
||||||
mem->bus.is_iomem = true;
|
mem->bus.is_iomem = true;
|
||||||
if (adev->gmc.xgmi.connected_to_cpu)
|
|
||||||
mem->bus.caching = ttm_cached;
|
|
||||||
else
|
|
||||||
mem->bus.caching = ttm_write_combined;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -696,7 +692,7 @@ int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo, struct page **pages)
|
|||||||
readonly = amdgpu_ttm_tt_is_readonly(ttm);
|
readonly = amdgpu_ttm_tt_is_readonly(ttm);
|
||||||
r = amdgpu_hmm_range_get_pages(&bo->notifier, mm, pages, start,
|
r = amdgpu_hmm_range_get_pages(&bo->notifier, mm, pages, start,
|
||||||
ttm->num_pages, >t->range, readonly,
|
ttm->num_pages, >t->range, readonly,
|
||||||
false);
|
false, NULL);
|
||||||
out_putmm:
|
out_putmm:
|
||||||
mmput(mm);
|
mmput(mm);
|
||||||
|
|
||||||
|
@ -463,6 +463,11 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
|
|||||||
if (i == 1)
|
if (i == 1)
|
||||||
node->base.placement |= TTM_PL_FLAG_CONTIGUOUS;
|
node->base.placement |= TTM_PL_FLAG_CONTIGUOUS;
|
||||||
|
|
||||||
|
if (adev->gmc.xgmi.connected_to_cpu)
|
||||||
|
node->base.bus.caching = ttm_cached;
|
||||||
|
else
|
||||||
|
node->base.bus.caching = ttm_write_combined;
|
||||||
|
|
||||||
atomic64_add(vis_usage, &mgr->vis_usage);
|
atomic64_add(vis_usage, &mgr->vis_usage);
|
||||||
*res = &node->base;
|
*res = &node->base;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -36,9 +36,12 @@ athub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *adev,
|
|||||||
{
|
{
|
||||||
uint32_t def, data;
|
uint32_t def, data;
|
||||||
|
|
||||||
|
if (!(adev->cg_flags & AMD_CG_SUPPORT_MC_MGCG))
|
||||||
|
return;
|
||||||
|
|
||||||
def = data = RREG32_SOC15(ATHUB, 0, mmATHUB_MISC_CNTL);
|
def = data = RREG32_SOC15(ATHUB, 0, mmATHUB_MISC_CNTL);
|
||||||
|
|
||||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_MGCG))
|
if (enable)
|
||||||
data |= ATHUB_MISC_CNTL__CG_ENABLE_MASK;
|
data |= ATHUB_MISC_CNTL__CG_ENABLE_MASK;
|
||||||
else
|
else
|
||||||
data &= ~ATHUB_MISC_CNTL__CG_ENABLE_MASK;
|
data &= ~ATHUB_MISC_CNTL__CG_ENABLE_MASK;
|
||||||
@ -53,10 +56,13 @@ athub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *adev,
|
|||||||
{
|
{
|
||||||
uint32_t def, data;
|
uint32_t def, data;
|
||||||
|
|
||||||
|
if (!((adev->cg_flags & AMD_CG_SUPPORT_MC_LS) &&
|
||||||
|
(adev->cg_flags & AMD_CG_SUPPORT_HDP_LS)))
|
||||||
|
return;
|
||||||
|
|
||||||
def = data = RREG32_SOC15(ATHUB, 0, mmATHUB_MISC_CNTL);
|
def = data = RREG32_SOC15(ATHUB, 0, mmATHUB_MISC_CNTL);
|
||||||
|
|
||||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_LS) &&
|
if (enable)
|
||||||
(adev->cg_flags & AMD_CG_SUPPORT_HDP_LS))
|
|
||||||
data |= ATHUB_MISC_CNTL__CG_MEM_LS_ENABLE_MASK;
|
data |= ATHUB_MISC_CNTL__CG_MEM_LS_ENABLE_MASK;
|
||||||
else
|
else
|
||||||
data &= ~ATHUB_MISC_CNTL__CG_MEM_LS_ENABLE_MASK;
|
data &= ~ATHUB_MISC_CNTL__CG_MEM_LS_ENABLE_MASK;
|
||||||
|
@ -5086,47 +5086,44 @@ static void gfx_v10_0_tcp_harvest(struct amdgpu_device *adev)
|
|||||||
4 + /* RMI */
|
4 + /* RMI */
|
||||||
1); /* SQG */
|
1); /* SQG */
|
||||||
|
|
||||||
if (adev->asic_type == CHIP_NAVI10 ||
|
mutex_lock(&adev->grbm_idx_mutex);
|
||||||
adev->asic_type == CHIP_NAVI14 ||
|
for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
|
||||||
adev->asic_type == CHIP_NAVI12) {
|
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
|
||||||
mutex_lock(&adev->grbm_idx_mutex);
|
gfx_v10_0_select_se_sh(adev, i, j, 0xffffffff);
|
||||||
for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
|
wgp_active_bitmap = gfx_v10_0_get_wgp_active_bitmap_per_sh(adev);
|
||||||
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
|
/*
|
||||||
gfx_v10_0_select_se_sh(adev, i, j, 0xffffffff);
|
* Set corresponding TCP bits for the inactive WGPs in
|
||||||
wgp_active_bitmap = gfx_v10_0_get_wgp_active_bitmap_per_sh(adev);
|
* GCRD_SA_TARGETS_DISABLE
|
||||||
/*
|
*/
|
||||||
* Set corresponding TCP bits for the inactive WGPs in
|
gcrd_targets_disable_tcp = 0;
|
||||||
* GCRD_SA_TARGETS_DISABLE
|
/* Set TCP & SQC bits in UTCL1_UTCL0_INVREQ_DISABLE */
|
||||||
*/
|
utcl_invreq_disable = 0;
|
||||||
gcrd_targets_disable_tcp = 0;
|
|
||||||
/* Set TCP & SQC bits in UTCL1_UTCL0_INVREQ_DISABLE */
|
|
||||||
utcl_invreq_disable = 0;
|
|
||||||
|
|
||||||
for (k = 0; k < max_wgp_per_sh; k++) {
|
for (k = 0; k < max_wgp_per_sh; k++) {
|
||||||
if (!(wgp_active_bitmap & (1 << k))) {
|
if (!(wgp_active_bitmap & (1 << k))) {
|
||||||
gcrd_targets_disable_tcp |= 3 << (2 * k);
|
gcrd_targets_disable_tcp |= 3 << (2 * k);
|
||||||
utcl_invreq_disable |= (3 << (2 * k)) |
|
gcrd_targets_disable_tcp |= 1 << (k + (max_wgp_per_sh * 2));
|
||||||
(3 << (2 * (max_wgp_per_sh + k)));
|
utcl_invreq_disable |= (3 << (2 * k)) |
|
||||||
}
|
(3 << (2 * (max_wgp_per_sh + k)));
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = RREG32_SOC15(GC, 0, mmUTCL1_UTCL0_INVREQ_DISABLE);
|
|
||||||
/* only override TCP & SQC bits */
|
|
||||||
tmp &= 0xffffffff << (4 * max_wgp_per_sh);
|
|
||||||
tmp |= (utcl_invreq_disable & utcl_invreq_disable_mask);
|
|
||||||
WREG32_SOC15(GC, 0, mmUTCL1_UTCL0_INVREQ_DISABLE, tmp);
|
|
||||||
|
|
||||||
tmp = RREG32_SOC15(GC, 0, mmGCRD_SA_TARGETS_DISABLE);
|
|
||||||
/* only override TCP bits */
|
|
||||||
tmp &= 0xffffffff << (2 * max_wgp_per_sh);
|
|
||||||
tmp |= (gcrd_targets_disable_tcp & gcrd_targets_disable_mask);
|
|
||||||
WREG32_SOC15(GC, 0, mmGCRD_SA_TARGETS_DISABLE, tmp);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
gfx_v10_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
|
tmp = RREG32_SOC15(GC, 0, mmUTCL1_UTCL0_INVREQ_DISABLE);
|
||||||
mutex_unlock(&adev->grbm_idx_mutex);
|
/* only override TCP & SQC bits */
|
||||||
|
tmp &= (0xffffffffU << (4 * max_wgp_per_sh));
|
||||||
|
tmp |= (utcl_invreq_disable & utcl_invreq_disable_mask);
|
||||||
|
WREG32_SOC15(GC, 0, mmUTCL1_UTCL0_INVREQ_DISABLE, tmp);
|
||||||
|
|
||||||
|
tmp = RREG32_SOC15(GC, 0, mmGCRD_SA_TARGETS_DISABLE);
|
||||||
|
/* only override TCP & SQC bits */
|
||||||
|
tmp &= (0xffffffffU << (3 * max_wgp_per_sh));
|
||||||
|
tmp |= (gcrd_targets_disable_tcp & gcrd_targets_disable_mask);
|
||||||
|
WREG32_SOC15(GC, 0, mmGCRD_SA_TARGETS_DISABLE, tmp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gfx_v10_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
|
||||||
|
mutex_unlock(&adev->grbm_idx_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gfx_v10_0_get_tcc_info(struct amdgpu_device *adev)
|
static void gfx_v10_0_get_tcc_info(struct amdgpu_device *adev)
|
||||||
@ -7404,7 +7401,10 @@ static int gfx_v10_0_hw_init(void *handle)
|
|||||||
* init golden registers and rlc resume may override some registers,
|
* init golden registers and rlc resume may override some registers,
|
||||||
* reconfig them here
|
* reconfig them here
|
||||||
*/
|
*/
|
||||||
gfx_v10_0_tcp_harvest(adev);
|
if (adev->asic_type == CHIP_NAVI10 ||
|
||||||
|
adev->asic_type == CHIP_NAVI14 ||
|
||||||
|
adev->asic_type == CHIP_NAVI12)
|
||||||
|
gfx_v10_0_tcp_harvest(adev);
|
||||||
|
|
||||||
r = gfx_v10_0_cp_resume(adev);
|
r = gfx_v10_0_cp_resume(adev);
|
||||||
if (r)
|
if (r)
|
||||||
@ -7777,6 +7777,9 @@ static void gfx_v10_0_update_medium_grain_clock_gating(struct amdgpu_device *ade
|
|||||||
{
|
{
|
||||||
uint32_t data, def;
|
uint32_t data, def;
|
||||||
|
|
||||||
|
if (!(adev->cg_flags & (AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS)))
|
||||||
|
return;
|
||||||
|
|
||||||
/* It is disabled by HW by default */
|
/* It is disabled by HW by default */
|
||||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
|
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
|
||||||
/* 0 - Disable some blocks' MGCG */
|
/* 0 - Disable some blocks' MGCG */
|
||||||
@ -7791,6 +7794,7 @@ static void gfx_v10_0_update_medium_grain_clock_gating(struct amdgpu_device *ade
|
|||||||
RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK |
|
RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK |
|
||||||
RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK |
|
RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK |
|
||||||
RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK |
|
RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK |
|
||||||
|
RLC_CGTT_MGCG_OVERRIDE__GFXIP_FGCG_OVERRIDE_MASK |
|
||||||
RLC_CGTT_MGCG_OVERRIDE__ENABLE_CGTS_LEGACY_MASK);
|
RLC_CGTT_MGCG_OVERRIDE__ENABLE_CGTS_LEGACY_MASK);
|
||||||
|
|
||||||
if (def != data)
|
if (def != data)
|
||||||
@ -7813,13 +7817,15 @@ static void gfx_v10_0_update_medium_grain_clock_gating(struct amdgpu_device *ade
|
|||||||
WREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL, data);
|
WREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!enable || !(adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
|
||||||
/* 1 - MGCG_OVERRIDE */
|
/* 1 - MGCG_OVERRIDE */
|
||||||
def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
|
def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
|
||||||
data |= (RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK |
|
data |= (RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK |
|
||||||
RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK |
|
RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK |
|
||||||
RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK |
|
RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK |
|
||||||
RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK);
|
RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK |
|
||||||
|
RLC_CGTT_MGCG_OVERRIDE__GFXIP_FGCG_OVERRIDE_MASK |
|
||||||
|
RLC_CGTT_MGCG_OVERRIDE__ENABLE_CGTS_LEGACY_MASK);
|
||||||
if (def != data)
|
if (def != data)
|
||||||
WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data);
|
WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data);
|
||||||
|
|
||||||
@ -7845,22 +7851,34 @@ static void gfx_v10_0_update_3d_clock_gating(struct amdgpu_device *adev,
|
|||||||
{
|
{
|
||||||
uint32_t data, def;
|
uint32_t data, def;
|
||||||
|
|
||||||
|
if (!(adev->cg_flags & (AMD_CG_SUPPORT_GFX_3D_CGCG | AMD_CG_SUPPORT_GFX_3D_CGLS)))
|
||||||
|
return;
|
||||||
|
|
||||||
/* Enable 3D CGCG/CGLS */
|
/* Enable 3D CGCG/CGLS */
|
||||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGCG)) {
|
if (enable) {
|
||||||
/* write cmd to clear cgcg/cgls ov */
|
/* write cmd to clear cgcg/cgls ov */
|
||||||
def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
|
def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
|
||||||
|
|
||||||
/* unset CGCG override */
|
/* unset CGCG override */
|
||||||
data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_GFX3D_CG_OVERRIDE_MASK;
|
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGCG)
|
||||||
|
data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_GFX3D_CG_OVERRIDE_MASK;
|
||||||
|
|
||||||
/* update CGCG and CGLS override bits */
|
/* update CGCG and CGLS override bits */
|
||||||
if (def != data)
|
if (def != data)
|
||||||
WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data);
|
WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data);
|
||||||
|
|
||||||
/* enable 3Dcgcg FSM(0x0000363f) */
|
/* enable 3Dcgcg FSM(0x0000363f) */
|
||||||
def = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D);
|
def = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D);
|
||||||
data = (0x36 << RLC_CGCG_CGLS_CTRL_3D__CGCG_GFX_IDLE_THRESHOLD__SHIFT) |
|
data = 0;
|
||||||
RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK;
|
|
||||||
|
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGCG)
|
||||||
|
data = (0x36 << RLC_CGCG_CGLS_CTRL_3D__CGCG_GFX_IDLE_THRESHOLD__SHIFT) |
|
||||||
|
RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK;
|
||||||
|
|
||||||
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGLS)
|
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGLS)
|
||||||
data |= (0x000F << RLC_CGCG_CGLS_CTRL_3D__CGLS_REP_COMPANSAT_DELAY__SHIFT) |
|
data |= (0x000F << RLC_CGCG_CGLS_CTRL_3D__CGLS_REP_COMPANSAT_DELAY__SHIFT) |
|
||||||
RLC_CGCG_CGLS_CTRL_3D__CGLS_EN_MASK;
|
RLC_CGCG_CGLS_CTRL_3D__CGLS_EN_MASK;
|
||||||
|
|
||||||
if (def != data)
|
if (def != data)
|
||||||
WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D, data);
|
WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D, data);
|
||||||
|
|
||||||
@ -7873,9 +7891,14 @@ static void gfx_v10_0_update_3d_clock_gating(struct amdgpu_device *adev,
|
|||||||
} else {
|
} else {
|
||||||
/* Disable CGCG/CGLS */
|
/* Disable CGCG/CGLS */
|
||||||
def = data = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D);
|
def = data = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D);
|
||||||
|
|
||||||
/* disable cgcg, cgls should be disabled */
|
/* disable cgcg, cgls should be disabled */
|
||||||
data &= ~(RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK |
|
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGCG)
|
||||||
RLC_CGCG_CGLS_CTRL_3D__CGLS_EN_MASK);
|
data &= ~RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK;
|
||||||
|
|
||||||
|
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGLS)
|
||||||
|
data &= ~RLC_CGCG_CGLS_CTRL_3D__CGLS_EN_MASK;
|
||||||
|
|
||||||
/* disable cgcg and cgls in FSM */
|
/* disable cgcg and cgls in FSM */
|
||||||
if (def != data)
|
if (def != data)
|
||||||
WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D, data);
|
WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D, data);
|
||||||
@ -7887,25 +7910,35 @@ static void gfx_v10_0_update_coarse_grain_clock_gating(struct amdgpu_device *ade
|
|||||||
{
|
{
|
||||||
uint32_t def, data;
|
uint32_t def, data;
|
||||||
|
|
||||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)) {
|
if (!(adev->cg_flags & (AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
|
def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
|
||||||
|
|
||||||
/* unset CGCG override */
|
/* unset CGCG override */
|
||||||
data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGCG_OVERRIDE_MASK;
|
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)
|
||||||
|
data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGCG_OVERRIDE_MASK;
|
||||||
|
|
||||||
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS)
|
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS)
|
||||||
data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGLS_OVERRIDE_MASK;
|
data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGLS_OVERRIDE_MASK;
|
||||||
else
|
|
||||||
data |= RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGLS_OVERRIDE_MASK;
|
|
||||||
/* update CGCG and CGLS override bits */
|
/* update CGCG and CGLS override bits */
|
||||||
if (def != data)
|
if (def != data)
|
||||||
WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data);
|
WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data);
|
||||||
|
|
||||||
/* enable cgcg FSM(0x0000363F) */
|
/* enable cgcg FSM(0x0000363F) */
|
||||||
def = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL);
|
def = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL);
|
||||||
data = (0x36 << RLC_CGCG_CGLS_CTRL__CGCG_GFX_IDLE_THRESHOLD__SHIFT) |
|
data = 0;
|
||||||
RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK;
|
|
||||||
|
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)
|
||||||
|
data = (0x36 << RLC_CGCG_CGLS_CTRL__CGCG_GFX_IDLE_THRESHOLD__SHIFT) |
|
||||||
|
RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK;
|
||||||
|
|
||||||
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS)
|
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS)
|
||||||
data |= (0x000F << RLC_CGCG_CGLS_CTRL__CGLS_REP_COMPANSAT_DELAY__SHIFT) |
|
data |= (0x000F << RLC_CGCG_CGLS_CTRL__CGLS_REP_COMPANSAT_DELAY__SHIFT) |
|
||||||
RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK;
|
RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK;
|
||||||
|
|
||||||
if (def != data)
|
if (def != data)
|
||||||
WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL, data);
|
WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL, data);
|
||||||
|
|
||||||
@ -7917,8 +7950,14 @@ static void gfx_v10_0_update_coarse_grain_clock_gating(struct amdgpu_device *ade
|
|||||||
WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_CNTL, data);
|
WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_CNTL, data);
|
||||||
} else {
|
} else {
|
||||||
def = data = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL);
|
def = data = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL);
|
||||||
|
|
||||||
/* reset CGCG/CGLS bits */
|
/* reset CGCG/CGLS bits */
|
||||||
data &= ~(RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK | RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK);
|
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)
|
||||||
|
data &= ~RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK;
|
||||||
|
|
||||||
|
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS)
|
||||||
|
data &= ~RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK;
|
||||||
|
|
||||||
/* disable cgcg and cgls in FSM */
|
/* disable cgcg and cgls in FSM */
|
||||||
if (def != data)
|
if (def != data)
|
||||||
WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL, data);
|
WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL, data);
|
||||||
@ -7930,7 +7969,10 @@ static void gfx_v10_0_update_fine_grain_clock_gating(struct amdgpu_device *adev,
|
|||||||
{
|
{
|
||||||
uint32_t def, data;
|
uint32_t def, data;
|
||||||
|
|
||||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_FGCG)) {
|
if (!(adev->cg_flags & AMD_CG_SUPPORT_GFX_FGCG))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
|
def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
|
||||||
/* unset FGCG override */
|
/* unset FGCG override */
|
||||||
data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_FGCG_OVERRIDE_MASK;
|
data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_FGCG_OVERRIDE_MASK;
|
||||||
@ -7961,6 +8003,97 @@ static void gfx_v10_0_update_fine_grain_clock_gating(struct amdgpu_device *adev,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gfx_v10_0_apply_medium_grain_clock_gating_workaround(struct amdgpu_device *adev)
|
||||||
|
{
|
||||||
|
uint32_t reg_data = 0;
|
||||||
|
uint32_t reg_idx = 0;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
const uint32_t tcp_ctrl_regs[] = {
|
||||||
|
mmCGTS_SA0_WGP00_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP00_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP01_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP01_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP02_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP02_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP10_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP10_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP11_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP11_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP12_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP12_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP00_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP00_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP01_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP01_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP02_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP02_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP10_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP10_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP11_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP11_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP12_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP12_CU1_TCP_CTRL_REG
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint32_t tcp_ctrl_regs_nv12[] = {
|
||||||
|
mmCGTS_SA0_WGP00_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP00_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP01_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP01_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP02_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP02_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP10_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP10_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP11_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA0_WGP11_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP00_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP00_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP01_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP01_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP02_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP02_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP10_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP10_CU1_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP11_CU0_TCP_CTRL_REG,
|
||||||
|
mmCGTS_SA1_WGP11_CU1_TCP_CTRL_REG,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint32_t sm_ctlr_regs[] = {
|
||||||
|
mmCGTS_SA0_QUAD0_SM_CTRL_REG,
|
||||||
|
mmCGTS_SA0_QUAD1_SM_CTRL_REG,
|
||||||
|
mmCGTS_SA1_QUAD0_SM_CTRL_REG,
|
||||||
|
mmCGTS_SA1_QUAD1_SM_CTRL_REG
|
||||||
|
};
|
||||||
|
|
||||||
|
if (adev->asic_type == CHIP_NAVI12) {
|
||||||
|
for (i = 0; i < ARRAY_SIZE(tcp_ctrl_regs_nv12); i++) {
|
||||||
|
reg_idx = adev->reg_offset[GC_HWIP][0][mmCGTS_SA0_WGP00_CU0_TCP_CTRL_REG_BASE_IDX] +
|
||||||
|
tcp_ctrl_regs_nv12[i];
|
||||||
|
reg_data = RREG32(reg_idx);
|
||||||
|
reg_data |= CGTS_SA0_WGP00_CU0_TCP_CTRL_REG__TCPI_LS_OVERRIDE_MASK;
|
||||||
|
WREG32(reg_idx, reg_data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < ARRAY_SIZE(tcp_ctrl_regs); i++) {
|
||||||
|
reg_idx = adev->reg_offset[GC_HWIP][0][mmCGTS_SA0_WGP00_CU0_TCP_CTRL_REG_BASE_IDX] +
|
||||||
|
tcp_ctrl_regs[i];
|
||||||
|
reg_data = RREG32(reg_idx);
|
||||||
|
reg_data |= CGTS_SA0_WGP00_CU0_TCP_CTRL_REG__TCPI_LS_OVERRIDE_MASK;
|
||||||
|
WREG32(reg_idx, reg_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(sm_ctlr_regs); i++) {
|
||||||
|
reg_idx = adev->reg_offset[GC_HWIP][0][mmCGTS_SA0_QUAD0_SM_CTRL_REG_BASE_IDX] +
|
||||||
|
sm_ctlr_regs[i];
|
||||||
|
reg_data = RREG32(reg_idx);
|
||||||
|
reg_data &= ~CGTS_SA0_QUAD0_SM_CTRL_REG__SM_MODE_MASK;
|
||||||
|
reg_data |= 2 << CGTS_SA0_QUAD0_SM_CTRL_REG__SM_MODE__SHIFT;
|
||||||
|
WREG32(reg_idx, reg_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int gfx_v10_0_update_gfx_clock_gating(struct amdgpu_device *adev,
|
static int gfx_v10_0_update_gfx_clock_gating(struct amdgpu_device *adev,
|
||||||
bool enable)
|
bool enable)
|
||||||
{
|
{
|
||||||
@ -7977,6 +8110,10 @@ static int gfx_v10_0_update_gfx_clock_gating(struct amdgpu_device *adev,
|
|||||||
gfx_v10_0_update_3d_clock_gating(adev, enable);
|
gfx_v10_0_update_3d_clock_gating(adev, enable);
|
||||||
/* === CGCG + CGLS === */
|
/* === CGCG + CGLS === */
|
||||||
gfx_v10_0_update_coarse_grain_clock_gating(adev, enable);
|
gfx_v10_0_update_coarse_grain_clock_gating(adev, enable);
|
||||||
|
|
||||||
|
if ((adev->asic_type >= CHIP_NAVI10) &&
|
||||||
|
(adev->asic_type <= CHIP_NAVI12))
|
||||||
|
gfx_v10_0_apply_medium_grain_clock_gating_workaround(adev);
|
||||||
} else {
|
} else {
|
||||||
/* CGCG/CGLS should be disabled before MGCG/MGLS
|
/* CGCG/CGLS should be disabled before MGCG/MGLS
|
||||||
* === CGCG + CGLS ===
|
* === CGCG + CGLS ===
|
||||||
@ -9324,17 +9461,22 @@ static void gfx_v10_0_set_user_wgp_inactive_bitmap_per_sh(struct amdgpu_device *
|
|||||||
|
|
||||||
static u32 gfx_v10_0_get_wgp_active_bitmap_per_sh(struct amdgpu_device *adev)
|
static u32 gfx_v10_0_get_wgp_active_bitmap_per_sh(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
u32 data, wgp_bitmask;
|
u32 disabled_mask =
|
||||||
data = RREG32_SOC15(GC, 0, mmCC_GC_SHADER_ARRAY_CONFIG);
|
~amdgpu_gfx_create_bitmask(adev->gfx.config.max_cu_per_sh >> 1);
|
||||||
data |= RREG32_SOC15(GC, 0, mmGC_USER_SHADER_ARRAY_CONFIG);
|
u32 efuse_setting = 0;
|
||||||
|
u32 vbios_setting = 0;
|
||||||
|
|
||||||
data &= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_WGPS_MASK;
|
efuse_setting = RREG32_SOC15(GC, 0, mmCC_GC_SHADER_ARRAY_CONFIG);
|
||||||
data >>= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_WGPS__SHIFT;
|
efuse_setting &= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_WGPS_MASK;
|
||||||
|
efuse_setting >>= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_WGPS__SHIFT;
|
||||||
|
|
||||||
wgp_bitmask =
|
vbios_setting = RREG32_SOC15(GC, 0, mmGC_USER_SHADER_ARRAY_CONFIG);
|
||||||
amdgpu_gfx_create_bitmask(adev->gfx.config.max_cu_per_sh >> 1);
|
vbios_setting &= GC_USER_SHADER_ARRAY_CONFIG__INACTIVE_WGPS_MASK;
|
||||||
|
vbios_setting >>= GC_USER_SHADER_ARRAY_CONFIG__INACTIVE_WGPS__SHIFT;
|
||||||
|
|
||||||
return (~data) & wgp_bitmask;
|
disabled_mask |= efuse_setting | vbios_setting;
|
||||||
|
|
||||||
|
return (~disabled_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 gfx_v10_0_get_cu_active_bitmap_per_sh(struct amdgpu_device *adev)
|
static u32 gfx_v10_0_get_cu_active_bitmap_per_sh(struct amdgpu_device *adev)
|
||||||
|
@ -90,45 +90,56 @@ static void hdp_v5_0_update_mem_power_gating(struct amdgpu_device *adev,
|
|||||||
RC_MEM_POWER_SD_EN, 0);
|
RC_MEM_POWER_SD_EN, 0);
|
||||||
WREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL, hdp_mem_pwr_cntl);
|
WREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL, hdp_mem_pwr_cntl);
|
||||||
|
|
||||||
/* only one clock gating mode (LS/DS/SD) can be enabled */
|
/* Already disabled above. The actions below are for "enabled" only */
|
||||||
if (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS) {
|
if (enable) {
|
||||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
/* only one clock gating mode (LS/DS/SD) can be enabled */
|
||||||
HDP_MEM_POWER_CTRL,
|
if (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS) {
|
||||||
IPH_MEM_POWER_LS_EN, enable);
|
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
||||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
HDP_MEM_POWER_CTRL,
|
||||||
HDP_MEM_POWER_CTRL,
|
IPH_MEM_POWER_LS_EN, 1);
|
||||||
RC_MEM_POWER_LS_EN, enable);
|
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
||||||
} else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_DS) {
|
HDP_MEM_POWER_CTRL,
|
||||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
RC_MEM_POWER_LS_EN, 1);
|
||||||
HDP_MEM_POWER_CTRL,
|
} else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_DS) {
|
||||||
IPH_MEM_POWER_DS_EN, enable);
|
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
||||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
HDP_MEM_POWER_CTRL,
|
||||||
HDP_MEM_POWER_CTRL,
|
IPH_MEM_POWER_DS_EN, 1);
|
||||||
RC_MEM_POWER_DS_EN, enable);
|
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
||||||
} else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_SD) {
|
HDP_MEM_POWER_CTRL,
|
||||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
RC_MEM_POWER_DS_EN, 1);
|
||||||
HDP_MEM_POWER_CTRL,
|
} else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_SD) {
|
||||||
IPH_MEM_POWER_SD_EN, enable);
|
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
||||||
/* RC should not use shut down mode, fallback to ds */
|
HDP_MEM_POWER_CTRL,
|
||||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
IPH_MEM_POWER_SD_EN, 1);
|
||||||
HDP_MEM_POWER_CTRL,
|
/* RC should not use shut down mode, fallback to ds or ls if allowed */
|
||||||
RC_MEM_POWER_DS_EN, enable);
|
if (adev->cg_flags & AMD_CG_SUPPORT_HDP_DS)
|
||||||
|
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
||||||
|
HDP_MEM_POWER_CTRL,
|
||||||
|
RC_MEM_POWER_DS_EN, 1);
|
||||||
|
else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS)
|
||||||
|
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
||||||
|
HDP_MEM_POWER_CTRL,
|
||||||
|
RC_MEM_POWER_LS_EN, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* confirmed that IPH_MEM_POWER_CTRL_EN and RC_MEM_POWER_CTRL_EN have to
|
||||||
|
* be set for SRAM LS/DS/SD */
|
||||||
|
if (adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_HDP_DS |
|
||||||
|
AMD_CG_SUPPORT_HDP_SD)) {
|
||||||
|
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
|
||||||
|
IPH_MEM_POWER_CTRL_EN, 1);
|
||||||
|
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
|
||||||
|
RC_MEM_POWER_CTRL_EN, 1);
|
||||||
|
WREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL, hdp_mem_pwr_cntl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* confirmed that IPH_MEM_POWER_CTRL_EN and RC_MEM_POWER_CTRL_EN have to
|
/* disable IPH & RC clock override after clock/power mode changing */
|
||||||
* be set for SRAM LS/DS/SD */
|
hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL,
|
||||||
if (adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_HDP_DS |
|
IPH_MEM_CLK_SOFT_OVERRIDE, 0);
|
||||||
AMD_CG_SUPPORT_HDP_SD)) {
|
hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL,
|
||||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
|
RC_MEM_CLK_SOFT_OVERRIDE, 0);
|
||||||
IPH_MEM_POWER_CTRL_EN, 1);
|
WREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL, hdp_clk_cntl);
|
||||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
|
|
||||||
RC_MEM_POWER_CTRL_EN, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
WREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL, hdp_mem_pwr_cntl);
|
|
||||||
|
|
||||||
/* restore IPH & RC clock override after clock/power mode changing */
|
|
||||||
WREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL, hdp_clk_cntl1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hdp_v5_0_update_medium_grain_clock_gating(struct amdgpu_device *adev,
|
static void hdp_v5_0_update_medium_grain_clock_gating(struct amdgpu_device *adev,
|
||||||
|
@ -568,6 +568,9 @@ static void mmhub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *ad
|
|||||||
{
|
{
|
||||||
uint32_t def, data, def1, data1;
|
uint32_t def, data, def1, data1;
|
||||||
|
|
||||||
|
if (!(adev->cg_flags & AMD_CG_SUPPORT_MC_MGCG))
|
||||||
|
return;
|
||||||
|
|
||||||
switch (adev->asic_type) {
|
switch (adev->asic_type) {
|
||||||
case CHIP_SIENNA_CICHLID:
|
case CHIP_SIENNA_CICHLID:
|
||||||
case CHIP_NAVY_FLOUNDER:
|
case CHIP_NAVY_FLOUNDER:
|
||||||
@ -582,7 +585,7 @@ static void mmhub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *ad
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_MGCG)) {
|
if (enable) {
|
||||||
data |= MM_ATC_L2_MISC_CG__ENABLE_MASK;
|
data |= MM_ATC_L2_MISC_CG__ENABLE_MASK;
|
||||||
|
|
||||||
data1 &= ~(DAGB0_CNTL_MISC2__DISABLE_WRREQ_CG_MASK |
|
data1 &= ~(DAGB0_CNTL_MISC2__DISABLE_WRREQ_CG_MASK |
|
||||||
@ -627,6 +630,9 @@ static void mmhub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *ade
|
|||||||
{
|
{
|
||||||
uint32_t def, data;
|
uint32_t def, data;
|
||||||
|
|
||||||
|
if (!(adev->cg_flags & AMD_CG_SUPPORT_MC_LS))
|
||||||
|
return;
|
||||||
|
|
||||||
switch (adev->asic_type) {
|
switch (adev->asic_type) {
|
||||||
case CHIP_SIENNA_CICHLID:
|
case CHIP_SIENNA_CICHLID:
|
||||||
case CHIP_NAVY_FLOUNDER:
|
case CHIP_NAVY_FLOUNDER:
|
||||||
@ -639,7 +645,7 @@ static void mmhub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *ade
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_LS))
|
if (enable)
|
||||||
data |= MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK;
|
data |= MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK;
|
||||||
else
|
else
|
||||||
data &= ~MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK;
|
data &= ~MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK;
|
||||||
|
@ -51,6 +51,8 @@
|
|||||||
#define mmBIF_MMSCH1_DOORBELL_RANGE 0x01d8
|
#define mmBIF_MMSCH1_DOORBELL_RANGE 0x01d8
|
||||||
#define mmBIF_MMSCH1_DOORBELL_RANGE_BASE_IDX 2
|
#define mmBIF_MMSCH1_DOORBELL_RANGE_BASE_IDX 2
|
||||||
|
|
||||||
|
#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288
|
||||||
|
|
||||||
static void nbio_v2_3_remap_hdp_registers(struct amdgpu_device *adev)
|
static void nbio_v2_3_remap_hdp_registers(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
WREG32_SOC15(NBIO, 0, mmREMAP_HDP_MEM_FLUSH_CNTL,
|
WREG32_SOC15(NBIO, 0, mmREMAP_HDP_MEM_FLUSH_CNTL,
|
||||||
@ -218,8 +220,11 @@ static void nbio_v2_3_update_medium_grain_clock_gating(struct amdgpu_device *ade
|
|||||||
{
|
{
|
||||||
uint32_t def, data;
|
uint32_t def, data;
|
||||||
|
|
||||||
|
if (!(adev->cg_flags & AMD_CG_SUPPORT_BIF_MGCG))
|
||||||
|
return;
|
||||||
|
|
||||||
def = data = RREG32_PCIE(smnCPM_CONTROL);
|
def = data = RREG32_PCIE(smnCPM_CONTROL);
|
||||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_BIF_MGCG)) {
|
if (enable) {
|
||||||
data |= (CPM_CONTROL__LCLK_DYN_GATE_ENABLE_MASK |
|
data |= (CPM_CONTROL__LCLK_DYN_GATE_ENABLE_MASK |
|
||||||
CPM_CONTROL__TXCLK_DYN_GATE_ENABLE_MASK |
|
CPM_CONTROL__TXCLK_DYN_GATE_ENABLE_MASK |
|
||||||
CPM_CONTROL__TXCLK_LCNT_GATE_ENABLE_MASK |
|
CPM_CONTROL__TXCLK_LCNT_GATE_ENABLE_MASK |
|
||||||
@ -244,8 +249,11 @@ static void nbio_v2_3_update_medium_grain_light_sleep(struct amdgpu_device *adev
|
|||||||
{
|
{
|
||||||
uint32_t def, data;
|
uint32_t def, data;
|
||||||
|
|
||||||
|
if (!(adev->cg_flags & AMD_CG_SUPPORT_BIF_LS))
|
||||||
|
return;
|
||||||
|
|
||||||
def = data = RREG32_PCIE(smnPCIE_CNTL2);
|
def = data = RREG32_PCIE(smnPCIE_CNTL2);
|
||||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_BIF_LS)) {
|
if (enable) {
|
||||||
data |= (PCIE_CNTL2__SLV_MEM_LS_EN_MASK |
|
data |= (PCIE_CNTL2__SLV_MEM_LS_EN_MASK |
|
||||||
PCIE_CNTL2__MST_MEM_LS_EN_MASK |
|
PCIE_CNTL2__MST_MEM_LS_EN_MASK |
|
||||||
PCIE_CNTL2__REPLAY_MEM_LS_EN_MASK);
|
PCIE_CNTL2__REPLAY_MEM_LS_EN_MASK);
|
||||||
@ -463,6 +471,43 @@ static void nbio_v2_3_program_aspm(struct amdgpu_device *adev)
|
|||||||
WREG32_PCIE(smnPCIE_LC_CNTL3, data);
|
WREG32_PCIE(smnPCIE_LC_CNTL3, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nbio_v2_3_apply_lc_spc_mode_wa(struct amdgpu_device *adev)
|
||||||
|
{
|
||||||
|
uint32_t reg_data = 0;
|
||||||
|
uint32_t link_width = 0;
|
||||||
|
|
||||||
|
if (!((adev->asic_type >= CHIP_NAVI10) &&
|
||||||
|
(adev->asic_type <= CHIP_NAVI12)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
reg_data = RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL);
|
||||||
|
link_width = (reg_data & PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
|
||||||
|
>> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Program PCIE_LC_CNTL6.LC_SPC_MODE_8GT to 0x2 (4 symbols per clock data)
|
||||||
|
* if link_width is 0x3 (x4)
|
||||||
|
*/
|
||||||
|
if (0x3 == link_width) {
|
||||||
|
reg_data = RREG32_PCIE(smnPCIE_LC_CNTL6);
|
||||||
|
reg_data &= ~PCIE_LC_CNTL6__LC_SPC_MODE_8GT_MASK;
|
||||||
|
reg_data |= (0x2 << PCIE_LC_CNTL6__LC_SPC_MODE_8GT__SHIFT);
|
||||||
|
WREG32_PCIE(smnPCIE_LC_CNTL6, reg_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nbio_v2_3_apply_l1_link_width_reconfig_wa(struct amdgpu_device *adev)
|
||||||
|
{
|
||||||
|
uint32_t reg_data = 0;
|
||||||
|
|
||||||
|
if (adev->asic_type != CHIP_NAVI10)
|
||||||
|
return;
|
||||||
|
|
||||||
|
reg_data = RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL);
|
||||||
|
reg_data |= PCIE_LC_LINK_WIDTH_CNTL__LC_L1_RECONFIG_EN_MASK;
|
||||||
|
WREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL, reg_data);
|
||||||
|
}
|
||||||
|
|
||||||
const struct amdgpu_nbio_funcs nbio_v2_3_funcs = {
|
const struct amdgpu_nbio_funcs nbio_v2_3_funcs = {
|
||||||
.get_hdp_flush_req_offset = nbio_v2_3_get_hdp_flush_req_offset,
|
.get_hdp_flush_req_offset = nbio_v2_3_get_hdp_flush_req_offset,
|
||||||
.get_hdp_flush_done_offset = nbio_v2_3_get_hdp_flush_done_offset,
|
.get_hdp_flush_done_offset = nbio_v2_3_get_hdp_flush_done_offset,
|
||||||
@ -484,4 +529,6 @@ const struct amdgpu_nbio_funcs nbio_v2_3_funcs = {
|
|||||||
.remap_hdp_registers = nbio_v2_3_remap_hdp_registers,
|
.remap_hdp_registers = nbio_v2_3_remap_hdp_registers,
|
||||||
.enable_aspm = nbio_v2_3_enable_aspm,
|
.enable_aspm = nbio_v2_3_enable_aspm,
|
||||||
.program_aspm = nbio_v2_3_program_aspm,
|
.program_aspm = nbio_v2_3_program_aspm,
|
||||||
|
.apply_lc_spc_mode_wa = nbio_v2_3_apply_lc_spc_mode_wa,
|
||||||
|
.apply_l1_link_width_reconfig_wa = nbio_v2_3_apply_l1_link_width_reconfig_wa,
|
||||||
};
|
};
|
||||||
|
@ -64,6 +64,13 @@
|
|||||||
#include "smuio_v11_0.h"
|
#include "smuio_v11_0.h"
|
||||||
#include "smuio_v11_0_6.h"
|
#include "smuio_v11_0_6.h"
|
||||||
|
|
||||||
|
#define codec_info_build(type, width, height, level) \
|
||||||
|
.codec_type = type,\
|
||||||
|
.max_width = width,\
|
||||||
|
.max_height = height,\
|
||||||
|
.max_pixels_per_frame = height * width,\
|
||||||
|
.max_level = level,
|
||||||
|
|
||||||
static const struct amd_ip_funcs nv_common_ip_funcs;
|
static const struct amd_ip_funcs nv_common_ip_funcs;
|
||||||
|
|
||||||
/* Navi */
|
/* Navi */
|
||||||
@ -309,6 +316,23 @@ static struct amdgpu_video_codecs sriov_sc_video_codecs_decode =
|
|||||||
.codec_array = sriov_sc_video_codecs_decode_array,
|
.codec_array = sriov_sc_video_codecs_decode_array,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Beige Goby*/
|
||||||
|
static const struct amdgpu_video_codec_info bg_video_codecs_decode_array[] = {
|
||||||
|
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)},
|
||||||
|
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)},
|
||||||
|
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct amdgpu_video_codecs bg_video_codecs_decode = {
|
||||||
|
.codec_count = ARRAY_SIZE(bg_video_codecs_decode_array),
|
||||||
|
.codec_array = bg_video_codecs_decode_array,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct amdgpu_video_codecs bg_video_codecs_encode = {
|
||||||
|
.codec_count = 0,
|
||||||
|
.codec_array = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
static int nv_query_video_codecs(struct amdgpu_device *adev, bool encode,
|
static int nv_query_video_codecs(struct amdgpu_device *adev, bool encode,
|
||||||
const struct amdgpu_video_codecs **codecs)
|
const struct amdgpu_video_codecs **codecs)
|
||||||
{
|
{
|
||||||
@ -335,6 +359,12 @@ static int nv_query_video_codecs(struct amdgpu_device *adev, bool encode,
|
|||||||
else
|
else
|
||||||
*codecs = &sc_video_codecs_decode;
|
*codecs = &sc_video_codecs_decode;
|
||||||
return 0;
|
return 0;
|
||||||
|
case CHIP_BEIGE_GOBY:
|
||||||
|
if (encode)
|
||||||
|
*codecs = &bg_video_codecs_encode;
|
||||||
|
else
|
||||||
|
*codecs = &bg_video_codecs_decode;
|
||||||
|
return 0;
|
||||||
case CHIP_NAVI10:
|
case CHIP_NAVI10:
|
||||||
case CHIP_NAVI14:
|
case CHIP_NAVI14:
|
||||||
case CHIP_NAVI12:
|
case CHIP_NAVI12:
|
||||||
@ -1275,7 +1305,6 @@ static int nv_common_early_init(void *handle)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CHIP_VANGOGH:
|
case CHIP_VANGOGH:
|
||||||
adev->apu_flags |= AMD_APU_IS_VANGOGH;
|
|
||||||
adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
|
adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
|
||||||
AMD_CG_SUPPORT_GFX_MGLS |
|
AMD_CG_SUPPORT_GFX_MGLS |
|
||||||
AMD_CG_SUPPORT_GFX_CP_LS |
|
AMD_CG_SUPPORT_GFX_CP_LS |
|
||||||
@ -1411,6 +1440,12 @@ static int nv_common_hw_init(void *handle)
|
|||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||||
|
|
||||||
|
if (adev->nbio.funcs->apply_lc_spc_mode_wa)
|
||||||
|
adev->nbio.funcs->apply_lc_spc_mode_wa(adev);
|
||||||
|
|
||||||
|
if (adev->nbio.funcs->apply_l1_link_width_reconfig_wa)
|
||||||
|
adev->nbio.funcs->apply_l1_link_width_reconfig_wa(adev);
|
||||||
|
|
||||||
/* enable pcie gen2/3 link */
|
/* enable pcie gen2/3 link */
|
||||||
nv_pcie_gen3_enable(adev);
|
nv_pcie_gen3_enable(adev);
|
||||||
/* enable aspm */
|
/* enable aspm */
|
||||||
|
@ -144,7 +144,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4_1[] = {
|
|||||||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
|
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
|
||||||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_IB_CNTL, 0x800f0111, 0x00000100),
|
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_IB_CNTL, 0x800f0111, 0x00000100),
|
||||||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
|
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
|
||||||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0),
|
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003e0),
|
||||||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000)
|
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -288,7 +288,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4_3[] = {
|
|||||||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_POWER_CNTL, 0x003fff07, 0x40000051),
|
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_POWER_CNTL, 0x003fff07, 0x40000051),
|
||||||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
|
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
|
||||||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
|
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
|
||||||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0),
|
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003e0),
|
||||||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x03fbe1fe)
|
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x03fbe1fe)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1896,8 +1896,11 @@ static int sdma_v4_0_late_init(void *handle)
|
|||||||
|
|
||||||
sdma_v4_0_setup_ulv(adev);
|
sdma_v4_0_setup_ulv(adev);
|
||||||
|
|
||||||
if (adev->sdma.funcs && adev->sdma.funcs->reset_ras_error_count)
|
if (!amdgpu_persistent_edc_harvesting_supported(adev)) {
|
||||||
adev->sdma.funcs->reset_ras_error_count(adev);
|
if (adev->sdma.funcs &&
|
||||||
|
adev->sdma.funcs->reset_ras_error_count)
|
||||||
|
adev->sdma.funcs->reset_ras_error_count(adev);
|
||||||
|
}
|
||||||
|
|
||||||
if (adev->sdma.funcs && adev->sdma.funcs->ras_late_init)
|
if (adev->sdma.funcs && adev->sdma.funcs->ras_late_init)
|
||||||
return adev->sdma.funcs->ras_late_init(adev, &ih_info);
|
return adev->sdma.funcs->ras_late_init(adev, &ih_info);
|
||||||
|
@ -43,9 +43,12 @@ static void smuio_v11_0_update_rom_clock_gating(struct amdgpu_device *adev, bool
|
|||||||
if (adev->flags & AMD_IS_APU)
|
if (adev->flags & AMD_IS_APU)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!(adev->cg_flags & AMD_CG_SUPPORT_ROM_MGCG))
|
||||||
|
return;
|
||||||
|
|
||||||
def = data = RREG32_SOC15(SMUIO, 0, mmCGTT_ROM_CLK_CTRL0);
|
def = data = RREG32_SOC15(SMUIO, 0, mmCGTT_ROM_CLK_CTRL0);
|
||||||
|
|
||||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_ROM_MGCG))
|
if (enable)
|
||||||
data &= ~(CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE0_MASK |
|
data &= ~(CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE0_MASK |
|
||||||
CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE1_MASK);
|
CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE1_MASK);
|
||||||
else
|
else
|
||||||
|
@ -1360,10 +1360,7 @@ static int soc15_common_early_init(void *handle)
|
|||||||
break;
|
break;
|
||||||
case CHIP_RAVEN:
|
case CHIP_RAVEN:
|
||||||
adev->asic_funcs = &soc15_asic_funcs;
|
adev->asic_funcs = &soc15_asic_funcs;
|
||||||
if (adev->pdev->device == 0x15dd)
|
|
||||||
adev->apu_flags |= AMD_APU_IS_RAVEN;
|
|
||||||
if (adev->pdev->device == 0x15d8)
|
|
||||||
adev->apu_flags |= AMD_APU_IS_PICASSO;
|
|
||||||
if (adev->rev_id >= 0x8)
|
if (adev->rev_id >= 0x8)
|
||||||
adev->apu_flags |= AMD_APU_IS_RAVEN2;
|
adev->apu_flags |= AMD_APU_IS_RAVEN2;
|
||||||
|
|
||||||
@ -1455,11 +1452,6 @@ static int soc15_common_early_init(void *handle)
|
|||||||
break;
|
break;
|
||||||
case CHIP_RENOIR:
|
case CHIP_RENOIR:
|
||||||
adev->asic_funcs = &soc15_asic_funcs;
|
adev->asic_funcs = &soc15_asic_funcs;
|
||||||
if ((adev->pdev->device == 0x1636) ||
|
|
||||||
(adev->pdev->device == 0x164c))
|
|
||||||
adev->apu_flags |= AMD_APU_IS_RENOIR;
|
|
||||||
else
|
|
||||||
adev->apu_flags |= AMD_APU_IS_GREEN_SARDINE;
|
|
||||||
|
|
||||||
if (adev->apu_flags & AMD_APU_IS_RENOIR)
|
if (adev->apu_flags & AMD_APU_IS_RENOIR)
|
||||||
adev->external_rev_id = adev->rev_id + 0x91;
|
adev->external_rev_id = adev->rev_id + 0x91;
|
||||||
|
@ -218,7 +218,8 @@ svm_migrate_get_vram_page(struct svm_range *prange, unsigned long pfn)
|
|||||||
struct page *page;
|
struct page *page;
|
||||||
|
|
||||||
page = pfn_to_page(pfn);
|
page = pfn_to_page(pfn);
|
||||||
page->zone_device_data = prange;
|
svm_range_bo_ref(prange->svm_bo);
|
||||||
|
page->zone_device_data = prange->svm_bo;
|
||||||
get_page(page);
|
get_page(page);
|
||||||
lock_page(page);
|
lock_page(page);
|
||||||
}
|
}
|
||||||
@ -293,15 +294,13 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
|
|||||||
for (i = j = 0; i < npages; i++) {
|
for (i = j = 0; i < npages; i++) {
|
||||||
struct page *spage;
|
struct page *spage;
|
||||||
|
|
||||||
dst[i] = cursor.start + (j << PAGE_SHIFT);
|
spage = migrate_pfn_to_page(migrate->src[i]);
|
||||||
migrate->dst[i] = svm_migrate_addr_to_pfn(adev, dst[i]);
|
if (spage && !is_zone_device_page(spage)) {
|
||||||
svm_migrate_get_vram_page(prange, migrate->dst[i]);
|
dst[i] = cursor.start + (j << PAGE_SHIFT);
|
||||||
|
migrate->dst[i] = svm_migrate_addr_to_pfn(adev, dst[i]);
|
||||||
migrate->dst[i] = migrate_pfn(migrate->dst[i]);
|
svm_migrate_get_vram_page(prange, migrate->dst[i]);
|
||||||
migrate->dst[i] |= MIGRATE_PFN_LOCKED;
|
migrate->dst[i] = migrate_pfn(migrate->dst[i]);
|
||||||
|
migrate->dst[i] |= MIGRATE_PFN_LOCKED;
|
||||||
if (migrate->src[i] & MIGRATE_PFN_VALID) {
|
|
||||||
spage = migrate_pfn_to_page(migrate->src[i]);
|
|
||||||
src[i] = dma_map_page(dev, spage, 0, PAGE_SIZE,
|
src[i] = dma_map_page(dev, spage, 0, PAGE_SIZE,
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
r = dma_mapping_error(dev, src[i]);
|
r = dma_mapping_error(dev, src[i]);
|
||||||
@ -355,6 +354,20 @@ out_free_vram_pages:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_FORCE_MIXED_DOMAINS
|
||||||
|
for (i = 0, j = 0; i < npages; i += 4, j++) {
|
||||||
|
if (j & 1)
|
||||||
|
continue;
|
||||||
|
svm_migrate_put_vram_page(adev, dst[i]);
|
||||||
|
migrate->dst[i] = 0;
|
||||||
|
svm_migrate_put_vram_page(adev, dst[i + 1]);
|
||||||
|
migrate->dst[i + 1] = 0;
|
||||||
|
svm_migrate_put_vram_page(adev, dst[i + 2]);
|
||||||
|
migrate->dst[i + 2] = 0;
|
||||||
|
svm_migrate_put_vram_page(adev, dst[i + 3]);
|
||||||
|
migrate->dst[i + 3] = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
out:
|
out:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -365,20 +378,20 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
|
|||||||
uint64_t end)
|
uint64_t end)
|
||||||
{
|
{
|
||||||
uint64_t npages = (end - start) >> PAGE_SHIFT;
|
uint64_t npages = (end - start) >> PAGE_SHIFT;
|
||||||
|
struct kfd_process_device *pdd;
|
||||||
struct dma_fence *mfence = NULL;
|
struct dma_fence *mfence = NULL;
|
||||||
struct migrate_vma migrate;
|
struct migrate_vma migrate;
|
||||||
dma_addr_t *scratch;
|
dma_addr_t *scratch;
|
||||||
size_t size;
|
size_t size;
|
||||||
void *buf;
|
void *buf;
|
||||||
int r = -ENOMEM;
|
int r = -ENOMEM;
|
||||||
int retry = 0;
|
|
||||||
|
|
||||||
memset(&migrate, 0, sizeof(migrate));
|
memset(&migrate, 0, sizeof(migrate));
|
||||||
migrate.vma = vma;
|
migrate.vma = vma;
|
||||||
migrate.start = start;
|
migrate.start = start;
|
||||||
migrate.end = end;
|
migrate.end = end;
|
||||||
migrate.flags = MIGRATE_VMA_SELECT_SYSTEM;
|
migrate.flags = MIGRATE_VMA_SELECT_SYSTEM;
|
||||||
migrate.pgmap_owner = adev;
|
migrate.pgmap_owner = SVM_ADEV_PGMAP_OWNER(adev);
|
||||||
|
|
||||||
size = 2 * sizeof(*migrate.src) + sizeof(uint64_t) + sizeof(dma_addr_t);
|
size = 2 * sizeof(*migrate.src) + sizeof(uint64_t) + sizeof(dma_addr_t);
|
||||||
size *= npages;
|
size *= npages;
|
||||||
@ -390,7 +403,6 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
|
|||||||
migrate.dst = migrate.src + npages;
|
migrate.dst = migrate.src + npages;
|
||||||
scratch = (dma_addr_t *)(migrate.dst + npages);
|
scratch = (dma_addr_t *)(migrate.dst + npages);
|
||||||
|
|
||||||
retry:
|
|
||||||
r = migrate_vma_setup(&migrate);
|
r = migrate_vma_setup(&migrate);
|
||||||
if (r) {
|
if (r) {
|
||||||
pr_debug("failed %d prepare migrate svms 0x%p [0x%lx 0x%lx]\n",
|
pr_debug("failed %d prepare migrate svms 0x%p [0x%lx 0x%lx]\n",
|
||||||
@ -398,17 +410,9 @@ retry:
|
|||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
if (migrate.cpages != npages) {
|
if (migrate.cpages != npages) {
|
||||||
pr_debug("collect 0x%lx/0x%llx pages, retry\n", migrate.cpages,
|
pr_debug("Partial migration. 0x%lx/0x%llx pages can be migrated\n",
|
||||||
|
migrate.cpages,
|
||||||
npages);
|
npages);
|
||||||
migrate_vma_finalize(&migrate);
|
|
||||||
if (retry++ >= 3) {
|
|
||||||
r = -ENOMEM;
|
|
||||||
pr_debug("failed %d migrate svms 0x%p [0x%lx 0x%lx]\n",
|
|
||||||
r, prange->svms, prange->start, prange->last);
|
|
||||||
goto out_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto retry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (migrate.cpages) {
|
if (migrate.cpages) {
|
||||||
@ -425,6 +429,12 @@ retry:
|
|||||||
out_free:
|
out_free:
|
||||||
kvfree(buf);
|
kvfree(buf);
|
||||||
out:
|
out:
|
||||||
|
if (!r) {
|
||||||
|
pdd = svm_range_get_pdd_by_adev(prange, adev);
|
||||||
|
if (pdd)
|
||||||
|
WRITE_ONCE(pdd->page_in, pdd->page_in + migrate.cpages);
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,7 +474,7 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
|
|||||||
prange->start, prange->last, best_loc);
|
prange->start, prange->last, best_loc);
|
||||||
|
|
||||||
/* FIXME: workaround for page locking bug with invalid pages */
|
/* FIXME: workaround for page locking bug with invalid pages */
|
||||||
svm_range_prefault(prange, mm);
|
svm_range_prefault(prange, mm, SVM_ADEV_PGMAP_OWNER(adev));
|
||||||
|
|
||||||
start = prange->start << PAGE_SHIFT;
|
start = prange->start << PAGE_SHIFT;
|
||||||
end = (prange->last + 1) << PAGE_SHIFT;
|
end = (prange->last + 1) << PAGE_SHIFT;
|
||||||
@ -493,15 +503,19 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
|
|||||||
|
|
||||||
static void svm_migrate_page_free(struct page *page)
|
static void svm_migrate_page_free(struct page *page)
|
||||||
{
|
{
|
||||||
/* Keep this function to avoid warning */
|
struct svm_range_bo *svm_bo = page->zone_device_data;
|
||||||
|
|
||||||
|
if (svm_bo) {
|
||||||
|
pr_debug("svm_bo ref left: %d\n", kref_read(&svm_bo->kref));
|
||||||
|
svm_range_bo_unref(svm_bo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||||
struct migrate_vma *migrate, struct dma_fence **mfence,
|
struct migrate_vma *migrate, struct dma_fence **mfence,
|
||||||
dma_addr_t *scratch)
|
dma_addr_t *scratch, uint64_t npages)
|
||||||
{
|
{
|
||||||
uint64_t npages = migrate->cpages;
|
|
||||||
struct device *dev = adev->dev;
|
struct device *dev = adev->dev;
|
||||||
uint64_t *src;
|
uint64_t *src;
|
||||||
dma_addr_t *dst;
|
dma_addr_t *dst;
|
||||||
@ -518,15 +532,23 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
|||||||
src = (uint64_t *)(scratch + npages);
|
src = (uint64_t *)(scratch + npages);
|
||||||
dst = scratch;
|
dst = scratch;
|
||||||
|
|
||||||
for (i = 0, j = 0; i < npages; i++, j++, addr += PAGE_SIZE) {
|
for (i = 0, j = 0; i < npages; i++, addr += PAGE_SIZE) {
|
||||||
struct page *spage;
|
struct page *spage;
|
||||||
|
|
||||||
spage = migrate_pfn_to_page(migrate->src[i]);
|
spage = migrate_pfn_to_page(migrate->src[i]);
|
||||||
if (!spage) {
|
if (!spage || !is_zone_device_page(spage)) {
|
||||||
pr_debug("failed get spage svms 0x%p [0x%lx 0x%lx]\n",
|
pr_debug("invalid page. Could be in CPU already svms 0x%p [0x%lx 0x%lx]\n",
|
||||||
prange->svms, prange->start, prange->last);
|
prange->svms, prange->start, prange->last);
|
||||||
r = -ENOMEM;
|
if (j) {
|
||||||
goto out_oom;
|
r = svm_migrate_copy_memory_gart(adev, dst + i - j,
|
||||||
|
src + i - j, j,
|
||||||
|
FROM_VRAM_TO_RAM,
|
||||||
|
mfence);
|
||||||
|
if (r)
|
||||||
|
goto out_oom;
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
src[i] = svm_migrate_addr(adev, spage);
|
src[i] = svm_migrate_addr(adev, spage);
|
||||||
if (i > 0 && src[i] != src[i - 1] + PAGE_SIZE) {
|
if (i > 0 && src[i] != src[i - 1] + PAGE_SIZE) {
|
||||||
@ -559,6 +581,7 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
|||||||
|
|
||||||
migrate->dst[i] = migrate_pfn(page_to_pfn(dpage));
|
migrate->dst[i] = migrate_pfn(page_to_pfn(dpage));
|
||||||
migrate->dst[i] |= MIGRATE_PFN_LOCKED;
|
migrate->dst[i] |= MIGRATE_PFN_LOCKED;
|
||||||
|
j++;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = svm_migrate_copy_memory_gart(adev, dst + i - j, src + i - j, j,
|
r = svm_migrate_copy_memory_gart(adev, dst + i - j, src + i - j, j,
|
||||||
@ -581,6 +604,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
|||||||
struct vm_area_struct *vma, uint64_t start, uint64_t end)
|
struct vm_area_struct *vma, uint64_t start, uint64_t end)
|
||||||
{
|
{
|
||||||
uint64_t npages = (end - start) >> PAGE_SHIFT;
|
uint64_t npages = (end - start) >> PAGE_SHIFT;
|
||||||
|
struct kfd_process_device *pdd;
|
||||||
struct dma_fence *mfence = NULL;
|
struct dma_fence *mfence = NULL;
|
||||||
struct migrate_vma migrate;
|
struct migrate_vma migrate;
|
||||||
dma_addr_t *scratch;
|
dma_addr_t *scratch;
|
||||||
@ -593,7 +617,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
|||||||
migrate.start = start;
|
migrate.start = start;
|
||||||
migrate.end = end;
|
migrate.end = end;
|
||||||
migrate.flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE;
|
migrate.flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE;
|
||||||
migrate.pgmap_owner = adev;
|
migrate.pgmap_owner = SVM_ADEV_PGMAP_OWNER(adev);
|
||||||
|
|
||||||
size = 2 * sizeof(*migrate.src) + sizeof(uint64_t) + sizeof(dma_addr_t);
|
size = 2 * sizeof(*migrate.src) + sizeof(uint64_t) + sizeof(dma_addr_t);
|
||||||
size *= npages;
|
size *= npages;
|
||||||
@ -616,7 +640,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
|||||||
|
|
||||||
if (migrate.cpages) {
|
if (migrate.cpages) {
|
||||||
r = svm_migrate_copy_to_ram(adev, prange, &migrate, &mfence,
|
r = svm_migrate_copy_to_ram(adev, prange, &migrate, &mfence,
|
||||||
scratch);
|
scratch, npages);
|
||||||
migrate_vma_pages(&migrate);
|
migrate_vma_pages(&migrate);
|
||||||
svm_migrate_copy_done(adev, mfence);
|
svm_migrate_copy_done(adev, mfence);
|
||||||
migrate_vma_finalize(&migrate);
|
migrate_vma_finalize(&migrate);
|
||||||
@ -630,6 +654,12 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
|||||||
out_free:
|
out_free:
|
||||||
kvfree(buf);
|
kvfree(buf);
|
||||||
out:
|
out:
|
||||||
|
if (!r) {
|
||||||
|
pdd = svm_range_get_pdd_by_adev(prange, adev);
|
||||||
|
if (pdd)
|
||||||
|
WRITE_ONCE(pdd->page_out,
|
||||||
|
pdd->page_out + migrate.cpages);
|
||||||
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -859,7 +889,7 @@ int svm_migrate_init(struct amdgpu_device *adev)
|
|||||||
pgmap->range.start = res->start;
|
pgmap->range.start = res->start;
|
||||||
pgmap->range.end = res->end;
|
pgmap->range.end = res->end;
|
||||||
pgmap->ops = &svm_migrate_pgmap_ops;
|
pgmap->ops = &svm_migrate_pgmap_ops;
|
||||||
pgmap->owner = adev;
|
pgmap->owner = SVM_ADEV_PGMAP_OWNER(adev);
|
||||||
pgmap->flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE;
|
pgmap->flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE;
|
||||||
r = devm_memremap_pages(adev->dev, pgmap);
|
r = devm_memremap_pages(adev->dev, pgmap);
|
||||||
if (IS_ERR(r)) {
|
if (IS_ERR(r)) {
|
||||||
|
@ -730,6 +730,15 @@ struct kfd_process_device {
|
|||||||
* number of CU's a device has along with number of other competing processes
|
* number of CU's a device has along with number of other competing processes
|
||||||
*/
|
*/
|
||||||
struct attribute attr_cu_occupancy;
|
struct attribute attr_cu_occupancy;
|
||||||
|
|
||||||
|
/* sysfs counters for GPU retry fault and page migration tracking */
|
||||||
|
struct kobject *kobj_counters;
|
||||||
|
struct attribute attr_faults;
|
||||||
|
struct attribute attr_page_in;
|
||||||
|
struct attribute attr_page_out;
|
||||||
|
uint64_t faults;
|
||||||
|
uint64_t page_in;
|
||||||
|
uint64_t page_out;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define qpd_to_pdd(x) container_of(x, struct kfd_process_device, qpd)
|
#define qpd_to_pdd(x) container_of(x, struct kfd_process_device, qpd)
|
||||||
|
@ -416,6 +416,29 @@ static ssize_t kfd_procfs_stats_show(struct kobject *kobj,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t kfd_sysfs_counters_show(struct kobject *kobj,
|
||||||
|
struct attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct kfd_process_device *pdd;
|
||||||
|
|
||||||
|
if (!strcmp(attr->name, "faults")) {
|
||||||
|
pdd = container_of(attr, struct kfd_process_device,
|
||||||
|
attr_faults);
|
||||||
|
return sysfs_emit(buf, "%llu\n", READ_ONCE(pdd->faults));
|
||||||
|
}
|
||||||
|
if (!strcmp(attr->name, "page_in")) {
|
||||||
|
pdd = container_of(attr, struct kfd_process_device,
|
||||||
|
attr_page_in);
|
||||||
|
return sysfs_emit(buf, "%llu\n", READ_ONCE(pdd->page_in));
|
||||||
|
}
|
||||||
|
if (!strcmp(attr->name, "page_out")) {
|
||||||
|
pdd = container_of(attr, struct kfd_process_device,
|
||||||
|
attr_page_out);
|
||||||
|
return sysfs_emit(buf, "%llu\n", READ_ONCE(pdd->page_out));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct attribute attr_queue_size = {
|
static struct attribute attr_queue_size = {
|
||||||
.name = "size",
|
.name = "size",
|
||||||
.mode = KFD_SYSFS_FILE_MODE
|
.mode = KFD_SYSFS_FILE_MODE
|
||||||
@ -451,13 +474,18 @@ static const struct sysfs_ops procfs_stats_ops = {
|
|||||||
.show = kfd_procfs_stats_show,
|
.show = kfd_procfs_stats_show,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attribute *procfs_stats_attrs[] = {
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct kobj_type procfs_stats_type = {
|
static struct kobj_type procfs_stats_type = {
|
||||||
.sysfs_ops = &procfs_stats_ops,
|
.sysfs_ops = &procfs_stats_ops,
|
||||||
.default_attrs = procfs_stats_attrs,
|
.release = kfd_procfs_kobj_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct sysfs_ops sysfs_counters_ops = {
|
||||||
|
.show = kfd_sysfs_counters_show,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct kobj_type sysfs_counters_type = {
|
||||||
|
.sysfs_ops = &sysfs_counters_ops,
|
||||||
|
.release = kfd_procfs_kobj_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
int kfd_procfs_add_queue(struct queue *q)
|
int kfd_procfs_add_queue(struct queue *q)
|
||||||
@ -484,34 +512,31 @@ int kfd_procfs_add_queue(struct queue *q)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kfd_sysfs_create_file(struct kfd_process *p, struct attribute *attr,
|
static void kfd_sysfs_create_file(struct kobject *kobj, struct attribute *attr,
|
||||||
char *name)
|
char *name)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret;
|
||||||
|
|
||||||
if (!p || !attr || !name)
|
if (!kobj || !attr || !name)
|
||||||
return -EINVAL;
|
return;
|
||||||
|
|
||||||
attr->name = name;
|
attr->name = name;
|
||||||
attr->mode = KFD_SYSFS_FILE_MODE;
|
attr->mode = KFD_SYSFS_FILE_MODE;
|
||||||
sysfs_attr_init(attr);
|
sysfs_attr_init(attr);
|
||||||
|
|
||||||
ret = sysfs_create_file(p->kobj, attr);
|
ret = sysfs_create_file(kobj, attr);
|
||||||
|
if (ret)
|
||||||
return ret;
|
pr_warn("Create sysfs %s/%s failed %d", kobj->name, name, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kfd_procfs_add_sysfs_stats(struct kfd_process *p)
|
static void kfd_procfs_add_sysfs_stats(struct kfd_process *p)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
char stats_dir_filename[MAX_SYSFS_FILENAME_LEN];
|
char stats_dir_filename[MAX_SYSFS_FILENAME_LEN];
|
||||||
|
|
||||||
if (!p)
|
if (!p || !p->kobj)
|
||||||
return -EINVAL;
|
return;
|
||||||
|
|
||||||
if (!p->kobj)
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create sysfs files for each GPU:
|
* Create sysfs files for each GPU:
|
||||||
@ -521,63 +546,87 @@ static int kfd_procfs_add_sysfs_stats(struct kfd_process *p)
|
|||||||
*/
|
*/
|
||||||
for (i = 0; i < p->n_pdds; i++) {
|
for (i = 0; i < p->n_pdds; i++) {
|
||||||
struct kfd_process_device *pdd = p->pdds[i];
|
struct kfd_process_device *pdd = p->pdds[i];
|
||||||
struct kobject *kobj_stats;
|
|
||||||
|
|
||||||
snprintf(stats_dir_filename, MAX_SYSFS_FILENAME_LEN,
|
snprintf(stats_dir_filename, MAX_SYSFS_FILENAME_LEN,
|
||||||
"stats_%u", pdd->dev->id);
|
"stats_%u", pdd->dev->id);
|
||||||
kobj_stats = kfd_alloc_struct(kobj_stats);
|
pdd->kobj_stats = kfd_alloc_struct(pdd->kobj_stats);
|
||||||
if (!kobj_stats)
|
if (!pdd->kobj_stats)
|
||||||
return -ENOMEM;
|
return;
|
||||||
|
|
||||||
ret = kobject_init_and_add(kobj_stats,
|
ret = kobject_init_and_add(pdd->kobj_stats,
|
||||||
&procfs_stats_type,
|
&procfs_stats_type,
|
||||||
p->kobj,
|
p->kobj,
|
||||||
stats_dir_filename);
|
stats_dir_filename);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_warn("Creating KFD proc/stats_%s folder failed",
|
pr_warn("Creating KFD proc/stats_%s folder failed",
|
||||||
stats_dir_filename);
|
stats_dir_filename);
|
||||||
kobject_put(kobj_stats);
|
kobject_put(pdd->kobj_stats);
|
||||||
goto err;
|
pdd->kobj_stats = NULL;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pdd->kobj_stats = kobj_stats;
|
kfd_sysfs_create_file(pdd->kobj_stats, &pdd->attr_evict,
|
||||||
pdd->attr_evict.name = "evicted_ms";
|
"evicted_ms");
|
||||||
pdd->attr_evict.mode = KFD_SYSFS_FILE_MODE;
|
|
||||||
sysfs_attr_init(&pdd->attr_evict);
|
|
||||||
ret = sysfs_create_file(kobj_stats, &pdd->attr_evict);
|
|
||||||
if (ret)
|
|
||||||
pr_warn("Creating eviction stats for gpuid %d failed",
|
|
||||||
(int)pdd->dev->id);
|
|
||||||
|
|
||||||
/* Add sysfs file to report compute unit occupancy */
|
/* Add sysfs file to report compute unit occupancy */
|
||||||
if (pdd->dev->kfd2kgd->get_cu_occupancy != NULL) {
|
if (pdd->dev->kfd2kgd->get_cu_occupancy)
|
||||||
pdd->attr_cu_occupancy.name = "cu_occupancy";
|
kfd_sysfs_create_file(pdd->kobj_stats,
|
||||||
pdd->attr_cu_occupancy.mode = KFD_SYSFS_FILE_MODE;
|
&pdd->attr_cu_occupancy,
|
||||||
sysfs_attr_init(&pdd->attr_cu_occupancy);
|
"cu_occupancy");
|
||||||
ret = sysfs_create_file(kobj_stats,
|
|
||||||
&pdd->attr_cu_occupancy);
|
|
||||||
if (ret)
|
|
||||||
pr_warn("Creating %s failed for gpuid: %d",
|
|
||||||
pdd->attr_cu_occupancy.name,
|
|
||||||
(int)pdd->dev->id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void kfd_procfs_add_sysfs_counters(struct kfd_process *p)
|
||||||
static int kfd_procfs_add_sysfs_files(struct kfd_process *p)
|
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int i;
|
int i;
|
||||||
|
char counters_dir_filename[MAX_SYSFS_FILENAME_LEN];
|
||||||
|
|
||||||
if (!p)
|
if (!p || !p->kobj)
|
||||||
return -EINVAL;
|
return;
|
||||||
|
|
||||||
if (!p->kobj)
|
/*
|
||||||
return -EFAULT;
|
* Create sysfs files for each GPU which supports SVM
|
||||||
|
* - proc/<pid>/counters_<gpuid>/
|
||||||
|
* - proc/<pid>/counters_<gpuid>/faults
|
||||||
|
* - proc/<pid>/counters_<gpuid>/page_in
|
||||||
|
* - proc/<pid>/counters_<gpuid>/page_out
|
||||||
|
*/
|
||||||
|
for_each_set_bit(i, p->svms.bitmap_supported, p->n_pdds) {
|
||||||
|
struct kfd_process_device *pdd = p->pdds[i];
|
||||||
|
struct kobject *kobj_counters;
|
||||||
|
|
||||||
|
snprintf(counters_dir_filename, MAX_SYSFS_FILENAME_LEN,
|
||||||
|
"counters_%u", pdd->dev->id);
|
||||||
|
kobj_counters = kfd_alloc_struct(kobj_counters);
|
||||||
|
if (!kobj_counters)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ret = kobject_init_and_add(kobj_counters, &sysfs_counters_type,
|
||||||
|
p->kobj, counters_dir_filename);
|
||||||
|
if (ret) {
|
||||||
|
pr_warn("Creating KFD proc/%s folder failed",
|
||||||
|
counters_dir_filename);
|
||||||
|
kobject_put(kobj_counters);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdd->kobj_counters = kobj_counters;
|
||||||
|
kfd_sysfs_create_file(kobj_counters, &pdd->attr_faults,
|
||||||
|
"faults");
|
||||||
|
kfd_sysfs_create_file(kobj_counters, &pdd->attr_page_in,
|
||||||
|
"page_in");
|
||||||
|
kfd_sysfs_create_file(kobj_counters, &pdd->attr_page_out,
|
||||||
|
"page_out");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kfd_procfs_add_sysfs_files(struct kfd_process *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!p || !p->kobj)
|
||||||
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create sysfs files for each GPU:
|
* Create sysfs files for each GPU:
|
||||||
@ -589,20 +638,14 @@ static int kfd_procfs_add_sysfs_files(struct kfd_process *p)
|
|||||||
|
|
||||||
snprintf(pdd->vram_filename, MAX_SYSFS_FILENAME_LEN, "vram_%u",
|
snprintf(pdd->vram_filename, MAX_SYSFS_FILENAME_LEN, "vram_%u",
|
||||||
pdd->dev->id);
|
pdd->dev->id);
|
||||||
ret = kfd_sysfs_create_file(p, &pdd->attr_vram, pdd->vram_filename);
|
kfd_sysfs_create_file(p->kobj, &pdd->attr_vram,
|
||||||
if (ret)
|
pdd->vram_filename);
|
||||||
pr_warn("Creating vram usage for gpu id %d failed",
|
|
||||||
(int)pdd->dev->id);
|
|
||||||
|
|
||||||
snprintf(pdd->sdma_filename, MAX_SYSFS_FILENAME_LEN, "sdma_%u",
|
snprintf(pdd->sdma_filename, MAX_SYSFS_FILENAME_LEN, "sdma_%u",
|
||||||
pdd->dev->id);
|
pdd->dev->id);
|
||||||
ret = kfd_sysfs_create_file(p, &pdd->attr_sdma, pdd->sdma_filename);
|
kfd_sysfs_create_file(p->kobj, &pdd->attr_sdma,
|
||||||
if (ret)
|
pdd->sdma_filename);
|
||||||
pr_warn("Creating sdma usage for gpu id %d failed",
|
|
||||||
(int)pdd->dev->id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void kfd_procfs_del_queue(struct queue *q)
|
void kfd_procfs_del_queue(struct queue *q)
|
||||||
@ -800,28 +843,17 @@ struct kfd_process *kfd_create_process(struct file *filep)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
process->attr_pasid.name = "pasid";
|
kfd_sysfs_create_file(process->kobj, &process->attr_pasid,
|
||||||
process->attr_pasid.mode = KFD_SYSFS_FILE_MODE;
|
"pasid");
|
||||||
sysfs_attr_init(&process->attr_pasid);
|
|
||||||
ret = sysfs_create_file(process->kobj, &process->attr_pasid);
|
|
||||||
if (ret)
|
|
||||||
pr_warn("Creating pasid for pid %d failed",
|
|
||||||
(int)process->lead_thread->pid);
|
|
||||||
|
|
||||||
process->kobj_queues = kobject_create_and_add("queues",
|
process->kobj_queues = kobject_create_and_add("queues",
|
||||||
process->kobj);
|
process->kobj);
|
||||||
if (!process->kobj_queues)
|
if (!process->kobj_queues)
|
||||||
pr_warn("Creating KFD proc/queues folder failed");
|
pr_warn("Creating KFD proc/queues folder failed");
|
||||||
|
|
||||||
ret = kfd_procfs_add_sysfs_stats(process);
|
kfd_procfs_add_sysfs_stats(process);
|
||||||
if (ret)
|
kfd_procfs_add_sysfs_files(process);
|
||||||
pr_warn("Creating sysfs stats dir for pid %d failed",
|
kfd_procfs_add_sysfs_counters(process);
|
||||||
(int)process->lead_thread->pid);
|
|
||||||
|
|
||||||
ret = kfd_procfs_add_sysfs_files(process);
|
|
||||||
if (ret)
|
|
||||||
pr_warn("Creating sysfs usage file for pid %d failed",
|
|
||||||
(int)process->lead_thread->pid);
|
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
if (!IS_ERR(process))
|
if (!IS_ERR(process))
|
||||||
@ -964,6 +996,50 @@ static void kfd_process_destroy_pdds(struct kfd_process *p)
|
|||||||
p->n_pdds = 0;
|
p->n_pdds = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void kfd_process_remove_sysfs(struct kfd_process *p)
|
||||||
|
{
|
||||||
|
struct kfd_process_device *pdd;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!p->kobj)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sysfs_remove_file(p->kobj, &p->attr_pasid);
|
||||||
|
kobject_del(p->kobj_queues);
|
||||||
|
kobject_put(p->kobj_queues);
|
||||||
|
p->kobj_queues = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < p->n_pdds; i++) {
|
||||||
|
pdd = p->pdds[i];
|
||||||
|
|
||||||
|
sysfs_remove_file(p->kobj, &pdd->attr_vram);
|
||||||
|
sysfs_remove_file(p->kobj, &pdd->attr_sdma);
|
||||||
|
|
||||||
|
sysfs_remove_file(pdd->kobj_stats, &pdd->attr_evict);
|
||||||
|
if (pdd->dev->kfd2kgd->get_cu_occupancy)
|
||||||
|
sysfs_remove_file(pdd->kobj_stats,
|
||||||
|
&pdd->attr_cu_occupancy);
|
||||||
|
kobject_del(pdd->kobj_stats);
|
||||||
|
kobject_put(pdd->kobj_stats);
|
||||||
|
pdd->kobj_stats = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for_each_set_bit(i, p->svms.bitmap_supported, p->n_pdds) {
|
||||||
|
pdd = p->pdds[i];
|
||||||
|
|
||||||
|
sysfs_remove_file(pdd->kobj_counters, &pdd->attr_faults);
|
||||||
|
sysfs_remove_file(pdd->kobj_counters, &pdd->attr_page_in);
|
||||||
|
sysfs_remove_file(pdd->kobj_counters, &pdd->attr_page_out);
|
||||||
|
kobject_del(pdd->kobj_counters);
|
||||||
|
kobject_put(pdd->kobj_counters);
|
||||||
|
pdd->kobj_counters = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
kobject_del(p->kobj);
|
||||||
|
kobject_put(p->kobj);
|
||||||
|
p->kobj = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* No process locking is needed in this function, because the process
|
/* No process locking is needed in this function, because the process
|
||||||
* is not findable any more. We must assume that no other thread is
|
* is not findable any more. We must assume that no other thread is
|
||||||
* using it any more, otherwise we couldn't safely free the process
|
* using it any more, otherwise we couldn't safely free the process
|
||||||
@ -973,33 +1049,7 @@ static void kfd_process_wq_release(struct work_struct *work)
|
|||||||
{
|
{
|
||||||
struct kfd_process *p = container_of(work, struct kfd_process,
|
struct kfd_process *p = container_of(work, struct kfd_process,
|
||||||
release_work);
|
release_work);
|
||||||
int i;
|
kfd_process_remove_sysfs(p);
|
||||||
|
|
||||||
/* Remove the procfs files */
|
|
||||||
if (p->kobj) {
|
|
||||||
sysfs_remove_file(p->kobj, &p->attr_pasid);
|
|
||||||
kobject_del(p->kobj_queues);
|
|
||||||
kobject_put(p->kobj_queues);
|
|
||||||
p->kobj_queues = NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < p->n_pdds; i++) {
|
|
||||||
struct kfd_process_device *pdd = p->pdds[i];
|
|
||||||
|
|
||||||
sysfs_remove_file(p->kobj, &pdd->attr_vram);
|
|
||||||
sysfs_remove_file(p->kobj, &pdd->attr_sdma);
|
|
||||||
sysfs_remove_file(p->kobj, &pdd->attr_evict);
|
|
||||||
if (pdd->dev->kfd2kgd->get_cu_occupancy != NULL)
|
|
||||||
sysfs_remove_file(p->kobj, &pdd->attr_cu_occupancy);
|
|
||||||
kobject_del(pdd->kobj_stats);
|
|
||||||
kobject_put(pdd->kobj_stats);
|
|
||||||
pdd->kobj_stats = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
kobject_del(p->kobj);
|
|
||||||
kobject_put(p->kobj);
|
|
||||||
p->kobj = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
kfd_iommu_unbind_process(p);
|
kfd_iommu_unbind_process(p);
|
||||||
|
|
||||||
kfd_process_free_outstanding_kfd_bos(p);
|
kfd_process_free_outstanding_kfd_bos(p);
|
||||||
|
@ -153,6 +153,7 @@ void pqm_uninit(struct process_queue_manager *pqm)
|
|||||||
if (pqn->q && pqn->q->gws)
|
if (pqn->q && pqn->q->gws)
|
||||||
amdgpu_amdkfd_remove_gws_from_process(pqm->process->kgd_process_info,
|
amdgpu_amdkfd_remove_gws_from_process(pqm->process->kgd_process_info,
|
||||||
pqn->q->gws);
|
pqn->q->gws);
|
||||||
|
kfd_procfs_del_queue(pqn->q);
|
||||||
uninit_queue(pqn->q);
|
uninit_queue(pqn->q);
|
||||||
list_del(&pqn->process_queue_list);
|
list_del(&pqn->process_queue_list);
|
||||||
kfree(pqn);
|
kfree(pqn);
|
||||||
|
@ -119,28 +119,40 @@ static void svm_range_remove_notifier(struct svm_range *prange)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
svm_range_dma_map_dev(struct device *dev, dma_addr_t **dma_addr,
|
svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
|
||||||
unsigned long *hmm_pfns, uint64_t npages)
|
unsigned long *hmm_pfns, uint32_t gpuidx)
|
||||||
{
|
{
|
||||||
enum dma_data_direction dir = DMA_BIDIRECTIONAL;
|
enum dma_data_direction dir = DMA_BIDIRECTIONAL;
|
||||||
dma_addr_t *addr = *dma_addr;
|
dma_addr_t *addr = prange->dma_addr[gpuidx];
|
||||||
|
struct device *dev = adev->dev;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
int i, r;
|
int i, r;
|
||||||
|
|
||||||
if (!addr) {
|
if (!addr) {
|
||||||
addr = kvmalloc_array(npages, sizeof(*addr),
|
addr = kvmalloc_array(prange->npages, sizeof(*addr),
|
||||||
GFP_KERNEL | __GFP_ZERO);
|
GFP_KERNEL | __GFP_ZERO);
|
||||||
if (!addr)
|
if (!addr)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
*dma_addr = addr;
|
prange->dma_addr[gpuidx] = addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < npages; i++) {
|
for (i = 0; i < prange->npages; i++) {
|
||||||
if (WARN_ONCE(addr[i] && !dma_mapping_error(dev, addr[i]),
|
if (WARN_ONCE(addr[i] && !dma_mapping_error(dev, addr[i]),
|
||||||
"leaking dma mapping\n"))
|
"leaking dma mapping\n"))
|
||||||
dma_unmap_page(dev, addr[i], PAGE_SIZE, dir);
|
dma_unmap_page(dev, addr[i], PAGE_SIZE, dir);
|
||||||
|
|
||||||
page = hmm_pfn_to_page(hmm_pfns[i]);
|
page = hmm_pfn_to_page(hmm_pfns[i]);
|
||||||
|
if (is_zone_device_page(page)) {
|
||||||
|
struct amdgpu_device *bo_adev =
|
||||||
|
amdgpu_ttm_adev(prange->svm_bo->bo->tbo.bdev);
|
||||||
|
|
||||||
|
addr[i] = (hmm_pfns[i] << PAGE_SHIFT) +
|
||||||
|
bo_adev->vm_manager.vram_base_offset -
|
||||||
|
bo_adev->kfd.dev->pgmap.range.start;
|
||||||
|
addr[i] |= SVM_RANGE_VRAM_DOMAIN;
|
||||||
|
pr_debug("vram address detected: 0x%llx\n", addr[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
addr[i] = dma_map_page(dev, page, 0, PAGE_SIZE, dir);
|
addr[i] = dma_map_page(dev, page, 0, PAGE_SIZE, dir);
|
||||||
r = dma_mapping_error(dev, addr[i]);
|
r = dma_mapping_error(dev, addr[i]);
|
||||||
if (r) {
|
if (r) {
|
||||||
@ -175,8 +187,7 @@ svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap,
|
|||||||
}
|
}
|
||||||
adev = (struct amdgpu_device *)pdd->dev->kgd;
|
adev = (struct amdgpu_device *)pdd->dev->kgd;
|
||||||
|
|
||||||
r = svm_range_dma_map_dev(adev->dev, &prange->dma_addr[gpuidx],
|
r = svm_range_dma_map_dev(adev, prange, hmm_pfns, gpuidx);
|
||||||
hmm_pfns, prange->npages);
|
|
||||||
if (r)
|
if (r)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -301,14 +312,6 @@ static bool svm_bo_ref_unless_zero(struct svm_range_bo *svm_bo)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct svm_range_bo *svm_range_bo_ref(struct svm_range_bo *svm_bo)
|
|
||||||
{
|
|
||||||
if (svm_bo)
|
|
||||||
kref_get(&svm_bo->kref);
|
|
||||||
|
|
||||||
return svm_bo;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void svm_range_bo_release(struct kref *kref)
|
static void svm_range_bo_release(struct kref *kref)
|
||||||
{
|
{
|
||||||
struct svm_range_bo *svm_bo;
|
struct svm_range_bo *svm_bo;
|
||||||
@ -347,7 +350,7 @@ static void svm_range_bo_release(struct kref *kref)
|
|||||||
kfree(svm_bo);
|
kfree(svm_bo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void svm_range_bo_unref(struct svm_range_bo *svm_bo)
|
void svm_range_bo_unref(struct svm_range_bo *svm_bo)
|
||||||
{
|
{
|
||||||
if (!svm_bo)
|
if (!svm_bo)
|
||||||
return;
|
return;
|
||||||
@ -564,6 +567,24 @@ svm_range_get_adev_by_id(struct svm_range *prange, uint32_t gpu_id)
|
|||||||
return (struct amdgpu_device *)pdd->dev->kgd;
|
return (struct amdgpu_device *)pdd->dev->kgd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct kfd_process_device *
|
||||||
|
svm_range_get_pdd_by_adev(struct svm_range *prange, struct amdgpu_device *adev)
|
||||||
|
{
|
||||||
|
struct kfd_process *p;
|
||||||
|
int32_t gpu_idx, gpuid;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
p = container_of(prange->svms, struct kfd_process, svms);
|
||||||
|
|
||||||
|
r = kfd_process_gpuid_from_kgd(p, adev, &gpuid, &gpu_idx);
|
||||||
|
if (r) {
|
||||||
|
pr_debug("failed to get device id by adev %p\n", adev);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return kfd_process_device_from_gpuidx(p, gpu_idx);
|
||||||
|
}
|
||||||
|
|
||||||
static int svm_range_bo_validate(void *param, struct amdgpu_bo *bo)
|
static int svm_range_bo_validate(void *param, struct amdgpu_bo *bo)
|
||||||
{
|
{
|
||||||
struct ttm_operation_ctx ctx = { false, false };
|
struct ttm_operation_ctx ctx = { false, false };
|
||||||
@ -1002,21 +1023,22 @@ svm_range_split_by_granularity(struct kfd_process *p, struct mm_struct *mm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t
|
static uint64_t
|
||||||
svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange)
|
svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange,
|
||||||
|
int domain)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *bo_adev;
|
struct amdgpu_device *bo_adev;
|
||||||
uint32_t flags = prange->flags;
|
uint32_t flags = prange->flags;
|
||||||
uint32_t mapping_flags = 0;
|
uint32_t mapping_flags = 0;
|
||||||
uint64_t pte_flags;
|
uint64_t pte_flags;
|
||||||
bool snoop = !prange->ttm_res;
|
bool snoop = (domain != SVM_RANGE_VRAM_DOMAIN);
|
||||||
bool coherent = flags & KFD_IOCTL_SVM_FLAG_COHERENT;
|
bool coherent = flags & KFD_IOCTL_SVM_FLAG_COHERENT;
|
||||||
|
|
||||||
if (prange->svm_bo && prange->ttm_res)
|
if (domain == SVM_RANGE_VRAM_DOMAIN)
|
||||||
bo_adev = amdgpu_ttm_adev(prange->svm_bo->bo->tbo.bdev);
|
bo_adev = amdgpu_ttm_adev(prange->svm_bo->bo->tbo.bdev);
|
||||||
|
|
||||||
switch (adev->asic_type) {
|
switch (adev->asic_type) {
|
||||||
case CHIP_ARCTURUS:
|
case CHIP_ARCTURUS:
|
||||||
if (prange->svm_bo && prange->ttm_res) {
|
if (domain == SVM_RANGE_VRAM_DOMAIN) {
|
||||||
if (bo_adev == adev) {
|
if (bo_adev == adev) {
|
||||||
mapping_flags |= coherent ?
|
mapping_flags |= coherent ?
|
||||||
AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW;
|
AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW;
|
||||||
@ -1032,7 +1054,7 @@ svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CHIP_ALDEBARAN:
|
case CHIP_ALDEBARAN:
|
||||||
if (prange->svm_bo && prange->ttm_res) {
|
if (domain == SVM_RANGE_VRAM_DOMAIN) {
|
||||||
if (bo_adev == adev) {
|
if (bo_adev == adev) {
|
||||||
mapping_flags |= coherent ?
|
mapping_flags |= coherent ?
|
||||||
AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW;
|
AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW;
|
||||||
@ -1062,14 +1084,14 @@ svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange)
|
|||||||
mapping_flags |= AMDGPU_VM_PAGE_EXECUTABLE;
|
mapping_flags |= AMDGPU_VM_PAGE_EXECUTABLE;
|
||||||
|
|
||||||
pte_flags = AMDGPU_PTE_VALID;
|
pte_flags = AMDGPU_PTE_VALID;
|
||||||
pte_flags |= prange->ttm_res ? 0 : AMDGPU_PTE_SYSTEM;
|
pte_flags |= (domain == SVM_RANGE_VRAM_DOMAIN) ? 0 : AMDGPU_PTE_SYSTEM;
|
||||||
pte_flags |= snoop ? AMDGPU_PTE_SNOOPED : 0;
|
pte_flags |= snoop ? AMDGPU_PTE_SNOOPED : 0;
|
||||||
|
|
||||||
pte_flags |= amdgpu_gem_va_map_flags(adev, mapping_flags);
|
pte_flags |= amdgpu_gem_va_map_flags(adev, mapping_flags);
|
||||||
|
|
||||||
pr_debug("svms 0x%p [0x%lx 0x%lx] vram %d PTE 0x%llx mapping 0x%x\n",
|
pr_debug("svms 0x%p [0x%lx 0x%lx] vram %d PTE 0x%llx mapping 0x%x\n",
|
||||||
prange->svms, prange->start, prange->last,
|
prange->svms, prange->start, prange->last,
|
||||||
prange->ttm_res ? 1:0, pte_flags, mapping_flags);
|
(domain == SVM_RANGE_VRAM_DOMAIN) ? 1:0, pte_flags, mapping_flags);
|
||||||
|
|
||||||
return pte_flags;
|
return pte_flags;
|
||||||
}
|
}
|
||||||
@ -1140,31 +1162,41 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||||||
struct amdgpu_bo_va bo_va;
|
struct amdgpu_bo_va bo_va;
|
||||||
bool table_freed = false;
|
bool table_freed = false;
|
||||||
uint64_t pte_flags;
|
uint64_t pte_flags;
|
||||||
|
unsigned long last_start;
|
||||||
|
int last_domain;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
int64_t i;
|
||||||
|
|
||||||
pr_debug("svms 0x%p [0x%lx 0x%lx]\n", prange->svms, prange->start,
|
pr_debug("svms 0x%p [0x%lx 0x%lx]\n", prange->svms, prange->start,
|
||||||
prange->last);
|
prange->last);
|
||||||
|
|
||||||
if (prange->svm_bo && prange->ttm_res) {
|
if (prange->svm_bo && prange->ttm_res)
|
||||||
bo_va.is_xgmi = amdgpu_xgmi_same_hive(adev, bo_adev);
|
bo_va.is_xgmi = amdgpu_xgmi_same_hive(adev, bo_adev);
|
||||||
prange->mapping.bo_va = &bo_va;
|
|
||||||
}
|
|
||||||
|
|
||||||
prange->mapping.start = prange->start;
|
last_start = prange->start;
|
||||||
prange->mapping.last = prange->last;
|
for (i = 0; i < prange->npages; i++) {
|
||||||
prange->mapping.offset = prange->ttm_res ? prange->offset : 0;
|
last_domain = dma_addr[i] & SVM_RANGE_VRAM_DOMAIN;
|
||||||
pte_flags = svm_range_get_pte_flags(adev, prange);
|
dma_addr[i] &= ~SVM_RANGE_VRAM_DOMAIN;
|
||||||
|
if ((prange->start + i) < prange->last &&
|
||||||
|
last_domain == (dma_addr[i + 1] & SVM_RANGE_VRAM_DOMAIN))
|
||||||
|
continue;
|
||||||
|
|
||||||
r = amdgpu_vm_bo_update_mapping(adev, bo_adev, vm, false, false, NULL,
|
pr_debug("Mapping range [0x%lx 0x%llx] on domain: %s\n",
|
||||||
prange->mapping.start,
|
last_start, prange->start + i, last_domain ? "GPU" : "CPU");
|
||||||
prange->mapping.last, pte_flags,
|
pte_flags = svm_range_get_pte_flags(adev, prange, last_domain);
|
||||||
prange->mapping.offset,
|
r = amdgpu_vm_bo_update_mapping(adev, bo_adev, vm, false, false, NULL,
|
||||||
prange->ttm_res,
|
last_start,
|
||||||
dma_addr, &vm->last_update,
|
prange->start + i, pte_flags,
|
||||||
&table_freed);
|
last_start - prange->start,
|
||||||
if (r) {
|
NULL,
|
||||||
pr_debug("failed %d to map to gpu 0x%lx\n", r, prange->start);
|
dma_addr,
|
||||||
goto out;
|
&vm->last_update,
|
||||||
|
&table_freed);
|
||||||
|
if (r) {
|
||||||
|
pr_debug("failed %d to map to gpu 0x%lx\n", r, prange->start);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
last_start = prange->start + i + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = amdgpu_vm_update_pdes(adev, vm, false);
|
r = amdgpu_vm_update_pdes(adev, vm, false);
|
||||||
@ -1185,7 +1217,6 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||||||
p->pasid, TLB_FLUSH_LEGACY);
|
p->pasid, TLB_FLUSH_LEGACY);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
prange->mapping.bo_va = NULL;
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1319,6 +1350,17 @@ static void svm_range_unreserve_bos(struct svm_validate_context *ctx)
|
|||||||
ttm_eu_backoff_reservation(&ctx->ticket, &ctx->validate_list);
|
ttm_eu_backoff_reservation(&ctx->ticket, &ctx->validate_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *kfd_svm_page_owner(struct kfd_process *p, int32_t gpuidx)
|
||||||
|
{
|
||||||
|
struct kfd_process_device *pdd;
|
||||||
|
struct amdgpu_device *adev;
|
||||||
|
|
||||||
|
pdd = kfd_process_device_from_gpuidx(p, gpuidx);
|
||||||
|
adev = (struct amdgpu_device *)pdd->dev->kgd;
|
||||||
|
|
||||||
|
return SVM_ADEV_PGMAP_OWNER(adev);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Validation+GPU mapping with concurrent invalidation (MMU notifiers)
|
* Validation+GPU mapping with concurrent invalidation (MMU notifiers)
|
||||||
*
|
*
|
||||||
@ -1349,6 +1391,9 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
|
|||||||
{
|
{
|
||||||
struct svm_validate_context ctx;
|
struct svm_validate_context ctx;
|
||||||
struct hmm_range *hmm_range;
|
struct hmm_range *hmm_range;
|
||||||
|
struct kfd_process *p;
|
||||||
|
void *owner;
|
||||||
|
int32_t idx;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
ctx.process = container_of(prange->svms, struct kfd_process, svms);
|
ctx.process = container_of(prange->svms, struct kfd_process, svms);
|
||||||
@ -1394,33 +1439,38 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
|
|||||||
|
|
||||||
svm_range_reserve_bos(&ctx);
|
svm_range_reserve_bos(&ctx);
|
||||||
|
|
||||||
if (!prange->actual_loc) {
|
p = container_of(prange->svms, struct kfd_process, svms);
|
||||||
r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL,
|
owner = kfd_svm_page_owner(p, find_first_bit(ctx.bitmap,
|
||||||
prange->start << PAGE_SHIFT,
|
MAX_GPU_INSTANCE));
|
||||||
prange->npages, &hmm_range,
|
for_each_set_bit(idx, ctx.bitmap, MAX_GPU_INSTANCE) {
|
||||||
false, true);
|
if (kfd_svm_page_owner(p, idx) != owner) {
|
||||||
if (r) {
|
owner = NULL;
|
||||||
pr_debug("failed %d to get svm range pages\n", r);
|
break;
|
||||||
goto unreserve_out;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
r = svm_range_dma_map(prange, ctx.bitmap,
|
r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL,
|
||||||
hmm_range->hmm_pfns);
|
prange->start << PAGE_SHIFT,
|
||||||
if (r) {
|
prange->npages, &hmm_range,
|
||||||
pr_debug("failed %d to dma map range\n", r);
|
false, true, owner);
|
||||||
goto unreserve_out;
|
if (r) {
|
||||||
}
|
pr_debug("failed %d to get svm range pages\n", r);
|
||||||
|
goto unreserve_out;
|
||||||
prange->validated_once = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r = svm_range_dma_map(prange, ctx.bitmap,
|
||||||
|
hmm_range->hmm_pfns);
|
||||||
|
if (r) {
|
||||||
|
pr_debug("failed %d to dma map range\n", r);
|
||||||
|
goto unreserve_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
prange->validated_once = true;
|
||||||
|
|
||||||
svm_range_lock(prange);
|
svm_range_lock(prange);
|
||||||
if (!prange->actual_loc) {
|
if (amdgpu_hmm_range_get_pages_done(hmm_range)) {
|
||||||
if (amdgpu_hmm_range_get_pages_done(hmm_range)) {
|
pr_debug("hmm update the range, need validate again\n");
|
||||||
pr_debug("hmm update the range, need validate again\n");
|
r = -EAGAIN;
|
||||||
r = -EAGAIN;
|
goto unlock_out;
|
||||||
goto unlock_out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!list_empty(&prange->child_list)) {
|
if (!list_empty(&prange->child_list)) {
|
||||||
pr_debug("range split by unmap in parallel, validate again\n");
|
pr_debug("range split by unmap in parallel, validate again\n");
|
||||||
@ -1572,6 +1622,7 @@ svm_range_evict(struct svm_range *prange, struct mm_struct *mm,
|
|||||||
unsigned long start, unsigned long last)
|
unsigned long start, unsigned long last)
|
||||||
{
|
{
|
||||||
struct svm_range_list *svms = prange->svms;
|
struct svm_range_list *svms = prange->svms;
|
||||||
|
struct svm_range *pchild;
|
||||||
struct kfd_process *p;
|
struct kfd_process *p;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
@ -1583,7 +1634,19 @@ svm_range_evict(struct svm_range *prange, struct mm_struct *mm,
|
|||||||
if (!p->xnack_enabled) {
|
if (!p->xnack_enabled) {
|
||||||
int evicted_ranges;
|
int evicted_ranges;
|
||||||
|
|
||||||
atomic_inc(&prange->invalid);
|
list_for_each_entry(pchild, &prange->child_list, child_list) {
|
||||||
|
mutex_lock_nested(&pchild->lock, 1);
|
||||||
|
if (pchild->start <= last && pchild->last >= start) {
|
||||||
|
pr_debug("increment pchild invalid [0x%lx 0x%lx]\n",
|
||||||
|
pchild->start, pchild->last);
|
||||||
|
atomic_inc(&pchild->invalid);
|
||||||
|
}
|
||||||
|
mutex_unlock(&pchild->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prange->start <= last && prange->last >= start)
|
||||||
|
atomic_inc(&prange->invalid);
|
||||||
|
|
||||||
evicted_ranges = atomic_inc_return(&svms->evicted_ranges);
|
evicted_ranges = atomic_inc_return(&svms->evicted_ranges);
|
||||||
if (evicted_ranges != 1)
|
if (evicted_ranges != 1)
|
||||||
return r;
|
return r;
|
||||||
@ -1600,7 +1663,6 @@ svm_range_evict(struct svm_range *prange, struct mm_struct *mm,
|
|||||||
schedule_delayed_work(&svms->restore_work,
|
schedule_delayed_work(&svms->restore_work,
|
||||||
msecs_to_jiffies(AMDGPU_SVM_RANGE_RESTORE_DELAY_MS));
|
msecs_to_jiffies(AMDGPU_SVM_RANGE_RESTORE_DELAY_MS));
|
||||||
} else {
|
} else {
|
||||||
struct svm_range *pchild;
|
|
||||||
unsigned long s, l;
|
unsigned long s, l;
|
||||||
|
|
||||||
pr_debug("invalidate unmap svms 0x%p [0x%lx 0x%lx] from GPUs\n",
|
pr_debug("invalidate unmap svms 0x%p [0x%lx 0x%lx] from GPUs\n",
|
||||||
@ -2311,6 +2373,27 @@ static bool svm_range_skip_recover(struct svm_range *prange)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
svm_range_count_fault(struct amdgpu_device *adev, struct kfd_process *p,
|
||||||
|
struct svm_range *prange, int32_t gpuidx)
|
||||||
|
{
|
||||||
|
struct kfd_process_device *pdd;
|
||||||
|
|
||||||
|
if (gpuidx == MAX_GPU_INSTANCE)
|
||||||
|
/* fault is on different page of same range
|
||||||
|
* or fault is skipped to recover later
|
||||||
|
*/
|
||||||
|
pdd = svm_range_get_pdd_by_adev(prange, adev);
|
||||||
|
else
|
||||||
|
/* fault recovered
|
||||||
|
* or fault cannot recover because GPU no access on the range
|
||||||
|
*/
|
||||||
|
pdd = kfd_process_device_from_gpuidx(p, gpuidx);
|
||||||
|
|
||||||
|
if (pdd)
|
||||||
|
WRITE_ONCE(pdd->faults, pdd->faults + 1);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
|
svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
|
||||||
uint64_t addr)
|
uint64_t addr)
|
||||||
@ -2320,7 +2403,8 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
|
|||||||
struct svm_range *prange;
|
struct svm_range *prange;
|
||||||
struct kfd_process *p;
|
struct kfd_process *p;
|
||||||
uint64_t timestamp;
|
uint64_t timestamp;
|
||||||
int32_t best_loc, gpuidx;
|
int32_t best_loc;
|
||||||
|
int32_t gpuidx = MAX_GPU_INSTANCE;
|
||||||
bool write_locked = false;
|
bool write_locked = false;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
@ -2440,6 +2524,9 @@ out_unlock_range:
|
|||||||
out_unlock_svms:
|
out_unlock_svms:
|
||||||
mutex_unlock(&svms->lock);
|
mutex_unlock(&svms->lock);
|
||||||
mmap_read_unlock(mm);
|
mmap_read_unlock(mm);
|
||||||
|
|
||||||
|
svm_range_count_fault(adev, p, prange, gpuidx);
|
||||||
|
|
||||||
mmput(mm);
|
mmput(mm);
|
||||||
out:
|
out:
|
||||||
kfd_unref_process(p);
|
kfd_unref_process(p);
|
||||||
@ -2662,7 +2749,8 @@ out:
|
|||||||
/* FIXME: This is a workaround for page locking bug when some pages are
|
/* FIXME: This is a workaround for page locking bug when some pages are
|
||||||
* invalid during migration to VRAM
|
* invalid during migration to VRAM
|
||||||
*/
|
*/
|
||||||
void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm)
|
void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm,
|
||||||
|
void *owner)
|
||||||
{
|
{
|
||||||
struct hmm_range *hmm_range;
|
struct hmm_range *hmm_range;
|
||||||
int r;
|
int r;
|
||||||
@ -2673,7 +2761,7 @@ void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm)
|
|||||||
r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL,
|
r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL,
|
||||||
prange->start << PAGE_SHIFT,
|
prange->start << PAGE_SHIFT,
|
||||||
prange->npages, &hmm_range,
|
prange->npages, &hmm_range,
|
||||||
false, true);
|
false, true, owner);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
amdgpu_hmm_range_get_pages_done(hmm_range);
|
amdgpu_hmm_range_get_pages_done(hmm_range);
|
||||||
prange->validated_once = true;
|
prange->validated_once = true;
|
||||||
@ -2718,16 +2806,6 @@ svm_range_trigger_migration(struct mm_struct *mm, struct svm_range *prange,
|
|||||||
best_loc == prange->actual_loc)
|
best_loc == prange->actual_loc)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
|
||||||
* Prefetch to GPU without host access flag, set actual_loc to gpu, then
|
|
||||||
* validate on gpu and map to gpus will be handled afterwards.
|
|
||||||
*/
|
|
||||||
if (best_loc && !prange->actual_loc &&
|
|
||||||
!(prange->flags & KFD_IOCTL_SVM_FLAG_HOST_ACCESS)) {
|
|
||||||
prange->actual_loc = best_loc;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!best_loc) {
|
if (!best_loc) {
|
||||||
r = svm_migrate_vram_to_ram(prange, mm);
|
r = svm_migrate_vram_to_ram(prange, mm);
|
||||||
*migrated = !r;
|
*migrated = !r;
|
||||||
|
@ -35,6 +35,10 @@
|
|||||||
#include "amdgpu.h"
|
#include "amdgpu.h"
|
||||||
#include "kfd_priv.h"
|
#include "kfd_priv.h"
|
||||||
|
|
||||||
|
#define SVM_RANGE_VRAM_DOMAIN (1UL << 0)
|
||||||
|
#define SVM_ADEV_PGMAP_OWNER(adev)\
|
||||||
|
((adev)->hive ? (void *)(adev)->hive : (void *)(adev))
|
||||||
|
|
||||||
struct svm_range_bo {
|
struct svm_range_bo {
|
||||||
struct amdgpu_bo *bo;
|
struct amdgpu_bo *bo;
|
||||||
struct kref kref;
|
struct kref kref;
|
||||||
@ -110,7 +114,6 @@ struct svm_range {
|
|||||||
struct list_head update_list;
|
struct list_head update_list;
|
||||||
struct list_head remove_list;
|
struct list_head remove_list;
|
||||||
struct list_head insert_list;
|
struct list_head insert_list;
|
||||||
struct amdgpu_bo_va_mapping mapping;
|
|
||||||
uint64_t npages;
|
uint64_t npages;
|
||||||
dma_addr_t *dma_addr[MAX_GPU_INSTANCE];
|
dma_addr_t *dma_addr[MAX_GPU_INSTANCE];
|
||||||
struct ttm_resource *ttm_res;
|
struct ttm_resource *ttm_res;
|
||||||
@ -147,6 +150,14 @@ static inline void svm_range_unlock(struct svm_range *prange)
|
|||||||
mutex_unlock(&prange->lock);
|
mutex_unlock(&prange->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct svm_range_bo *svm_range_bo_ref(struct svm_range_bo *svm_bo)
|
||||||
|
{
|
||||||
|
if (svm_bo)
|
||||||
|
kref_get(&svm_bo->kref);
|
||||||
|
|
||||||
|
return svm_bo;
|
||||||
|
}
|
||||||
|
|
||||||
int svm_range_list_init(struct kfd_process *p);
|
int svm_range_list_init(struct kfd_process *p);
|
||||||
void svm_range_list_fini(struct kfd_process *p);
|
void svm_range_list_fini(struct kfd_process *p);
|
||||||
int svm_ioctl(struct kfd_process *p, enum kfd_ioctl_svm_op op, uint64_t start,
|
int svm_ioctl(struct kfd_process *p, enum kfd_ioctl_svm_op op, uint64_t start,
|
||||||
@ -173,13 +184,17 @@ void schedule_deferred_list_work(struct svm_range_list *svms);
|
|||||||
void svm_range_dma_unmap(struct device *dev, dma_addr_t *dma_addr,
|
void svm_range_dma_unmap(struct device *dev, dma_addr_t *dma_addr,
|
||||||
unsigned long offset, unsigned long npages);
|
unsigned long offset, unsigned long npages);
|
||||||
void svm_range_free_dma_mappings(struct svm_range *prange);
|
void svm_range_free_dma_mappings(struct svm_range *prange);
|
||||||
void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm);
|
void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm,
|
||||||
|
void *owner);
|
||||||
|
struct kfd_process_device *
|
||||||
|
svm_range_get_pdd_by_adev(struct svm_range *prange, struct amdgpu_device *adev);
|
||||||
|
|
||||||
/* SVM API and HMM page migration work together, device memory type
|
/* SVM API and HMM page migration work together, device memory type
|
||||||
* is initialized to not 0 when page migration register device memory.
|
* is initialized to not 0 when page migration register device memory.
|
||||||
*/
|
*/
|
||||||
#define KFD_IS_SVM_API_SUPPORTED(dev) ((dev)->pgmap.type != 0)
|
#define KFD_IS_SVM_API_SUPPORTED(dev) ((dev)->pgmap.type != 0)
|
||||||
|
|
||||||
|
void svm_range_bo_unref(struct svm_range_bo *svm_bo);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
struct kfd_process;
|
struct kfd_process;
|
||||||
|
@ -1160,6 +1160,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
|||||||
if (amdgpu_dc_feature_mask & DC_DISABLE_FRACTIONAL_PWM_MASK)
|
if (amdgpu_dc_feature_mask & DC_DISABLE_FRACTIONAL_PWM_MASK)
|
||||||
init_data.flags.disable_fractional_pwm = true;
|
init_data.flags.disable_fractional_pwm = true;
|
||||||
|
|
||||||
|
if (amdgpu_dc_feature_mask & DC_EDP_NO_POWER_SEQUENCING)
|
||||||
|
init_data.flags.edp_no_power_sequencing = true;
|
||||||
|
|
||||||
init_data.flags.power_down_display_on_boot = true;
|
init_data.flags.power_down_display_on_boot = true;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&adev->dm.da_list);
|
INIT_LIST_HEAD(&adev->dm.da_list);
|
||||||
@ -10118,7 +10121,7 @@ static int validate_overlay(struct drm_atomic_state *state)
|
|||||||
int i;
|
int i;
|
||||||
struct drm_plane *plane;
|
struct drm_plane *plane;
|
||||||
struct drm_plane_state *new_plane_state;
|
struct drm_plane_state *new_plane_state;
|
||||||
struct drm_plane_state *primary_state, *cursor_state, *overlay_state = NULL;
|
struct drm_plane_state *primary_state, *overlay_state = NULL;
|
||||||
|
|
||||||
/* Check if primary plane is contained inside overlay */
|
/* Check if primary plane is contained inside overlay */
|
||||||
for_each_new_plane_in_state_reverse(state, plane, new_plane_state, i) {
|
for_each_new_plane_in_state_reverse(state, plane, new_plane_state, i) {
|
||||||
@ -10148,14 +10151,6 @@ static int validate_overlay(struct drm_atomic_state *state)
|
|||||||
if (!primary_state->crtc)
|
if (!primary_state->crtc)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* check if cursor plane is enabled */
|
|
||||||
cursor_state = drm_atomic_get_plane_state(state, overlay_state->crtc->cursor);
|
|
||||||
if (IS_ERR(cursor_state))
|
|
||||||
return PTR_ERR(cursor_state);
|
|
||||||
|
|
||||||
if (drm_atomic_plane_disabling(plane->state, cursor_state))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Perform the bounds check to ensure the overlay plane covers the primary */
|
/* Perform the bounds check to ensure the overlay plane covers the primary */
|
||||||
if (primary_state->crtc_x < overlay_state->crtc_x ||
|
if (primary_state->crtc_x < overlay_state->crtc_x ||
|
||||||
primary_state->crtc_y < overlay_state->crtc_y ||
|
primary_state->crtc_y < overlay_state->crtc_y ||
|
||||||
|
@ -297,6 +297,7 @@ struct dc_config {
|
|||||||
bool allow_seamless_boot_optimization;
|
bool allow_seamless_boot_optimization;
|
||||||
bool power_down_display_on_boot;
|
bool power_down_display_on_boot;
|
||||||
bool edp_not_connected;
|
bool edp_not_connected;
|
||||||
|
bool edp_no_power_sequencing;
|
||||||
bool force_enum_edp;
|
bool force_enum_edp;
|
||||||
bool forced_clocks;
|
bool forced_clocks;
|
||||||
bool allow_lttpr_non_transparent_mode;
|
bool allow_lttpr_non_transparent_mode;
|
||||||
|
@ -1022,8 +1022,20 @@ void dce110_edp_backlight_control(
|
|||||||
/* dc_service_sleep_in_milliseconds(50); */
|
/* dc_service_sleep_in_milliseconds(50); */
|
||||||
/*edp 1.2*/
|
/*edp 1.2*/
|
||||||
panel_instance = link->panel_cntl->inst;
|
panel_instance = link->panel_cntl->inst;
|
||||||
if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON)
|
|
||||||
edp_receiver_ready_T7(link);
|
if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) {
|
||||||
|
if (!link->dc->config.edp_no_power_sequencing)
|
||||||
|
/*
|
||||||
|
* Sometimes, DP receiver chip power-controlled externally by an
|
||||||
|
* Embedded Controller could be treated and used as eDP,
|
||||||
|
* if it drives mobile display. In this case,
|
||||||
|
* we shouldn't be doing power-sequencing, hence we can skip
|
||||||
|
* waiting for T7-ready.
|
||||||
|
*/
|
||||||
|
edp_receiver_ready_T7(link);
|
||||||
|
else
|
||||||
|
DC_LOG_DC("edp_receiver_ready_T7 skipped\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->dc->ctx->dmub_srv &&
|
if (ctx->dc->ctx->dmub_srv &&
|
||||||
ctx->dc->debug.dmub_command_table) {
|
ctx->dc->debug.dmub_command_table) {
|
||||||
@ -1048,8 +1060,19 @@ void dce110_edp_backlight_control(
|
|||||||
dc_link_backlight_enable_aux(link, enable);
|
dc_link_backlight_enable_aux(link, enable);
|
||||||
|
|
||||||
/*edp 1.2*/
|
/*edp 1.2*/
|
||||||
if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF)
|
if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF) {
|
||||||
edp_add_delay_for_T9(link);
|
if (!link->dc->config.edp_no_power_sequencing)
|
||||||
|
/*
|
||||||
|
* Sometimes, DP receiver chip power-controlled externally by an
|
||||||
|
* Embedded Controller could be treated and used as eDP,
|
||||||
|
* if it drives mobile display. In this case,
|
||||||
|
* we shouldn't be doing power-sequencing, hence we can skip
|
||||||
|
* waiting for T9-ready.
|
||||||
|
*/
|
||||||
|
edp_add_delay_for_T9(link);
|
||||||
|
else
|
||||||
|
DC_LOG_DC("edp_receiver_ready_T9 skipped\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (!enable && link->dpcd_sink_ext_caps.bits.oled)
|
if (!enable && link->dpcd_sink_ext_caps.bits.oled)
|
||||||
msleep(OLED_PRE_T11_DELAY);
|
msleep(OLED_PRE_T11_DELAY);
|
||||||
|
@ -28,6 +28,7 @@ endif
|
|||||||
CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o += -mhard-float
|
CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o += -mhard-float
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_X86
|
||||||
ifdef IS_OLD_GCC
|
ifdef IS_OLD_GCC
|
||||||
# Stack alignment mismatch, proceed with caution.
|
# Stack alignment mismatch, proceed with caution.
|
||||||
# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
|
# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
|
||||||
@ -36,6 +37,7 @@ CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o += -mpreferred-stack-boundary=4
|
|||||||
else
|
else
|
||||||
CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o += -msse2
|
CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o += -msse2
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
AMD_DAL_DCN31 = $(addprefix $(AMDDALPATH)/dc/dcn31/,$(DCN31))
|
AMD_DAL_DCN31 = $(addprefix $(AMDDALPATH)/dc/dcn31/,$(DCN31))
|
||||||
|
|
||||||
|
@ -50,6 +50,10 @@ dml_ccflags += -msse2
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq ($(CONFIG_FRAME_WARN),0)
|
||||||
|
frame_warn_flag := -Wframe-larger-than=2048
|
||||||
|
endif
|
||||||
|
|
||||||
CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
|
CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
|
||||||
|
|
||||||
ifdef CONFIG_DRM_AMD_DC_DCN
|
ifdef CONFIG_DRM_AMD_DC_DCN
|
||||||
@ -60,9 +64,9 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_ccflags)
|
|||||||
CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20v2.o := $(dml_ccflags)
|
CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20v2.o := $(dml_ccflags)
|
||||||
CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_mode_vba_21.o := $(dml_ccflags)
|
CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_mode_vba_21.o := $(dml_ccflags)
|
||||||
CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_rq_dlg_calc_21.o := $(dml_ccflags)
|
CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_rq_dlg_calc_21.o := $(dml_ccflags)
|
||||||
CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) -Wframe-larger-than=2048
|
CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) $(frame_warn_flag)
|
||||||
CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags)
|
CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags)
|
||||||
CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) -Wframe-larger-than=2048
|
CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) $(frame_warn_flag)
|
||||||
CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags)
|
CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags)
|
||||||
CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
|
CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
|
||||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_rcflags)
|
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_rcflags)
|
||||||
|
@ -119,7 +119,7 @@ bool dal_irq_service_set(
|
|||||||
|
|
||||||
dal_irq_service_ack(irq_service, source);
|
dal_irq_service_ack(irq_service, source);
|
||||||
|
|
||||||
if (info->funcs->set)
|
if (info->funcs && info->funcs->set)
|
||||||
return info->funcs->set(irq_service, info, enable);
|
return info->funcs->set(irq_service, info, enable);
|
||||||
|
|
||||||
dal_irq_service_set_generic(irq_service, info, enable);
|
dal_irq_service_set_generic(irq_service, info, enable);
|
||||||
@ -153,7 +153,7 @@ bool dal_irq_service_ack(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->funcs->ack)
|
if (info->funcs && info->funcs->ack)
|
||||||
return info->funcs->ack(irq_service, info);
|
return info->funcs->ack(irq_service, info);
|
||||||
|
|
||||||
dal_irq_service_ack_generic(irq_service, info);
|
dal_irq_service_ack_generic(irq_service, info);
|
||||||
|
@ -165,7 +165,7 @@ enum irq_type
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define DAL_VALID_IRQ_SRC_NUM(src) \
|
#define DAL_VALID_IRQ_SRC_NUM(src) \
|
||||||
((src) <= DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID)
|
((src) < DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID)
|
||||||
|
|
||||||
/* Number of Page Flip IRQ Sources. */
|
/* Number of Page Flip IRQ Sources. */
|
||||||
#define DAL_PFLIP_IRQ_SRC_NUM \
|
#define DAL_PFLIP_IRQ_SRC_NUM \
|
||||||
|
@ -352,3 +352,63 @@ uint32_t dmub_dcn31_get_current_time(struct dmub_srv *dmub)
|
|||||||
{
|
{
|
||||||
return REG_READ(DMCUB_TIMER_CURRENT);
|
return REG_READ(DMCUB_TIMER_CURRENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data)
|
||||||
|
{
|
||||||
|
uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset;
|
||||||
|
uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled;
|
||||||
|
|
||||||
|
if (!dmub || !diag_data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memset(diag_data, 0, sizeof(*diag_data));
|
||||||
|
|
||||||
|
diag_data->dmcub_version = dmub->fw_version;
|
||||||
|
|
||||||
|
diag_data->scratch[0] = REG_READ(DMCUB_SCRATCH0);
|
||||||
|
diag_data->scratch[1] = REG_READ(DMCUB_SCRATCH1);
|
||||||
|
diag_data->scratch[2] = REG_READ(DMCUB_SCRATCH2);
|
||||||
|
diag_data->scratch[3] = REG_READ(DMCUB_SCRATCH3);
|
||||||
|
diag_data->scratch[4] = REG_READ(DMCUB_SCRATCH4);
|
||||||
|
diag_data->scratch[5] = REG_READ(DMCUB_SCRATCH5);
|
||||||
|
diag_data->scratch[6] = REG_READ(DMCUB_SCRATCH6);
|
||||||
|
diag_data->scratch[7] = REG_READ(DMCUB_SCRATCH7);
|
||||||
|
diag_data->scratch[8] = REG_READ(DMCUB_SCRATCH8);
|
||||||
|
diag_data->scratch[9] = REG_READ(DMCUB_SCRATCH9);
|
||||||
|
diag_data->scratch[10] = REG_READ(DMCUB_SCRATCH10);
|
||||||
|
diag_data->scratch[11] = REG_READ(DMCUB_SCRATCH11);
|
||||||
|
diag_data->scratch[12] = REG_READ(DMCUB_SCRATCH12);
|
||||||
|
diag_data->scratch[13] = REG_READ(DMCUB_SCRATCH13);
|
||||||
|
diag_data->scratch[14] = REG_READ(DMCUB_SCRATCH14);
|
||||||
|
diag_data->scratch[15] = REG_READ(DMCUB_SCRATCH15);
|
||||||
|
|
||||||
|
diag_data->undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR);
|
||||||
|
diag_data->inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR);
|
||||||
|
diag_data->data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR);
|
||||||
|
|
||||||
|
diag_data->inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR);
|
||||||
|
diag_data->inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR);
|
||||||
|
diag_data->inbox1_size = REG_READ(DMCUB_INBOX1_SIZE);
|
||||||
|
|
||||||
|
diag_data->inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR);
|
||||||
|
diag_data->inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR);
|
||||||
|
diag_data->inbox0_size = REG_READ(DMCUB_INBOX0_SIZE);
|
||||||
|
|
||||||
|
REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
|
||||||
|
diag_data->is_dmcub_enabled = is_dmub_enabled;
|
||||||
|
|
||||||
|
REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset);
|
||||||
|
diag_data->is_dmcub_soft_reset = is_soft_reset;
|
||||||
|
|
||||||
|
REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset);
|
||||||
|
diag_data->is_dmcub_secure_reset = is_sec_reset;
|
||||||
|
|
||||||
|
REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
|
||||||
|
diag_data->is_traceport_en = is_traceport_enabled;
|
||||||
|
|
||||||
|
REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled);
|
||||||
|
diag_data->is_cw0_enabled = is_cw0_enabled;
|
||||||
|
|
||||||
|
REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
|
||||||
|
diag_data->is_cw6_enabled = is_cw6_enabled;
|
||||||
|
}
|
||||||
|
@ -36,6 +36,9 @@ struct dmub_srv;
|
|||||||
DMUB_SR(DMCUB_CNTL) \
|
DMUB_SR(DMCUB_CNTL) \
|
||||||
DMUB_SR(DMCUB_CNTL2) \
|
DMUB_SR(DMCUB_CNTL2) \
|
||||||
DMUB_SR(DMCUB_SEC_CNTL) \
|
DMUB_SR(DMCUB_SEC_CNTL) \
|
||||||
|
DMUB_SR(DMCUB_INBOX0_SIZE) \
|
||||||
|
DMUB_SR(DMCUB_INBOX0_RPTR) \
|
||||||
|
DMUB_SR(DMCUB_INBOX0_WPTR) \
|
||||||
DMUB_SR(DMCUB_INBOX1_BASE_ADDRESS) \
|
DMUB_SR(DMCUB_INBOX1_BASE_ADDRESS) \
|
||||||
DMUB_SR(DMCUB_INBOX1_SIZE) \
|
DMUB_SR(DMCUB_INBOX1_SIZE) \
|
||||||
DMUB_SR(DMCUB_INBOX1_RPTR) \
|
DMUB_SR(DMCUB_INBOX1_RPTR) \
|
||||||
@ -103,11 +106,15 @@ struct dmub_srv;
|
|||||||
DMUB_SR(DMCUB_SCRATCH14) \
|
DMUB_SR(DMCUB_SCRATCH14) \
|
||||||
DMUB_SR(DMCUB_SCRATCH15) \
|
DMUB_SR(DMCUB_SCRATCH15) \
|
||||||
DMUB_SR(DMCUB_GPINT_DATAIN1) \
|
DMUB_SR(DMCUB_GPINT_DATAIN1) \
|
||||||
|
DMUB_SR(DMCUB_GPINT_DATAOUT) \
|
||||||
DMUB_SR(CC_DC_PIPE_DIS) \
|
DMUB_SR(CC_DC_PIPE_DIS) \
|
||||||
DMUB_SR(MMHUBBUB_SOFT_RESET) \
|
DMUB_SR(MMHUBBUB_SOFT_RESET) \
|
||||||
DMUB_SR(DCN_VM_FB_LOCATION_BASE) \
|
DMUB_SR(DCN_VM_FB_LOCATION_BASE) \
|
||||||
DMUB_SR(DCN_VM_FB_OFFSET) \
|
DMUB_SR(DCN_VM_FB_OFFSET) \
|
||||||
DMUB_SR(DMCUB_TIMER_CURRENT)
|
DMUB_SR(DMCUB_TIMER_CURRENT) \
|
||||||
|
DMUB_SR(DMCUB_INST_FETCH_FAULT_ADDR) \
|
||||||
|
DMUB_SR(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR) \
|
||||||
|
DMUB_SR(DMCUB_DATA_WRITE_FAULT_ADDR)
|
||||||
|
|
||||||
#define DMUB_DCN31_FIELDS() \
|
#define DMUB_DCN31_FIELDS() \
|
||||||
DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \
|
DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \
|
||||||
@ -115,6 +122,7 @@ struct dmub_srv;
|
|||||||
DMUB_SF(DMCUB_CNTL2, DMCUB_SOFT_RESET) \
|
DMUB_SF(DMCUB_CNTL2, DMCUB_SOFT_RESET) \
|
||||||
DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET) \
|
DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET) \
|
||||||
DMUB_SF(DMCUB_SEC_CNTL, DMCUB_MEM_UNIT_ID) \
|
DMUB_SF(DMCUB_SEC_CNTL, DMCUB_MEM_UNIT_ID) \
|
||||||
|
DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS) \
|
||||||
DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_TOP_ADDRESS) \
|
DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_TOP_ADDRESS) \
|
||||||
DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE) \
|
DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE) \
|
||||||
DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_TOP_ADDRESS) \
|
DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_TOP_ADDRESS) \
|
||||||
@ -138,11 +146,13 @@ struct dmub_srv;
|
|||||||
DMUB_SF(CC_DC_PIPE_DIS, DC_DMCUB_ENABLE) \
|
DMUB_SF(CC_DC_PIPE_DIS, DC_DMCUB_ENABLE) \
|
||||||
DMUB_SF(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET) \
|
DMUB_SF(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET) \
|
||||||
DMUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE) \
|
DMUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE) \
|
||||||
DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET)
|
DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET) \
|
||||||
|
DMUB_SF(DMCUB_INBOX0_WPTR, DMCUB_INBOX0_WPTR)
|
||||||
|
|
||||||
struct dmub_srv_dcn31_reg_offset {
|
struct dmub_srv_dcn31_reg_offset {
|
||||||
#define DMUB_SR(reg) uint32_t reg;
|
#define DMUB_SR(reg) uint32_t reg;
|
||||||
DMUB_DCN31_REGS()
|
DMUB_DCN31_REGS()
|
||||||
|
DMCUB_INTERNAL_REGS()
|
||||||
#undef DMUB_SR
|
#undef DMUB_SR
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -227,4 +237,6 @@ void dmub_dcn31_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset);
|
|||||||
|
|
||||||
uint32_t dmub_dcn31_get_current_time(struct dmub_srv *dmub);
|
uint32_t dmub_dcn31_get_current_time(struct dmub_srv *dmub);
|
||||||
|
|
||||||
|
void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data);
|
||||||
|
|
||||||
#endif /* _DMUB_DCN31_H_ */
|
#endif /* _DMUB_DCN31_H_ */
|
||||||
|
@ -208,6 +208,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DMUB_ASIC_DCN31:
|
case DMUB_ASIC_DCN31:
|
||||||
|
dmub->regs_dcn31 = &dmub_srv_dcn31_regs;
|
||||||
funcs->reset = dmub_dcn31_reset;
|
funcs->reset = dmub_dcn31_reset;
|
||||||
funcs->reset_release = dmub_dcn31_reset_release;
|
funcs->reset_release = dmub_dcn31_reset_release;
|
||||||
funcs->backdoor_load = dmub_dcn31_backdoor_load;
|
funcs->backdoor_load = dmub_dcn31_backdoor_load;
|
||||||
@ -231,9 +232,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
|
|||||||
funcs->get_outbox0_wptr = dmub_dcn31_get_outbox0_wptr;
|
funcs->get_outbox0_wptr = dmub_dcn31_get_outbox0_wptr;
|
||||||
funcs->set_outbox0_rptr = dmub_dcn31_set_outbox0_rptr;
|
funcs->set_outbox0_rptr = dmub_dcn31_set_outbox0_rptr;
|
||||||
|
|
||||||
if (asic == DMUB_ASIC_DCN31) {
|
funcs->get_diagnostic_data = dmub_dcn31_get_diagnostic_data;
|
||||||
dmub->regs_dcn31 = &dmub_srv_dcn31_regs;
|
|
||||||
}
|
|
||||||
|
|
||||||
funcs->get_current_time = dmub_dcn31_get_current_time;
|
funcs->get_current_time = dmub_dcn31_get_current_time;
|
||||||
|
|
||||||
|
@ -223,10 +223,12 @@ enum amd_harvest_ip_mask {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum DC_FEATURE_MASK {
|
enum DC_FEATURE_MASK {
|
||||||
DC_FBC_MASK = 0x1,
|
//Default value can be found at "uint amdgpu_dc_feature_mask"
|
||||||
DC_MULTI_MON_PP_MCLK_SWITCH_MASK = 0x2,
|
DC_FBC_MASK = (1 << 0), //0x1, disabled by default
|
||||||
DC_DISABLE_FRACTIONAL_PWM_MASK = 0x4,
|
DC_MULTI_MON_PP_MCLK_SWITCH_MASK = (1 << 1), //0x2, enabled by default
|
||||||
DC_PSR_MASK = 0x8,
|
DC_DISABLE_FRACTIONAL_PWM_MASK = (1 << 2), //0x4, disabled by default
|
||||||
|
DC_PSR_MASK = (1 << 3), //0x8, disabled by default
|
||||||
|
DC_EDP_NO_POWER_SEQUENCING = (1 << 4), //0x10, disabled by default
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DC_DEBUG_MASK {
|
enum DC_DEBUG_MASK {
|
||||||
|
@ -430,7 +430,7 @@ ARRAY_2D_DEPTH = 0x00000001,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
typedef enum ENUM_NUM_SIMD_PER_CU {
|
typedef enum ENUM_NUM_SIMD_PER_CU {
|
||||||
NUM_SIMD_PER_CU = 0x00000004,
|
NUM_SIMD_PER_CU = 0x00000002,
|
||||||
} ENUM_NUM_SIMD_PER_CU;
|
} ENUM_NUM_SIMD_PER_CU;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2902,14 +2902,15 @@ static ssize_t amdgpu_hwmon_show_power_cap_min(struct device *dev,
|
|||||||
return sprintf(buf, "%i\n", 0);
|
return sprintf(buf, "%i\n", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev,
|
|
||||||
struct device_attribute *attr,
|
static ssize_t amdgpu_hwmon_show_power_cap_generic(struct device *dev,
|
||||||
char *buf)
|
struct device_attribute *attr,
|
||||||
|
char *buf,
|
||||||
|
enum pp_power_limit_level pp_limit_level)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = dev_get_drvdata(dev);
|
struct amdgpu_device *adev = dev_get_drvdata(dev);
|
||||||
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
||||||
enum pp_power_type power_type = to_sensor_dev_attr(attr)->index;
|
enum pp_power_type power_type = to_sensor_dev_attr(attr)->index;
|
||||||
enum pp_power_limit_level pp_limit_level = PP_PWR_LIMIT_MAX;
|
|
||||||
uint32_t limit;
|
uint32_t limit;
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
int r;
|
int r;
|
||||||
@ -2919,17 +2920,17 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev,
|
|||||||
if (adev->in_suspend && !adev->in_runpm)
|
if (adev->in_suspend && !adev->in_runpm)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
|
if ( !(pp_funcs && pp_funcs->get_power_limit))
|
||||||
|
return -ENODATA;
|
||||||
|
|
||||||
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
|
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
|
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pp_funcs && pp_funcs->get_power_limit)
|
r = pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit,
|
||||||
r = pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit,
|
pp_limit_level, power_type);
|
||||||
pp_limit_level, power_type);
|
|
||||||
else
|
|
||||||
r = -ENODATA;
|
|
||||||
|
|
||||||
if (!r)
|
if (!r)
|
||||||
size = sysfs_emit(buf, "%u\n", limit * 1000000);
|
size = sysfs_emit(buf, "%u\n", limit * 1000000);
|
||||||
@ -2942,85 +2943,31 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev,
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
return amdgpu_hwmon_show_power_cap_generic(dev, attr, buf, PP_PWR_LIMIT_MAX);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev,
|
static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev,
|
||||||
struct device_attribute *attr,
|
struct device_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = dev_get_drvdata(dev);
|
return amdgpu_hwmon_show_power_cap_generic(dev, attr, buf, PP_PWR_LIMIT_CURRENT);
|
||||||
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
|
||||||
enum pp_power_type power_type = to_sensor_dev_attr(attr)->index;
|
|
||||||
enum pp_power_limit_level pp_limit_level = PP_PWR_LIMIT_CURRENT;
|
|
||||||
uint32_t limit;
|
|
||||||
ssize_t size;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (amdgpu_in_reset(adev))
|
|
||||||
return -EPERM;
|
|
||||||
if (adev->in_suspend && !adev->in_runpm)
|
|
||||||
return -EPERM;
|
|
||||||
|
|
||||||
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
|
|
||||||
if (r < 0) {
|
|
||||||
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pp_funcs && pp_funcs->get_power_limit)
|
|
||||||
r = pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit,
|
|
||||||
pp_limit_level, power_type);
|
|
||||||
else
|
|
||||||
r = -ENODATA;
|
|
||||||
|
|
||||||
if (!r)
|
|
||||||
size = sysfs_emit(buf, "%u\n", limit * 1000000);
|
|
||||||
else
|
|
||||||
size = sysfs_emit(buf, "\n");
|
|
||||||
|
|
||||||
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
|
|
||||||
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t amdgpu_hwmon_show_power_cap_default(struct device *dev,
|
static ssize_t amdgpu_hwmon_show_power_cap_default(struct device *dev,
|
||||||
struct device_attribute *attr,
|
struct device_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = dev_get_drvdata(dev);
|
return amdgpu_hwmon_show_power_cap_generic(dev, attr, buf, PP_PWR_LIMIT_DEFAULT);
|
||||||
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
|
||||||
enum pp_power_type power_type = to_sensor_dev_attr(attr)->index;
|
|
||||||
enum pp_power_limit_level pp_limit_level = PP_PWR_LIMIT_DEFAULT;
|
|
||||||
uint32_t limit;
|
|
||||||
ssize_t size;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (amdgpu_in_reset(adev))
|
|
||||||
return -EPERM;
|
|
||||||
if (adev->in_suspend && !adev->in_runpm)
|
|
||||||
return -EPERM;
|
|
||||||
|
|
||||||
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
|
|
||||||
if (r < 0) {
|
|
||||||
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pp_funcs && pp_funcs->get_power_limit)
|
|
||||||
r = pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit,
|
|
||||||
pp_limit_level, power_type);
|
|
||||||
else
|
|
||||||
r = -ENODATA;
|
|
||||||
|
|
||||||
if (!r)
|
|
||||||
size = sysfs_emit(buf, "%u\n", limit * 1000000);
|
|
||||||
else
|
|
||||||
size = sysfs_emit(buf, "\n");
|
|
||||||
|
|
||||||
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
|
|
||||||
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t amdgpu_hwmon_show_power_label(struct device *dev,
|
static ssize_t amdgpu_hwmon_show_power_label(struct device *dev,
|
||||||
struct device_attribute *attr,
|
struct device_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
|
@ -1453,10 +1453,14 @@ static int smu_hw_fini(void *handle)
|
|||||||
|
|
||||||
if (smu->is_apu) {
|
if (smu->is_apu) {
|
||||||
smu_powergate_sdma(&adev->smu, true);
|
smu_powergate_sdma(&adev->smu, true);
|
||||||
smu_dpm_set_vcn_enable(smu, false);
|
|
||||||
smu_dpm_set_jpeg_enable(smu, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
smu_dpm_set_vcn_enable(smu, false);
|
||||||
|
smu_dpm_set_jpeg_enable(smu, false);
|
||||||
|
|
||||||
|
adev->vcn.cur_state = AMD_PG_STATE_GATE;
|
||||||
|
adev->jpeg.cur_state = AMD_PG_STATE_GATE;
|
||||||
|
|
||||||
if (!smu->pm_enabled)
|
if (!smu->pm_enabled)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -189,10 +189,11 @@ err0_out:
|
|||||||
static int yellow_carp_system_features_control(struct smu_context *smu, bool en)
|
static int yellow_carp_system_features_control(struct smu_context *smu, bool en)
|
||||||
{
|
{
|
||||||
struct smu_feature *feature = &smu->smu_feature;
|
struct smu_feature *feature = &smu->smu_feature;
|
||||||
|
struct amdgpu_device *adev = smu->adev;
|
||||||
uint32_t feature_mask[2];
|
uint32_t feature_mask[2];
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!en)
|
if (!en && !adev->in_s0ix)
|
||||||
ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL);
|
ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL);
|
||||||
|
|
||||||
bitmap_zero(feature->enabled, feature->feature_num);
|
bitmap_zero(feature->enabled, feature->feature_num);
|
||||||
|
@ -1325,6 +1325,7 @@ radeon_user_framebuffer_create(struct drm_device *dev,
|
|||||||
/* Handle is imported dma-buf, so cannot be migrated to VRAM for scanout */
|
/* Handle is imported dma-buf, so cannot be migrated to VRAM for scanout */
|
||||||
if (obj->import_attach) {
|
if (obj->import_attach) {
|
||||||
DRM_DEBUG_KMS("Cannot create framebuffer from imported dma_buf\n");
|
DRM_DEBUG_KMS("Cannot create framebuffer from imported dma_buf\n");
|
||||||
|
drm_gem_object_put(obj);
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,13 +374,13 @@ radeon_pci_shutdown(struct pci_dev *pdev)
|
|||||||
if (radeon_device_is_virtual())
|
if (radeon_device_is_virtual())
|
||||||
radeon_pci_remove(pdev);
|
radeon_pci_remove(pdev);
|
||||||
|
|
||||||
#ifdef CONFIG_PPC64
|
#if defined(CONFIG_PPC64) || defined(CONFIG_MACH_LOONGSON64)
|
||||||
/*
|
/*
|
||||||
* Some adapters need to be suspended before a
|
* Some adapters need to be suspended before a
|
||||||
* shutdown occurs in order to prevent an error
|
* shutdown occurs in order to prevent an error
|
||||||
* during kexec.
|
* during kexec, shutdown or reboot.
|
||||||
* Make this power specific becauase it breaks
|
* Make this power and Loongson specific because
|
||||||
* some non-power boards.
|
* it breaks some other boards.
|
||||||
*/
|
*/
|
||||||
radeon_suspend_kms(pci_get_drvdata(pdev), true, true, false);
|
radeon_suspend_kms(pci_get_drvdata(pdev), true, true, false);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user