Merge tag 'drm-next-5.3-2019-06-25' of git://people.freedesktop.org/~agd5f/linux into drm-next
drm-next-5.3-2019-06-25: Merge drm-next amdgpu: - SR-IOV L1 policy fixes - Removed no longer needed vram_page_split module parameter - Add module parameter to override default ABM level - Gamma fixes - No need to check return values for debugfs - Improve HMM error handling - Avoid possible OOM situations when lots of thread are submitting with memory contention - Improve hw i2c access abritration - DSC (Display Stream Compression) support in DC - Initial navi10 support * DC support * GFX/Compute support * SDMA support * Power Management support * VCN support - Static checker fixes - Misc cleanups - fix long udelay on arm amdkfd: - Implement priority controls for gfx9 - Enable VEGAM - Rework mqd allocation and init - Circular locking fix - Fix SDMA queue allocation race condition - No need to check return values for debugfs - Add proc style process information - Initial navi10 support radeon: - No need to check return values for debugfs UAPI changes: - GDDR6 added to vram type query - New Navi10 details added gpu info query - Navi family added to asic family query Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexdeucher@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20190625195520.3817-1-alexander.deucher@amd.com
This commit is contained in:
commit
14808a12bd
|
@ -54,7 +54,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
|
|||
amdgpu_gtt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o amdgpu_atomfirmware.o \
|
||||
amdgpu_vf_error.o amdgpu_sched.o amdgpu_debugfs.o amdgpu_ids.o \
|
||||
amdgpu_gmc.o amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \
|
||||
amdgpu_vm_sdma.o
|
||||
amdgpu_vm_sdma.o amdgpu_pmu.o amdgpu_discovery.o
|
||||
|
||||
# add asic specific block
|
||||
amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \
|
||||
|
@ -64,7 +64,7 @@ amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce
|
|||
|
||||
amdgpu-y += \
|
||||
vi.o mxgpu_vi.o nbio_v6_1.o soc15.o emu_soc.o mxgpu_ai.o nbio_v7_0.o vega10_reg_init.o \
|
||||
vega20_reg_init.o nbio_v7_4.o
|
||||
vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o navi10_reg_init.o
|
||||
|
||||
# add DF block
|
||||
amdgpu-y += \
|
||||
|
@ -75,7 +75,8 @@ amdgpu-y += \
|
|||
amdgpu-y += \
|
||||
gmc_v7_0.o \
|
||||
gmc_v8_0.o \
|
||||
gfxhub_v1_0.o mmhub_v1_0.o gmc_v9_0.o gfxhub_v1_1.o
|
||||
gfxhub_v1_0.o mmhub_v1_0.o gmc_v9_0.o gfxhub_v1_1.o \
|
||||
gfxhub_v2_0.o mmhub_v2_0.o gmc_v10_0.o
|
||||
|
||||
# add IH block
|
||||
amdgpu-y += \
|
||||
|
@ -84,7 +85,8 @@ amdgpu-y += \
|
|||
iceland_ih.o \
|
||||
tonga_ih.o \
|
||||
cz_ih.o \
|
||||
vega10_ih.o
|
||||
vega10_ih.o \
|
||||
navi10_ih.o
|
||||
|
||||
# add PSP block
|
||||
amdgpu-y += \
|
||||
|
@ -108,14 +110,20 @@ amdgpu-y += \
|
|||
amdgpu_gfx.o \
|
||||
amdgpu_rlc.o \
|
||||
gfx_v8_0.o \
|
||||
gfx_v9_0.o
|
||||
gfx_v9_0.o \
|
||||
gfx_v10_0.o
|
||||
|
||||
# add async DMA block
|
||||
amdgpu-y += \
|
||||
amdgpu_sdma.o \
|
||||
sdma_v2_4.o \
|
||||
sdma_v3_0.o \
|
||||
sdma_v4_0.o
|
||||
sdma_v4_0.o \
|
||||
sdma_v5_0.o
|
||||
|
||||
# add MES block
|
||||
amdgpu-y += \
|
||||
mes_v10_1.o
|
||||
|
||||
# add UVD block
|
||||
amdgpu-y += \
|
||||
|
@ -133,7 +141,12 @@ amdgpu-y += \
|
|||
# add VCN block
|
||||
amdgpu-y += \
|
||||
amdgpu_vcn.o \
|
||||
vcn_v1_0.o
|
||||
vcn_v1_0.o \
|
||||
vcn_v2_0.o
|
||||
|
||||
# add ATHUB block
|
||||
amdgpu-y += \
|
||||
athub_v2_0.o
|
||||
|
||||
# add amdkfd interfaces
|
||||
amdgpu-y += amdgpu_amdkfd.o
|
||||
|
@ -146,7 +159,8 @@ amdgpu-y += \
|
|||
amdgpu_amdkfd_fence.o \
|
||||
amdgpu_amdkfd_gpuvm.o \
|
||||
amdgpu_amdkfd_gfx_v8.o \
|
||||
amdgpu_amdkfd_gfx_v9.o
|
||||
amdgpu_amdkfd_gfx_v9.o \
|
||||
amdgpu_amdkfd_gfx_v10.o
|
||||
|
||||
ifneq ($(CONFIG_DRM_AMDGPU_CIK),)
|
||||
amdgpu-y += amdgpu_amdkfd_gfx_v7.o
|
||||
|
|
|
@ -84,6 +84,8 @@
|
|||
#include "amdgpu_doorbell.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_smu.h"
|
||||
#include "amdgpu_discovery.h"
|
||||
#include "amdgpu_mes.h"
|
||||
|
||||
#define MAX_GPU_INSTANCE 16
|
||||
|
||||
|
@ -142,7 +144,6 @@ extern uint amdgpu_sdma_phase_quantum;
|
|||
extern char *amdgpu_disable_cu;
|
||||
extern char *amdgpu_virtual_display;
|
||||
extern uint amdgpu_pp_feature_mask;
|
||||
extern int amdgpu_vram_page_split;
|
||||
extern int amdgpu_ngg;
|
||||
extern int amdgpu_prim_buf_per_se;
|
||||
extern int amdgpu_pos_buf_per_se;
|
||||
|
@ -155,9 +156,14 @@ extern int amdgpu_gpu_recovery;
|
|||
extern int amdgpu_emu_mode;
|
||||
extern uint amdgpu_smu_memory_pool_size;
|
||||
extern uint amdgpu_dc_feature_mask;
|
||||
extern uint amdgpu_dm_abm_level;
|
||||
extern struct amdgpu_mgpu_info mgpu_info;
|
||||
extern int amdgpu_ras_enable;
|
||||
extern uint amdgpu_ras_mask;
|
||||
extern int amdgpu_async_gfx_ring;
|
||||
extern int amdgpu_mcbp;
|
||||
extern int amdgpu_discovery;
|
||||
extern int amdgpu_mes;
|
||||
|
||||
#ifdef CONFIG_DRM_AMDGPU_SI
|
||||
extern int amdgpu_si_support;
|
||||
|
@ -213,7 +219,8 @@ struct amdgpu_atif;
|
|||
struct kfd_vm_fault_info;
|
||||
|
||||
enum amdgpu_cp_irq {
|
||||
AMDGPU_CP_IRQ_GFX_EOP = 0,
|
||||
AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP = 0,
|
||||
AMDGPU_CP_IRQ_GFX_ME0_PIPE1_EOP,
|
||||
AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP,
|
||||
AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE1_EOP,
|
||||
AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE2_EOP,
|
||||
|
@ -659,6 +666,8 @@ struct amdgpu_nbio_funcs {
|
|||
u32 (*get_memsize)(struct amdgpu_device *adev);
|
||||
void (*sdma_doorbell_range)(struct amdgpu_device *adev, int instance,
|
||||
bool use_doorbell, int doorbell_index, int doorbell_size);
|
||||
void (*vcn_doorbell_range)(struct amdgpu_device *adev, bool use_doorbell,
|
||||
int doorbell_index);
|
||||
void (*enable_doorbell_aperture)(struct amdgpu_device *adev,
|
||||
bool enable);
|
||||
void (*enable_doorbell_selfring_aperture)(struct amdgpu_device *adev,
|
||||
|
@ -678,7 +687,7 @@ struct amdgpu_nbio_funcs {
|
|||
};
|
||||
|
||||
struct amdgpu_df_funcs {
|
||||
void (*init)(struct amdgpu_device *adev);
|
||||
void (*sw_init)(struct amdgpu_device *adev);
|
||||
void (*enable_broadcast_mode)(struct amdgpu_device *adev,
|
||||
bool enable);
|
||||
u32 (*get_fb_channel_number)(struct amdgpu_device *adev);
|
||||
|
@ -729,6 +738,7 @@ struct amd_powerplay {
|
|||
};
|
||||
|
||||
#define AMDGPU_RESET_MAGIC_NUM 64
|
||||
#define AMDGPU_MAX_DF_PERFMONS 4
|
||||
struct amdgpu_device {
|
||||
struct device *dev;
|
||||
struct drm_device *ddev;
|
||||
|
@ -755,6 +765,7 @@ struct amdgpu_device {
|
|||
struct amdgpu_debugfs debugfs[AMDGPU_DEBUGFS_MAX_COMPONENTS];
|
||||
unsigned debugfs_count;
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
struct dentry *debugfs_preempt;
|
||||
struct dentry *debugfs_regs[AMDGPU_DEBUGFS_MAX_COMPONENTS];
|
||||
#endif
|
||||
struct amdgpu_atif *atif;
|
||||
|
@ -905,6 +916,13 @@ struct amdgpu_device {
|
|||
/* display related functionality */
|
||||
struct amdgpu_display_manager dm;
|
||||
|
||||
/* discovery */
|
||||
uint8_t *discovery;
|
||||
|
||||
/* mes */
|
||||
bool enable_mes;
|
||||
struct amdgpu_mes mes;
|
||||
|
||||
struct amdgpu_ip_block ip_blocks[AMDGPU_MAX_IP_NUM];
|
||||
int num_ip_blocks;
|
||||
struct mutex mn_lock;
|
||||
|
@ -959,6 +977,7 @@ struct amdgpu_device {
|
|||
long compute_timeout;
|
||||
|
||||
uint64_t unique_id;
|
||||
uint64_t df_perfmon_config_assign_mask[AMDGPU_MAX_DF_PERFMONS];
|
||||
};
|
||||
|
||||
static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev)
|
||||
|
@ -1198,4 +1217,19 @@ static inline int amdgpu_dm_display_resume(struct amdgpu_device *adev) { return
|
|||
#endif
|
||||
|
||||
#include "amdgpu_object.h"
|
||||
|
||||
/* used by df_v3_6.c and amdgpu_pmu.c */
|
||||
#define AMDGPU_PMU_ATTR(_name, _object) \
|
||||
static ssize_t \
|
||||
_name##_show(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *page) \
|
||||
{ \
|
||||
BUILD_BUG_ON(sizeof(_object) >= PAGE_SIZE - 1); \
|
||||
return sprintf(page, _object "\n"); \
|
||||
} \
|
||||
\
|
||||
static struct device_attribute pmu_attr_##_name = __ATTR_RO(_name)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev)
|
|||
case CHIP_POLARIS10:
|
||||
case CHIP_POLARIS11:
|
||||
case CHIP_POLARIS12:
|
||||
case CHIP_VEGAM:
|
||||
kfd2kgd = amdgpu_amdkfd_gfx_8_0_get_functions();
|
||||
break;
|
||||
case CHIP_VEGA10:
|
||||
|
@ -86,6 +87,9 @@ void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev)
|
|||
case CHIP_RAVEN:
|
||||
kfd2kgd = amdgpu_amdkfd_gfx_9_0_get_functions();
|
||||
break;
|
||||
case CHIP_NAVI10:
|
||||
kfd2kgd = amdgpu_amdkfd_gfx_10_0_get_functions();
|
||||
break;
|
||||
default:
|
||||
dev_info(adev->dev, "kfd not supported on this ASIC\n");
|
||||
return;
|
||||
|
@ -158,7 +162,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
|
|||
|
||||
/* remove the KIQ bit as well */
|
||||
if (adev->gfx.kiq.ring.sched.ready)
|
||||
clear_bit(amdgpu_gfx_queue_to_bit(adev,
|
||||
clear_bit(amdgpu_gfx_mec_queue_to_bit(adev,
|
||||
adev->gfx.kiq.ring.me - 1,
|
||||
adev->gfx.kiq.ring.pipe,
|
||||
adev->gfx.kiq.ring.queue),
|
||||
|
@ -436,9 +440,12 @@ void amdgpu_amdkfd_get_local_mem_info(struct kgd_dev *kgd,
|
|||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
mem_info->mem_clk_max = adev->clock.default_mclk / 100;
|
||||
else if (adev->powerplay.pp_funcs)
|
||||
mem_info->mem_clk_max = amdgpu_dpm_get_mclk(adev, false) / 100;
|
||||
else
|
||||
else if (adev->powerplay.pp_funcs) {
|
||||
if (amdgpu_emu_mode == 1)
|
||||
mem_info->mem_clk_max = 0;
|
||||
else
|
||||
mem_info->mem_clk_max = amdgpu_dpm_get_mclk(adev, false) / 100;
|
||||
} else
|
||||
mem_info->mem_clk_max = 100;
|
||||
}
|
||||
|
||||
|
@ -701,6 +708,11 @@ struct kfd2kgd_calls *amdgpu_amdkfd_gfx_9_0_get_functions(void)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct kfd2kgd_calls *amdgpu_amdkfd_gfx_10_0_get_functions(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev,
|
||||
const struct kfd2kgd_calls *f2g)
|
||||
{
|
||||
|
|
|
@ -139,6 +139,7 @@ void amdgpu_amdkfd_set_compute_idle(struct kgd_dev *kgd, bool idle);
|
|||
struct kfd2kgd_calls *amdgpu_amdkfd_gfx_7_get_functions(void);
|
||||
struct kfd2kgd_calls *amdgpu_amdkfd_gfx_8_0_get_functions(void);
|
||||
struct kfd2kgd_calls *amdgpu_amdkfd_gfx_9_0_get_functions(void);
|
||||
struct kfd2kgd_calls *amdgpu_amdkfd_gfx_10_0_get_functions(void);
|
||||
|
||||
bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid);
|
||||
|
||||
|
|
|
@ -0,0 +1,975 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "kfd2kgd: " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/fdtable.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/mmu_context.h>
|
||||
#include <drm/drmP.h>
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_ucode.h"
|
||||
#include "soc15_hw_ip.h"
|
||||
#include "gc/gc_10_1_0_offset.h"
|
||||
#include "gc/gc_10_1_0_sh_mask.h"
|
||||
#include "navi10_enum.h"
|
||||
#include "athub/athub_2_0_0_offset.h"
|
||||
#include "athub/athub_2_0_0_sh_mask.h"
|
||||
#include "oss/osssys_5_0_0_offset.h"
|
||||
#include "oss/osssys_5_0_0_sh_mask.h"
|
||||
#include "soc15_common.h"
|
||||
#include "v10_structs.h"
|
||||
#include "nv.h"
|
||||
#include "nvd.h"
|
||||
|
||||
enum hqd_dequeue_request_type {
|
||||
NO_ACTION = 0,
|
||||
DRAIN_PIPE,
|
||||
RESET_WAVES,
|
||||
SAVE_WAVES
|
||||
};
|
||||
|
||||
/*
|
||||
* Register access functions
|
||||
*/
|
||||
|
||||
static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
||||
uint32_t sh_mem_config,
|
||||
uint32_t sh_mem_ape1_base, uint32_t sh_mem_ape1_limit,
|
||||
uint32_t sh_mem_bases);
|
||||
static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,
|
||||
unsigned int vmid);
|
||||
static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id);
|
||||
static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
||||
uint32_t queue_id, uint32_t __user *wptr,
|
||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
||||
struct mm_struct *mm);
|
||||
static int kgd_hqd_dump(struct kgd_dev *kgd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs);
|
||||
static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
||||
uint32_t __user *wptr, struct mm_struct *mm);
|
||||
static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
||||
uint32_t engine_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs);
|
||||
static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
||||
uint32_t pipe_id, uint32_t queue_id);
|
||||
static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd);
|
||||
static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
enum kfd_preempt_type reset_type,
|
||||
unsigned int utimeout, uint32_t pipe_id,
|
||||
uint32_t queue_id);
|
||||
static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
unsigned int utimeout);
|
||||
#if 0
|
||||
static uint32_t get_watch_base_addr(struct amdgpu_device *adev);
|
||||
#endif
|
||||
static int kgd_address_watch_disable(struct kgd_dev *kgd);
|
||||
static int kgd_address_watch_execute(struct kgd_dev *kgd,
|
||||
unsigned int watch_point_id,
|
||||
uint32_t cntl_val,
|
||||
uint32_t addr_hi,
|
||||
uint32_t addr_lo);
|
||||
static int kgd_wave_control_execute(struct kgd_dev *kgd,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd);
|
||||
static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd,
|
||||
unsigned int watch_point_id,
|
||||
unsigned int reg_offset);
|
||||
|
||||
static bool get_atc_vmid_pasid_mapping_valid(struct kgd_dev *kgd,
|
||||
uint8_t vmid);
|
||||
static uint16_t get_atc_vmid_pasid_mapping_pasid(struct kgd_dev *kgd,
|
||||
uint8_t vmid);
|
||||
static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
|
||||
uint64_t page_table_base);
|
||||
static int invalidate_tlbs(struct kgd_dev *kgd, uint16_t pasid);
|
||||
static int invalidate_tlbs_vmid(struct kgd_dev *kgd, uint16_t vmid);
|
||||
|
||||
/* Because of REG_GET_FIELD() being used, we put this function in the
|
||||
* asic specific file.
|
||||
*/
|
||||
static int amdgpu_amdkfd_get_tile_config(struct kgd_dev *kgd,
|
||||
struct tile_config *config)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
config->gb_addr_config = adev->gfx.config.gb_addr_config;
|
||||
#if 0
|
||||
/* TODO - confirm REG_GET_FIELD x2, should be OK as is... but
|
||||
* MC_ARB_RAMCFG register doesn't exist on Vega10 - initial amdgpu
|
||||
* changes commented out related code, doing the same here for now but
|
||||
* need to sync with Ken et al
|
||||
*/
|
||||
config->num_banks = REG_GET_FIELD(adev->gfx.config.mc_arb_ramcfg,
|
||||
MC_ARB_RAMCFG, NOOFBANK);
|
||||
config->num_ranks = REG_GET_FIELD(adev->gfx.config.mc_arb_ramcfg,
|
||||
MC_ARB_RAMCFG, NOOFRANKS);
|
||||
#endif
|
||||
|
||||
config->tile_config_ptr = adev->gfx.config.tile_mode_array;
|
||||
config->num_tile_configs =
|
||||
ARRAY_SIZE(adev->gfx.config.tile_mode_array);
|
||||
config->macro_tile_config_ptr =
|
||||
adev->gfx.config.macrotile_mode_array;
|
||||
config->num_macro_tile_configs =
|
||||
ARRAY_SIZE(adev->gfx.config.macrotile_mode_array);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct kfd2kgd_calls kfd2kgd = {
|
||||
.program_sh_mem_settings = kgd_program_sh_mem_settings,
|
||||
.set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping,
|
||||
.init_interrupts = kgd_init_interrupts,
|
||||
.hqd_load = kgd_hqd_load,
|
||||
.hqd_sdma_load = kgd_hqd_sdma_load,
|
||||
.hqd_dump = kgd_hqd_dump,
|
||||
.hqd_sdma_dump = kgd_hqd_sdma_dump,
|
||||
.hqd_is_occupied = kgd_hqd_is_occupied,
|
||||
.hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied,
|
||||
.hqd_destroy = kgd_hqd_destroy,
|
||||
.hqd_sdma_destroy = kgd_hqd_sdma_destroy,
|
||||
.address_watch_disable = kgd_address_watch_disable,
|
||||
.address_watch_execute = kgd_address_watch_execute,
|
||||
.wave_control_execute = kgd_wave_control_execute,
|
||||
.address_watch_get_offset = kgd_address_watch_get_offset,
|
||||
.get_atc_vmid_pasid_mapping_pasid =
|
||||
get_atc_vmid_pasid_mapping_pasid,
|
||||
.get_atc_vmid_pasid_mapping_valid =
|
||||
get_atc_vmid_pasid_mapping_valid,
|
||||
.invalidate_tlbs = invalidate_tlbs,
|
||||
.invalidate_tlbs_vmid = invalidate_tlbs_vmid,
|
||||
.set_vm_context_page_table_base = set_vm_context_page_table_base,
|
||||
.get_tile_config = amdgpu_amdkfd_get_tile_config,
|
||||
};
|
||||
|
||||
struct kfd2kgd_calls *amdgpu_amdkfd_gfx_10_0_get_functions()
|
||||
{
|
||||
return (struct kfd2kgd_calls *)&kfd2kgd;
|
||||
}
|
||||
|
||||
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
|
||||
{
|
||||
return (struct amdgpu_device *)kgd;
|
||||
}
|
||||
|
||||
static void lock_srbm(struct kgd_dev *kgd, uint32_t mec, uint32_t pipe,
|
||||
uint32_t queue, uint32_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
nv_grbm_select(adev, mec, pipe, queue, vmid);
|
||||
}
|
||||
|
||||
static void unlock_srbm(struct kgd_dev *kgd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
nv_grbm_select(adev, 0, 0, 0, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
}
|
||||
|
||||
static void acquire_queue(struct kgd_dev *kgd, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
lock_srbm(kgd, mec, pipe, queue_id, 0);
|
||||
}
|
||||
|
||||
static uint32_t get_queue_mask(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id)
|
||||
{
|
||||
unsigned int bit = (pipe_id * adev->gfx.mec.num_queue_per_pipe +
|
||||
queue_id) & 31;
|
||||
|
||||
return ((uint32_t)1) << bit;
|
||||
}
|
||||
|
||||
static void release_queue(struct kgd_dev *kgd)
|
||||
{
|
||||
unlock_srbm(kgd);
|
||||
}
|
||||
|
||||
static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
||||
uint32_t sh_mem_config,
|
||||
uint32_t sh_mem_ape1_base,
|
||||
uint32_t sh_mem_ape1_limit,
|
||||
uint32_t sh_mem_bases)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_CONFIG), sh_mem_config);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_BASES), sh_mem_bases);
|
||||
/* APE1 no longer exists on GFX9 */
|
||||
|
||||
unlock_srbm(kgd);
|
||||
}
|
||||
|
||||
static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,
|
||||
unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
/*
|
||||
* We have to assume that there is no outstanding mapping.
|
||||
* The ATC_VMID_PASID_MAPPING_UPDATE_STATUS bit could be 0 because
|
||||
* a mapping is in progress or because a mapping finished
|
||||
* and the SW cleared it.
|
||||
* So the protocol is to always wait & clear.
|
||||
*/
|
||||
uint32_t pasid_mapping = (pasid == 0) ? 0 : (uint32_t)pasid |
|
||||
ATC_VMID0_PASID_MAPPING__VALID_MASK;
|
||||
|
||||
pr_debug("pasid 0x%x vmid %d, reg value %x\n", pasid, vmid, pasid_mapping);
|
||||
/*
|
||||
* need to do this twice, once for gfx and once for mmhub
|
||||
* for ATC add 16 to VMID for mmhub, for IH different registers.
|
||||
* ATC_VMID0..15 registers are separate from ATC_VMID16..31.
|
||||
*/
|
||||
|
||||
pr_debug("ATHUB, reg %x\n", SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING) + vmid);
|
||||
WREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING) + vmid,
|
||||
pasid_mapping);
|
||||
|
||||
#if 0
|
||||
/* TODO: uncomment this code when the hardware support is ready. */
|
||||
while (!(RREG32(SOC15_REG_OFFSET(
|
||||
ATHUB, 0,
|
||||
mmATC_VMID_PASID_MAPPING_UPDATE_STATUS)) &
|
||||
(1U << vmid)))
|
||||
cpu_relax();
|
||||
|
||||
pr_debug("ATHUB mapping update finished\n");
|
||||
WREG32(SOC15_REG_OFFSET(ATHUB, 0,
|
||||
mmATC_VMID_PASID_MAPPING_UPDATE_STATUS),
|
||||
1U << vmid);
|
||||
#endif
|
||||
|
||||
/* Mapping vmid to pasid also for IH block */
|
||||
pr_debug("update mapping for IH block and mmhub");
|
||||
WREG32(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_VMID_0_LUT) + vmid,
|
||||
pasid_mapping);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO - RING0 form of field is obsolete, seems to date back to SI
|
||||
* but still works
|
||||
*/
|
||||
|
||||
static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t mec;
|
||||
uint32_t pipe;
|
||||
|
||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
lock_srbm(kgd, mec, pipe, 0, 0);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCPC_INT_CNTL),
|
||||
CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
||||
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
||||
|
||||
unlock_srbm(kgd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t get_sdma_base_addr(struct amdgpu_device *adev,
|
||||
unsigned int engine_id,
|
||||
unsigned int queue_id)
|
||||
{
|
||||
uint32_t base[2] = {
|
||||
SOC15_REG_OFFSET(SDMA0, 0,
|
||||
mmSDMA0_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL,
|
||||
/* On gfx10, mmSDMA1_xxx registers are defined NOT based
|
||||
* on SDMA1 base address (dw 0x1860) but based on SDMA0
|
||||
* base address (dw 0x1260). Therefore use mmSDMA0_RLC0_RB_CNTL
|
||||
* instead of mmSDMA1_RLC0_RB_CNTL for the base address calc
|
||||
* below
|
||||
*/
|
||||
SOC15_REG_OFFSET(SDMA1, 0,
|
||||
mmSDMA1_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL
|
||||
};
|
||||
uint32_t retval;
|
||||
|
||||
retval = base[engine_id] + queue_id * (mmSDMA0_RLC1_RB_CNTL -
|
||||
mmSDMA0_RLC0_RB_CNTL);
|
||||
|
||||
pr_debug("sdma base address: 0x%x\n", retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static uint32_t get_watch_base_addr(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t retval = SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_ADDR_H) -
|
||||
mmTCP_WATCH0_ADDR_H;
|
||||
|
||||
pr_debug("kfd: reg watch base address: 0x%x\n", retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline struct v10_compute_mqd *get_mqd(void *mqd)
|
||||
{
|
||||
return (struct v10_compute_mqd *)mqd;
|
||||
}
|
||||
|
||||
static inline struct v10_sdma_mqd *get_sdma_mqd(void *mqd)
|
||||
{
|
||||
return (struct v10_sdma_mqd *)mqd;
|
||||
}
|
||||
|
||||
static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
||||
uint32_t queue_id, uint32_t __user *wptr,
|
||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v10_compute_mqd *m;
|
||||
uint32_t *mqd_hqd;
|
||||
uint32_t reg, hqd_base, data;
|
||||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
pr_debug("Load hqd of pipe %d queue %d\n", pipe_id, queue_id);
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
|
||||
/* HIQ is set during driver init period with vmid set to 0*/
|
||||
if (m->cp_hqd_vmid == 0) {
|
||||
uint32_t value, mec, pipe;
|
||||
|
||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
pr_debug("kfd: set HIQ, mec:%d, pipe:%d, queue:%d.\n",
|
||||
mec, pipe, queue_id);
|
||||
value = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CP_SCHEDULERS));
|
||||
value = REG_SET_FIELD(value, RLC_CP_SCHEDULERS, scheduler1,
|
||||
((mec << 5) | (pipe << 3) | queue_id | 0x80));
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CP_SCHEDULERS), value);
|
||||
}
|
||||
|
||||
/* HQD registers extend from CP_MQD_BASE_ADDR to CP_HQD_EOP_WPTR_MEM. */
|
||||
mqd_hqd = &m->cp_mqd_base_addr_lo;
|
||||
hqd_base = SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR);
|
||||
|
||||
for (reg = hqd_base;
|
||||
reg <= SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI); reg++)
|
||||
WREG32(reg, mqd_hqd[reg - hqd_base]);
|
||||
|
||||
|
||||
/* Activate doorbell logic before triggering WPTR poll. */
|
||||
data = REG_SET_FIELD(m->cp_hqd_pq_doorbell_control,
|
||||
CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 1);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL), data);
|
||||
|
||||
if (wptr) {
|
||||
/* Don't read wptr with get_user because the user
|
||||
* context may not be accessible (if this function
|
||||
* runs in a work queue). Instead trigger a one-shot
|
||||
* polling read from memory in the CP. This assumes
|
||||
* that wptr is GPU-accessible in the queue's VMID via
|
||||
* ATC or SVM. WPTR==RPTR before starting the poll so
|
||||
* the CP starts fetching new commands from the right
|
||||
* place.
|
||||
*
|
||||
* Guessing a 64-bit WPTR from a 32-bit RPTR is a bit
|
||||
* tricky. Assume that the queue didn't overflow. The
|
||||
* number of valid bits in the 32-bit RPTR depends on
|
||||
* the queue size. The remaining bits are taken from
|
||||
* the saved 64-bit WPTR. If the WPTR wrapped, add the
|
||||
* queue size.
|
||||
*/
|
||||
uint32_t queue_size =
|
||||
2 << REG_GET_FIELD(m->cp_hqd_pq_control,
|
||||
CP_HQD_PQ_CONTROL, QUEUE_SIZE);
|
||||
uint64_t guessed_wptr = m->cp_hqd_pq_rptr & (queue_size - 1);
|
||||
|
||||
if ((m->cp_hqd_pq_wptr_lo & (queue_size - 1)) < guessed_wptr)
|
||||
guessed_wptr += queue_size;
|
||||
guessed_wptr += m->cp_hqd_pq_wptr_lo & ~(queue_size - 1);
|
||||
guessed_wptr += (uint64_t)m->cp_hqd_pq_wptr_hi << 32;
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_LO),
|
||||
lower_32_bits(guessed_wptr));
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI),
|
||||
upper_32_bits(guessed_wptr));
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR),
|
||||
lower_32_bits((uint64_t)wptr));
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI),
|
||||
upper_32_bits((uint64_t)wptr));
|
||||
pr_debug("%s setting CP_PQ_WPTR_POLL_CNTL1 to %x\n", __func__, get_queue_mask(adev, pipe_id, queue_id));
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_PQ_WPTR_POLL_CNTL1),
|
||||
get_queue_mask(adev, pipe_id, queue_id));
|
||||
}
|
||||
|
||||
/* Start the EOP fetcher */
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_RPTR),
|
||||
REG_SET_FIELD(m->cp_hqd_eop_rptr,
|
||||
CP_HQD_EOP_RPTR, INIT_FETCHER, 1));
|
||||
|
||||
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE), data);
|
||||
|
||||
release_queue(kgd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_dump(struct kgd_dev *kgd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t i = 0, reg;
|
||||
#define HQD_N_REGS 56
|
||||
#define DUMP_REG(addr) do { \
|
||||
if (WARN_ON_ONCE(i >= HQD_N_REGS)) \
|
||||
break; \
|
||||
(*dump)[i][0] = (addr) << 2; \
|
||||
(*dump)[i++][1] = RREG32(addr); \
|
||||
} while (0)
|
||||
|
||||
*dump = kmalloc(HQD_N_REGS*2*sizeof(uint32_t), GFP_KERNEL);
|
||||
if (*dump == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
|
||||
for (reg = SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR);
|
||||
reg <= SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI); reg++)
|
||||
DUMP_REG(reg);
|
||||
|
||||
release_queue(kgd);
|
||||
|
||||
WARN_ON_ONCE(i != HQD_N_REGS);
|
||||
*n_regs = i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
||||
uint32_t __user *wptr, struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v10_sdma_mqd *m;
|
||||
uint32_t sdma_base_addr, sdmax_gfx_context_cntl;
|
||||
unsigned long end_jiffies;
|
||||
uint32_t data;
|
||||
uint64_t data64;
|
||||
uint64_t __user *wptr64 = (uint64_t __user *)wptr;
|
||||
|
||||
m = get_sdma_mqd(mqd);
|
||||
sdma_base_addr = get_sdma_base_addr(adev, m->sdma_engine_id,
|
||||
m->sdma_queue_id);
|
||||
pr_debug("sdma load base addr %x for engine %d, queue %d\n", sdma_base_addr, m->sdma_engine_id, m->sdma_queue_id);
|
||||
sdmax_gfx_context_cntl = m->sdma_engine_id ?
|
||||
SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_GFX_CONTEXT_CNTL) :
|
||||
SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_GFX_CONTEXT_CNTL);
|
||||
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL,
|
||||
m->sdmax_rlcx_rb_cntl & (~SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK));
|
||||
|
||||
end_jiffies = msecs_to_jiffies(2000) + jiffies;
|
||||
while (true) {
|
||||
data = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS);
|
||||
if (data & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK)
|
||||
break;
|
||||
if (time_after(jiffies, end_jiffies))
|
||||
return -ETIME;
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
data = RREG32(sdmax_gfx_context_cntl);
|
||||
data = REG_SET_FIELD(data, SDMA0_GFX_CONTEXT_CNTL,
|
||||
RESUME_CTX, 0);
|
||||
WREG32(sdmax_gfx_context_cntl, data);
|
||||
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL_OFFSET,
|
||||
m->sdmax_rlcx_doorbell_offset);
|
||||
|
||||
data = REG_SET_FIELD(m->sdmax_rlcx_doorbell, SDMA0_RLC0_DOORBELL,
|
||||
ENABLE, 1);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, data);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR, m->sdmax_rlcx_rb_rptr);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_HI,
|
||||
m->sdmax_rlcx_rb_rptr_hi);
|
||||
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_MINOR_PTR_UPDATE, 1);
|
||||
if (read_user_wptr(mm, wptr64, data64)) {
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR,
|
||||
lower_32_bits(data64));
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR_HI,
|
||||
upper_32_bits(data64));
|
||||
} else {
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR,
|
||||
m->sdmax_rlcx_rb_rptr);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR_HI,
|
||||
m->sdmax_rlcx_rb_rptr_hi);
|
||||
}
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_MINOR_PTR_UPDATE, 0);
|
||||
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE, m->sdmax_rlcx_rb_base);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE_HI,
|
||||
m->sdmax_rlcx_rb_base_hi);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_LO,
|
||||
m->sdmax_rlcx_rb_rptr_addr_lo);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_HI,
|
||||
m->sdmax_rlcx_rb_rptr_addr_hi);
|
||||
|
||||
data = REG_SET_FIELD(m->sdmax_rlcx_rb_cntl, SDMA0_RLC0_RB_CNTL,
|
||||
RB_ENABLE, 1);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
||||
uint32_t engine_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t sdma_base_addr = get_sdma_base_addr(adev, engine_id, queue_id);
|
||||
uint32_t i = 0, reg;
|
||||
#undef HQD_N_REGS
|
||||
#define HQD_N_REGS (19+6+7+10)
|
||||
|
||||
pr_debug("sdma dump engine id %d queue_id %d\n", engine_id, queue_id);
|
||||
pr_debug("sdma base addr %x\n", sdma_base_addr);
|
||||
|
||||
*dump = kmalloc(HQD_N_REGS*2*sizeof(uint32_t), GFP_KERNEL);
|
||||
if (*dump == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
for (reg = mmSDMA0_RLC0_RB_CNTL; reg <= mmSDMA0_RLC0_DOORBELL; reg++)
|
||||
DUMP_REG(sdma_base_addr + reg);
|
||||
for (reg = mmSDMA0_RLC0_STATUS; reg <= mmSDMA0_RLC0_CSA_ADDR_HI; reg++)
|
||||
DUMP_REG(sdma_base_addr + reg);
|
||||
for (reg = mmSDMA0_RLC0_IB_SUB_REMAIN;
|
||||
reg <= mmSDMA0_RLC0_MINOR_PTR_UPDATE; reg++)
|
||||
DUMP_REG(sdma_base_addr + reg);
|
||||
for (reg = mmSDMA0_RLC0_MIDCMD_DATA0;
|
||||
reg <= mmSDMA0_RLC0_MIDCMD_CNTL; reg++)
|
||||
DUMP_REG(sdma_base_addr + reg);
|
||||
|
||||
WARN_ON_ONCE(i != HQD_N_REGS);
|
||||
*n_regs = i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
||||
uint32_t pipe_id, uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t act;
|
||||
bool retval = false;
|
||||
uint32_t low, high;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
act = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE));
|
||||
if (act) {
|
||||
low = lower_32_bits(queue_address >> 8);
|
||||
high = upper_32_bits(queue_address >> 8);
|
||||
|
||||
if (low == RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_BASE)) &&
|
||||
high == RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_BASE_HI)))
|
||||
retval = true;
|
||||
}
|
||||
release_queue(kgd);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v10_sdma_mqd *m;
|
||||
uint32_t sdma_base_addr;
|
||||
uint32_t sdma_rlc_rb_cntl;
|
||||
|
||||
m = get_sdma_mqd(mqd);
|
||||
sdma_base_addr = get_sdma_base_addr(adev, m->sdma_engine_id,
|
||||
m->sdma_queue_id);
|
||||
|
||||
sdma_rlc_rb_cntl = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL);
|
||||
|
||||
if (sdma_rlc_rb_cntl & SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
enum kfd_preempt_type reset_type,
|
||||
unsigned int utimeout, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
enum hqd_dequeue_request_type type;
|
||||
unsigned long end_jiffies;
|
||||
uint32_t temp;
|
||||
struct v10_compute_mqd *m = get_mqd(mqd);
|
||||
|
||||
#if 0
|
||||
unsigned long flags;
|
||||
int retry;
|
||||
#endif
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
|
||||
if (m->cp_hqd_vmid == 0)
|
||||
WREG32_FIELD15(GC, 0, RLC_CP_SCHEDULERS, scheduler1, 0);
|
||||
|
||||
switch (reset_type) {
|
||||
case KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN:
|
||||
type = DRAIN_PIPE;
|
||||
break;
|
||||
case KFD_PREEMPT_TYPE_WAVEFRONT_RESET:
|
||||
type = RESET_WAVES;
|
||||
break;
|
||||
default:
|
||||
type = DRAIN_PIPE;
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0 /* Is this still needed? */
|
||||
/* Workaround: If IQ timer is active and the wait time is close to or
|
||||
* equal to 0, dequeueing is not safe. Wait until either the wait time
|
||||
* is larger or timer is cleared. Also, ensure that IQ_REQ_PEND is
|
||||
* cleared before continuing. Also, ensure wait times are set to at
|
||||
* least 0x3.
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
preempt_disable();
|
||||
retry = 5000; /* wait for 500 usecs at maximum */
|
||||
while (true) {
|
||||
temp = RREG32(mmCP_HQD_IQ_TIMER);
|
||||
if (REG_GET_FIELD(temp, CP_HQD_IQ_TIMER, PROCESSING_IQ)) {
|
||||
pr_debug("HW is processing IQ\n");
|
||||
goto loop;
|
||||
}
|
||||
if (REG_GET_FIELD(temp, CP_HQD_IQ_TIMER, ACTIVE)) {
|
||||
if (REG_GET_FIELD(temp, CP_HQD_IQ_TIMER, RETRY_TYPE)
|
||||
== 3) /* SEM-rearm is safe */
|
||||
break;
|
||||
/* Wait time 3 is safe for CP, but our MMIO read/write
|
||||
* time is close to 1 microsecond, so check for 10 to
|
||||
* leave more buffer room
|
||||
*/
|
||||
if (REG_GET_FIELD(temp, CP_HQD_IQ_TIMER, WAIT_TIME)
|
||||
>= 10)
|
||||
break;
|
||||
pr_debug("IQ timer is active\n");
|
||||
} else
|
||||
break;
|
||||
loop:
|
||||
if (!retry) {
|
||||
pr_err("CP HQD IQ timer status time out\n");
|
||||
break;
|
||||
}
|
||||
ndelay(100);
|
||||
--retry;
|
||||
}
|
||||
retry = 1000;
|
||||
while (true) {
|
||||
temp = RREG32(mmCP_HQD_DEQUEUE_REQUEST);
|
||||
if (!(temp & CP_HQD_DEQUEUE_REQUEST__IQ_REQ_PEND_MASK))
|
||||
break;
|
||||
pr_debug("Dequeue request is pending\n");
|
||||
|
||||
if (!retry) {
|
||||
pr_err("CP HQD dequeue request time out\n");
|
||||
break;
|
||||
}
|
||||
ndelay(100);
|
||||
--retry;
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
preempt_enable();
|
||||
#endif
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_DEQUEUE_REQUEST), type);
|
||||
|
||||
end_jiffies = (utimeout * HZ / 1000) + jiffies;
|
||||
while (true) {
|
||||
temp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE));
|
||||
if (!(temp & CP_HQD_ACTIVE__ACTIVE_MASK))
|
||||
break;
|
||||
if (time_after(jiffies, end_jiffies)) {
|
||||
pr_err("cp queue preemption time out.\n");
|
||||
release_queue(kgd);
|
||||
return -ETIME;
|
||||
}
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
|
||||
release_queue(kgd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
unsigned int utimeout)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v10_sdma_mqd *m;
|
||||
uint32_t sdma_base_addr;
|
||||
uint32_t temp;
|
||||
unsigned long end_jiffies = (utimeout * HZ / 1000) + jiffies;
|
||||
|
||||
m = get_sdma_mqd(mqd);
|
||||
sdma_base_addr = get_sdma_base_addr(adev, m->sdma_engine_id,
|
||||
m->sdma_queue_id);
|
||||
|
||||
temp = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL);
|
||||
temp = temp & ~SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK;
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL, temp);
|
||||
|
||||
while (true) {
|
||||
temp = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS);
|
||||
if (temp & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK)
|
||||
break;
|
||||
if (time_after(jiffies, end_jiffies))
|
||||
return -ETIME;
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, 0);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL,
|
||||
RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL) |
|
||||
SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK);
|
||||
|
||||
m->sdmax_rlcx_rb_rptr = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR);
|
||||
m->sdmax_rlcx_rb_rptr_hi =
|
||||
RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_HI);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool get_atc_vmid_pasid_mapping_valid(struct kgd_dev *kgd,
|
||||
uint8_t vmid)
|
||||
{
|
||||
uint32_t reg;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
|
||||
reg = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING)
|
||||
+ vmid);
|
||||
return reg & ATC_VMID0_PASID_MAPPING__VALID_MASK;
|
||||
}
|
||||
|
||||
static uint16_t get_atc_vmid_pasid_mapping_pasid(struct kgd_dev *kgd,
|
||||
uint8_t vmid)
|
||||
{
|
||||
uint32_t reg;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
|
||||
reg = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING)
|
||||
+ vmid);
|
||||
return reg & ATC_VMID0_PASID_MAPPING__PASID_MASK;
|
||||
}
|
||||
|
||||
static void write_vmid_invalidate_request(struct kgd_dev *kgd, uint8_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
uint32_t req = (1 << vmid) |
|
||||
(0 << GCVM_INVALIDATE_ENG0_REQ__FLUSH_TYPE__SHIFT) |/* legacy */
|
||||
GCVM_INVALIDATE_ENG0_REQ__INVALIDATE_L2_PTES_MASK |
|
||||
GCVM_INVALIDATE_ENG0_REQ__INVALIDATE_L2_PDE0_MASK |
|
||||
GCVM_INVALIDATE_ENG0_REQ__INVALIDATE_L2_PDE1_MASK |
|
||||
GCVM_INVALIDATE_ENG0_REQ__INVALIDATE_L2_PDE2_MASK |
|
||||
GCVM_INVALIDATE_ENG0_REQ__INVALIDATE_L1_PTES_MASK;
|
||||
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
|
||||
/* Use light weight invalidation.
|
||||
*
|
||||
* TODO 1: agree on the right set of invalidation registers for
|
||||
* KFD use. Use the last one for now. Invalidate only GCHUB as
|
||||
* SDMA is now moved to GCHUB
|
||||
*
|
||||
* TODO 2: support range-based invalidation, requires kfg2kgd
|
||||
* interface change
|
||||
*/
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmGCVM_INVALIDATE_ENG0_ADDR_RANGE_LO32),
|
||||
0xffffffff);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmGCVM_INVALIDATE_ENG0_ADDR_RANGE_HI32),
|
||||
0x0000001f);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmGCVM_INVALIDATE_ENG0_REQ), req);
|
||||
|
||||
while (!(RREG32(SOC15_REG_OFFSET(GC, 0, mmGCVM_INVALIDATE_ENG0_ACK)) &
|
||||
(1 << vmid)))
|
||||
cpu_relax();
|
||||
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
}
|
||||
|
||||
static int invalidate_tlbs_with_kiq(struct amdgpu_device *adev, uint16_t pasid)
|
||||
{
|
||||
signed long r;
|
||||
uint32_t seq;
|
||||
struct amdgpu_ring *ring = &adev->gfx.kiq.ring;
|
||||
|
||||
spin_lock(&adev->gfx.kiq.ring_lock);
|
||||
amdgpu_ring_alloc(ring, 12); /* fence + invalidate_tlbs package*/
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_INVALIDATE_TLBS, 0));
|
||||
amdgpu_ring_write(ring,
|
||||
PACKET3_INVALIDATE_TLBS_DST_SEL(1) |
|
||||
PACKET3_INVALIDATE_TLBS_PASID(pasid));
|
||||
amdgpu_fence_emit_polling(ring, &seq);
|
||||
amdgpu_ring_commit(ring);
|
||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||
|
||||
r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout);
|
||||
if (r < 1) {
|
||||
DRM_ERROR("wait for kiq fence error: %ld.\n", r);
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int invalidate_tlbs(struct kgd_dev *kgd, uint16_t pasid)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
int vmid;
|
||||
struct amdgpu_ring *ring = &adev->gfx.kiq.ring;
|
||||
|
||||
if (amdgpu_emu_mode == 0 && ring->sched.ready)
|
||||
return invalidate_tlbs_with_kiq(adev, pasid);
|
||||
|
||||
for (vmid = 0; vmid < 16; vmid++) {
|
||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid))
|
||||
continue;
|
||||
if (get_atc_vmid_pasid_mapping_valid(kgd, vmid)) {
|
||||
if (get_atc_vmid_pasid_mapping_pasid(kgd, vmid)
|
||||
== pasid) {
|
||||
write_vmid_invalidate_request(kgd, vmid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int invalidate_tlbs_vmid(struct kgd_dev *kgd, uint16_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
|
||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
||||
pr_err("non kfd vmid %d\n", vmid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
write_vmid_invalidate_request(kgd, vmid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_address_watch_disable(struct kgd_dev *kgd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_address_watch_execute(struct kgd_dev *kgd,
|
||||
unsigned int watch_point_id,
|
||||
uint32_t cntl_val,
|
||||
uint32_t addr_hi,
|
||||
uint32_t addr_lo)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_wave_control_execute(struct kgd_dev *kgd,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t data = 0;
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_INDEX), gfx_index_val);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_CMD), sq_cmd);
|
||||
|
||||
data = REG_SET_FIELD(data, GRBM_GFX_INDEX,
|
||||
INSTANCE_BROADCAST_WRITES, 1);
|
||||
data = REG_SET_FIELD(data, GRBM_GFX_INDEX,
|
||||
SA_BROADCAST_WRITES, 1);
|
||||
data = REG_SET_FIELD(data, GRBM_GFX_INDEX,
|
||||
SE_BROADCAST_WRITES, 1);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_INDEX), data);
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd,
|
||||
unsigned int watch_point_id,
|
||||
unsigned int reg_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
|
||||
uint64_t page_table_base)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint64_t base = page_table_base | AMDGPU_PTE_VALID;
|
||||
|
||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
||||
pr_err("trying to set page table base for wrong VMID %u\n",
|
||||
vmid);
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: take advantage of per-process address space size. For
|
||||
* now, all processes share the same address space size, like
|
||||
* on GFX8 and older.
|
||||
*/
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32) + (vmid*2), 0);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32) + (vmid*2), 0);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32) + (vmid*2),
|
||||
lower_32_bits(adev->vm_manager.max_pfn - 1));
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32) + (vmid*2),
|
||||
upper_32_bits(adev->vm_manager.max_pfn - 1));
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32) + (vmid*2), lower_32_bits(base));
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32) + (vmid*2), upper_32_bits(base));
|
||||
}
|
|
@ -1732,37 +1732,19 @@ static int update_invalid_user_pages(struct amdkfd_process_info *process_info,
|
|||
ret = amdgpu_ttm_tt_get_user_pages(bo->tbo.ttm,
|
||||
bo->tbo.ttm->pages);
|
||||
if (ret) {
|
||||
bo->tbo.ttm->pages[0] = NULL;
|
||||
pr_info("%s: Failed to get user pages: %d\n",
|
||||
pr_debug("%s: Failed to get user pages: %d\n",
|
||||
__func__, ret);
|
||||
/* Pretend it succeeded. It will fail later
|
||||
* with a VM fault if the GPU tries to access
|
||||
* it. Better than hanging indefinitely with
|
||||
* stalled user mode queues.
|
||||
*/
|
||||
|
||||
/* Return error -EBUSY or -ENOMEM, retry restore */
|
||||
return ret;
|
||||
}
|
||||
|
||||
amdgpu_ttm_tt_get_user_pages_done(bo->tbo.ttm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remove invalid userptr BOs from hmm track list
|
||||
*
|
||||
* Stop HMM track the userptr update
|
||||
*/
|
||||
static void untrack_invalid_user_pages(struct amdkfd_process_info *process_info)
|
||||
{
|
||||
struct kgd_mem *mem, *tmp_mem;
|
||||
struct amdgpu_bo *bo;
|
||||
|
||||
list_for_each_entry_safe(mem, tmp_mem,
|
||||
&process_info->userptr_inval_list,
|
||||
validate_list.head) {
|
||||
bo = mem->bo;
|
||||
amdgpu_ttm_tt_get_user_pages_done(bo->tbo.ttm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Validate invalid userptr BOs
|
||||
*
|
||||
* Validates BOs on the userptr_inval_list, and moves them back to the
|
||||
|
@ -1842,13 +1824,6 @@ static int validate_invalid_user_pages(struct amdkfd_process_info *process_info)
|
|||
list_move_tail(&mem->validate_list.head,
|
||||
&process_info->userptr_valid_list);
|
||||
|
||||
/* Stop HMM track the userptr update. We dont check the return
|
||||
* value for concurrent CPU page table update because we will
|
||||
* reschedule the restore worker if process_info->evicted_bos
|
||||
* is updated.
|
||||
*/
|
||||
amdgpu_ttm_tt_get_user_pages_done(bo->tbo.ttm);
|
||||
|
||||
/* Update mapping. If the BO was not validated
|
||||
* (because we couldn't get user pages), this will
|
||||
* clear the page table entries, which will result in
|
||||
|
@ -1947,7 +1922,6 @@ static void amdgpu_amdkfd_restore_userptr_worker(struct work_struct *work)
|
|||
}
|
||||
|
||||
unlock_out:
|
||||
untrack_invalid_user_pages(process_info);
|
||||
mutex_unlock(&process_info->lock);
|
||||
mmput(mm);
|
||||
put_task_struct(usertask);
|
||||
|
@ -2153,12 +2127,16 @@ int amdgpu_amdkfd_add_gws_to_process(void *info, void *gws, struct kgd_mem **mem
|
|||
* Add process eviction fence to bo so they can
|
||||
* evict each other.
|
||||
*/
|
||||
ret = reservation_object_reserve_shared(gws_bo->tbo.resv, 1);
|
||||
if (ret)
|
||||
goto reserve_shared_fail;
|
||||
amdgpu_bo_fence(gws_bo, &process_info->eviction_fence->base, true);
|
||||
amdgpu_bo_unreserve(gws_bo);
|
||||
mutex_unlock(&(*mem)->process_info->lock);
|
||||
|
||||
return ret;
|
||||
|
||||
reserve_shared_fail:
|
||||
bo_validation_failure:
|
||||
amdgpu_bo_unreserve(gws_bo);
|
||||
bo_reservation_failure:
|
||||
|
|
|
@ -118,6 +118,7 @@ union umc_info {
|
|||
|
||||
union vram_info {
|
||||
struct atom_vram_info_header_v2_3 v23;
|
||||
struct atom_vram_info_header_v2_4 v24;
|
||||
};
|
||||
/*
|
||||
* Return vram width from integrated system info table, if available,
|
||||
|
@ -126,22 +127,50 @@ union vram_info {
|
|||
int amdgpu_atomfirmware_get_vram_width(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_mode_info *mode_info = &adev->mode_info;
|
||||
int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
|
||||
integratedsysteminfo);
|
||||
int index;
|
||||
u16 data_offset, size;
|
||||
union igp_info *igp_info;
|
||||
union vram_info *vram_info;
|
||||
u32 mem_channel_number;
|
||||
u32 mem_channel_width;
|
||||
u8 frev, crev;
|
||||
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
|
||||
integratedsysteminfo);
|
||||
else
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
|
||||
vram_info);
|
||||
|
||||
/* get any igp specific overrides */
|
||||
if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, &size,
|
||||
&frev, &crev, &data_offset)) {
|
||||
igp_info = (union igp_info *)
|
||||
(mode_info->atom_context->bios + data_offset);
|
||||
switch (crev) {
|
||||
case 11:
|
||||
return igp_info->v11.umachannelnumber * 64;
|
||||
default:
|
||||
return 0;
|
||||
if (adev->flags & AMD_IS_APU) {
|
||||
igp_info = (union igp_info *)
|
||||
(mode_info->atom_context->bios + data_offset);
|
||||
switch (crev) {
|
||||
case 11:
|
||||
mem_channel_number = igp_info->v11.umachannelnumber;
|
||||
/* channel width is 64 */
|
||||
return mem_channel_number * 64;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
vram_info = (union vram_info *)
|
||||
(mode_info->atom_context->bios + data_offset);
|
||||
switch (crev) {
|
||||
case 3:
|
||||
mem_channel_number = vram_info->v23.vram_module[0].channel_num;
|
||||
mem_channel_width = vram_info->v23.vram_module[0].channel_width;
|
||||
return mem_channel_number * (1 << mem_channel_width);
|
||||
case 4:
|
||||
mem_channel_number = vram_info->v24.vram_module[0].channel_num;
|
||||
mem_channel_width = vram_info->v24.vram_module[0].channel_width;
|
||||
return mem_channel_number * (1 << mem_channel_width);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,6 +208,9 @@ static int convert_atom_mem_type_to_vram_type (struct amdgpu_device *adev,
|
|||
case ATOM_DGPU_VRAM_TYPE_HBM2:
|
||||
vram_type = AMDGPU_VRAM_TYPE_HBM;
|
||||
break;
|
||||
case ATOM_DGPU_VRAM_TYPE_GDDR6:
|
||||
vram_type = AMDGPU_VRAM_TYPE_GDDR6;
|
||||
break;
|
||||
default:
|
||||
vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
|
||||
break;
|
||||
|
@ -227,6 +259,9 @@ int amdgpu_atomfirmware_get_vram_type(struct amdgpu_device *adev)
|
|||
case 3:
|
||||
mem_type = vram_info->v23.vram_module[0].memory_type;
|
||||
return convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
case 4:
|
||||
mem_type = vram_info->v24.vram_module[0].memory_type;
|
||||
return convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -650,7 +650,7 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
|
|||
}
|
||||
|
||||
r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true,
|
||||
&duplicates, true);
|
||||
&duplicates, false);
|
||||
if (unlikely(r != 0)) {
|
||||
if (r != -ERESTARTSYS)
|
||||
DRM_ERROR("ttm_eu_reserve_buffers failed.\n");
|
||||
|
@ -673,16 +673,12 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
|
|||
}
|
||||
|
||||
r = amdgpu_cs_list_validate(p, &duplicates);
|
||||
if (r) {
|
||||
DRM_ERROR("amdgpu_cs_list_validate(duplicates) failed.\n");
|
||||
if (r)
|
||||
goto error_validate;
|
||||
}
|
||||
|
||||
r = amdgpu_cs_list_validate(p, &p->validated);
|
||||
if (r) {
|
||||
DRM_ERROR("amdgpu_cs_list_validate(validated) failed.\n");
|
||||
if (r)
|
||||
goto error_validate;
|
||||
}
|
||||
|
||||
amdgpu_cs_report_moved_bytes(p->adev, p->bytes_moved,
|
||||
p->bytes_moved_vis);
|
||||
|
@ -878,7 +874,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) {
|
||||
struct dma_fence *f;
|
||||
|
||||
bo_va = fpriv->csa_va;
|
||||
|
@ -967,7 +963,8 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev,
|
|||
if (chunk->chunk_id != AMDGPU_CHUNK_ID_IB)
|
||||
continue;
|
||||
|
||||
if (chunk_ib->ip_type == AMDGPU_HW_IP_GFX && amdgpu_sriov_vf(adev)) {
|
||||
if (chunk_ib->ip_type == AMDGPU_HW_IP_GFX &&
|
||||
(amdgpu_mcbp || amdgpu_sriov_vf(adev))) {
|
||||
if (chunk_ib->flags & AMDGPU_IB_FLAG_PREEMPT) {
|
||||
if (chunk_ib->flags & AMDGPU_IB_FLAG_CE)
|
||||
ce_preempt++;
|
||||
|
@ -1385,7 +1382,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
|||
if (r) {
|
||||
if (r == -ENOMEM)
|
||||
DRM_ERROR("Not enough memory for command submission!\n");
|
||||
else if (r != -ERESTARTSYS)
|
||||
else if (r != -ERESTARTSYS && r != -EAGAIN)
|
||||
DRM_ERROR("Failed to process the buffer list %d!\n", r);
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ int amdgpu_allocate_static_csa(struct amdgpu_device *adev, struct amdgpu_bo **bo
|
|||
return -ENOMEM;
|
||||
|
||||
memset(ptr, 0, size);
|
||||
adev->virt.csa_cpu_addr = ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -79,7 +80,7 @@ int amdgpu_map_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
list_add(&csa_tv.head, &list);
|
||||
amdgpu_vm_get_pd_bo(vm, &list, &pd);
|
||||
|
||||
r = ttm_eu_reserve_buffers(&ticket, &list, true, NULL, true);
|
||||
r = ttm_eu_reserve_buffers(&ticket, &list, true, NULL, false);
|
||||
if (r) {
|
||||
DRM_ERROR("failed to reserve CSA,PD BOs: err=%d\n", r);
|
||||
return r;
|
||||
|
|
|
@ -923,17 +923,195 @@ static const struct drm_info_list amdgpu_debugfs_list[] = {
|
|||
{"amdgpu_evict_gtt", &amdgpu_debugfs_evict_gtt},
|
||||
};
|
||||
|
||||
static void amdgpu_ib_preempt_fences_swap(struct amdgpu_ring *ring,
|
||||
struct dma_fence **fences)
|
||||
{
|
||||
struct amdgpu_fence_driver *drv = &ring->fence_drv;
|
||||
uint32_t sync_seq, last_seq;
|
||||
|
||||
last_seq = atomic_read(&ring->fence_drv.last_seq);
|
||||
sync_seq = ring->fence_drv.sync_seq;
|
||||
|
||||
last_seq &= drv->num_fences_mask;
|
||||
sync_seq &= drv->num_fences_mask;
|
||||
|
||||
do {
|
||||
struct dma_fence *fence, **ptr;
|
||||
|
||||
++last_seq;
|
||||
last_seq &= drv->num_fences_mask;
|
||||
ptr = &drv->fences[last_seq];
|
||||
|
||||
fence = rcu_dereference_protected(*ptr, 1);
|
||||
RCU_INIT_POINTER(*ptr, NULL);
|
||||
|
||||
if (!fence)
|
||||
continue;
|
||||
|
||||
fences[last_seq] = fence;
|
||||
|
||||
} while (last_seq != sync_seq);
|
||||
}
|
||||
|
||||
static void amdgpu_ib_preempt_signal_fences(struct dma_fence **fences,
|
||||
int length)
|
||||
{
|
||||
int i;
|
||||
struct dma_fence *fence;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
fence = fences[i];
|
||||
if (!fence)
|
||||
continue;
|
||||
dma_fence_signal(fence);
|
||||
dma_fence_put(fence);
|
||||
}
|
||||
}
|
||||
|
||||
static void amdgpu_ib_preempt_job_recovery(struct drm_gpu_scheduler *sched)
|
||||
{
|
||||
struct drm_sched_job *s_job;
|
||||
struct dma_fence *fence;
|
||||
|
||||
spin_lock(&sched->job_list_lock);
|
||||
list_for_each_entry(s_job, &sched->ring_mirror_list, node) {
|
||||
fence = sched->ops->run_job(s_job);
|
||||
dma_fence_put(fence);
|
||||
}
|
||||
spin_unlock(&sched->job_list_lock);
|
||||
}
|
||||
|
||||
static void amdgpu_ib_preempt_mark_partial_job(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_job *job;
|
||||
struct drm_sched_job *s_job;
|
||||
uint32_t preempt_seq;
|
||||
struct dma_fence *fence, **ptr;
|
||||
struct amdgpu_fence_driver *drv = &ring->fence_drv;
|
||||
struct drm_gpu_scheduler *sched = &ring->sched;
|
||||
|
||||
if (ring->funcs->type != AMDGPU_RING_TYPE_GFX)
|
||||
return;
|
||||
|
||||
preempt_seq = le32_to_cpu(*(drv->cpu_addr + 2));
|
||||
if (preempt_seq <= atomic_read(&drv->last_seq))
|
||||
return;
|
||||
|
||||
preempt_seq &= drv->num_fences_mask;
|
||||
ptr = &drv->fences[preempt_seq];
|
||||
fence = rcu_dereference_protected(*ptr, 1);
|
||||
|
||||
spin_lock(&sched->job_list_lock);
|
||||
list_for_each_entry(s_job, &sched->ring_mirror_list, node) {
|
||||
job = to_amdgpu_job(s_job);
|
||||
if (job->fence == fence)
|
||||
/* mark the job as preempted */
|
||||
job->preemption_status |= AMDGPU_IB_PREEMPTED;
|
||||
}
|
||||
spin_unlock(&sched->job_list_lock);
|
||||
}
|
||||
|
||||
static int amdgpu_debugfs_ib_preempt(void *data, u64 val)
|
||||
{
|
||||
int r, resched, length;
|
||||
struct amdgpu_ring *ring;
|
||||
struct dma_fence **fences = NULL;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)data;
|
||||
|
||||
if (val >= AMDGPU_MAX_RINGS)
|
||||
return -EINVAL;
|
||||
|
||||
ring = adev->rings[val];
|
||||
|
||||
if (!ring || !ring->funcs->preempt_ib || !ring->sched.thread)
|
||||
return -EINVAL;
|
||||
|
||||
/* the last preemption failed */
|
||||
if (ring->trail_seq != le32_to_cpu(*ring->trail_fence_cpu_addr))
|
||||
return -EBUSY;
|
||||
|
||||
length = ring->fence_drv.num_fences_mask + 1;
|
||||
fences = kcalloc(length, sizeof(void *), GFP_KERNEL);
|
||||
if (!fences)
|
||||
return -ENOMEM;
|
||||
|
||||
/* stop the scheduler */
|
||||
kthread_park(ring->sched.thread);
|
||||
|
||||
resched = ttm_bo_lock_delayed_workqueue(&adev->mman.bdev);
|
||||
|
||||
/* preempt the IB */
|
||||
r = amdgpu_ring_preempt_ib(ring);
|
||||
if (r) {
|
||||
DRM_WARN("failed to preempt ring %d\n", ring->idx);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
amdgpu_fence_process(ring);
|
||||
|
||||
if (atomic_read(&ring->fence_drv.last_seq) !=
|
||||
ring->fence_drv.sync_seq) {
|
||||
DRM_INFO("ring %d was preempted\n", ring->idx);
|
||||
|
||||
amdgpu_ib_preempt_mark_partial_job(ring);
|
||||
|
||||
/* swap out the old fences */
|
||||
amdgpu_ib_preempt_fences_swap(ring, fences);
|
||||
|
||||
amdgpu_fence_driver_force_completion(ring);
|
||||
|
||||
/* resubmit unfinished jobs */
|
||||
amdgpu_ib_preempt_job_recovery(&ring->sched);
|
||||
|
||||
/* wait for jobs finished */
|
||||
amdgpu_fence_wait_empty(ring);
|
||||
|
||||
/* signal the old fences */
|
||||
amdgpu_ib_preempt_signal_fences(fences, length);
|
||||
}
|
||||
|
||||
failure:
|
||||
/* restart the scheduler */
|
||||
kthread_unpark(ring->sched.thread);
|
||||
|
||||
ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched);
|
||||
|
||||
if (fences)
|
||||
kfree(fences);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(fops_ib_preempt, NULL,
|
||||
amdgpu_debugfs_ib_preempt, "%llu\n");
|
||||
|
||||
int amdgpu_debugfs_init(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->debugfs_preempt =
|
||||
debugfs_create_file("amdgpu_preempt_ib", 0600,
|
||||
adev->ddev->primary->debugfs_root,
|
||||
(void *)adev, &fops_ib_preempt);
|
||||
if (!(adev->debugfs_preempt)) {
|
||||
DRM_ERROR("unable to create amdgpu_preempt_ib debugsfs file\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_list,
|
||||
ARRAY_SIZE(amdgpu_debugfs_list));
|
||||
}
|
||||
|
||||
void amdgpu_debugfs_preempt_cleanup(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->debugfs_preempt)
|
||||
debugfs_remove(adev->debugfs_preempt);
|
||||
}
|
||||
|
||||
#else
|
||||
int amdgpu_debugfs_init(struct amdgpu_device *adev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void amdgpu_debugfs_preempt_cleanup(struct amdgpu_device *adev) { }
|
||||
int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -34,6 +34,7 @@ struct amdgpu_debugfs {
|
|||
int amdgpu_debugfs_regs_init(struct amdgpu_device *adev);
|
||||
void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev);
|
||||
int amdgpu_debugfs_init(struct amdgpu_device *adev);
|
||||
void amdgpu_debugfs_preempt_cleanup(struct amdgpu_device *adev);
|
||||
int amdgpu_debugfs_add_files(struct amdgpu_device *adev,
|
||||
const struct drm_info_list *files,
|
||||
unsigned nfiles);
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#endif
|
||||
#include "vi.h"
|
||||
#include "soc15.h"
|
||||
#include "nv.h"
|
||||
#include "bif/bif_4_1_d.h"
|
||||
#include <linux/pci.h>
|
||||
#include <linux/firmware.h>
|
||||
|
@ -62,12 +63,14 @@
|
|||
|
||||
#include "amdgpu_xgmi.h"
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_pmu.h"
|
||||
|
||||
MODULE_FIRMWARE("amdgpu/vega10_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/vega12_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/raven_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/picasso_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/raven2_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/navi10_gpu_info.bin");
|
||||
|
||||
#define AMDGPU_RESUME_MS 2000
|
||||
|
||||
|
@ -95,6 +98,7 @@ static const char *amdgpu_asic_name[] = {
|
|||
"VEGA12",
|
||||
"VEGA20",
|
||||
"RAVEN",
|
||||
"NAVI10",
|
||||
"LAST",
|
||||
};
|
||||
|
||||
|
@ -507,7 +511,10 @@ void amdgpu_device_program_register_sequence(struct amdgpu_device *adev,
|
|||
} else {
|
||||
tmp = RREG32(reg);
|
||||
tmp &= ~and_mask;
|
||||
tmp |= or_mask;
|
||||
if (adev->family >= AMDGPU_FAMILY_AI)
|
||||
tmp |= (or_mask & and_mask);
|
||||
else
|
||||
tmp |= or_mask;
|
||||
}
|
||||
WREG32(reg, tmp);
|
||||
}
|
||||
|
@ -974,13 +981,6 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev)
|
|||
|
||||
amdgpu_device_check_block_size(adev);
|
||||
|
||||
if (amdgpu_vram_page_split != -1 && (amdgpu_vram_page_split < 16 ||
|
||||
!is_power_of_2(amdgpu_vram_page_split))) {
|
||||
dev_warn(adev->dev, "invalid VRAM page split (%d)\n",
|
||||
amdgpu_vram_page_split);
|
||||
amdgpu_vram_page_split = 1024;
|
||||
}
|
||||
|
||||
ret = amdgpu_device_get_job_timeout_settings(adev);
|
||||
if (ret) {
|
||||
dev_err(adev->dev, "invalid lockup_timeout parameter syntax\n");
|
||||
|
@ -1384,6 +1384,9 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
|
|||
else
|
||||
chip_name = "raven";
|
||||
break;
|
||||
case CHIP_NAVI10:
|
||||
chip_name = "navi10";
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_gpu_info.bin", chip_name);
|
||||
|
@ -1430,6 +1433,23 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
|
|||
adev->gfx.cu_info.max_scratch_slots_per_cu =
|
||||
le32_to_cpu(gpu_info_fw->gc_max_scratch_slots_per_cu);
|
||||
adev->gfx.cu_info.lds_size = le32_to_cpu(gpu_info_fw->gc_lds_size);
|
||||
if (hdr->version_minor >= 1) {
|
||||
const struct gpu_info_firmware_v1_1 *gpu_info_fw =
|
||||
(const struct gpu_info_firmware_v1_1 *)(adev->firmware.gpu_info_fw->data +
|
||||
le32_to_cpu(hdr->header.ucode_array_offset_bytes));
|
||||
adev->gfx.config.num_sc_per_sh =
|
||||
le32_to_cpu(gpu_info_fw->num_sc_per_sh);
|
||||
adev->gfx.config.num_packer_per_sc =
|
||||
le32_to_cpu(gpu_info_fw->num_packer_per_sc);
|
||||
}
|
||||
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
|
||||
if (hdr->version_minor == 2) {
|
||||
const struct gpu_info_firmware_v1_2 *gpu_info_fw =
|
||||
(const struct gpu_info_firmware_v1_2 *)(adev->firmware.gpu_info_fw->data +
|
||||
le32_to_cpu(hdr->header.ucode_array_offset_bytes));
|
||||
adev->dm.soc_bounding_box = &gpu_info_fw->soc_bounding_box;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -1518,6 +1538,13 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
|||
if (r)
|
||||
return r;
|
||||
break;
|
||||
case CHIP_NAVI10:
|
||||
adev->family = AMDGPU_FAMILY_NV;
|
||||
|
||||
r = nv_set_ip_blocks(adev);
|
||||
if (r)
|
||||
return r;
|
||||
break;
|
||||
default:
|
||||
/* FIXME: not supported yet */
|
||||
return -EINVAL;
|
||||
|
@ -1542,17 +1569,6 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
|||
if (amdgpu_sriov_vf(adev))
|
||||
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
|
||||
|
||||
/* Read BIOS */
|
||||
if (!amdgpu_get_bios(adev))
|
||||
return -EINVAL;
|
||||
|
||||
r = amdgpu_atombios_init(adev);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "amdgpu_atombios_init failed\n");
|
||||
amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_INIT_FAIL, 0, 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
for (i = 0; i < adev->num_ip_blocks; i++) {
|
||||
if ((amdgpu_ip_block_mask & (1 << i)) == 0) {
|
||||
DRM_ERROR("disabled ip block: %d <%s>\n",
|
||||
|
@ -1574,6 +1590,19 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
|||
adev->ip_blocks[i].status.valid = true;
|
||||
}
|
||||
}
|
||||
/* get the vbios after the asic_funcs are set up */
|
||||
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON) {
|
||||
/* Read BIOS */
|
||||
if (!amdgpu_get_bios(adev))
|
||||
return -EINVAL;
|
||||
|
||||
r = amdgpu_atombios_init(adev);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "amdgpu_atombios_init failed\n");
|
||||
amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_INIT_FAIL, 0, 0);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
adev->cg_flags &= amdgpu_cg_mask;
|
||||
|
@ -1713,7 +1742,7 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
|||
adev->ip_blocks[i].status.hw = true;
|
||||
|
||||
/* right after GMC hw init, we create CSA */
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) {
|
||||
r = amdgpu_allocate_static_csa(adev, &adev->virt.csa_obj,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
AMDGPU_CSA_SIZE);
|
||||
|
@ -2394,6 +2423,9 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
|
|||
case CHIP_VEGA20:
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
|
||||
case CHIP_RAVEN:
|
||||
#endif
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
|
||||
case CHIP_NAVI10:
|
||||
#endif
|
||||
return amdgpu_dc != 0;
|
||||
#endif
|
||||
|
@ -2566,6 +2598,20 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||
|
||||
amdgpu_device_get_pcie_info(adev);
|
||||
|
||||
if (amdgpu_mcbp)
|
||||
DRM_INFO("MCBP is enabled\n");
|
||||
|
||||
if (amdgpu_mes && adev->asic_type >= CHIP_NAVI10)
|
||||
adev->enable_mes = true;
|
||||
|
||||
if (amdgpu_discovery) {
|
||||
r = amdgpu_discovery_init(adev);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "amdgpu_discovery_init failed\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* early init functions */
|
||||
r = amdgpu_device_ip_early_init(adev);
|
||||
if (r)
|
||||
|
@ -2690,6 +2736,9 @@ fence_driver_init:
|
|||
|
||||
amdgpu_fbdev_init(adev);
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && amdgim_is_hwperf(adev))
|
||||
amdgpu_pm_virt_sysfs_init(adev);
|
||||
|
||||
r = amdgpu_pm_sysfs_init(adev);
|
||||
if (r)
|
||||
DRM_ERROR("registering pm debugfs failed (%d).\n", r);
|
||||
|
@ -2749,6 +2798,10 @@ fence_driver_init:
|
|||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_pmu_init(adev);
|
||||
if (r)
|
||||
dev_err(adev->dev, "amdgpu_pmu_init failed\n");
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
|
@ -2811,9 +2864,16 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
|
|||
iounmap(adev->rmmio);
|
||||
adev->rmmio = NULL;
|
||||
amdgpu_device_doorbell_fini(adev);
|
||||
if (amdgpu_sriov_vf(adev) && amdgim_is_hwperf(adev))
|
||||
amdgpu_pm_virt_sysfs_fini(adev);
|
||||
|
||||
amdgpu_debugfs_regs_cleanup(adev);
|
||||
device_remove_file(adev->dev, &dev_attr_pcie_replay_count);
|
||||
amdgpu_ucode_sysfs_fini(adev);
|
||||
amdgpu_pmu_fini(adev);
|
||||
amdgpu_debugfs_preempt_cleanup(adev);
|
||||
if (amdgpu_discovery)
|
||||
amdgpu_discovery_fini(adev);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,415 @@
|
|||
/*
|
||||
* Copyright 2018 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_discovery.h"
|
||||
#include "soc15_common.h"
|
||||
#include "soc15_hw_ip.h"
|
||||
#include "nbio/nbio_2_3_offset.h"
|
||||
#include "discovery.h"
|
||||
|
||||
#define mmRCC_CONFIG_MEMSIZE 0xde3
|
||||
#define mmMM_INDEX 0x0
|
||||
#define mmMM_INDEX_HI 0x6
|
||||
#define mmMM_DATA 0x1
|
||||
#define HW_ID_MAX 300
|
||||
|
||||
const char *hw_id_names[HW_ID_MAX] = {
|
||||
[MP1_HWID] = "MP1",
|
||||
[MP2_HWID] = "MP2",
|
||||
[THM_HWID] = "THM",
|
||||
[SMUIO_HWID] = "SMUIO",
|
||||
[FUSE_HWID] = "FUSE",
|
||||
[CLKA_HWID] = "CLKA",
|
||||
[PWR_HWID] = "PWR",
|
||||
[GC_HWID] = "GC",
|
||||
[UVD_HWID] = "UVD",
|
||||
[AUDIO_AZ_HWID] = "AUDIO_AZ",
|
||||
[ACP_HWID] = "ACP",
|
||||
[DCI_HWID] = "DCI",
|
||||
[DMU_HWID] = "DMU",
|
||||
[DCO_HWID] = "DCO",
|
||||
[DIO_HWID] = "DIO",
|
||||
[XDMA_HWID] = "XDMA",
|
||||
[DCEAZ_HWID] = "DCEAZ",
|
||||
[DAZ_HWID] = "DAZ",
|
||||
[SDPMUX_HWID] = "SDPMUX",
|
||||
[NTB_HWID] = "NTB",
|
||||
[IOHC_HWID] = "IOHC",
|
||||
[L2IMU_HWID] = "L2IMU",
|
||||
[VCE_HWID] = "VCE",
|
||||
[MMHUB_HWID] = "MMHUB",
|
||||
[ATHUB_HWID] = "ATHUB",
|
||||
[DBGU_NBIO_HWID] = "DBGU_NBIO",
|
||||
[DFX_HWID] = "DFX",
|
||||
[DBGU0_HWID] = "DBGU0",
|
||||
[DBGU1_HWID] = "DBGU1",
|
||||
[OSSSYS_HWID] = "OSSSYS",
|
||||
[HDP_HWID] = "HDP",
|
||||
[SDMA0_HWID] = "SDMA0",
|
||||
[SDMA1_HWID] = "SDMA1",
|
||||
[ISP_HWID] = "ISP",
|
||||
[DBGU_IO_HWID] = "DBGU_IO",
|
||||
[DF_HWID] = "DF",
|
||||
[CLKB_HWID] = "CLKB",
|
||||
[FCH_HWID] = "FCH",
|
||||
[DFX_DAP_HWID] = "DFX_DAP",
|
||||
[L1IMU_PCIE_HWID] = "L1IMU_PCIE",
|
||||
[L1IMU_NBIF_HWID] = "L1IMU_NBIF",
|
||||
[L1IMU_IOAGR_HWID] = "L1IMU_IOAGR",
|
||||
[L1IMU3_HWID] = "L1IMU3",
|
||||
[L1IMU4_HWID] = "L1IMU4",
|
||||
[L1IMU5_HWID] = "L1IMU5",
|
||||
[L1IMU6_HWID] = "L1IMU6",
|
||||
[L1IMU7_HWID] = "L1IMU7",
|
||||
[L1IMU8_HWID] = "L1IMU8",
|
||||
[L1IMU9_HWID] = "L1IMU9",
|
||||
[L1IMU10_HWID] = "L1IMU10",
|
||||
[L1IMU11_HWID] = "L1IMU11",
|
||||
[L1IMU12_HWID] = "L1IMU12",
|
||||
[L1IMU13_HWID] = "L1IMU13",
|
||||
[L1IMU14_HWID] = "L1IMU14",
|
||||
[L1IMU15_HWID] = "L1IMU15",
|
||||
[WAFLC_HWID] = "WAFLC",
|
||||
[FCH_USB_PD_HWID] = "FCH_USB_PD",
|
||||
[PCIE_HWID] = "PCIE",
|
||||
[PCS_HWID] = "PCS",
|
||||
[DDCL_HWID] = "DDCL",
|
||||
[SST_HWID] = "SST",
|
||||
[IOAGR_HWID] = "IOAGR",
|
||||
[NBIF_HWID] = "NBIF",
|
||||
[IOAPIC_HWID] = "IOAPIC",
|
||||
[SYSTEMHUB_HWID] = "SYSTEMHUB",
|
||||
[NTBCCP_HWID] = "NTBCCP",
|
||||
[UMC_HWID] = "UMC",
|
||||
[SATA_HWID] = "SATA",
|
||||
[USB_HWID] = "USB",
|
||||
[CCXSEC_HWID] = "CCXSEC",
|
||||
[XGMI_HWID] = "XGMI",
|
||||
[XGBE_HWID] = "XGBE",
|
||||
[MP0_HWID] = "MP0",
|
||||
};
|
||||
|
||||
static int hw_id_map[MAX_HWIP] = {
|
||||
[GC_HWIP] = GC_HWID,
|
||||
[HDP_HWIP] = HDP_HWID,
|
||||
[SDMA0_HWIP] = SDMA0_HWID,
|
||||
[SDMA1_HWIP] = SDMA1_HWID,
|
||||
[MMHUB_HWIP] = MMHUB_HWID,
|
||||
[ATHUB_HWIP] = ATHUB_HWID,
|
||||
[NBIO_HWIP] = NBIF_HWID,
|
||||
[MP0_HWIP] = MP0_HWID,
|
||||
[MP1_HWIP] = MP1_HWID,
|
||||
[UVD_HWIP] = UVD_HWID,
|
||||
[VCE_HWIP] = VCE_HWID,
|
||||
[DF_HWIP] = DF_HWID,
|
||||
[DCE_HWIP] = DCEAZ_HWID,
|
||||
[OSSSYS_HWIP] = OSSSYS_HWID,
|
||||
[SMUIO_HWIP] = SMUIO_HWID,
|
||||
[PWR_HWIP] = PWR_HWID,
|
||||
[NBIF_HWIP] = NBIF_HWID,
|
||||
[THM_HWIP] = THM_HWID,
|
||||
[CLK_HWIP] = CLKA_HWID,
|
||||
};
|
||||
|
||||
static int amdgpu_discovery_read_binary(struct amdgpu_device *adev, uint8_t *binary)
|
||||
{
|
||||
uint32_t *p = (uint32_t *)binary;
|
||||
uint64_t vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
|
||||
uint64_t pos = vram_size - BINARY_MAX_SIZE;
|
||||
unsigned long flags;
|
||||
|
||||
while (pos < vram_size) {
|
||||
spin_lock_irqsave(&adev->mmio_idx_lock, flags);
|
||||
WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)pos) | 0x80000000);
|
||||
WREG32_NO_KIQ(mmMM_INDEX_HI, pos >> 31);
|
||||
*p++ = RREG32_NO_KIQ(mmMM_DATA);
|
||||
spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
|
||||
pos += 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint16_t amdgpu_discovery_calculate_checksum(uint8_t *data, uint32_t size)
|
||||
{
|
||||
uint16_t checksum = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
checksum += data[i];
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
static inline bool amdgpu_discovery_verify_checksum(uint8_t *data, uint32_t size,
|
||||
uint16_t expected)
|
||||
{
|
||||
return !!(amdgpu_discovery_calculate_checksum(data, size) == expected);
|
||||
}
|
||||
|
||||
int amdgpu_discovery_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct table_info *info;
|
||||
struct binary_header *bhdr;
|
||||
struct ip_discovery_header *ihdr;
|
||||
struct gpu_info_header *ghdr;
|
||||
uint16_t offset;
|
||||
uint16_t size;
|
||||
uint16_t checksum;
|
||||
int r;
|
||||
|
||||
adev->discovery = kzalloc(BINARY_MAX_SIZE, GFP_KERNEL);
|
||||
if (!adev->discovery)
|
||||
return -ENOMEM;
|
||||
|
||||
r = amdgpu_discovery_read_binary(adev, adev->discovery);
|
||||
if (r) {
|
||||
DRM_ERROR("failed to read ip discovery binary\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
bhdr = (struct binary_header *)adev->discovery;
|
||||
|
||||
if (le32_to_cpu(bhdr->binary_signature) != BINARY_SIGNATURE) {
|
||||
DRM_ERROR("invalid ip discovery binary signature\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
offset = offsetof(struct binary_header, binary_checksum) +
|
||||
sizeof(bhdr->binary_checksum);
|
||||
size = bhdr->binary_size - offset;
|
||||
checksum = bhdr->binary_checksum;
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(adev->discovery + offset,
|
||||
size, checksum)) {
|
||||
DRM_ERROR("invalid ip discovery binary checksum\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
info = &bhdr->table_list[IP_DISCOVERY];
|
||||
offset = le16_to_cpu(info->offset);
|
||||
checksum = le16_to_cpu(info->checksum);
|
||||
ihdr = (struct ip_discovery_header *)(adev->discovery + offset);
|
||||
|
||||
if (le32_to_cpu(ihdr->signature) != DISCOVERY_TABLE_SIGNATURE) {
|
||||
DRM_ERROR("invalid ip discovery data table signature\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(adev->discovery + offset,
|
||||
ihdr->size, checksum)) {
|
||||
DRM_ERROR("invalid ip discovery data table checksum\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
info = &bhdr->table_list[GC];
|
||||
offset = le16_to_cpu(info->offset);
|
||||
checksum = le16_to_cpu(info->checksum);
|
||||
ghdr = (struct gpu_info_header *)(adev->discovery + offset);
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(adev->discovery + offset,
|
||||
ghdr->size, checksum)) {
|
||||
DRM_ERROR("invalid gc data table checksum\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
kfree(adev->discovery);
|
||||
adev->discovery = NULL;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void amdgpu_discovery_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
kfree(adev->discovery);
|
||||
adev->discovery = NULL;
|
||||
}
|
||||
|
||||
int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct binary_header *bhdr;
|
||||
struct ip_discovery_header *ihdr;
|
||||
struct die_header *dhdr;
|
||||
struct ip *ip;
|
||||
uint16_t die_offset;
|
||||
uint16_t ip_offset;
|
||||
uint16_t num_dies;
|
||||
uint16_t num_ips;
|
||||
uint8_t num_base_address;
|
||||
int hw_ip;
|
||||
int i, j, k;
|
||||
|
||||
if (!adev->discovery) {
|
||||
DRM_ERROR("ip discovery uninitialized\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bhdr = (struct binary_header *)adev->discovery;
|
||||
ihdr = (struct ip_discovery_header *)(adev->discovery +
|
||||
le16_to_cpu(bhdr->table_list[IP_DISCOVERY].offset));
|
||||
num_dies = le16_to_cpu(ihdr->num_dies);
|
||||
|
||||
DRM_DEBUG("number of dies: %d\n", num_dies);
|
||||
|
||||
for (i = 0; i < num_dies; i++) {
|
||||
die_offset = le16_to_cpu(ihdr->die_info[i].die_offset);
|
||||
dhdr = (struct die_header *)(adev->discovery + die_offset);
|
||||
num_ips = le16_to_cpu(dhdr->num_ips);
|
||||
ip_offset = die_offset + sizeof(*dhdr);
|
||||
|
||||
if (le16_to_cpu(dhdr->die_id) != i) {
|
||||
DRM_ERROR("invalid die id %d, expected %d\n",
|
||||
le16_to_cpu(dhdr->die_id), i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG("number of hardware IPs on die%d: %d\n",
|
||||
le16_to_cpu(dhdr->die_id), num_ips);
|
||||
|
||||
for (j = 0; j < num_ips; j++) {
|
||||
ip = (struct ip *)(adev->discovery + ip_offset);
|
||||
num_base_address = ip->num_base_address;
|
||||
|
||||
DRM_DEBUG("%s(%d) #%d v%d.%d.%d:\n",
|
||||
hw_id_names[le16_to_cpu(ip->hw_id)],
|
||||
le16_to_cpu(ip->hw_id),
|
||||
ip->number_instance,
|
||||
ip->major, ip->minor,
|
||||
ip->revision);
|
||||
|
||||
for (k = 0; k < num_base_address; k++) {
|
||||
/*
|
||||
* convert the endianness of base addresses in place,
|
||||
* so that we don't need to convert them when accessing adev->reg_offset.
|
||||
*/
|
||||
ip->base_address[k] = le32_to_cpu(ip->base_address[k]);
|
||||
DRM_DEBUG("\t0x%08x\n", ip->base_address[k]);
|
||||
}
|
||||
|
||||
for (hw_ip = 0; hw_ip < MAX_HWIP; hw_ip++) {
|
||||
if (hw_id_map[hw_ip] == le16_to_cpu(ip->hw_id)) {
|
||||
DRM_INFO("set register base offset for %s\n",
|
||||
hw_id_names[le16_to_cpu(ip->hw_id)]);
|
||||
adev->reg_offset[hw_ip][ip->number_instance] =
|
||||
ip->base_address;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ip_offset += sizeof(*ip) + 4 * (ip->num_base_address - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id,
|
||||
int *major, int *minor)
|
||||
{
|
||||
struct binary_header *bhdr;
|
||||
struct ip_discovery_header *ihdr;
|
||||
struct die_header *dhdr;
|
||||
struct ip *ip;
|
||||
uint16_t die_offset;
|
||||
uint16_t ip_offset;
|
||||
uint16_t num_dies;
|
||||
uint16_t num_ips;
|
||||
int i, j;
|
||||
|
||||
if (!adev->discovery) {
|
||||
DRM_ERROR("ip discovery uninitialized\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bhdr = (struct binary_header *)adev->discovery;
|
||||
ihdr = (struct ip_discovery_header *)(adev->discovery +
|
||||
le16_to_cpu(bhdr->table_list[IP_DISCOVERY].offset));
|
||||
num_dies = le16_to_cpu(ihdr->num_dies);
|
||||
|
||||
for (i = 0; i < num_dies; i++) {
|
||||
die_offset = le16_to_cpu(ihdr->die_info[i].die_offset);
|
||||
dhdr = (struct die_header *)(adev->discovery + die_offset);
|
||||
num_ips = le16_to_cpu(dhdr->num_ips);
|
||||
ip_offset = die_offset + sizeof(*dhdr);
|
||||
|
||||
for (j = 0; j < num_ips; j++) {
|
||||
ip = (struct ip *)(adev->discovery + ip_offset);
|
||||
|
||||
if (le16_to_cpu(ip->hw_id) == hw_id) {
|
||||
if (major)
|
||||
*major = ip->major;
|
||||
if (minor)
|
||||
*minor = ip->minor;
|
||||
return 0;
|
||||
}
|
||||
ip_offset += sizeof(*ip) + 4 * (ip->num_base_address - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev)
|
||||
{
|
||||
struct binary_header *bhdr;
|
||||
struct gc_info_v1_0 *gc_info;
|
||||
|
||||
if (!adev->discovery) {
|
||||
DRM_ERROR("ip discovery uninitialized\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bhdr = (struct binary_header *)adev->discovery;
|
||||
gc_info = (struct gc_info_v1_0 *)(adev->discovery +
|
||||
le16_to_cpu(bhdr->table_list[GC].offset));
|
||||
|
||||
adev->gfx.config.max_shader_engines = le32_to_cpu(gc_info->gc_num_se);
|
||||
adev->gfx.config.max_cu_per_sh = 2 * (le32_to_cpu(gc_info->gc_num_wgp0_per_sa) +
|
||||
le32_to_cpu(gc_info->gc_num_wgp1_per_sa));
|
||||
adev->gfx.config.max_sh_per_se = le32_to_cpu(gc_info->gc_num_sa_per_se);
|
||||
adev->gfx.config.max_backends_per_se = le32_to_cpu(gc_info->gc_num_rb_per_se);
|
||||
adev->gfx.config.max_texture_channel_caches = le32_to_cpu(gc_info->gc_num_gl2c);
|
||||
adev->gfx.config.max_gprs = le32_to_cpu(gc_info->gc_num_gprs);
|
||||
adev->gfx.config.max_gs_threads = le32_to_cpu(gc_info->gc_num_max_gs_thds);
|
||||
adev->gfx.config.gs_vgt_table_depth = le32_to_cpu(gc_info->gc_gs_table_depth);
|
||||
adev->gfx.config.gs_prim_buffer_depth = le32_to_cpu(gc_info->gc_gsprim_buff_depth);
|
||||
adev->gfx.config.double_offchip_lds_buf = le32_to_cpu(gc_info->gc_double_offchip_lds_buffer);
|
||||
adev->gfx.cu_info.wave_front_size = le32_to_cpu(gc_info->gc_wave_size);
|
||||
adev->gfx.cu_info.max_waves_per_simd = le32_to_cpu(gc_info->gc_max_waves_per_simd);
|
||||
adev->gfx.cu_info.max_scratch_slots_per_cu = le32_to_cpu(gc_info->gc_max_scratch_slots_per_cu);
|
||||
adev->gfx.cu_info.lds_size = le32_to_cpu(gc_info->gc_lds_size);
|
||||
adev->gfx.config.num_sc_per_sh = le32_to_cpu(gc_info->gc_num_sc_per_se) /
|
||||
le32_to_cpu(gc_info->gc_num_sa_per_se);
|
||||
adev->gfx.config.num_packer_per_sc = le32_to_cpu(gc_info->gc_num_packer_per_sc);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright 2018 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __AMDGPU_DISCOVERY__
|
||||
#define __AMDGPU_DISCOVERY__
|
||||
|
||||
int amdgpu_discovery_init(struct amdgpu_device *adev);
|
||||
void amdgpu_discovery_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev);
|
||||
int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id,
|
||||
int *major, int *minor);
|
||||
int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev);
|
||||
|
||||
#endif /* __AMDGPU_DISCOVERY__ */
|
|
@ -51,6 +51,7 @@ struct amdgpu_doorbell_index {
|
|||
uint32_t userqueue_start;
|
||||
uint32_t userqueue_end;
|
||||
uint32_t gfx_ring0;
|
||||
uint32_t gfx_ring1;
|
||||
uint32_t sdma_engine[8];
|
||||
uint32_t ih;
|
||||
union {
|
||||
|
@ -153,6 +154,45 @@ typedef enum _AMDGPU_VEGA20_DOORBELL_ASSIGNMENT
|
|||
AMDGPU_VEGA20_DOORBELL_INVALID = 0xFFFF
|
||||
} AMDGPU_VEGA20_DOORBELL_ASSIGNMENT;
|
||||
|
||||
typedef enum _AMDGPU_NAVI10_DOORBELL_ASSIGNMENT
|
||||
{
|
||||
/* Compute + GFX: 0~255 */
|
||||
AMDGPU_NAVI10_DOORBELL_KIQ = 0x000,
|
||||
AMDGPU_NAVI10_DOORBELL_HIQ = 0x001,
|
||||
AMDGPU_NAVI10_DOORBELL_DIQ = 0x002,
|
||||
AMDGPU_NAVI10_DOORBELL_MEC_RING0 = 0x003,
|
||||
AMDGPU_NAVI10_DOORBELL_MEC_RING1 = 0x004,
|
||||
AMDGPU_NAVI10_DOORBELL_MEC_RING2 = 0x005,
|
||||
AMDGPU_NAVI10_DOORBELL_MEC_RING3 = 0x006,
|
||||
AMDGPU_NAVI10_DOORBELL_MEC_RING4 = 0x007,
|
||||
AMDGPU_NAVI10_DOORBELL_MEC_RING5 = 0x008,
|
||||
AMDGPU_NAVI10_DOORBELL_MEC_RING6 = 0x009,
|
||||
AMDGPU_NAVI10_DOORBELL_MEC_RING7 = 0x00A,
|
||||
AMDGPU_NAVI10_DOORBELL_USERQUEUE_START = 0x00B,
|
||||
AMDGPU_NAVI10_DOORBELL_USERQUEUE_END = 0x08A,
|
||||
AMDGPU_NAVI10_DOORBELL_GFX_RING0 = 0x08B,
|
||||
AMDGPU_NAVI10_DOORBELL_GFX_RING1 = 0x08C,
|
||||
/* SDMA:256~335*/
|
||||
AMDGPU_NAVI10_DOORBELL_sDMA_ENGINE0 = 0x100,
|
||||
AMDGPU_NAVI10_DOORBELL_sDMA_ENGINE1 = 0x10A,
|
||||
/* IH: 376~391 */
|
||||
AMDGPU_NAVI10_DOORBELL_IH = 0x178,
|
||||
/* MMSCH: 392~407
|
||||
* overlap the doorbell assignment with VCN as they are mutually exclusive
|
||||
* VCE engine's doorbell is 32 bit and two VCE ring share one QWORD
|
||||
*/
|
||||
AMDGPU_NAVI10_DOORBELL64_VCN0_1 = 0x188, /* lower 32 bits for VNC0 and upper 32 bits for VNC1 */
|
||||
AMDGPU_NAVI10_DOORBELL64_VCN2_3 = 0x189,
|
||||
AMDGPU_NAVI10_DOORBELL64_VCN4_5 = 0x18A,
|
||||
AMDGPU_NAVI10_DOORBELL64_VCN6_7 = 0x18B,
|
||||
|
||||
AMDGPU_NAVI10_DOORBELL64_FIRST_NON_CP = AMDGPU_NAVI10_DOORBELL_sDMA_ENGINE0,
|
||||
AMDGPU_NAVI10_DOORBELL64_LAST_NON_CP = AMDGPU_NAVI10_DOORBELL64_VCN6_7,
|
||||
|
||||
AMDGPU_NAVI10_DOORBELL_MAX_ASSIGNMENT = 0x18F,
|
||||
AMDGPU_NAVI10_DOORBELL_INVALID = 0xFFFF
|
||||
} AMDGPU_NAVI10_DOORBELL_ASSIGNMENT;
|
||||
|
||||
/*
|
||||
* 64bit doorbell, offset are in QWORD, occupy 2KB doorbell space
|
||||
*/
|
||||
|
|
|
@ -906,16 +906,63 @@ amdgpu_get_vce_clock_state(void *handle, u32 idx)
|
|||
|
||||
int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low)
|
||||
{
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_get_sclk(&adev->smu, low);
|
||||
else
|
||||
uint32_t clk_freq;
|
||||
int ret = 0;
|
||||
if (is_support_sw_smu(adev)) {
|
||||
ret = smu_get_dpm_freq_range(&adev->smu, SMU_GFXCLK,
|
||||
low ? &clk_freq : NULL,
|
||||
!low ? &clk_freq : NULL);
|
||||
if (ret)
|
||||
return 0;
|
||||
return clk_freq * 100;
|
||||
|
||||
} else {
|
||||
return (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (low));
|
||||
}
|
||||
}
|
||||
|
||||
int amdgpu_dpm_get_mclk(struct amdgpu_device *adev, bool low)
|
||||
{
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_get_mclk(&adev->smu, low);
|
||||
else
|
||||
uint32_t clk_freq;
|
||||
int ret = 0;
|
||||
if (is_support_sw_smu(adev)) {
|
||||
ret = smu_get_dpm_freq_range(&adev->smu, SMU_UCLK,
|
||||
low ? &clk_freq : NULL,
|
||||
!low ? &clk_freq : NULL);
|
||||
if (ret)
|
||||
return 0;
|
||||
return clk_freq * 100;
|
||||
|
||||
} else {
|
||||
return (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (low));
|
||||
}
|
||||
}
|
||||
|
||||
int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block_type, bool gate)
|
||||
{
|
||||
int ret = 0;
|
||||
bool swsmu = is_support_sw_smu(adev);
|
||||
|
||||
switch (block_type) {
|
||||
case AMD_IP_BLOCK_TYPE_GFX:
|
||||
case AMD_IP_BLOCK_TYPE_UVD:
|
||||
case AMD_IP_BLOCK_TYPE_VCN:
|
||||
case AMD_IP_BLOCK_TYPE_VCE:
|
||||
if (swsmu)
|
||||
ret = smu_dpm_set_power_gate(&adev->smu, block_type, gate);
|
||||
else
|
||||
ret = ((adev)->powerplay.pp_funcs->set_powergating_by_smu(
|
||||
(adev)->powerplay.pp_handle, block_type, gate));
|
||||
break;
|
||||
case AMD_IP_BLOCK_TYPE_GMC:
|
||||
case AMD_IP_BLOCK_TYPE_ACP:
|
||||
case AMD_IP_BLOCK_TYPE_SDMA:
|
||||
ret = ((adev)->powerplay.pp_funcs->set_powergating_by_smu(
|
||||
(adev)->powerplay.pp_handle, block_type, gate));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -355,10 +355,6 @@ enum amdgpu_pcie_gen {
|
|||
((adev)->powerplay.pp_funcs->set_clockgating_by_smu(\
|
||||
(adev)->powerplay.pp_handle, msg_id))
|
||||
|
||||
#define amdgpu_dpm_set_powergating_by_smu(adev, block_type, gate) \
|
||||
((adev)->powerplay.pp_funcs->set_powergating_by_smu(\
|
||||
(adev)->powerplay.pp_handle, block_type, gate))
|
||||
|
||||
#define amdgpu_dpm_get_power_profile_mode(adev, buf) \
|
||||
((adev)->powerplay.pp_funcs->get_power_profile_mode(\
|
||||
(adev)->powerplay.pp_handle, buf))
|
||||
|
@ -520,6 +516,9 @@ enum amdgpu_pcie_gen amdgpu_get_pcie_gen_support(struct amdgpu_device *adev,
|
|||
struct amd_vce_state*
|
||||
amdgpu_get_vce_clock_state(void *handle, u32 idx);
|
||||
|
||||
int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev,
|
||||
uint32_t block_type, bool gate);
|
||||
|
||||
extern int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low);
|
||||
|
||||
extern int amdgpu_dpm_get_mclk(struct amdgpu_device *adev, bool low);
|
||||
|
|
|
@ -78,9 +78,10 @@
|
|||
* - 3.30.0 - Add AMDGPU_SCHED_OP_CONTEXT_PRIORITY_OVERRIDE.
|
||||
* - 3.31.0 - Add support for per-flip tiling attribute changes with DC
|
||||
* - 3.32.0 - Add syncobj timeline support to AMDGPU_CS.
|
||||
* - 3.33.0 - Fixes for GDS ENOMEM failures in AMDGPU_CS.
|
||||
*/
|
||||
#define KMS_DRIVER_MAJOR 3
|
||||
#define KMS_DRIVER_MINOR 32
|
||||
#define KMS_DRIVER_MINOR 33
|
||||
#define KMS_DRIVER_PATCHLEVEL 0
|
||||
|
||||
#define AMDGPU_MAX_TIMEOUT_PARAM_LENTH 256
|
||||
|
@ -110,7 +111,6 @@ int amdgpu_vm_fragment_size = -1;
|
|||
int amdgpu_vm_block_size = -1;
|
||||
int amdgpu_vm_fault_stop = 0;
|
||||
int amdgpu_vm_debug = 0;
|
||||
int amdgpu_vram_page_split = 512;
|
||||
int amdgpu_vm_update_mode = -1;
|
||||
int amdgpu_exp_hw_support = 0;
|
||||
int amdgpu_dc = -1;
|
||||
|
@ -138,6 +138,10 @@ int amdgpu_emu_mode = 0;
|
|||
uint amdgpu_smu_memory_pool_size = 0;
|
||||
/* FBC (bit 0) disabled by default*/
|
||||
uint amdgpu_dc_feature_mask = 0;
|
||||
int amdgpu_async_gfx_ring = 1;
|
||||
int amdgpu_mcbp = 0;
|
||||
int amdgpu_discovery = 0;
|
||||
int amdgpu_mes = 0;
|
||||
|
||||
struct amdgpu_mgpu_info mgpu_info = {
|
||||
.mutex = __MUTEX_INITIALIZER(mgpu_info.mutex),
|
||||
|
@ -249,7 +253,9 @@ module_param_string(lockup_timeout, amdgpu_lockup_timeout, sizeof(amdgpu_lockup_
|
|||
|
||||
/**
|
||||
* DOC: dpm (int)
|
||||
* Override for dynamic power management setting (1 = enable, 0 = disable). The default is -1 (auto).
|
||||
* Override for dynamic power management setting
|
||||
* (0 = disable, 1 = enable, 2 = enable sw smu driver for vega20)
|
||||
* The default is -1 (auto).
|
||||
*/
|
||||
MODULE_PARM_DESC(dpm, "DPM support (1 = enable, 0 = disable, -1 = auto)");
|
||||
module_param_named(dpm, amdgpu_dpm, int, 0444);
|
||||
|
@ -344,13 +350,6 @@ module_param_named(vm_debug, amdgpu_vm_debug, int, 0644);
|
|||
MODULE_PARM_DESC(vm_update_mode, "VM update using CPU (0 = never (default except for large BAR(LB)), 1 = Graphics only, 2 = Compute only (default for LB), 3 = Both");
|
||||
module_param_named(vm_update_mode, amdgpu_vm_update_mode, int, 0444);
|
||||
|
||||
/**
|
||||
* DOC: vram_page_split (int)
|
||||
* Override the number of pages after we split VRAM allocations (default 512, -1 = disable). The default is 512.
|
||||
*/
|
||||
MODULE_PARM_DESC(vram_page_split, "Number of pages after we split VRAM allocations (default 512, -1 = disable)");
|
||||
module_param_named(vram_page_split, amdgpu_vram_page_split, int, 0444);
|
||||
|
||||
/**
|
||||
* DOC: exp_hw_support (int)
|
||||
* Enable experimental hw support (1 = enable). The default is 0 (disabled).
|
||||
|
@ -574,6 +573,26 @@ MODULE_PARM_DESC(smu_memory_pool_size,
|
|||
"0x1 = 256Mbyte, 0x2 = 512Mbyte, 0x4 = 1 Gbyte, 0x8 = 2GByte");
|
||||
module_param_named(smu_memory_pool_size, amdgpu_smu_memory_pool_size, uint, 0444);
|
||||
|
||||
/**
|
||||
* DOC: async_gfx_ring (int)
|
||||
* It is used to enable gfx rings that could be configured with different prioritites or equal priorities
|
||||
*/
|
||||
MODULE_PARM_DESC(async_gfx_ring,
|
||||
"Asynchronous GFX rings that could be configured with either different priorities (HP3D ring and LP3D ring), or equal priorities (0 = disabled, 1 = enabled (default))");
|
||||
module_param_named(async_gfx_ring, amdgpu_async_gfx_ring, int, 0444);
|
||||
|
||||
MODULE_PARM_DESC(mcbp,
|
||||
"Enable Mid-command buffer preemption (0 = disabled (default), 1 = enabled)");
|
||||
module_param_named(mcbp, amdgpu_mcbp, int, 0444);
|
||||
|
||||
MODULE_PARM_DESC(discovery,
|
||||
"Allow driver to discover hardware IPs from IP Discovery table at the top of VRAM");
|
||||
module_param_named(discovery, amdgpu_discovery, int, 0444);
|
||||
|
||||
MODULE_PARM_DESC(mes,
|
||||
"Enable Micro Engine Scheduler (0 = disabled (default), 1 = enabled)");
|
||||
module_param_named(mes, amdgpu_mes, int, 0444);
|
||||
|
||||
#ifdef CONFIG_HSA_AMD
|
||||
/**
|
||||
* DOC: sched_policy (int)
|
||||
|
@ -678,6 +697,14 @@ MODULE_PARM_DESC(halt_if_hws_hang, "Halt if HWS hang is detected (0 = off (defau
|
|||
bool hws_gws_support;
|
||||
module_param(hws_gws_support, bool, 0444);
|
||||
MODULE_PARM_DESC(hws_gws_support, "MEC FW support gws barriers (false = not supported (Default), true = supported)");
|
||||
|
||||
/**
|
||||
* DOC: queue_preemption_timeout_ms (int)
|
||||
* queue preemption timeout in ms (1 = Minimum, 9000 = default)
|
||||
*/
|
||||
int queue_preemption_timeout_ms;
|
||||
module_param(queue_preemption_timeout_ms, int, 0644);
|
||||
MODULE_PARM_DESC(queue_preemption_timeout_ms, "queue preemption timeout in ms (1 = Minimum, 9000 = default)");
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -688,6 +715,22 @@ MODULE_PARM_DESC(hws_gws_support, "MEC FW support gws barriers (false = not supp
|
|||
MODULE_PARM_DESC(dcfeaturemask, "all stable DC features enabled (default))");
|
||||
module_param_named(dcfeaturemask, amdgpu_dc_feature_mask, uint, 0444);
|
||||
|
||||
/**
|
||||
* DOC: abmlevel (uint)
|
||||
* Override the default ABM (Adaptive Backlight Management) level used for DC
|
||||
* enabled hardware. Requires DMCU to be supported and loaded.
|
||||
* Valid levels are 0-4. A value of 0 indicates that ABM should be disabled by
|
||||
* default. Values 1-4 control the maximum allowable brightness reduction via
|
||||
* the ABM algorithm, with 1 being the least reduction and 4 being the most
|
||||
* reduction.
|
||||
*
|
||||
* Defaults to 0, or disabled. Userspace can still override this level later
|
||||
* after boot.
|
||||
*/
|
||||
uint amdgpu_dm_abm_level = 0;
|
||||
MODULE_PARM_DESC(abmlevel, "ABM level (0 = off (default), 1-4 = backlight reduction level) ");
|
||||
module_param_named(abmlevel, amdgpu_dm_abm_level, uint, 0444);
|
||||
|
||||
static const struct pci_device_id pciidlist[] = {
|
||||
#ifdef CONFIG_DRM_AMDGPU_SI
|
||||
{0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
|
||||
|
@ -944,6 +987,14 @@ static const struct pci_device_id pciidlist[] = {
|
|||
/* Raven */
|
||||
{0x1002, 0x15dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RAVEN|AMD_IS_APU},
|
||||
{0x1002, 0x15d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RAVEN|AMD_IS_APU},
|
||||
/* Navi10 */
|
||||
{0x1002, 0x7310, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
|
||||
{0x1002, 0x7312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
|
||||
{0x1002, 0x7318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
|
||||
{0x1002, 0x7319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
|
||||
{0x1002, 0x731A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
|
||||
{0x1002, 0x731B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
|
||||
{0x1002, 0x731F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
|
||||
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
|
|
@ -709,22 +709,30 @@ static int amdgpu_debugfs_fence_info(struct seq_file *m, void *data)
|
|||
amdgpu_fence_process(ring);
|
||||
|
||||
seq_printf(m, "--- ring %d (%s) ---\n", i, ring->name);
|
||||
seq_printf(m, "Last signaled fence 0x%08x\n",
|
||||
seq_printf(m, "Last signaled fence 0x%08x\n",
|
||||
atomic_read(&ring->fence_drv.last_seq));
|
||||
seq_printf(m, "Last emitted 0x%08x\n",
|
||||
seq_printf(m, "Last emitted 0x%08x\n",
|
||||
ring->fence_drv.sync_seq);
|
||||
|
||||
if (ring->funcs->type == AMDGPU_RING_TYPE_GFX ||
|
||||
ring->funcs->type == AMDGPU_RING_TYPE_SDMA) {
|
||||
seq_printf(m, "Last signaled trailing fence 0x%08x\n",
|
||||
le32_to_cpu(*ring->trail_fence_cpu_addr));
|
||||
seq_printf(m, "Last emitted 0x%08x\n",
|
||||
ring->trail_seq);
|
||||
}
|
||||
|
||||
if (ring->funcs->type != AMDGPU_RING_TYPE_GFX)
|
||||
continue;
|
||||
|
||||
/* set in CP_VMID_PREEMPT and preemption occurred */
|
||||
seq_printf(m, "Last preempted 0x%08x\n",
|
||||
seq_printf(m, "Last preempted 0x%08x\n",
|
||||
le32_to_cpu(*(ring->fence_drv.cpu_addr + 2)));
|
||||
/* set in CP_VMID_RESET and reset occurred */
|
||||
seq_printf(m, "Last reset 0x%08x\n",
|
||||
seq_printf(m, "Last reset 0x%08x\n",
|
||||
le32_to_cpu(*(ring->fence_drv.cpu_addr + 4)));
|
||||
/* Both preemption and reset occurred */
|
||||
seq_printf(m, "Last both 0x%08x\n",
|
||||
seq_printf(m, "Last both 0x%08x\n",
|
||||
le32_to_cpu(*(ring->fence_drv.cpu_addr + 6)));
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -175,7 +175,7 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj,
|
|||
|
||||
amdgpu_vm_get_pd_bo(vm, &list, &vm_pd);
|
||||
|
||||
r = ttm_eu_reserve_buffers(&ticket, &list, false, &duplicates, true);
|
||||
r = ttm_eu_reserve_buffers(&ticket, &list, false, &duplicates, false);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "leaking bo va because "
|
||||
"we fail to reserve bo (%d)\n", r);
|
||||
|
@ -612,7 +612,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
|
|||
|
||||
amdgpu_vm_get_pd_bo(&fpriv->vm, &list, &vm_pd);
|
||||
|
||||
r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates, true);
|
||||
r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates, false);
|
||||
if (r)
|
||||
goto error_unref;
|
||||
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
* GPU GFX IP block helpers function.
|
||||
*/
|
||||
|
||||
int amdgpu_gfx_queue_to_bit(struct amdgpu_device *adev, int mec,
|
||||
int pipe, int queue)
|
||||
int amdgpu_gfx_mec_queue_to_bit(struct amdgpu_device *adev, int mec,
|
||||
int pipe, int queue)
|
||||
{
|
||||
int bit = 0;
|
||||
|
||||
|
@ -47,8 +47,8 @@ int amdgpu_gfx_queue_to_bit(struct amdgpu_device *adev, int mec,
|
|||
return bit;
|
||||
}
|
||||
|
||||
void amdgpu_gfx_bit_to_queue(struct amdgpu_device *adev, int bit,
|
||||
int *mec, int *pipe, int *queue)
|
||||
void amdgpu_gfx_bit_to_mec_queue(struct amdgpu_device *adev, int bit,
|
||||
int *mec, int *pipe, int *queue)
|
||||
{
|
||||
*queue = bit % adev->gfx.mec.num_queue_per_pipe;
|
||||
*pipe = (bit / adev->gfx.mec.num_queue_per_pipe)
|
||||
|
@ -61,10 +61,40 @@ void amdgpu_gfx_bit_to_queue(struct amdgpu_device *adev, int bit,
|
|||
bool amdgpu_gfx_is_mec_queue_enabled(struct amdgpu_device *adev,
|
||||
int mec, int pipe, int queue)
|
||||
{
|
||||
return test_bit(amdgpu_gfx_queue_to_bit(adev, mec, pipe, queue),
|
||||
return test_bit(amdgpu_gfx_mec_queue_to_bit(adev, mec, pipe, queue),
|
||||
adev->gfx.mec.queue_bitmap);
|
||||
}
|
||||
|
||||
int amdgpu_gfx_me_queue_to_bit(struct amdgpu_device *adev,
|
||||
int me, int pipe, int queue)
|
||||
{
|
||||
int bit = 0;
|
||||
|
||||
bit += me * adev->gfx.me.num_pipe_per_me
|
||||
* adev->gfx.me.num_queue_per_pipe;
|
||||
bit += pipe * adev->gfx.me.num_queue_per_pipe;
|
||||
bit += queue;
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
void amdgpu_gfx_bit_to_me_queue(struct amdgpu_device *adev, int bit,
|
||||
int *me, int *pipe, int *queue)
|
||||
{
|
||||
*queue = bit % adev->gfx.me.num_queue_per_pipe;
|
||||
*pipe = (bit / adev->gfx.me.num_queue_per_pipe)
|
||||
% adev->gfx.me.num_pipe_per_me;
|
||||
*me = (bit / adev->gfx.me.num_queue_per_pipe)
|
||||
/ adev->gfx.me.num_pipe_per_me;
|
||||
}
|
||||
|
||||
bool amdgpu_gfx_is_me_queue_enabled(struct amdgpu_device *adev,
|
||||
int me, int pipe, int queue)
|
||||
{
|
||||
return test_bit(amdgpu_gfx_me_queue_to_bit(adev, me, pipe, queue),
|
||||
adev->gfx.me.queue_bitmap);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_gfx_scratch_get - Allocate a scratch register
|
||||
*
|
||||
|
@ -199,6 +229,30 @@ void amdgpu_gfx_compute_queue_acquire(struct amdgpu_device *adev)
|
|||
adev->gfx.num_compute_rings = AMDGPU_MAX_COMPUTE_RINGS;
|
||||
}
|
||||
|
||||
void amdgpu_gfx_graphics_queue_acquire(struct amdgpu_device *adev)
|
||||
{
|
||||
int i, queue, pipe, me;
|
||||
|
||||
for (i = 0; i < AMDGPU_MAX_GFX_QUEUES; ++i) {
|
||||
queue = i % adev->gfx.me.num_queue_per_pipe;
|
||||
pipe = (i / adev->gfx.me.num_queue_per_pipe)
|
||||
% adev->gfx.me.num_pipe_per_me;
|
||||
me = (i / adev->gfx.me.num_queue_per_pipe)
|
||||
/ adev->gfx.me.num_pipe_per_me;
|
||||
|
||||
if (me >= adev->gfx.me.num_me)
|
||||
break;
|
||||
/* policy: amdgpu owns the first queue per pipe at this stage
|
||||
* will extend to mulitple queues per pipe later */
|
||||
if (me == 0 && queue < 1)
|
||||
set_bit(i, adev->gfx.me.queue_bitmap);
|
||||
}
|
||||
|
||||
/* update the number of active graphics rings */
|
||||
adev->gfx.num_gfx_rings =
|
||||
bitmap_weight(adev->gfx.me.queue_bitmap, AMDGPU_MAX_GFX_QUEUES);
|
||||
}
|
||||
|
||||
static int amdgpu_gfx_kiq_acquire(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring)
|
||||
{
|
||||
|
@ -213,7 +267,7 @@ static int amdgpu_gfx_kiq_acquire(struct amdgpu_device *adev,
|
|||
if (test_bit(queue_bit, adev->gfx.mec.queue_bitmap))
|
||||
continue;
|
||||
|
||||
amdgpu_gfx_bit_to_queue(adev, queue_bit, &mec, &pipe, &queue);
|
||||
amdgpu_gfx_bit_to_mec_queue(adev, queue_bit, &mec, &pipe, &queue);
|
||||
|
||||
/*
|
||||
* 1. Using pipes 2/3 from MEC 2 seems cause problems.
|
||||
|
@ -306,9 +360,9 @@ int amdgpu_gfx_kiq_init(struct amdgpu_device *adev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* create MQD for each compute queue */
|
||||
int amdgpu_gfx_compute_mqd_sw_init(struct amdgpu_device *adev,
|
||||
unsigned mqd_size)
|
||||
/* create MQD for each compute/gfx queue */
|
||||
int amdgpu_gfx_mqd_sw_init(struct amdgpu_device *adev,
|
||||
unsigned mqd_size)
|
||||
{
|
||||
struct amdgpu_ring *ring = NULL;
|
||||
int r, i;
|
||||
|
@ -335,6 +389,27 @@ int amdgpu_gfx_compute_mqd_sw_init(struct amdgpu_device *adev,
|
|||
dev_warn(adev->dev, "no memory to create MQD backup for ring %s\n", ring->name);
|
||||
}
|
||||
|
||||
if (adev->asic_type == CHIP_NAVI10 && amdgpu_async_gfx_ring) {
|
||||
/* create MQD for each KGQ */
|
||||
for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
|
||||
ring = &adev->gfx.gfx_ring[i];
|
||||
if (!ring->mqd_obj) {
|
||||
r = amdgpu_bo_create_kernel(adev, mqd_size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_GTT, &ring->mqd_obj,
|
||||
&ring->mqd_gpu_addr, &ring->mqd_ptr);
|
||||
if (r) {
|
||||
dev_warn(adev->dev, "failed to create ring mqd bo (%d)", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* prepare MQD backup */
|
||||
adev->gfx.me.mqd_backup[i] = kmalloc(mqd_size, GFP_KERNEL);
|
||||
if (!adev->gfx.me.mqd_backup[i])
|
||||
dev_warn(adev->dev, "no memory to create MQD backup for ring %s\n", ring->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* create MQD for each KCQ */
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
|
||||
ring = &adev->gfx.compute_ring[i];
|
||||
|
@ -343,7 +418,7 @@ int amdgpu_gfx_compute_mqd_sw_init(struct amdgpu_device *adev,
|
|||
AMDGPU_GEM_DOMAIN_GTT, &ring->mqd_obj,
|
||||
&ring->mqd_gpu_addr, &ring->mqd_ptr);
|
||||
if (r) {
|
||||
dev_warn(adev->dev, "failed to create ring mqd ob (%d)", r);
|
||||
dev_warn(adev->dev, "failed to create ring mqd bo (%d)", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -357,11 +432,21 @@ int amdgpu_gfx_compute_mqd_sw_init(struct amdgpu_device *adev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_gfx_compute_mqd_sw_fini(struct amdgpu_device *adev)
|
||||
void amdgpu_gfx_mqd_sw_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ring *ring = NULL;
|
||||
int i;
|
||||
|
||||
if (adev->asic_type == CHIP_NAVI10 && amdgpu_async_gfx_ring) {
|
||||
for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
|
||||
ring = &adev->gfx.gfx_ring[i];
|
||||
kfree(adev->gfx.me.mqd_backup[i]);
|
||||
amdgpu_bo_free_kernel(&ring->mqd_obj,
|
||||
&ring->mqd_gpu_addr,
|
||||
&ring->mqd_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
|
||||
ring = &adev->gfx.compute_ring[i];
|
||||
kfree(adev->gfx.mec.mqd_backup[i]);
|
||||
|
@ -371,12 +456,81 @@ void amdgpu_gfx_compute_mqd_sw_fini(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
ring = &adev->gfx.kiq.ring;
|
||||
if (adev->asic_type == CHIP_NAVI10 && amdgpu_async_gfx_ring)
|
||||
kfree(adev->gfx.me.mqd_backup[AMDGPU_MAX_GFX_RINGS]);
|
||||
kfree(adev->gfx.mec.mqd_backup[AMDGPU_MAX_COMPUTE_RINGS]);
|
||||
amdgpu_bo_free_kernel(&ring->mqd_obj,
|
||||
&ring->mqd_gpu_addr,
|
||||
&ring->mqd_ptr);
|
||||
}
|
||||
|
||||
int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq;
|
||||
struct amdgpu_ring *kiq_ring = &kiq->ring;
|
||||
int i;
|
||||
|
||||
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
|
||||
return -EINVAL;
|
||||
|
||||
if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size *
|
||||
adev->gfx.num_compute_rings))
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++)
|
||||
kiq->pmf->kiq_unmap_queues(kiq_ring, &adev->gfx.compute_ring[i],
|
||||
RESET_QUEUES, 0, 0);
|
||||
|
||||
return amdgpu_ring_test_ring(kiq_ring);
|
||||
}
|
||||
|
||||
int amdgpu_gfx_enable_kcq(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq;
|
||||
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
|
||||
uint64_t queue_mask = 0;
|
||||
int r, i;
|
||||
|
||||
if (!kiq->pmf || !kiq->pmf->kiq_map_queues || !kiq->pmf->kiq_set_resources)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < AMDGPU_MAX_COMPUTE_QUEUES; ++i) {
|
||||
if (!test_bit(i, adev->gfx.mec.queue_bitmap))
|
||||
continue;
|
||||
|
||||
/* This situation may be hit in the future if a new HW
|
||||
* generation exposes more than 64 queues. If so, the
|
||||
* definition of queue_mask needs updating */
|
||||
if (WARN_ON(i > (sizeof(queue_mask)*8))) {
|
||||
DRM_ERROR("Invalid KCQ enabled: %d\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
queue_mask |= (1ull << i);
|
||||
}
|
||||
|
||||
DRM_INFO("kiq ring mec %d pipe %d q %d\n", kiq_ring->me, kiq_ring->pipe,
|
||||
kiq_ring->queue);
|
||||
|
||||
r = amdgpu_ring_alloc(kiq_ring, kiq->pmf->map_queues_size *
|
||||
adev->gfx.num_compute_rings +
|
||||
kiq->pmf->set_resources_size);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to lock KIQ (%d).\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
kiq->pmf->kiq_set_resources(kiq_ring, queue_mask);
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++)
|
||||
kiq->pmf->kiq_map_queues(kiq_ring, &adev->gfx.compute_ring[i]);
|
||||
|
||||
r = amdgpu_ring_test_helper(kiq_ring);
|
||||
if (r)
|
||||
DRM_ERROR("KCQ enable failed\n");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* amdgpu_gfx_off_ctrl - Handle gfx off feature enable/disable
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
|
@ -393,7 +547,9 @@ void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable)
|
|||
if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
|
||||
return;
|
||||
|
||||
if (!adev->powerplay.pp_funcs || !adev->powerplay.pp_funcs->set_powergating_by_smu)
|
||||
if (!is_support_sw_smu(adev) &&
|
||||
(!adev->powerplay.pp_funcs ||
|
||||
!adev->powerplay.pp_funcs->set_powergating_by_smu))
|
||||
return;
|
||||
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#define AMDGPU_GFX_CG_DISABLED_MODE 0x00000004L
|
||||
#define AMDGPU_GFX_LBPW_DISABLED_MODE 0x00000008L
|
||||
|
||||
#define AMDGPU_MAX_GFX_QUEUES KGD_MAX_QUEUES
|
||||
#define AMDGPU_MAX_COMPUTE_QUEUES KGD_MAX_QUEUES
|
||||
|
||||
struct amdgpu_mec {
|
||||
|
@ -54,12 +55,41 @@ struct amdgpu_mec {
|
|||
DECLARE_BITMAP(queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
|
||||
};
|
||||
|
||||
enum amdgpu_unmap_queues_action {
|
||||
PREEMPT_QUEUES = 0,
|
||||
RESET_QUEUES,
|
||||
DISABLE_PROCESS_QUEUES,
|
||||
PREEMPT_QUEUES_NO_UNMAP,
|
||||
};
|
||||
|
||||
struct kiq_pm4_funcs {
|
||||
/* Support ASIC-specific kiq pm4 packets*/
|
||||
void (*kiq_set_resources)(struct amdgpu_ring *kiq_ring,
|
||||
uint64_t queue_mask);
|
||||
void (*kiq_map_queues)(struct amdgpu_ring *kiq_ring,
|
||||
struct amdgpu_ring *ring);
|
||||
void (*kiq_unmap_queues)(struct amdgpu_ring *kiq_ring,
|
||||
struct amdgpu_ring *ring,
|
||||
enum amdgpu_unmap_queues_action action,
|
||||
u64 gpu_addr, u64 seq);
|
||||
void (*kiq_query_status)(struct amdgpu_ring *kiq_ring,
|
||||
struct amdgpu_ring *ring,
|
||||
u64 addr,
|
||||
u64 seq);
|
||||
/* Packet sizes */
|
||||
int set_resources_size;
|
||||
int map_queues_size;
|
||||
int unmap_queues_size;
|
||||
int query_status_size;
|
||||
};
|
||||
|
||||
struct amdgpu_kiq {
|
||||
u64 eop_gpu_addr;
|
||||
struct amdgpu_bo *eop_obj;
|
||||
spinlock_t ring_lock;
|
||||
struct amdgpu_ring ring;
|
||||
struct amdgpu_irq_src irq;
|
||||
const struct kiq_pm4_funcs *pmf;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -131,6 +161,10 @@ struct amdgpu_gfx_config {
|
|||
uint32_t double_offchip_lds_buf;
|
||||
/* cached value of DB_DEBUG2 */
|
||||
uint32_t db_debug2;
|
||||
/* gfx10 specific config */
|
||||
uint32_t num_sc_per_sh;
|
||||
uint32_t num_packer_per_sc;
|
||||
uint32_t pa_sc_tile_steering_override;
|
||||
};
|
||||
|
||||
struct amdgpu_cu_info {
|
||||
|
@ -191,10 +225,38 @@ struct sq_work {
|
|||
unsigned ih_data;
|
||||
};
|
||||
|
||||
struct amdgpu_pfp {
|
||||
struct amdgpu_bo *pfp_fw_obj;
|
||||
uint64_t pfp_fw_gpu_addr;
|
||||
uint32_t *pfp_fw_ptr;
|
||||
};
|
||||
|
||||
struct amdgpu_ce {
|
||||
struct amdgpu_bo *ce_fw_obj;
|
||||
uint64_t ce_fw_gpu_addr;
|
||||
uint32_t *ce_fw_ptr;
|
||||
};
|
||||
|
||||
struct amdgpu_me {
|
||||
struct amdgpu_bo *me_fw_obj;
|
||||
uint64_t me_fw_gpu_addr;
|
||||
uint32_t *me_fw_ptr;
|
||||
uint32_t num_me;
|
||||
uint32_t num_pipe_per_me;
|
||||
uint32_t num_queue_per_pipe;
|
||||
void *mqd_backup[AMDGPU_MAX_GFX_RINGS + 1];
|
||||
|
||||
/* These are the resources for which amdgpu takes ownership */
|
||||
DECLARE_BITMAP(queue_bitmap, AMDGPU_MAX_GFX_QUEUES);
|
||||
};
|
||||
|
||||
struct amdgpu_gfx {
|
||||
struct mutex gpu_clock_mutex;
|
||||
struct amdgpu_gfx_config config;
|
||||
struct amdgpu_rlc rlc;
|
||||
struct amdgpu_pfp pfp;
|
||||
struct amdgpu_ce ce;
|
||||
struct amdgpu_me me;
|
||||
struct amdgpu_mec mec;
|
||||
struct amdgpu_kiq kiq;
|
||||
struct amdgpu_scratch scratch;
|
||||
|
@ -297,17 +359,27 @@ void amdgpu_gfx_kiq_fini(struct amdgpu_device *adev);
|
|||
int amdgpu_gfx_kiq_init(struct amdgpu_device *adev,
|
||||
unsigned hpd_size);
|
||||
|
||||
int amdgpu_gfx_compute_mqd_sw_init(struct amdgpu_device *adev,
|
||||
unsigned mqd_size);
|
||||
void amdgpu_gfx_compute_mqd_sw_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_gfx_mqd_sw_init(struct amdgpu_device *adev,
|
||||
unsigned mqd_size);
|
||||
void amdgpu_gfx_mqd_sw_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev);
|
||||
int amdgpu_gfx_enable_kcq(struct amdgpu_device *adev);
|
||||
|
||||
void amdgpu_gfx_compute_queue_acquire(struct amdgpu_device *adev);
|
||||
int amdgpu_gfx_queue_to_bit(struct amdgpu_device *adev, int mec,
|
||||
int pipe, int queue);
|
||||
void amdgpu_gfx_bit_to_queue(struct amdgpu_device *adev, int bit,
|
||||
int *mec, int *pipe, int *queue);
|
||||
void amdgpu_gfx_graphics_queue_acquire(struct amdgpu_device *adev);
|
||||
|
||||
int amdgpu_gfx_mec_queue_to_bit(struct amdgpu_device *adev, int mec,
|
||||
int pipe, int queue);
|
||||
void amdgpu_gfx_bit_to_mec_queue(struct amdgpu_device *adev, int bit,
|
||||
int *mec, int *pipe, int *queue);
|
||||
bool amdgpu_gfx_is_mec_queue_enabled(struct amdgpu_device *adev, int mec,
|
||||
int pipe, int queue);
|
||||
int amdgpu_gfx_me_queue_to_bit(struct amdgpu_device *adev, int me,
|
||||
int pipe, int queue);
|
||||
void amdgpu_gfx_bit_to_me_queue(struct amdgpu_device *adev, int bit,
|
||||
int *me, int *pipe, int *queue);
|
||||
bool amdgpu_gfx_is_me_queue_enabled(struct amdgpu_device *adev, int me,
|
||||
int pipe, int queue);
|
||||
void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -211,6 +211,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
|
|||
skip_preamble = ring->current_ctx == fence_ctx;
|
||||
if (job && ring->funcs->emit_cntxcntl) {
|
||||
status |= job->preamble_status;
|
||||
status |= job->preemption_status;
|
||||
amdgpu_ring_emit_cntxcntl(ring, status);
|
||||
}
|
||||
|
||||
|
@ -219,9 +220,10 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
|
|||
|
||||
/* drop preamble IBs if we don't have a context switch */
|
||||
if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) &&
|
||||
skip_preamble &&
|
||||
!(status & AMDGPU_PREAMBLE_IB_PRESENT_FIRST) &&
|
||||
!amdgpu_sriov_vf(adev)) /* for SRIOV preemption, Preamble CE ib must be inserted anyway */
|
||||
skip_preamble &&
|
||||
!(status & AMDGPU_PREAMBLE_IB_PRESENT_FIRST) &&
|
||||
!amdgpu_mcbp &&
|
||||
!amdgpu_sriov_vf(adev)) /* for SRIOV preemption, Preamble CE ib must be inserted anyway */
|
||||
continue;
|
||||
|
||||
amdgpu_ring_emit_ib(ring, job, ib, status);
|
||||
|
|
|
@ -364,8 +364,11 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm,
|
|||
if (updates && (!flushed || dma_fence_is_later(updates, flushed)))
|
||||
needs_flush = true;
|
||||
|
||||
/* Concurrent flushes are only possible starting with Vega10 */
|
||||
if (adev->asic_type < CHIP_VEGA10 && needs_flush)
|
||||
/* Concurrent flushes are only possible starting with Vega10 and
|
||||
* are broken on Navi10 and Navi14.
|
||||
*/
|
||||
if (needs_flush && (adev->asic_type < CHIP_VEGA10 ||
|
||||
adev->asic_type == CHIP_NAVI10))
|
||||
continue;
|
||||
|
||||
/* Good, we can use this VMID. Remember this submission as
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#define AMDGPU_PREAMBLE_IB_PRESENT_FIRST (1 << 1)
|
||||
/* bit set means context switch occured */
|
||||
#define AMDGPU_HAVE_CTX_SWITCH (1 << 2)
|
||||
/* bit set means IB is preempted */
|
||||
#define AMDGPU_IB_PREEMPTED (1 << 3)
|
||||
|
||||
#define to_amdgpu_job(sched_job) \
|
||||
container_of((sched_job), struct amdgpu_job, base)
|
||||
|
@ -45,6 +47,7 @@ struct amdgpu_job {
|
|||
struct amdgpu_ib *ibs;
|
||||
struct dma_fence *fence; /* the hw fence */
|
||||
uint32_t preamble_status;
|
||||
uint32_t preemption_status;
|
||||
uint32_t num_ibs;
|
||||
void *owner;
|
||||
bool vm_needs_flush;
|
||||
|
|
|
@ -712,7 +712,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
|
|||
dev_info.ids_flags = 0;
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
dev_info.ids_flags |= AMDGPU_IDS_FLAGS_FUSION;
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
if (amdgpu_mcbp || amdgpu_sriov_vf(adev))
|
||||
dev_info.ids_flags |= AMDGPU_IDS_FLAGS_PREEMPTION;
|
||||
|
||||
vm_size = adev->vm_manager.max_pfn * AMDGPU_GPU_PAGE_SIZE;
|
||||
|
@ -765,6 +765,10 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
|
|||
dev_info.gs_prim_buffer_depth = adev->gfx.config.gs_prim_buffer_depth;
|
||||
dev_info.max_gs_waves_per_vgt = adev->gfx.config.max_gs_threads;
|
||||
|
||||
if (adev->family >= AMDGPU_FAMILY_NV)
|
||||
dev_info.pa_sc_tile_steering_override =
|
||||
adev->gfx.config.pa_sc_tile_steering_override;
|
||||
|
||||
return copy_to_user(out, &dev_info,
|
||||
min((size_t)size, sizeof(dev_info))) ? -EFAULT : 0;
|
||||
}
|
||||
|
@ -1006,7 +1010,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
|
|||
goto error_vm;
|
||||
}
|
||||
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) {
|
||||
uint64_t csa_addr = amdgpu_csa_vaddr(adev) & AMDGPU_GMC_HOLE_MASK;
|
||||
|
||||
r = amdgpu_map_static_csa(adev, &fpriv->vm, adev->virt.csa_obj,
|
||||
|
@ -1069,7 +1073,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
|
|||
|
||||
amdgpu_vm_bo_rmv(adev, fpriv->prt_va);
|
||||
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) {
|
||||
/* TODO: how to handle reserve failure */
|
||||
BUG_ON(amdgpu_bo_reserve(adev->virt.csa_obj, true));
|
||||
amdgpu_vm_bo_rmv(adev, fpriv->csa_va);
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __AMDGPU_MES_H__
|
||||
#define __AMDGPU_MES_H__
|
||||
|
||||
struct amdgpu_mes_funcs;
|
||||
|
||||
struct amdgpu_mes {
|
||||
struct amdgpu_adev *adev;
|
||||
|
||||
const struct firmware *fw;
|
||||
|
||||
/* mes ucode */
|
||||
struct amdgpu_bo *ucode_fw_obj;
|
||||
uint64_t ucode_fw_gpu_addr;
|
||||
uint32_t *ucode_fw_ptr;
|
||||
uint32_t ucode_fw_version;
|
||||
uint64_t uc_start_addr;
|
||||
|
||||
/* mes ucode data */
|
||||
struct amdgpu_bo *data_fw_obj;
|
||||
uint64_t data_fw_gpu_addr;
|
||||
uint32_t *data_fw_ptr;
|
||||
uint32_t data_fw_version;
|
||||
uint64_t data_start_addr;
|
||||
|
||||
/* ip specific functions */
|
||||
struct amdgpu_mes_funcs *funcs;
|
||||
};
|
||||
|
||||
struct mes_add_queue_input {
|
||||
uint32_t process_id;
|
||||
uint64_t page_table_base_addr;
|
||||
uint64_t process_va_start;
|
||||
uint64_t process_va_end;
|
||||
uint64_t process_quantum;
|
||||
uint64_t process_context_addr;
|
||||
uint64_t gang_quantum;
|
||||
uint64_t gang_context_addr;
|
||||
uint32_t inprocess_gang_priority;
|
||||
uint32_t gang_global_priority_level;
|
||||
uint32_t doorbell_offset;
|
||||
uint64_t mqd_addr;
|
||||
uint64_t wptr_addr;
|
||||
uint32_t queue_type;
|
||||
uint32_t paging;
|
||||
};
|
||||
|
||||
struct mes_remove_queue_input {
|
||||
uint32_t doorbell_offset;
|
||||
uint64_t gang_context_addr;
|
||||
};
|
||||
|
||||
struct mes_suspend_gang_input {
|
||||
bool suspend_all_gangs;
|
||||
uint64_t gang_context_addr;
|
||||
uint64_t suspend_fence_addr;
|
||||
uint32_t suspend_fence_value;
|
||||
};
|
||||
|
||||
struct mes_resume_gang_input {
|
||||
bool resume_all_gangs;
|
||||
uint64_t gang_context_addr;
|
||||
};
|
||||
|
||||
struct amdgpu_mes_funcs {
|
||||
int (*add_hw_queue)(struct amdgpu_mes *mes,
|
||||
struct mes_add_queue_input *input);
|
||||
|
||||
int (*remove_hw_queue)(struct amdgpu_mes *mes,
|
||||
struct mes_remove_queue_input *input);
|
||||
|
||||
int (*suspend_gang)(struct amdgpu_mes *mes,
|
||||
struct mes_suspend_gang_input *input);
|
||||
|
||||
int (*resume_gang)(struct amdgpu_mes *mes,
|
||||
struct mes_resume_gang_input *input);
|
||||
};
|
||||
|
||||
#endif /* __AMDGPU_MES_H__ */
|
|
@ -519,7 +519,6 @@ void amdgpu_hmm_init_range(struct hmm_range *range)
|
|||
range->flags = hmm_range_flags;
|
||||
range->values = hmm_range_values;
|
||||
range->pfn_shift = PAGE_SHIFT;
|
||||
range->pfns = NULL;
|
||||
INIT_LIST_HEAD(&range->list);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -495,7 +495,11 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev,
|
|||
#endif
|
||||
|
||||
bo->tbo.bdev = &adev->mman.bdev;
|
||||
amdgpu_bo_placement_from_domain(bo, bp->domain);
|
||||
if (bp->domain & (AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA |
|
||||
AMDGPU_GEM_DOMAIN_GDS))
|
||||
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU);
|
||||
else
|
||||
amdgpu_bo_placement_from_domain(bo, bp->domain);
|
||||
if (bp->type == ttm_bo_type_kernel)
|
||||
bo->tbo.priority = 1;
|
||||
|
||||
|
@ -975,6 +979,7 @@ static const char *amdgpu_vram_names[] = {
|
|||
"HBM",
|
||||
"DDR3",
|
||||
"DDR4",
|
||||
"GDDR6",
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -155,7 +155,7 @@ static inline int amdgpu_bo_reserve(struct amdgpu_bo *bo, bool no_intr)
|
|||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
int r;
|
||||
|
||||
r = ttm_bo_reserve(&bo->tbo, !no_intr, false, NULL);
|
||||
r = __ttm_bo_reserve(&bo->tbo, !no_intr, false, NULL);
|
||||
if (unlikely(r != 0)) {
|
||||
if (r != -ERESTARTSYS)
|
||||
dev_err(adev->dev, "%p reserve failed\n", bo);
|
||||
|
|
|
@ -67,6 +67,9 @@ static const struct cg_flag_name clocks[] = {
|
|||
{AMD_CG_SUPPORT_DRM_LS, "Digital Right Management Light Sleep"},
|
||||
{AMD_CG_SUPPORT_ROM_MGCG, "Rom Medium Grain Clock Gating"},
|
||||
{AMD_CG_SUPPORT_DF_MGCG, "Data Fabric Medium Grain Clock Gating"},
|
||||
|
||||
{AMD_CG_SUPPORT_ATHUB_MGCG, "Address Translation Hub Medium Grain Clock Gating"},
|
||||
{AMD_CG_SUPPORT_ATHUB_LS, "Address Translation Hub Light Sleep"},
|
||||
{0, NULL},
|
||||
};
|
||||
|
||||
|
@ -272,8 +275,11 @@ static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev,
|
|||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
enum amd_dpm_forced_level level = 0xff;
|
||||
|
||||
if ((adev->flags & AMD_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
if ((adev->flags & AMD_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
|
||||
return snprintf(buf, PAGE_SIZE, "off\n");
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
|
@ -311,10 +317,12 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
|
|||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
|
||||
return -EINVAL;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
current_level = smu_get_performance_level(&adev->smu);
|
||||
else if (adev->powerplay.pp_funcs->get_performance_level)
|
||||
current_level = amdgpu_dpm_get_performance_level(adev);
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
if (is_support_sw_smu(adev))
|
||||
current_level = smu_get_performance_level(&adev->smu);
|
||||
else if (adev->powerplay.pp_funcs->get_performance_level)
|
||||
current_level = amdgpu_dpm_get_performance_level(adev);
|
||||
}
|
||||
|
||||
if (strncmp("low", buf, strlen("low")) == 0) {
|
||||
level = AMD_DPM_FORCED_LEVEL_LOW;
|
||||
|
@ -365,18 +373,9 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
|
|||
}
|
||||
|
||||
if (is_support_sw_smu(adev)) {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
if (adev->pm.dpm.thermal_active) {
|
||||
count = -EINVAL;
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
goto fail;
|
||||
}
|
||||
ret = smu_force_performance_level(&adev->smu, level);
|
||||
if (ret)
|
||||
count = -EINVAL;
|
||||
else
|
||||
adev->pm.dpm.forced_level = level;
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
} else if (adev->powerplay.pp_funcs->force_performance_level) {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
if (adev->pm.dpm.thermal_active) {
|
||||
|
@ -690,12 +689,12 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev,
|
|||
if (ret)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (adev->powerplay.pp_funcs->odn_edit_dpm_table)
|
||||
if (adev->powerplay.pp_funcs->odn_edit_dpm_table) {
|
||||
ret = amdgpu_dpm_odn_edit_dpm_table(adev, type,
|
||||
parameter, parameter_size);
|
||||
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (type == PP_OD_COMMIT_DPM_TABLE) {
|
||||
if (adev->powerplay.pp_funcs->dispatch_tasks) {
|
||||
|
@ -721,10 +720,10 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev,
|
|||
uint32_t size = 0;
|
||||
|
||||
if (is_support_sw_smu(adev)) {
|
||||
size = smu_print_clk_levels(&adev->smu, OD_SCLK, buf);
|
||||
size += smu_print_clk_levels(&adev->smu, OD_MCLK, buf+size);
|
||||
size += smu_print_clk_levels(&adev->smu, OD_VDDC_CURVE, buf+size);
|
||||
size += smu_print_clk_levels(&adev->smu, OD_RANGE, buf+size);
|
||||
size = smu_print_clk_levels(&adev->smu, SMU_OD_SCLK, buf);
|
||||
size += smu_print_clk_levels(&adev->smu, SMU_OD_MCLK, buf+size);
|
||||
size += smu_print_clk_levels(&adev->smu, SMU_OD_VDDC_CURVE, buf+size);
|
||||
size += smu_print_clk_levels(&adev->smu, SMU_OD_RANGE, buf+size);
|
||||
return size;
|
||||
} else if (adev->powerplay.pp_funcs->print_clock_levels) {
|
||||
size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf);
|
||||
|
@ -835,7 +834,7 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev,
|
|||
return adev->virt.ops->get_pp_clk(adev, PP_SCLK, buf);
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_print_clk_levels(&adev->smu, PP_SCLK, buf);
|
||||
return smu_print_clk_levels(&adev->smu, SMU_SCLK, buf);
|
||||
else if (adev->powerplay.pp_funcs->print_clock_levels)
|
||||
return amdgpu_dpm_print_clock_levels(adev, PP_SCLK, buf);
|
||||
else
|
||||
|
@ -888,12 +887,15 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev,
|
|||
int ret;
|
||||
uint32_t mask = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
ret = amdgpu_read_mask(buf, count, &mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
ret = smu_force_clk_levels(&adev->smu, PP_SCLK, mask);
|
||||
ret = smu_force_clk_levels(&adev->smu, SMU_SCLK, mask);
|
||||
else if (adev->powerplay.pp_funcs->force_clock_level)
|
||||
ret = amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask);
|
||||
|
||||
|
@ -910,8 +912,12 @@ static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev,
|
|||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && amdgim_is_hwperf(adev) &&
|
||||
adev->virt.ops->get_pp_clk)
|
||||
return adev->virt.ops->get_pp_clk(adev, PP_MCLK, buf);
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_print_clk_levels(&adev->smu, PP_MCLK, buf);
|
||||
return smu_print_clk_levels(&adev->smu, SMU_MCLK, buf);
|
||||
else if (adev->powerplay.pp_funcs->print_clock_levels)
|
||||
return amdgpu_dpm_print_clock_levels(adev, PP_MCLK, buf);
|
||||
else
|
||||
|
@ -928,12 +934,15 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev,
|
|||
int ret;
|
||||
uint32_t mask = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
ret = amdgpu_read_mask(buf, count, &mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
ret = smu_force_clk_levels(&adev->smu, PP_MCLK, mask);
|
||||
ret = smu_force_clk_levels(&adev->smu, SMU_MCLK, mask);
|
||||
else if (adev->powerplay.pp_funcs->force_clock_level)
|
||||
ret = amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask);
|
||||
|
||||
|
@ -951,7 +960,7 @@ static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev,
|
|||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_print_clk_levels(&adev->smu, PP_SOCCLK, buf);
|
||||
return smu_print_clk_levels(&adev->smu, SMU_SOCCLK, buf);
|
||||
else if (adev->powerplay.pp_funcs->print_clock_levels)
|
||||
return amdgpu_dpm_print_clock_levels(adev, PP_SOCCLK, buf);
|
||||
else
|
||||
|
@ -973,7 +982,7 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev,
|
|||
return ret;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
ret = smu_force_clk_levels(&adev->smu, PP_SOCCLK, mask);
|
||||
ret = smu_force_clk_levels(&adev->smu, SMU_SOCCLK, mask);
|
||||
else if (adev->powerplay.pp_funcs->force_clock_level)
|
||||
ret = amdgpu_dpm_force_clock_level(adev, PP_SOCCLK, mask);
|
||||
|
||||
|
@ -991,7 +1000,7 @@ static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev,
|
|||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_print_clk_levels(&adev->smu, PP_FCLK, buf);
|
||||
return smu_print_clk_levels(&adev->smu, SMU_FCLK, buf);
|
||||
else if (adev->powerplay.pp_funcs->print_clock_levels)
|
||||
return amdgpu_dpm_print_clock_levels(adev, PP_FCLK, buf);
|
||||
else
|
||||
|
@ -1013,7 +1022,7 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev,
|
|||
return ret;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
ret = smu_force_clk_levels(&adev->smu, PP_FCLK, mask);
|
||||
ret = smu_force_clk_levels(&adev->smu, SMU_FCLK, mask);
|
||||
else if (adev->powerplay.pp_funcs->force_clock_level)
|
||||
ret = amdgpu_dpm_force_clock_level(adev, PP_FCLK, mask);
|
||||
|
||||
|
@ -1031,7 +1040,7 @@ static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev,
|
|||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_print_clk_levels(&adev->smu, PP_DCEFCLK, buf);
|
||||
return smu_print_clk_levels(&adev->smu, SMU_DCEFCLK, buf);
|
||||
else if (adev->powerplay.pp_funcs->print_clock_levels)
|
||||
return amdgpu_dpm_print_clock_levels(adev, PP_DCEFCLK, buf);
|
||||
else
|
||||
|
@ -1053,7 +1062,7 @@ static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev,
|
|||
return ret;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
ret = smu_force_clk_levels(&adev->smu, PP_DCEFCLK, mask);
|
||||
ret = smu_force_clk_levels(&adev->smu, SMU_DCEFCLK, mask);
|
||||
else if (adev->powerplay.pp_funcs->force_clock_level)
|
||||
ret = amdgpu_dpm_force_clock_level(adev, PP_DCEFCLK, mask);
|
||||
|
||||
|
@ -1071,7 +1080,7 @@ static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev,
|
|||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_print_clk_levels(&adev->smu, PP_PCIE, buf);
|
||||
return smu_print_clk_levels(&adev->smu, SMU_PCIE, buf);
|
||||
else if (adev->powerplay.pp_funcs->print_clock_levels)
|
||||
return amdgpu_dpm_print_clock_levels(adev, PP_PCIE, buf);
|
||||
else
|
||||
|
@ -1093,7 +1102,7 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev,
|
|||
return ret;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
ret = smu_force_clk_levels(&adev->smu, PP_PCIE, mask);
|
||||
ret = smu_force_clk_levels(&adev->smu, SMU_PCIE, mask);
|
||||
else if (adev->powerplay.pp_funcs->force_clock_level)
|
||||
ret = amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask);
|
||||
|
||||
|
@ -1112,7 +1121,7 @@ static ssize_t amdgpu_get_pp_sclk_od(struct device *dev,
|
|||
uint32_t value = 0;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
value = smu_get_od_percentage(&(adev->smu), OD_SCLK);
|
||||
value = smu_get_od_percentage(&(adev->smu), SMU_OD_SCLK);
|
||||
else if (adev->powerplay.pp_funcs->get_sclk_od)
|
||||
value = amdgpu_dpm_get_sclk_od(adev);
|
||||
|
||||
|
@ -1137,7 +1146,7 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev,
|
|||
}
|
||||
|
||||
if (is_support_sw_smu(adev)) {
|
||||
value = smu_set_od_percentage(&(adev->smu), OD_SCLK, (uint32_t)value);
|
||||
value = smu_set_od_percentage(&(adev->smu), SMU_OD_SCLK, (uint32_t)value);
|
||||
} else {
|
||||
if (adev->powerplay.pp_funcs->set_sclk_od)
|
||||
amdgpu_dpm_set_sclk_od(adev, (uint32_t)value);
|
||||
|
@ -1163,7 +1172,7 @@ static ssize_t amdgpu_get_pp_mclk_od(struct device *dev,
|
|||
uint32_t value = 0;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
value = smu_get_od_percentage(&(adev->smu), OD_MCLK);
|
||||
value = smu_get_od_percentage(&(adev->smu), SMU_OD_MCLK);
|
||||
else if (adev->powerplay.pp_funcs->get_mclk_od)
|
||||
value = amdgpu_dpm_get_mclk_od(adev);
|
||||
|
||||
|
@ -1188,7 +1197,7 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev,
|
|||
}
|
||||
|
||||
if (is_support_sw_smu(adev)) {
|
||||
value = smu_set_od_percentage(&(adev->smu), OD_MCLK, (uint32_t)value);
|
||||
value = smu_set_od_percentage(&(adev->smu), SMU_OD_MCLK, (uint32_t)value);
|
||||
} else {
|
||||
if (adev->powerplay.pp_funcs->set_mclk_od)
|
||||
amdgpu_dpm_set_mclk_od(adev, (uint32_t)value);
|
||||
|
@ -1453,7 +1462,7 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev,
|
|||
struct amdgpu_device *adev = dev_get_drvdata(dev);
|
||||
struct drm_device *ddev = adev->ddev;
|
||||
int channel = to_sensor_dev_attr(attr)->index;
|
||||
int r, temp, size = sizeof(temp);
|
||||
int r, temp = 0, size = sizeof(temp);
|
||||
|
||||
/* Can't get temperature when the card is off */
|
||||
if ((adev->flags & AMD_IS_PX) &&
|
||||
|
@ -2701,6 +2710,44 @@ void amdgpu_pm_print_power_states(struct amdgpu_device *adev)
|
|||
|
||||
}
|
||||
|
||||
int amdgpu_pm_virt_sysfs_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!(amdgpu_sriov_vf(adev) && amdgim_is_hwperf(adev)))
|
||||
return ret;
|
||||
|
||||
ret = device_create_file(adev->dev, &dev_attr_pp_dpm_sclk);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create device file pp_dpm_sclk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = device_create_file(adev->dev, &dev_attr_pp_dpm_mclk);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create device file pp_dpm_mclk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = device_create_file(adev->dev, &dev_attr_power_dpm_force_performance_level);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create device file for dpm state\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void amdgpu_pm_virt_sysfs_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
if (!(amdgpu_sriov_vf(adev) && amdgim_is_hwperf(adev)))
|
||||
return;
|
||||
|
||||
device_remove_file(adev->dev, &dev_attr_power_dpm_force_performance_level);
|
||||
device_remove_file(adev->dev, &dev_attr_pp_dpm_sclk);
|
||||
device_remove_file(adev->dev, &dev_attr_pp_dpm_mclk);
|
||||
}
|
||||
|
||||
int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version)
|
||||
{
|
||||
int r;
|
||||
|
|
|
@ -32,7 +32,9 @@ struct cg_flag_name
|
|||
|
||||
void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev);
|
||||
int amdgpu_pm_sysfs_init(struct amdgpu_device *adev);
|
||||
int amdgpu_pm_virt_sysfs_init(struct amdgpu_device *adev);
|
||||
void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev);
|
||||
void amdgpu_pm_virt_sysfs_fini(struct amdgpu_device *adev);
|
||||
void amdgpu_pm_print_power_states(struct amdgpu_device *adev);
|
||||
int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version);
|
||||
void amdgpu_pm_compute_clocks(struct amdgpu_device *adev);
|
||||
|
|
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author: Jonathan Kim <jonathan.kim@amd.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/init.h>
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_pmu.h"
|
||||
#include "df_v3_6.h"
|
||||
|
||||
#define PMU_NAME_SIZE 32
|
||||
|
||||
/* record to keep track of pmu entry per pmu type per device */
|
||||
struct amdgpu_pmu_entry {
|
||||
struct list_head entry;
|
||||
struct amdgpu_device *adev;
|
||||
struct pmu pmu;
|
||||
unsigned int pmu_perf_type;
|
||||
};
|
||||
|
||||
static LIST_HEAD(amdgpu_pmu_list);
|
||||
|
||||
|
||||
/* initialize perf counter */
|
||||
static int amdgpu_perf_event_init(struct perf_event *event)
|
||||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
|
||||
/* test the event attr type check for PMU enumeration */
|
||||
if (event->attr.type != event->pmu->type)
|
||||
return -ENOENT;
|
||||
|
||||
/* update the hw_perf_event struct with config data */
|
||||
hwc->conf = event->attr.config;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* start perf counter */
|
||||
static void amdgpu_perf_start(struct perf_event *event, int flags)
|
||||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
struct amdgpu_pmu_entry *pe = container_of(event->pmu,
|
||||
struct amdgpu_pmu_entry,
|
||||
pmu);
|
||||
|
||||
if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
|
||||
return;
|
||||
|
||||
WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
|
||||
hwc->state = 0;
|
||||
|
||||
switch (pe->pmu_perf_type) {
|
||||
case PERF_TYPE_AMDGPU_DF:
|
||||
if (!(flags & PERF_EF_RELOAD))
|
||||
pe->adev->df_funcs->pmc_start(pe->adev, hwc->conf, 1);
|
||||
|
||||
pe->adev->df_funcs->pmc_start(pe->adev, hwc->conf, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
perf_event_update_userpage(event);
|
||||
|
||||
}
|
||||
|
||||
/* read perf counter */
|
||||
static void amdgpu_perf_read(struct perf_event *event)
|
||||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
struct amdgpu_pmu_entry *pe = container_of(event->pmu,
|
||||
struct amdgpu_pmu_entry,
|
||||
pmu);
|
||||
|
||||
u64 count, prev;
|
||||
|
||||
do {
|
||||
prev = local64_read(&hwc->prev_count);
|
||||
|
||||
switch (pe->pmu_perf_type) {
|
||||
case PERF_TYPE_AMDGPU_DF:
|
||||
pe->adev->df_funcs->pmc_get_count(pe->adev, hwc->conf,
|
||||
&count);
|
||||
break;
|
||||
default:
|
||||
count = 0;
|
||||
break;
|
||||
};
|
||||
} while (local64_cmpxchg(&hwc->prev_count, prev, count) != prev);
|
||||
|
||||
local64_add(count - prev, &event->count);
|
||||
}
|
||||
|
||||
/* stop perf counter */
|
||||
static void amdgpu_perf_stop(struct perf_event *event, int flags)
|
||||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
struct amdgpu_pmu_entry *pe = container_of(event->pmu,
|
||||
struct amdgpu_pmu_entry,
|
||||
pmu);
|
||||
|
||||
if (hwc->state & PERF_HES_UPTODATE)
|
||||
return;
|
||||
|
||||
switch (pe->pmu_perf_type) {
|
||||
case PERF_TYPE_AMDGPU_DF:
|
||||
pe->adev->df_funcs->pmc_stop(pe->adev, hwc->conf, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
|
||||
hwc->state |= PERF_HES_STOPPED;
|
||||
|
||||
if (hwc->state & PERF_HES_UPTODATE)
|
||||
return;
|
||||
|
||||
amdgpu_perf_read(event);
|
||||
hwc->state |= PERF_HES_UPTODATE;
|
||||
}
|
||||
|
||||
/* add perf counter */
|
||||
static int amdgpu_perf_add(struct perf_event *event, int flags)
|
||||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
int retval;
|
||||
|
||||
struct amdgpu_pmu_entry *pe = container_of(event->pmu,
|
||||
struct amdgpu_pmu_entry,
|
||||
pmu);
|
||||
|
||||
event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
|
||||
|
||||
switch (pe->pmu_perf_type) {
|
||||
case PERF_TYPE_AMDGPU_DF:
|
||||
retval = pe->adev->df_funcs->pmc_start(pe->adev, hwc->conf, 1);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if (flags & PERF_EF_START)
|
||||
amdgpu_perf_start(event, PERF_EF_RELOAD);
|
||||
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
||||
/* delete perf counter */
|
||||
static void amdgpu_perf_del(struct perf_event *event, int flags)
|
||||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
struct amdgpu_pmu_entry *pe = container_of(event->pmu,
|
||||
struct amdgpu_pmu_entry,
|
||||
pmu);
|
||||
|
||||
amdgpu_perf_stop(event, PERF_EF_UPDATE);
|
||||
|
||||
switch (pe->pmu_perf_type) {
|
||||
case PERF_TYPE_AMDGPU_DF:
|
||||
pe->adev->df_funcs->pmc_stop(pe->adev, hwc->conf, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
perf_event_update_userpage(event);
|
||||
}
|
||||
|
||||
/* vega20 pmus */
|
||||
|
||||
/* init pmu tracking per pmu type */
|
||||
static int init_pmu_by_type(struct amdgpu_device *adev,
|
||||
const struct attribute_group *attr_groups[],
|
||||
char *pmu_type_name, char *pmu_file_prefix,
|
||||
unsigned int pmu_perf_type,
|
||||
unsigned int num_counters)
|
||||
{
|
||||
char pmu_name[PMU_NAME_SIZE];
|
||||
struct amdgpu_pmu_entry *pmu_entry;
|
||||
int ret = 0;
|
||||
|
||||
pmu_entry = kzalloc(sizeof(struct amdgpu_pmu_entry), GFP_KERNEL);
|
||||
|
||||
if (!pmu_entry)
|
||||
return -ENOMEM;
|
||||
|
||||
pmu_entry->adev = adev;
|
||||
pmu_entry->pmu = (struct pmu){
|
||||
.event_init = amdgpu_perf_event_init,
|
||||
.add = amdgpu_perf_add,
|
||||
.del = amdgpu_perf_del,
|
||||
.start = amdgpu_perf_start,
|
||||
.stop = amdgpu_perf_stop,
|
||||
.read = amdgpu_perf_read,
|
||||
.task_ctx_nr = perf_invalid_context,
|
||||
};
|
||||
|
||||
pmu_entry->pmu.attr_groups = attr_groups;
|
||||
pmu_entry->pmu_perf_type = pmu_perf_type;
|
||||
snprintf(pmu_name, PMU_NAME_SIZE, "%s_%d",
|
||||
pmu_file_prefix, adev->ddev->primary->index);
|
||||
|
||||
ret = perf_pmu_register(&pmu_entry->pmu, pmu_name, -1);
|
||||
|
||||
if (ret) {
|
||||
kfree(pmu_entry);
|
||||
pr_warn("Error initializing AMDGPU %s PMUs.\n", pmu_type_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pr_info("Detected AMDGPU %s Counters. # of Counters = %d.\n",
|
||||
pmu_type_name, num_counters);
|
||||
|
||||
list_add_tail(&pmu_entry->entry, &amdgpu_pmu_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* init amdgpu_pmu */
|
||||
int amdgpu_pmu_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA20:
|
||||
/* init df */
|
||||
ret = init_pmu_by_type(adev, df_v3_6_attr_groups,
|
||||
"DF", "amdgpu_df", PERF_TYPE_AMDGPU_DF,
|
||||
DF_V3_6_MAX_COUNTERS);
|
||||
|
||||
/* other pmu types go here*/
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* destroy all pmu data associated with target device */
|
||||
void amdgpu_pmu_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_pmu_entry *pe, *temp;
|
||||
|
||||
list_for_each_entry_safe(pe, temp, &amdgpu_pmu_list, entry) {
|
||||
if (pe->adev == adev) {
|
||||
list_del(&pe->entry);
|
||||
perf_pmu_unregister(&pe->pmu);
|
||||
kfree(pe);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author: Jonathan Kim <jonathan.kim@amd.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _AMDGPU_PMU_H_
|
||||
#define _AMDGPU_PMU_H_
|
||||
|
||||
enum amdgpu_pmu_perf_type {
|
||||
PERF_TYPE_AMDGPU_DF = 0,
|
||||
PERF_TYPE_AMDGPU_MAX
|
||||
};
|
||||
|
||||
int amdgpu_pmu_init(struct amdgpu_device *adev);
|
||||
void amdgpu_pmu_fini(struct amdgpu_device *adev);
|
||||
|
||||
#endif /* _AMDGPU_PMU_H_ */
|
|
@ -46,12 +46,19 @@ static int psp_early_init(void *handle)
|
|||
case CHIP_VEGA10:
|
||||
case CHIP_VEGA12:
|
||||
psp_v3_1_set_psp_funcs(psp);
|
||||
psp->autoload_supported = false;
|
||||
break;
|
||||
case CHIP_RAVEN:
|
||||
psp_v10_0_set_psp_funcs(psp);
|
||||
psp->autoload_supported = false;
|
||||
break;
|
||||
case CHIP_VEGA20:
|
||||
psp_v11_0_set_psp_funcs(psp);
|
||||
psp->autoload_supported = false;
|
||||
break;
|
||||
case CHIP_NAVI10:
|
||||
psp_v11_0_set_psp_funcs(psp);
|
||||
psp->autoload_supported = true;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -182,10 +189,44 @@ static void psp_prep_tmr_cmd_buf(struct psp_context *psp,
|
|||
cmd->cmd.cmd_setup_tmr.buf_size = size;
|
||||
}
|
||||
|
||||
static void psp_prep_load_toc_cmd_buf(struct psp_gfx_cmd_resp *cmd,
|
||||
uint64_t pri_buf_mc, uint32_t size)
|
||||
{
|
||||
cmd->cmd_id = GFX_CMD_ID_LOAD_TOC;
|
||||
cmd->cmd.cmd_load_toc.toc_phy_addr_lo = lower_32_bits(pri_buf_mc);
|
||||
cmd->cmd.cmd_load_toc.toc_phy_addr_hi = upper_32_bits(pri_buf_mc);
|
||||
cmd->cmd.cmd_load_toc.toc_size = size;
|
||||
}
|
||||
|
||||
/* Issue LOAD TOC cmd to PSP to part toc and calculate tmr size needed */
|
||||
static int psp_load_toc(struct psp_context *psp,
|
||||
uint32_t *tmr_size)
|
||||
{
|
||||
int ret;
|
||||
struct psp_gfx_cmd_resp *cmd;
|
||||
|
||||
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
/* Copy toc to psp firmware private buffer */
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
memcpy(psp->fw_pri_buf, psp->toc_start_addr, psp->toc_bin_size);
|
||||
|
||||
psp_prep_load_toc_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->toc_bin_size);
|
||||
|
||||
ret = psp_cmd_submit_buf(psp, NULL, cmd,
|
||||
psp->fence_buf_mc_addr);
|
||||
if (!ret)
|
||||
*tmr_size = psp->cmd_buf_mem->resp.tmr_size;
|
||||
kfree(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set up Trusted Memory Region */
|
||||
static int psp_tmr_init(struct psp_context *psp)
|
||||
{
|
||||
int ret;
|
||||
int tmr_size;
|
||||
|
||||
/*
|
||||
* According to HW engineer, they prefer the TMR address be "naturally
|
||||
|
@ -194,7 +235,21 @@ static int psp_tmr_init(struct psp_context *psp)
|
|||
* Note: this memory need be reserved till the driver
|
||||
* uninitializes.
|
||||
*/
|
||||
ret = amdgpu_bo_create_kernel(psp->adev, PSP_TMR_SIZE, PSP_TMR_SIZE,
|
||||
tmr_size = PSP_TMR_SIZE;
|
||||
|
||||
/* For ASICs support RLC autoload, psp will parse the toc
|
||||
* and calculate the total size of TMR needed */
|
||||
if (psp->toc_start_addr &&
|
||||
psp->toc_bin_size &&
|
||||
psp->fw_pri_buf) {
|
||||
ret = psp_load_toc(psp, &tmr_size);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to load toc\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = amdgpu_bo_create_kernel(psp->adev, tmr_size, PSP_TMR_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf);
|
||||
|
||||
|
@ -210,9 +265,10 @@ static int psp_tmr_load(struct psp_context *psp)
|
|||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
psp_prep_tmr_cmd_buf(psp, cmd, psp->tmr_mc_addr, PSP_TMR_SIZE);
|
||||
DRM_INFO("reserve 0x%x from 0x%llx for PSP TMR SIZE\n",
|
||||
PSP_TMR_SIZE, psp->tmr_mc_addr);
|
||||
psp_prep_tmr_cmd_buf(psp, cmd, psp->tmr_mc_addr,
|
||||
amdgpu_bo_size(psp->tmr_bo));
|
||||
DRM_INFO("reserve 0x%lx from 0x%llx for PSP TMR\n",
|
||||
amdgpu_bo_size(psp->tmr_bo), psp->tmr_mc_addr);
|
||||
|
||||
ret = psp_cmd_submit_buf(psp, NULL, cmd,
|
||||
psp->fence_buf_mc_addr);
|
||||
|
@ -726,12 +782,24 @@ static int psp_hw_start(struct psp_context *psp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = psp_tmr_init(psp);
|
||||
if (ret) {
|
||||
DRM_ERROR("PSP tmr init failed!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = psp_tmr_load(psp);
|
||||
if (ret) {
|
||||
DRM_ERROR("PSP load tmr failed!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = psp_asd_init(psp);
|
||||
if (ret) {
|
||||
DRM_ERROR("PSP asd init failed!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = psp_asd_load(psp);
|
||||
if (ret) {
|
||||
DRM_ERROR("PSP load asd failed!\n");
|
||||
|
@ -823,6 +891,12 @@ static int psp_get_fw_type(struct amdgpu_firmware_info *ucode,
|
|||
case AMDGPU_UCODE_ID_DMCU_INTV:
|
||||
*type = GFX_FW_TYPE_DMCU_ISR;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_VCN0_RAM:
|
||||
*type = GFX_FW_TYPE_VCN0_RAM;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_VCN1_RAM:
|
||||
*type = GFX_FW_TYPE_VCN1_RAM;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_MAXIMUM:
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -851,19 +925,45 @@ static int psp_prep_load_ip_fw_cmd_buf(struct amdgpu_firmware_info *ucode,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int psp_execute_np_fw_load(struct psp_context *psp,
|
||||
struct amdgpu_firmware_info *ucode)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = psp_prep_load_ip_fw_cmd_buf(ucode, psp->cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = psp_cmd_submit_buf(psp, ucode, psp->cmd,
|
||||
psp->fence_buf_mc_addr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psp_np_fw_load(struct psp_context *psp)
|
||||
{
|
||||
int i, ret;
|
||||
struct amdgpu_firmware_info *ucode;
|
||||
struct amdgpu_device* adev = psp->adev;
|
||||
|
||||
if (psp->autoload_supported) {
|
||||
ucode = &adev->firmware.ucode[AMDGPU_UCODE_ID_SMC];
|
||||
if (!ucode->fw)
|
||||
goto out;
|
||||
|
||||
ret = psp_execute_np_fw_load(psp, ucode);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
out:
|
||||
for (i = 0; i < adev->firmware.max_ucodes; i++) {
|
||||
ucode = &adev->firmware.ucode[i];
|
||||
if (!ucode->fw)
|
||||
continue;
|
||||
|
||||
if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC &&
|
||||
psp_smu_reload_quirk(psp))
|
||||
(psp_smu_reload_quirk(psp) || psp->autoload_supported))
|
||||
continue;
|
||||
if (amdgpu_sriov_vf(adev) &&
|
||||
(ucode->ucode_id == AMDGPU_UCODE_ID_SDMA0
|
||||
|
@ -871,16 +971,24 @@ static int psp_np_fw_load(struct psp_context *psp)
|
|||
|| ucode->ucode_id == AMDGPU_UCODE_ID_RLC_G))
|
||||
/*skip ucode loading in SRIOV VF */
|
||||
continue;
|
||||
if (psp->autoload_supported &&
|
||||
(ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC1_JT ||
|
||||
ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC2_JT))
|
||||
/* skip mec JT when autoload is enabled */
|
||||
continue;
|
||||
|
||||
ret = psp_prep_load_ip_fw_cmd_buf(ucode, psp->cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = psp_cmd_submit_buf(psp, ucode, psp->cmd,
|
||||
psp->fence_buf_mc_addr);
|
||||
ret = psp_execute_np_fw_load(psp, ucode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Start rlc autoload after psp recieved all the gfx firmware */
|
||||
if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM) {
|
||||
ret = psp_rlc_autoload(psp);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to start rlc autoload\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
/* check if firmware loaded sucessfully */
|
||||
if (!amdgpu_psp_check_fw_loading_status(adev, i))
|
||||
|
@ -939,18 +1047,6 @@ static int psp_load_fw(struct amdgpu_device *adev)
|
|||
goto failed;
|
||||
}
|
||||
|
||||
ret = psp_tmr_init(psp);
|
||||
if (ret) {
|
||||
DRM_ERROR("PSP tmr init failed!\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ret = psp_asd_init(psp);
|
||||
if (ret) {
|
||||
DRM_ERROR("PSP asd init failed!\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
skip_memalloc:
|
||||
ret = psp_hw_start(psp);
|
||||
if (ret)
|
||||
|
@ -1098,6 +1194,39 @@ int psp_gpu_reset(struct amdgpu_device *adev)
|
|||
return psp_mode1_reset(&adev->psp);
|
||||
}
|
||||
|
||||
int psp_rlc_autoload_start(struct psp_context *psp)
|
||||
{
|
||||
int ret;
|
||||
struct psp_gfx_cmd_resp *cmd;
|
||||
|
||||
if (amdgpu_sriov_vf(psp->adev))
|
||||
return 0;
|
||||
|
||||
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd->cmd_id = GFX_CMD_ID_AUTOLOAD_RLC;
|
||||
|
||||
ret = psp_cmd_submit_buf(psp, NULL, cmd,
|
||||
psp->fence_buf_mc_addr);
|
||||
kfree(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int psp_update_vcn_sram(struct amdgpu_device *adev, int inst_idx,
|
||||
uint64_t cmd_gpu_addr, int cmd_size)
|
||||
{
|
||||
struct amdgpu_firmware_info ucode = {0};
|
||||
|
||||
ucode.ucode_id = inst_idx ? AMDGPU_UCODE_ID_VCN1_RAM :
|
||||
AMDGPU_UCODE_ID_VCN0_RAM;
|
||||
ucode.mc_addr = cmd_gpu_addr;
|
||||
ucode.ucode_size = cmd_size;
|
||||
|
||||
return psp_execute_np_fw_load(&adev->psp, &ucode);
|
||||
}
|
||||
|
||||
static bool psp_check_fw_loading_status(struct amdgpu_device *adev,
|
||||
enum AMDGPU_UCODE_ID ucode_type)
|
||||
{
|
||||
|
|
|
@ -101,6 +101,7 @@ struct psp_funcs
|
|||
int (*ras_trigger_error)(struct psp_context *psp,
|
||||
struct ta_ras_trigger_error_input *info);
|
||||
int (*ras_cure_posion)(struct psp_context *psp, uint64_t *mode_ptr);
|
||||
int (*rlc_autoload_start)(struct psp_context *psp);
|
||||
};
|
||||
|
||||
#define AMDGPU_XGMI_MAX_CONNECTED_NODES 64
|
||||
|
@ -154,8 +155,10 @@ struct psp_context
|
|||
uint32_t sos_feature_version;
|
||||
uint32_t sys_bin_size;
|
||||
uint32_t sos_bin_size;
|
||||
uint32_t toc_bin_size;
|
||||
uint8_t *sys_start_addr;
|
||||
uint8_t *sos_start_addr;
|
||||
uint8_t *toc_start_addr;
|
||||
|
||||
/* tmr buffer */
|
||||
struct amdgpu_bo *tmr_bo;
|
||||
|
@ -184,6 +187,8 @@ struct psp_context
|
|||
|
||||
/* fence value associated with cmd buffer */
|
||||
atomic_t fence_value;
|
||||
/* flag to mark whether gfx fw autoload is supported or not */
|
||||
bool autoload_supported;
|
||||
|
||||
/* xgmi ta firmware and buffer */
|
||||
const struct firmware *ta_fw;
|
||||
|
@ -234,6 +239,8 @@ struct amdgpu_psp_funcs {
|
|||
#define psp_xgmi_set_topology_info(psp, num_device, topology) \
|
||||
((psp)->funcs->xgmi_set_topology_info ? \
|
||||
(psp)->funcs->xgmi_set_topology_info((psp), (num_device), (topology)) : -EINVAL)
|
||||
#define psp_rlc_autoload(psp) \
|
||||
((psp)->funcs->rlc_autoload_start ? (psp)->funcs->rlc_autoload_start((psp)) : 0)
|
||||
|
||||
#define amdgpu_psp_check_fw_loading_status(adev, i) (adev)->firmware.funcs->check_fw_loading_status((adev), (i))
|
||||
|
||||
|
@ -253,12 +260,17 @@ extern int psp_wait_for(struct psp_context *psp, uint32_t reg_index,
|
|||
extern const struct amdgpu_ip_block_version psp_v10_0_ip_block;
|
||||
|
||||
int psp_gpu_reset(struct amdgpu_device *adev);
|
||||
int psp_update_vcn_sram(struct amdgpu_device *adev, int inst_idx,
|
||||
uint64_t cmd_gpu_addr, int cmd_size);
|
||||
|
||||
int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id);
|
||||
|
||||
int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id);
|
||||
int psp_ras_enable_features(struct psp_context *psp,
|
||||
union ta_ras_cmd_input *info, bool enable);
|
||||
|
||||
int psp_rlc_autoload_start(struct psp_context *psp);
|
||||
|
||||
extern const struct amdgpu_ip_block_version psp_v11_0_ip_block;
|
||||
int psp_reg_program(struct psp_context *psp, enum psp_reg_prog_id reg,
|
||||
uint32_t value);
|
||||
|
|
|
@ -335,12 +335,13 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *
|
|||
case 2:
|
||||
ret = amdgpu_ras_reserve_vram(adev,
|
||||
data.inject.address, PAGE_SIZE, &bo);
|
||||
/* This address might be used already on failure. In fact we can
|
||||
* perform an injection in such case.
|
||||
*/
|
||||
if (ret)
|
||||
break;
|
||||
data.inject.address = amdgpu_bo_gpu_offset(bo);
|
||||
if (ret) {
|
||||
/* address was offset, now it is absolute.*/
|
||||
data.inject.address += adev->gmc.vram_start;
|
||||
if (data.inject.address > adev->gmc.vram_end)
|
||||
break;
|
||||
} else
|
||||
data.inject.address = amdgpu_bo_gpu_offset(bo);
|
||||
ret = amdgpu_ras_error_inject(adev, &data.inject);
|
||||
amdgpu_ras_release_vram(adev, &bo);
|
||||
break;
|
||||
|
@ -969,40 +970,24 @@ static int amdgpu_ras_sysfs_remove_all(struct amdgpu_device *adev)
|
|||
/* sysfs end */
|
||||
|
||||
/* debugfs begin */
|
||||
static int amdgpu_ras_debugfs_create_ctrl_node(struct amdgpu_device *adev)
|
||||
static void amdgpu_ras_debugfs_create_ctrl_node(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct drm_minor *minor = adev->ddev->primary;
|
||||
struct dentry *root = minor->debugfs_root, *dir;
|
||||
struct dentry *ent;
|
||||
|
||||
dir = debugfs_create_dir("ras", root);
|
||||
if (IS_ERR(dir))
|
||||
return -EINVAL;
|
||||
|
||||
con->dir = dir;
|
||||
|
||||
ent = debugfs_create_file("ras_ctrl",
|
||||
S_IWUGO | S_IRUGO, con->dir,
|
||||
adev, &amdgpu_ras_debugfs_ctrl_ops);
|
||||
if (IS_ERR(ent)) {
|
||||
debugfs_remove(con->dir);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
con->ent = ent;
|
||||
return 0;
|
||||
con->dir = debugfs_create_dir("ras", minor->debugfs_root);
|
||||
con->ent = debugfs_create_file("ras_ctrl", S_IWUGO | S_IRUGO, con->dir,
|
||||
adev, &amdgpu_ras_debugfs_ctrl_ops);
|
||||
}
|
||||
|
||||
int amdgpu_ras_debugfs_create(struct amdgpu_device *adev,
|
||||
void amdgpu_ras_debugfs_create(struct amdgpu_device *adev,
|
||||
struct ras_fs_if *head)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct ras_manager *obj = amdgpu_ras_find_obj(adev, &head->head);
|
||||
struct dentry *ent;
|
||||
|
||||
if (!obj || obj->ent)
|
||||
return -EINVAL;
|
||||
return;
|
||||
|
||||
get_obj(obj);
|
||||
|
||||
|
@ -1010,34 +995,25 @@ int amdgpu_ras_debugfs_create(struct amdgpu_device *adev,
|
|||
head->debugfs_name,
|
||||
sizeof(obj->fs_data.debugfs_name));
|
||||
|
||||
ent = debugfs_create_file(obj->fs_data.debugfs_name,
|
||||
S_IWUGO | S_IRUGO, con->dir,
|
||||
obj, &amdgpu_ras_debugfs_ops);
|
||||
|
||||
if (IS_ERR(ent))
|
||||
return -EINVAL;
|
||||
|
||||
obj->ent = ent;
|
||||
|
||||
return 0;
|
||||
obj->ent = debugfs_create_file(obj->fs_data.debugfs_name,
|
||||
S_IWUGO | S_IRUGO, con->dir, obj,
|
||||
&amdgpu_ras_debugfs_ops);
|
||||
}
|
||||
|
||||
int amdgpu_ras_debugfs_remove(struct amdgpu_device *adev,
|
||||
void amdgpu_ras_debugfs_remove(struct amdgpu_device *adev,
|
||||
struct ras_common_if *head)
|
||||
{
|
||||
struct ras_manager *obj = amdgpu_ras_find_obj(adev, head);
|
||||
|
||||
if (!obj || !obj->ent)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
debugfs_remove(obj->ent);
|
||||
obj->ent = NULL;
|
||||
put_obj(obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_ras_debugfs_remove_all(struct amdgpu_device *adev)
|
||||
static void amdgpu_ras_debugfs_remove_all(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct ras_manager *obj, *tmp;
|
||||
|
@ -1050,8 +1026,6 @@ static int amdgpu_ras_debugfs_remove_all(struct amdgpu_device *adev)
|
|||
debugfs_remove(con->dir);
|
||||
con->dir = NULL;
|
||||
con->ent = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* debugfs end */
|
||||
|
||||
|
|
|
@ -276,10 +276,10 @@ int amdgpu_ras_sysfs_create(struct amdgpu_device *adev,
|
|||
int amdgpu_ras_sysfs_remove(struct amdgpu_device *adev,
|
||||
struct ras_common_if *head);
|
||||
|
||||
int amdgpu_ras_debugfs_create(struct amdgpu_device *adev,
|
||||
void amdgpu_ras_debugfs_create(struct amdgpu_device *adev,
|
||||
struct ras_fs_if *head);
|
||||
|
||||
int amdgpu_ras_debugfs_remove(struct amdgpu_device *adev,
|
||||
void amdgpu_ras_debugfs_remove(struct amdgpu_device *adev,
|
||||
struct ras_common_if *head);
|
||||
|
||||
int amdgpu_ras_error_query(struct amdgpu_device *adev,
|
||||
|
|
|
@ -282,6 +282,16 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
|
|||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_device_wb_get(adev, &ring->trail_fence_offs);
|
||||
if (r) {
|
||||
dev_err(adev->dev,
|
||||
"(%d) ring trail_fence_offs wb alloc failed\n", r);
|
||||
return r;
|
||||
}
|
||||
ring->trail_fence_gpu_addr =
|
||||
adev->wb.gpu_addr + (ring->trail_fence_offs * 4);
|
||||
ring->trail_fence_cpu_addr = &adev->wb.wb[ring->trail_fence_offs];
|
||||
|
||||
r = amdgpu_device_wb_get(adev, &ring->cond_exe_offs);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "(%d) ring cond_exec_polling wb alloc failed\n", r);
|
||||
|
@ -400,7 +410,7 @@ bool amdgpu_ring_soft_recovery(struct amdgpu_ring *ring, unsigned int vmid,
|
|||
{
|
||||
ktime_t deadline = ktime_add_us(ktime_get(), 10000);
|
||||
|
||||
if (!ring->funcs->soft_recovery || !fence)
|
||||
if (amdgpu_sriov_vf(ring->adev) || !ring->funcs->soft_recovery || !fence)
|
||||
return false;
|
||||
|
||||
atomic_inc(&ring->adev->gpu_reset_counter);
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
#include <drm/drm_print.h>
|
||||
|
||||
/* max number of rings */
|
||||
#define AMDGPU_MAX_RINGS 23
|
||||
#define AMDGPU_MAX_GFX_RINGS 1
|
||||
#define AMDGPU_MAX_RINGS 24
|
||||
#define AMDGPU_MAX_GFX_RINGS 2
|
||||
#define AMDGPU_MAX_COMPUTE_RINGS 8
|
||||
#define AMDGPU_MAX_VCE_RINGS 3
|
||||
#define AMDGPU_MAX_UVD_ENC_RINGS 2
|
||||
|
@ -172,6 +172,7 @@ struct amdgpu_ring_funcs {
|
|||
enum drm_sched_priority priority);
|
||||
/* Try to soft recover the ring to make the fence signal */
|
||||
void (*soft_recovery)(struct amdgpu_ring *ring, unsigned vmid);
|
||||
int (*preempt_ib)(struct amdgpu_ring *ring);
|
||||
};
|
||||
|
||||
struct amdgpu_ring {
|
||||
|
@ -206,6 +207,10 @@ struct amdgpu_ring {
|
|||
unsigned fence_offs;
|
||||
uint64_t current_ctx;
|
||||
char name[16];
|
||||
u32 trail_seq;
|
||||
unsigned trail_fence_offs;
|
||||
u64 trail_fence_gpu_addr;
|
||||
volatile u32 *trail_fence_cpu_addr;
|
||||
unsigned cond_exe_offs;
|
||||
u64 cond_exe_gpu_addr;
|
||||
volatile u32 *cond_exe_cpu_addr;
|
||||
|
@ -246,6 +251,7 @@ struct amdgpu_ring {
|
|||
#define amdgpu_ring_pad_ib(r, ib) ((r)->funcs->pad_ib((r), (ib)))
|
||||
#define amdgpu_ring_init_cond_exec(r) (r)->funcs->init_cond_exec((r))
|
||||
#define amdgpu_ring_patch_cond_exec(r,o) (r)->funcs->patch_cond_exec((r),(o))
|
||||
#define amdgpu_ring_preempt_ib(r) (r)->funcs->preempt_ib(r)
|
||||
|
||||
int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned ndw);
|
||||
void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count);
|
||||
|
@ -266,6 +272,12 @@ void amdgpu_ring_emit_reg_write_reg_wait_helper(struct amdgpu_ring *ring,
|
|||
bool amdgpu_ring_soft_recovery(struct amdgpu_ring *ring, unsigned int vmid,
|
||||
struct dma_fence *fence);
|
||||
|
||||
static inline void amdgpu_ring_set_preempt_cond_exec(struct amdgpu_ring *ring,
|
||||
bool cond_exec)
|
||||
{
|
||||
*ring->cond_exe_cpu_addr = cond_exec;
|
||||
}
|
||||
|
||||
static inline void amdgpu_ring_clear_ring(struct amdgpu_ring *ring)
|
||||
{
|
||||
int i = 0;
|
||||
|
|
|
@ -26,6 +26,94 @@
|
|||
|
||||
#include "clearstate_defs.h"
|
||||
|
||||
/* firmware ID used in rlc toc */
|
||||
typedef enum _FIRMWARE_ID_ {
|
||||
FIRMWARE_ID_INVALID = 0,
|
||||
FIRMWARE_ID_RLC_G_UCODE = 1,
|
||||
FIRMWARE_ID_RLC_TOC = 2,
|
||||
FIRMWARE_ID_RLCG_SCRATCH = 3,
|
||||
FIRMWARE_ID_RLC_SRM_ARAM = 4,
|
||||
FIRMWARE_ID_RLC_SRM_INDEX_ADDR = 5,
|
||||
FIRMWARE_ID_RLC_SRM_INDEX_DATA = 6,
|
||||
FIRMWARE_ID_RLC_P_UCODE = 7,
|
||||
FIRMWARE_ID_RLC_V_UCODE = 8,
|
||||
FIRMWARE_ID_RLX6_UCODE = 9,
|
||||
FIRMWARE_ID_RLX6_DRAM_BOOT = 10,
|
||||
FIRMWARE_ID_GLOBAL_TAP_DELAYS = 11,
|
||||
FIRMWARE_ID_SE0_TAP_DELAYS = 12,
|
||||
FIRMWARE_ID_SE1_TAP_DELAYS = 13,
|
||||
FIRMWARE_ID_GLOBAL_SE0_SE1_SKEW_DELAYS = 14,
|
||||
FIRMWARE_ID_SDMA0_UCODE = 15,
|
||||
FIRMWARE_ID_SDMA0_JT = 16,
|
||||
FIRMWARE_ID_SDMA1_UCODE = 17,
|
||||
FIRMWARE_ID_SDMA1_JT = 18,
|
||||
FIRMWARE_ID_CP_CE = 19,
|
||||
FIRMWARE_ID_CP_PFP = 20,
|
||||
FIRMWARE_ID_CP_ME = 21,
|
||||
FIRMWARE_ID_CP_MEC = 22,
|
||||
FIRMWARE_ID_CP_MES = 23,
|
||||
FIRMWARE_ID_MES_STACK = 24,
|
||||
FIRMWARE_ID_RLC_SRM_DRAM_SR = 25,
|
||||
FIRMWARE_ID_RLCG_SCRATCH_SR = 26,
|
||||
FIRMWARE_ID_RLCP_SCRATCH_SR = 27,
|
||||
FIRMWARE_ID_RLCV_SCRATCH_SR = 28,
|
||||
FIRMWARE_ID_RLX6_DRAM_SR = 29,
|
||||
FIRMWARE_ID_SDMA0_PG_CONTEXT = 30,
|
||||
FIRMWARE_ID_SDMA1_PG_CONTEXT = 31,
|
||||
FIRMWARE_ID_GLOBAL_MUX_SELECT_RAM = 32,
|
||||
FIRMWARE_ID_SE0_MUX_SELECT_RAM = 33,
|
||||
FIRMWARE_ID_SE1_MUX_SELECT_RAM = 34,
|
||||
FIRMWARE_ID_ACCUM_CTRL_RAM = 35,
|
||||
FIRMWARE_ID_RLCP_CAM = 36,
|
||||
FIRMWARE_ID_RLC_SPP_CAM_EXT = 37,
|
||||
FIRMWARE_ID_MAX = 38,
|
||||
} FIRMWARE_ID;
|
||||
|
||||
typedef struct _RLC_TABLE_OF_CONTENT {
|
||||
union {
|
||||
unsigned int DW0;
|
||||
struct {
|
||||
unsigned int offset : 25;
|
||||
unsigned int id : 7;
|
||||
};
|
||||
};
|
||||
|
||||
union {
|
||||
unsigned int DW1;
|
||||
struct {
|
||||
unsigned int load_at_boot : 1;
|
||||
unsigned int load_at_vddgfx : 1;
|
||||
unsigned int load_at_reset : 1;
|
||||
unsigned int memory_destination : 2;
|
||||
unsigned int vfflr_image_code : 4;
|
||||
unsigned int load_mode_direct : 1;
|
||||
unsigned int save_for_vddgfx : 1;
|
||||
unsigned int save_for_vfflr : 1;
|
||||
unsigned int reserved : 1;
|
||||
unsigned int signed_source : 1;
|
||||
unsigned int size : 18;
|
||||
};
|
||||
};
|
||||
|
||||
union {
|
||||
unsigned int DW2;
|
||||
struct {
|
||||
unsigned int indirect_addr_reg : 16;
|
||||
unsigned int index : 16;
|
||||
};
|
||||
};
|
||||
|
||||
union {
|
||||
unsigned int DW3;
|
||||
struct {
|
||||
unsigned int indirect_data_reg : 16;
|
||||
unsigned int indirect_start_offset : 16;
|
||||
};
|
||||
};
|
||||
} RLC_TABLE_OF_CONTENT;
|
||||
|
||||
#define RLC_TOC_MAX_SIZE 64
|
||||
|
||||
struct amdgpu_rlc_funcs {
|
||||
bool (*is_rlc_enabled)(struct amdgpu_device *adev);
|
||||
void (*set_safe_mode)(struct amdgpu_device *adev);
|
||||
|
@ -85,6 +173,16 @@ struct amdgpu_rlc {
|
|||
u8 *save_restore_list_srm;
|
||||
|
||||
bool is_rlc_v2_1;
|
||||
|
||||
/* for rlc autoload */
|
||||
struct amdgpu_bo *rlc_autoload_bo;
|
||||
u64 rlc_autoload_gpu_addr;
|
||||
void *rlc_autoload_ptr;
|
||||
|
||||
/* rlc toc buffer */
|
||||
struct amdgpu_bo *rlc_toc_bo;
|
||||
uint64_t rlc_toc_gpu_addr;
|
||||
void *rlc_toc_buf;
|
||||
};
|
||||
|
||||
void amdgpu_gfx_rlc_enter_safe_mode(struct amdgpu_device *adev);
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
#include "amdgpu.h"
|
||||
#include "amdgpu_sdma.h"
|
||||
|
||||
#define AMDGPU_CSA_SDMA_SIZE 64
|
||||
/* SDMA CSA reside in the 3rd page of CSA */
|
||||
#define AMDGPU_CSA_SDMA_OFFSET (4096 * 2)
|
||||
|
||||
/*
|
||||
* GPU SDMA IP block helpers function.
|
||||
*/
|
||||
|
@ -56,3 +60,26 @@ int amdgpu_sdma_get_index_from_ring(struct amdgpu_ring *ring, uint32_t *index)
|
|||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
uint64_t amdgpu_sdma_get_csa_mc_addr(struct amdgpu_ring *ring,
|
||||
unsigned vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
uint64_t csa_mc_addr;
|
||||
uint32_t index = 0;
|
||||
int r;
|
||||
|
||||
if (vmid == 0 || !amdgpu_mcbp)
|
||||
return 0;
|
||||
|
||||
r = amdgpu_sdma_get_index_from_ring(ring, &index);
|
||||
|
||||
if (r || index > 31)
|
||||
csa_mc_addr = 0;
|
||||
else
|
||||
csa_mc_addr = amdgpu_csa_vaddr(adev) +
|
||||
AMDGPU_CSA_SDMA_OFFSET +
|
||||
index * AMDGPU_CSA_SDMA_SIZE;
|
||||
|
||||
return csa_mc_addr;
|
||||
}
|
||||
|
|
|
@ -97,5 +97,5 @@ struct amdgpu_buffer_funcs {
|
|||
struct amdgpu_sdma_instance *
|
||||
amdgpu_sdma_get_instance_from_ring(struct amdgpu_ring *ring);
|
||||
int amdgpu_sdma_get_index_from_ring(struct amdgpu_ring *ring, uint32_t *index);
|
||||
|
||||
uint64_t amdgpu_sdma_get_csa_mc_addr(struct amdgpu_ring *ring, unsigned vmid);
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#ifndef __AMDGPU_SOCBB_H__
|
||||
#define __AMDGPU_SOCBB_H__
|
||||
|
||||
struct gpu_info_voltage_scaling_v1_0 {
|
||||
uint32_t state;
|
||||
uint32_t dscclk_mhz;
|
||||
uint32_t dcfclk_mhz;
|
||||
uint32_t socclk_mhz;
|
||||
uint32_t dram_speed_mts;
|
||||
uint32_t fabricclk_mhz;
|
||||
uint32_t dispclk_mhz;
|
||||
uint32_t phyclk_mhz;
|
||||
uint32_t dppclk_mhz;
|
||||
};
|
||||
|
||||
struct gpu_info_soc_bounding_box_v1_0 {
|
||||
uint32_t sr_exit_time_us;
|
||||
uint32_t sr_enter_plus_exit_time_us;
|
||||
uint32_t urgent_latency_us;
|
||||
uint32_t urgent_latency_pixel_data_only_us;
|
||||
uint32_t urgent_latency_pixel_mixed_with_vm_data_us;
|
||||
uint32_t urgent_latency_vm_data_only_us;
|
||||
uint32_t writeback_latency_us;
|
||||
uint32_t ideal_dram_bw_after_urgent_percent;
|
||||
uint32_t pct_ideal_dram_sdp_bw_after_urgent_pixel_only; // PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelDataOnly
|
||||
uint32_t pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm;
|
||||
uint32_t pct_ideal_dram_sdp_bw_after_urgent_vm_only;
|
||||
uint32_t max_avg_sdp_bw_use_normal_percent;
|
||||
uint32_t max_avg_dram_bw_use_normal_percent;
|
||||
uint32_t max_request_size_bytes;
|
||||
uint32_t downspread_percent;
|
||||
uint32_t dram_page_open_time_ns;
|
||||
uint32_t dram_rw_turnaround_time_ns;
|
||||
uint32_t dram_return_buffer_per_channel_bytes;
|
||||
uint32_t dram_channel_width_bytes;
|
||||
uint32_t fabric_datapath_to_dcn_data_return_bytes;
|
||||
uint32_t dcn_downspread_percent;
|
||||
uint32_t dispclk_dppclk_vco_speed_mhz;
|
||||
uint32_t dfs_vco_period_ps;
|
||||
uint32_t urgent_out_of_order_return_per_channel_pixel_only_bytes;
|
||||
uint32_t urgent_out_of_order_return_per_channel_pixel_and_vm_bytes;
|
||||
uint32_t urgent_out_of_order_return_per_channel_vm_only_bytes;
|
||||
uint32_t round_trip_ping_latency_dcfclk_cycles;
|
||||
uint32_t urgent_out_of_order_return_per_channel_bytes;
|
||||
uint32_t channel_interleave_bytes;
|
||||
uint32_t num_banks;
|
||||
uint32_t num_chans;
|
||||
uint32_t vmm_page_size_bytes;
|
||||
uint32_t dram_clock_change_latency_us;
|
||||
uint32_t writeback_dram_clock_change_latency_us;
|
||||
uint32_t return_bus_width_bytes;
|
||||
uint32_t voltage_override;
|
||||
uint32_t xfc_bus_transport_time_us;
|
||||
uint32_t xfc_xbuf_latency_tolerance_us;
|
||||
uint32_t use_urgent_burst_bw;
|
||||
uint32_t num_states;
|
||||
struct gpu_info_voltage_scaling_v1_0 clock_limits[8];
|
||||
};
|
||||
|
||||
#endif
|
|
@ -716,8 +716,7 @@ struct amdgpu_ttm_tt {
|
|||
struct task_struct *usertask;
|
||||
uint32_t userflags;
|
||||
#if IS_ENABLED(CONFIG_DRM_AMDGPU_USERPTR)
|
||||
struct hmm_range *ranges;
|
||||
int nr_ranges;
|
||||
struct hmm_range *range;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -730,57 +729,36 @@ struct amdgpu_ttm_tt {
|
|||
*/
|
||||
#if IS_ENABLED(CONFIG_DRM_AMDGPU_USERPTR)
|
||||
|
||||
/* Support Userptr pages cross max 16 vmas */
|
||||
#define MAX_NR_VMAS (16)
|
||||
#define MAX_RETRY_HMM_RANGE_FAULT 16
|
||||
|
||||
int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages)
|
||||
{
|
||||
struct amdgpu_ttm_tt *gtt = (void *)ttm;
|
||||
struct mm_struct *mm = gtt->usertask->mm;
|
||||
unsigned long start = gtt->userptr;
|
||||
unsigned long end = start + ttm->num_pages * PAGE_SIZE;
|
||||
struct vm_area_struct *vma = NULL, *vmas[MAX_NR_VMAS];
|
||||
struct hmm_range *ranges;
|
||||
unsigned long nr_pages, i;
|
||||
uint64_t *pfns, f;
|
||||
struct vm_area_struct *vma;
|
||||
struct hmm_range *range;
|
||||
unsigned long i;
|
||||
uint64_t *pfns;
|
||||
int retry = 0;
|
||||
int r = 0;
|
||||
|
||||
if (!mm) /* Happens during process shutdown */
|
||||
return -ESRCH;
|
||||
|
||||
down_read(&mm->mmap_sem);
|
||||
|
||||
/* user pages may cross multiple VMAs */
|
||||
gtt->nr_ranges = 0;
|
||||
do {
|
||||
unsigned long vm_start;
|
||||
|
||||
if (gtt->nr_ranges >= MAX_NR_VMAS) {
|
||||
DRM_ERROR("Too many VMAs in userptr range\n");
|
||||
r = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
vm_start = vma ? vma->vm_end : start;
|
||||
vma = find_vma(mm, vm_start);
|
||||
if (unlikely(!vma || vm_start < vma->vm_start)) {
|
||||
r = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
vmas[gtt->nr_ranges++] = vma;
|
||||
} while (end > vma->vm_end);
|
||||
|
||||
DRM_DEBUG_DRIVER("0x%lx nr_ranges %d pages 0x%lx\n",
|
||||
start, gtt->nr_ranges, ttm->num_pages);
|
||||
|
||||
vma = find_vma(mm, start);
|
||||
if (unlikely(!vma || start < vma->vm_start)) {
|
||||
r = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
if (unlikely((gtt->userflags & AMDGPU_GEM_USERPTR_ANONONLY) &&
|
||||
vmas[0]->vm_file)) {
|
||||
vma->vm_file)) {
|
||||
r = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ranges = kvmalloc_array(gtt->nr_ranges, sizeof(*ranges), GFP_KERNEL);
|
||||
if (unlikely(!ranges)) {
|
||||
range = kzalloc(sizeof(*range), GFP_KERNEL);
|
||||
if (unlikely(!range)) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
@ -791,61 +769,67 @@ int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages)
|
|||
goto out_free_ranges;
|
||||
}
|
||||
|
||||
for (i = 0; i < gtt->nr_ranges; i++)
|
||||
amdgpu_hmm_init_range(&ranges[i]);
|
||||
amdgpu_hmm_init_range(range);
|
||||
range->default_flags = range->flags[HMM_PFN_VALID];
|
||||
range->default_flags |= amdgpu_ttm_tt_is_readonly(ttm) ?
|
||||
0 : range->flags[HMM_PFN_WRITE];
|
||||
range->pfn_flags_mask = 0;
|
||||
range->pfns = pfns;
|
||||
hmm_range_register(range, mm, start,
|
||||
start + ttm->num_pages * PAGE_SIZE, PAGE_SHIFT);
|
||||
|
||||
f = ranges[0].flags[HMM_PFN_VALID];
|
||||
f |= amdgpu_ttm_tt_is_readonly(ttm) ?
|
||||
0 : ranges[0].flags[HMM_PFN_WRITE];
|
||||
memset64(pfns, f, ttm->num_pages);
|
||||
retry:
|
||||
/*
|
||||
* Just wait for range to be valid, safe to ignore return value as we
|
||||
* will use the return value of hmm_range_fault() below under the
|
||||
* mmap_sem to ascertain the validity of the range.
|
||||
*/
|
||||
hmm_range_wait_until_valid(range, HMM_RANGE_DEFAULT_TIMEOUT);
|
||||
|
||||
for (nr_pages = 0, i = 0; i < gtt->nr_ranges; i++) {
|
||||
ranges[i].vma = vmas[i];
|
||||
ranges[i].start = max(start, vmas[i]->vm_start);
|
||||
ranges[i].end = min(end, vmas[i]->vm_end);
|
||||
ranges[i].pfns = pfns + nr_pages;
|
||||
nr_pages += (ranges[i].end - ranges[i].start) / PAGE_SIZE;
|
||||
down_read(&mm->mmap_sem);
|
||||
|
||||
r = hmm_vma_fault(&ranges[i], true);
|
||||
if (unlikely(r))
|
||||
break;
|
||||
}
|
||||
if (unlikely(r)) {
|
||||
while (i--)
|
||||
hmm_vma_range_done(&ranges[i]);
|
||||
r = hmm_range_fault(range, true);
|
||||
if (unlikely(r < 0)) {
|
||||
if (likely(r == -EAGAIN)) {
|
||||
/*
|
||||
* return -EAGAIN, mmap_sem is dropped
|
||||
*/
|
||||
if (retry++ < MAX_RETRY_HMM_RANGE_FAULT)
|
||||
goto retry;
|
||||
else
|
||||
pr_err("Retry hmm fault too many times\n");
|
||||
}
|
||||
|
||||
goto out_free_pfns;
|
||||
goto out_up_read;
|
||||
}
|
||||
|
||||
up_read(&mm->mmap_sem);
|
||||
|
||||
for (i = 0; i < ttm->num_pages; i++) {
|
||||
pages[i] = hmm_pfn_to_page(&ranges[0], pfns[i]);
|
||||
if (!pages[i]) {
|
||||
pages[i] = hmm_device_entry_to_page(range, pfns[i]);
|
||||
if (unlikely(!pages[i])) {
|
||||
pr_err("Page fault failed for pfn[%lu] = 0x%llx\n",
|
||||
i, pfns[i]);
|
||||
goto out_invalid_pfn;
|
||||
r = -ENOMEM;
|
||||
|
||||
goto out_free_pfns;
|
||||
}
|
||||
}
|
||||
gtt->ranges = ranges;
|
||||
|
||||
gtt->range = range;
|
||||
|
||||
return 0;
|
||||
|
||||
out_up_read:
|
||||
if (likely(r != -EAGAIN))
|
||||
up_read(&mm->mmap_sem);
|
||||
out_free_pfns:
|
||||
hmm_range_unregister(range);
|
||||
kvfree(pfns);
|
||||
out_free_ranges:
|
||||
kvfree(ranges);
|
||||
kfree(range);
|
||||
out:
|
||||
up_read(&mm->mmap_sem);
|
||||
|
||||
return r;
|
||||
|
||||
out_invalid_pfn:
|
||||
for (i = 0; i < gtt->nr_ranges; i++)
|
||||
hmm_vma_range_done(&ranges[i]);
|
||||
kvfree(pfns);
|
||||
kvfree(ranges);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -858,23 +842,23 @@ bool amdgpu_ttm_tt_get_user_pages_done(struct ttm_tt *ttm)
|
|||
{
|
||||
struct amdgpu_ttm_tt *gtt = (void *)ttm;
|
||||
bool r = false;
|
||||
int i;
|
||||
|
||||
if (!gtt || !gtt->userptr)
|
||||
return false;
|
||||
|
||||
DRM_DEBUG_DRIVER("user_pages_done 0x%llx nr_ranges %d pages 0x%lx\n",
|
||||
gtt->userptr, gtt->nr_ranges, ttm->num_pages);
|
||||
DRM_DEBUG_DRIVER("user_pages_done 0x%llx pages 0x%lx\n",
|
||||
gtt->userptr, ttm->num_pages);
|
||||
|
||||
WARN_ONCE(!gtt->ranges || !gtt->ranges[0].pfns,
|
||||
WARN_ONCE(!gtt->range || !gtt->range->pfns,
|
||||
"No user pages to check\n");
|
||||
|
||||
if (gtt->ranges) {
|
||||
for (i = 0; i < gtt->nr_ranges; i++)
|
||||
r |= hmm_vma_range_done(>t->ranges[i]);
|
||||
kvfree(gtt->ranges[0].pfns);
|
||||
kvfree(gtt->ranges);
|
||||
gtt->ranges = NULL;
|
||||
if (gtt->range) {
|
||||
r = hmm_range_valid(gtt->range);
|
||||
hmm_range_unregister(gtt->range);
|
||||
|
||||
kvfree(gtt->range->pfns);
|
||||
kfree(gtt->range);
|
||||
gtt->range = NULL;
|
||||
}
|
||||
|
||||
return r;
|
||||
|
@ -958,9 +942,9 @@ static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm)
|
|||
sg_free_table(ttm->sg);
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_AMDGPU_USERPTR)
|
||||
if (gtt->ranges &&
|
||||
ttm->pages[0] == hmm_pfn_to_page(>t->ranges[0],
|
||||
gtt->ranges[0].pfns[0]))
|
||||
if (gtt->range &&
|
||||
ttm->pages[0] == hmm_device_entry_to_page(gtt->range,
|
||||
gtt->range->pfns[0]))
|
||||
WARN_ONCE(1, "Missing get_user_page_done\n");
|
||||
#endif
|
||||
}
|
||||
|
@ -983,8 +967,8 @@ int amdgpu_ttm_gart_bind(struct amdgpu_device *adev,
|
|||
goto gart_bind_fail;
|
||||
|
||||
/* Patch mtype of the second part BO */
|
||||
flags &= ~AMDGPU_PTE_MTYPE_MASK;
|
||||
flags |= AMDGPU_PTE_MTYPE(AMDGPU_MTYPE_NC);
|
||||
flags &= ~AMDGPU_PTE_MTYPE_VG10_MASK;
|
||||
flags |= AMDGPU_PTE_MTYPE_VG10(AMDGPU_MTYPE_NC);
|
||||
|
||||
r = amdgpu_gart_bind(adev,
|
||||
gtt->offset + (page_idx << PAGE_SHIFT),
|
||||
|
|
|
@ -77,6 +77,14 @@ void amdgpu_ucode_print_smc_hdr(const struct common_firmware_header *hdr)
|
|||
container_of(hdr, struct smc_firmware_header_v1_0, header);
|
||||
|
||||
DRM_DEBUG("ucode_start_addr: %u\n", le32_to_cpu(smc_hdr->ucode_start_addr));
|
||||
} else if (version_major == 2) {
|
||||
const struct smc_firmware_header_v1_0 *v1_hdr =
|
||||
container_of(hdr, struct smc_firmware_header_v1_0, header);
|
||||
const struct smc_firmware_header_v2_0 *v2_hdr =
|
||||
container_of(v1_hdr, struct smc_firmware_header_v2_0, v1_0);
|
||||
|
||||
DRM_INFO("ppt_offset_bytes: %u\n", le32_to_cpu(v2_hdr->ppt_offset_bytes));
|
||||
DRM_INFO("ppt_size_bytes: %u\n", le32_to_cpu(v2_hdr->ppt_size_bytes));
|
||||
} else {
|
||||
DRM_ERROR("Unknown SMC ucode version: %u.%u\n", version_major, version_minor);
|
||||
}
|
||||
|
@ -227,6 +235,40 @@ void amdgpu_ucode_print_sdma_hdr(const struct common_firmware_header *hdr)
|
|||
}
|
||||
}
|
||||
|
||||
void amdgpu_ucode_print_psp_hdr(const struct common_firmware_header *hdr)
|
||||
{
|
||||
uint16_t version_major = le16_to_cpu(hdr->header_version_major);
|
||||
uint16_t version_minor = le16_to_cpu(hdr->header_version_minor);
|
||||
|
||||
DRM_DEBUG("PSP\n");
|
||||
amdgpu_ucode_print_common_hdr(hdr);
|
||||
|
||||
if (version_major == 1) {
|
||||
const struct psp_firmware_header_v1_0 *psp_hdr =
|
||||
container_of(hdr, struct psp_firmware_header_v1_0, header);
|
||||
|
||||
DRM_DEBUG("ucode_feature_version: %u\n",
|
||||
le32_to_cpu(psp_hdr->ucode_feature_version));
|
||||
DRM_DEBUG("sos_offset_bytes: %u\n",
|
||||
le32_to_cpu(psp_hdr->sos_offset_bytes));
|
||||
DRM_DEBUG("sos_size_bytes: %u\n",
|
||||
le32_to_cpu(psp_hdr->sos_size_bytes));
|
||||
if (version_minor == 1) {
|
||||
const struct psp_firmware_header_v1_1 *psp_hdr_v1_1 =
|
||||
container_of(psp_hdr, struct psp_firmware_header_v1_1, v1_0);
|
||||
DRM_DEBUG("toc_header_version: %u\n",
|
||||
le32_to_cpu(psp_hdr_v1_1->toc_header_version));
|
||||
DRM_DEBUG("toc_offset_bytes: %u\n",
|
||||
le32_to_cpu(psp_hdr_v1_1->toc_offset_bytes));
|
||||
DRM_DEBUG("toc_size_bytes: %u\n",
|
||||
le32_to_cpu(psp_hdr_v1_1->toc_size_bytes));
|
||||
}
|
||||
} else {
|
||||
DRM_ERROR("Unknown PSP ucode version: %u.%u\n",
|
||||
version_major, version_minor);
|
||||
}
|
||||
}
|
||||
|
||||
void amdgpu_ucode_print_gpu_info_hdr(const struct common_firmware_header *hdr)
|
||||
{
|
||||
uint16_t version_major = le16_to_cpu(hdr->header_version_major);
|
||||
|
@ -302,6 +344,7 @@ amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type)
|
|||
case CHIP_RAVEN:
|
||||
case CHIP_VEGA12:
|
||||
case CHIP_VEGA20:
|
||||
case CHIP_NAVI10:
|
||||
if (!load_type)
|
||||
return AMDGPU_FW_LOAD_DIRECT;
|
||||
else
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#ifndef __AMDGPU_UCODE_H__
|
||||
#define __AMDGPU_UCODE_H__
|
||||
|
||||
#include "amdgpu_socbb.h"
|
||||
|
||||
struct common_firmware_header {
|
||||
uint32_t size_bytes; /* size of the entire header+image(s) in bytes */
|
||||
uint32_t header_size_bytes; /* size of just the header in bytes */
|
||||
|
@ -49,6 +51,26 @@ struct smc_firmware_header_v1_0 {
|
|||
uint32_t ucode_start_addr;
|
||||
};
|
||||
|
||||
/* version_major=2, version_minor=0 */
|
||||
struct smc_firmware_header_v2_0 {
|
||||
struct smc_firmware_header_v1_0 v1_0;
|
||||
uint32_t ppt_offset_bytes; /* soft pptable offset */
|
||||
uint32_t ppt_size_bytes; /* soft pptable size */
|
||||
};
|
||||
|
||||
struct smc_soft_pptable_entry {
|
||||
uint32_t id;
|
||||
uint32_t ppt_offset_bytes;
|
||||
uint32_t ppt_size_bytes;
|
||||
};
|
||||
|
||||
/* version_major=2, version_minor=1 */
|
||||
struct smc_firmware_header_v2_1 {
|
||||
struct smc_firmware_header_v1_0 v1_0;
|
||||
uint32_t pptable_count;
|
||||
uint32_t pptable_entry_offset;
|
||||
};
|
||||
|
||||
/* version_major=1, version_minor=0 */
|
||||
struct psp_firmware_header_v1_0 {
|
||||
struct common_firmware_header header;
|
||||
|
@ -57,6 +79,14 @@ struct psp_firmware_header_v1_0 {
|
|||
uint32_t sos_size_bytes;
|
||||
};
|
||||
|
||||
/* version_major=1, version_minor=1 */
|
||||
struct psp_firmware_header_v1_1 {
|
||||
struct psp_firmware_header_v1_0 v1_0;
|
||||
uint32_t toc_header_version;
|
||||
uint32_t toc_offset_bytes;
|
||||
uint32_t toc_size_bytes;
|
||||
};
|
||||
|
||||
/* version_major=1, version_minor=0 */
|
||||
struct ta_firmware_header_v1_0 {
|
||||
struct common_firmware_header header;
|
||||
|
@ -76,6 +106,21 @@ struct gfx_firmware_header_v1_0 {
|
|||
uint32_t jt_size; /* size of jt */
|
||||
};
|
||||
|
||||
/* version_major=1, version_minor=0 */
|
||||
struct mes_firmware_header_v1_0 {
|
||||
struct common_firmware_header header;
|
||||
uint32_t mes_ucode_version;
|
||||
uint32_t mes_ucode_size_bytes;
|
||||
uint32_t mes_ucode_offset_bytes;
|
||||
uint32_t mes_ucode_data_version;
|
||||
uint32_t mes_ucode_data_size_bytes;
|
||||
uint32_t mes_ucode_data_offset_bytes;
|
||||
uint32_t mes_uc_start_addr_lo;
|
||||
uint32_t mes_uc_start_addr_hi;
|
||||
uint32_t mes_data_start_addr_lo;
|
||||
uint32_t mes_data_start_addr_hi;
|
||||
};
|
||||
|
||||
/* version_major=1, version_minor=0 */
|
||||
struct rlc_firmware_header_v1_0 {
|
||||
struct common_firmware_header header;
|
||||
|
@ -161,6 +206,19 @@ struct gpu_info_firmware_v1_0 {
|
|||
uint32_t gc_lds_size;
|
||||
};
|
||||
|
||||
struct gpu_info_firmware_v1_1 {
|
||||
struct gpu_info_firmware_v1_0 v1_0;
|
||||
uint32_t num_sc_per_sh;
|
||||
uint32_t num_packer_per_sc;
|
||||
};
|
||||
|
||||
/* gpu info payload
|
||||
* version_major=1, version_minor=1 */
|
||||
struct gpu_info_firmware_v1_2 {
|
||||
struct gpu_info_firmware_v1_1 v1_1;
|
||||
struct gpu_info_soc_bounding_box_v1_0 soc_bounding_box;
|
||||
};
|
||||
|
||||
/* version_major=1, version_minor=0 */
|
||||
struct gpu_info_firmware_header_v1_0 {
|
||||
struct common_firmware_header header;
|
||||
|
@ -180,7 +238,9 @@ union amdgpu_firmware_header {
|
|||
struct common_firmware_header common;
|
||||
struct mc_firmware_header_v1_0 mc;
|
||||
struct smc_firmware_header_v1_0 smc;
|
||||
struct smc_firmware_header_v2_0 smc_v2_0;
|
||||
struct psp_firmware_header_v1_0 psp;
|
||||
struct psp_firmware_header_v1_1 psp_v1_1;
|
||||
struct ta_firmware_header_v1_0 ta;
|
||||
struct gfx_firmware_header_v1_0 gfx;
|
||||
struct rlc_firmware_header_v1_0 rlc;
|
||||
|
@ -206,6 +266,8 @@ enum AMDGPU_UCODE_ID {
|
|||
AMDGPU_UCODE_ID_CP_MEC1_JT,
|
||||
AMDGPU_UCODE_ID_CP_MEC2,
|
||||
AMDGPU_UCODE_ID_CP_MEC2_JT,
|
||||
AMDGPU_UCODE_ID_CP_MES,
|
||||
AMDGPU_UCODE_ID_CP_MES_DATA,
|
||||
AMDGPU_UCODE_ID_RLC_G,
|
||||
AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL,
|
||||
AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM,
|
||||
|
@ -218,6 +280,8 @@ enum AMDGPU_UCODE_ID {
|
|||
AMDGPU_UCODE_ID_VCN,
|
||||
AMDGPU_UCODE_ID_DMCU_ERAM,
|
||||
AMDGPU_UCODE_ID_DMCU_INTV,
|
||||
AMDGPU_UCODE_ID_VCN0_RAM,
|
||||
AMDGPU_UCODE_ID_VCN1_RAM,
|
||||
AMDGPU_UCODE_ID_MAXIMUM,
|
||||
};
|
||||
|
||||
|
@ -232,6 +296,7 @@ enum amdgpu_firmware_load_type {
|
|||
AMDGPU_FW_LOAD_DIRECT = 0,
|
||||
AMDGPU_FW_LOAD_SMU,
|
||||
AMDGPU_FW_LOAD_PSP,
|
||||
AMDGPU_FW_LOAD_RLC_BACKDOOR_AUTO,
|
||||
};
|
||||
|
||||
/* conform to smu_ucode_xfer_cz.h */
|
||||
|
@ -284,6 +349,7 @@ void amdgpu_ucode_print_smc_hdr(const struct common_firmware_header *hdr);
|
|||
void amdgpu_ucode_print_gfx_hdr(const struct common_firmware_header *hdr);
|
||||
void amdgpu_ucode_print_rlc_hdr(const struct common_firmware_header *hdr);
|
||||
void amdgpu_ucode_print_sdma_hdr(const struct common_firmware_header *hdr);
|
||||
void amdgpu_ucode_print_psp_hdr(const struct common_firmware_header *hdr);
|
||||
void amdgpu_ucode_print_gpu_info_hdr(const struct common_firmware_header *hdr);
|
||||
int amdgpu_ucode_validate(const struct firmware *fw);
|
||||
bool amdgpu_ucode_hdr_version(union amdgpu_firmware_header *hdr,
|
||||
|
|
|
@ -46,10 +46,12 @@
|
|||
#define FIRMWARE_RAVEN "amdgpu/raven_vcn.bin"
|
||||
#define FIRMWARE_PICASSO "amdgpu/picasso_vcn.bin"
|
||||
#define FIRMWARE_RAVEN2 "amdgpu/raven2_vcn.bin"
|
||||
#define FIRMWARE_NAVI10 "amdgpu/navi10_vcn.bin"
|
||||
|
||||
MODULE_FIRMWARE(FIRMWARE_RAVEN);
|
||||
MODULE_FIRMWARE(FIRMWARE_PICASSO);
|
||||
MODULE_FIRMWARE(FIRMWARE_RAVEN2);
|
||||
MODULE_FIRMWARE(FIRMWARE_NAVI10);
|
||||
|
||||
static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
|
||||
|
||||
|
@ -72,6 +74,12 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
|
|||
else
|
||||
fw_name = FIRMWARE_RAVEN;
|
||||
break;
|
||||
case CHIP_NAVI10:
|
||||
fw_name = FIRMWARE_NAVI10;
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -133,6 +141,16 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
|
|||
return r;
|
||||
}
|
||||
|
||||
if (adev->vcn.indirect_sram) {
|
||||
r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM, &adev->vcn.dpg_sram_bo,
|
||||
&adev->vcn.dpg_sram_gpu_addr, &adev->vcn.dpg_sram_cpu_addr);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "(%d) failed to allocate DPG bo\n", r);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -142,6 +160,12 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
|
|||
|
||||
kvfree(adev->vcn.saved_bo);
|
||||
|
||||
if (adev->vcn.indirect_sram) {
|
||||
amdgpu_bo_free_kernel(&adev->vcn.dpg_sram_bo,
|
||||
&adev->vcn.dpg_sram_gpu_addr,
|
||||
(void **)&adev->vcn.dpg_sram_cpu_addr);
|
||||
}
|
||||
|
||||
amdgpu_bo_free_kernel(&adev->vcn.vcpu_bo,
|
||||
&adev->vcn.gpu_addr,
|
||||
(void **)&adev->vcn.cpu_addr);
|
||||
|
@ -245,7 +269,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
|
|||
|
||||
if (fences == 0) {
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
if (adev->pm.dpm_enabled)
|
||||
if (adev->asic_type < CHIP_NAVI10 && adev->pm.dpm_enabled)
|
||||
amdgpu_dpm_enable_uvd(adev, false);
|
||||
else
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
|
||||
|
@ -262,7 +286,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
|
|||
|
||||
if (set_clocks) {
|
||||
amdgpu_gfx_off_ctrl(adev, false);
|
||||
if (adev->pm.dpm_enabled)
|
||||
if (adev->asic_type < CHIP_NAVI10 && adev->pm.dpm_enabled)
|
||||
amdgpu_dpm_enable_uvd(adev, true);
|
||||
else
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
|
||||
|
@ -308,17 +332,15 @@ int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)
|
|||
unsigned i;
|
||||
int r;
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9), 0xCAFEDEAD);
|
||||
WREG32(adev->vcn.external.scratch9, 0xCAFEDEAD);
|
||||
r = amdgpu_ring_alloc(ring, 3);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9), 0));
|
||||
amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0));
|
||||
amdgpu_ring_write(ring, 0xDEADBEEF);
|
||||
amdgpu_ring_commit(ring);
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
tmp = RREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9));
|
||||
tmp = RREG32(adev->vcn.external.scratch9);
|
||||
if (tmp == 0xDEADBEEF)
|
||||
break;
|
||||
udelay(1);
|
||||
|
@ -347,14 +369,14 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
|
|||
|
||||
ib = &job->ibs[0];
|
||||
addr = amdgpu_bo_gpu_offset(bo);
|
||||
ib->ptr[0] = PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0), 0);
|
||||
ib->ptr[0] = PACKET0(adev->vcn.internal.data0, 0);
|
||||
ib->ptr[1] = addr;
|
||||
ib->ptr[2] = PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1), 0);
|
||||
ib->ptr[2] = PACKET0(adev->vcn.internal.data1, 0);
|
||||
ib->ptr[3] = addr >> 32;
|
||||
ib->ptr[4] = PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD), 0);
|
||||
ib->ptr[4] = PACKET0(adev->vcn.internal.cmd, 0);
|
||||
ib->ptr[5] = 0;
|
||||
for (i = 6; i < 16; i += 2) {
|
||||
ib->ptr[i] = PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP), 0);
|
||||
ib->ptr[i] = PACKET0(adev->vcn.internal.nop, 0);
|
||||
ib->ptr[i+1] = 0;
|
||||
}
|
||||
ib->length_dw = 16;
|
||||
|
@ -629,19 +651,17 @@ int amdgpu_vcn_jpeg_ring_test_ring(struct amdgpu_ring *ring)
|
|||
unsigned i;
|
||||
int r;
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9), 0xCAFEDEAD);
|
||||
WREG32(adev->vcn.external.jpeg_pitch, 0xCAFEDEAD);
|
||||
r = amdgpu_ring_alloc(ring, 3);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9), 0, 0, 0));
|
||||
amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.jpeg_pitch, 0));
|
||||
amdgpu_ring_write(ring, 0xDEADBEEF);
|
||||
amdgpu_ring_commit(ring);
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
tmp = RREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9));
|
||||
tmp = RREG32(adev->vcn.external.jpeg_pitch);
|
||||
if (tmp == 0xDEADBEEF)
|
||||
break;
|
||||
udelay(1);
|
||||
|
@ -669,7 +689,7 @@ static int amdgpu_vcn_jpeg_set_reg(struct amdgpu_ring *ring, uint32_t handle,
|
|||
|
||||
ib = &job->ibs[0];
|
||||
|
||||
ib->ptr[0] = PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9), 0, 0, PACKETJ_TYPE0);
|
||||
ib->ptr[0] = PACKETJ(adev->vcn.internal.jpeg_pitch, 0, 0, PACKETJ_TYPE0);
|
||||
ib->ptr[1] = 0xDEADBEEF;
|
||||
for (i = 2; i < 16; i += 2) {
|
||||
ib->ptr[i] = PACKETJ(0, 0, 0, PACKETJ_TYPE6);
|
||||
|
@ -715,7 +735,7 @@ int amdgpu_vcn_jpeg_ring_test_ib(struct amdgpu_ring *ring, long timeout)
|
|||
}
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
tmp = RREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9));
|
||||
tmp = RREG32(adev->vcn.external.jpeg_pitch);
|
||||
if (tmp == 0xDEADBEEF)
|
||||
break;
|
||||
udelay(1);
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#define __AMDGPU_VCN_H__
|
||||
|
||||
#define AMDGPU_VCN_STACK_SIZE (128*1024)
|
||||
#define AMDGPU_VCN_CONTEXT_SIZE (512*1024)
|
||||
#define AMDGPU_VCN_CONTEXT_SIZE (512*1024)
|
||||
|
||||
#define AMDGPU_VCN_FIRMWARE_OFFSET 256
|
||||
#define AMDGPU_VCN_MAX_ENC_RINGS 3
|
||||
|
@ -45,6 +45,11 @@
|
|||
#define VCN_ENC_CMD_REG_WRITE 0x0000000b
|
||||
#define VCN_ENC_CMD_REG_WAIT 0x0000000c
|
||||
|
||||
#define VCN_VID_SOC_ADDRESS_2_0 0x1fa00
|
||||
#define VCN_AON_SOC_ADDRESS_2_0 0x1f800
|
||||
#define VCN_VID_IP_ADDRESS_2_0 0x0
|
||||
#define VCN_AON_IP_ADDRESS_2_0 0x30000
|
||||
|
||||
#define RREG32_SOC15_DPG_MODE(ip, inst, reg, mask, sram_sel) \
|
||||
({ WREG32_SOC15(ip, inst, mmUVD_DPG_LMA_MASK, mask); \
|
||||
WREG32_SOC15(ip, inst, mmUVD_DPG_LMA_CTL, \
|
||||
|
@ -66,8 +71,55 @@
|
|||
(sram_sel << UVD_DPG_LMA_CTL__SRAM_SEL__SHIFT)); \
|
||||
} while (0)
|
||||
|
||||
#define SOC15_DPG_MODE_OFFSET_2_0(ip, inst, reg) \
|
||||
({ \
|
||||
uint32_t internal_reg_offset, addr; \
|
||||
bool video_range, aon_range; \
|
||||
\
|
||||
addr = (adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg); \
|
||||
addr <<= 2; \
|
||||
video_range = ((((0xFFFFF & addr) >= (VCN_VID_SOC_ADDRESS_2_0)) && \
|
||||
((0xFFFFF & addr) < ((VCN_VID_SOC_ADDRESS_2_0 + 0x2600))))); \
|
||||
aon_range = ((((0xFFFFF & addr) >= (VCN_AON_SOC_ADDRESS_2_0)) && \
|
||||
((0xFFFFF & addr) < ((VCN_AON_SOC_ADDRESS_2_0 + 0x600))))); \
|
||||
if (video_range) \
|
||||
internal_reg_offset = ((0xFFFFF & addr) - (VCN_VID_SOC_ADDRESS_2_0) + \
|
||||
(VCN_VID_IP_ADDRESS_2_0)); \
|
||||
else if (aon_range) \
|
||||
internal_reg_offset = ((0xFFFFF & addr) - (VCN_AON_SOC_ADDRESS_2_0) + \
|
||||
(VCN_AON_IP_ADDRESS_2_0)); \
|
||||
else \
|
||||
internal_reg_offset = (0xFFFFF & addr); \
|
||||
\
|
||||
internal_reg_offset >>= 2; \
|
||||
})
|
||||
|
||||
#define RREG32_SOC15_DPG_MODE_2_0(offset, mask_en) \
|
||||
({ \
|
||||
WREG32_SOC15(VCN, 0, mmUVD_DPG_LMA_CTL, \
|
||||
(0x0 << UVD_DPG_LMA_CTL__READ_WRITE__SHIFT | \
|
||||
mask_en << UVD_DPG_LMA_CTL__MASK_EN__SHIFT | \
|
||||
offset << UVD_DPG_LMA_CTL__READ_WRITE_ADDR__SHIFT)); \
|
||||
RREG32_SOC15(VCN, 0, mmUVD_DPG_LMA_DATA); \
|
||||
})
|
||||
|
||||
#define WREG32_SOC15_DPG_MODE_2_0(offset, value, mask_en, indirect) \
|
||||
do { \
|
||||
if (!indirect) { \
|
||||
WREG32_SOC15(VCN, 0, mmUVD_DPG_LMA_DATA, value); \
|
||||
WREG32_SOC15(VCN, 0, mmUVD_DPG_LMA_CTL, \
|
||||
(0x1 << UVD_DPG_LMA_CTL__READ_WRITE__SHIFT | \
|
||||
mask_en << UVD_DPG_LMA_CTL__MASK_EN__SHIFT | \
|
||||
offset << UVD_DPG_LMA_CTL__READ_WRITE_ADDR__SHIFT)); \
|
||||
} else { \
|
||||
*adev->vcn.dpg_sram_curr_addr++ = offset; \
|
||||
*adev->vcn.dpg_sram_curr_addr++ = value; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
enum engine_status_constants {
|
||||
UVD_PGFSM_STATUS__UVDM_UVDU_PWR_ON = 0x2AAAA0,
|
||||
UVD_PGFSM_STATUS__UVDM_UVDU_PWR_ON_2_0 = 0xAAAA0,
|
||||
UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON = 0x00000002,
|
||||
UVD_STATUS__UVD_BUSY = 0x00000004,
|
||||
GB_ADDR_CONFIG_DEFAULT = 0x26010011,
|
||||
|
@ -75,6 +127,7 @@ enum engine_status_constants {
|
|||
UVD_STATUS__BUSY = 0x5,
|
||||
UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF = 0x1,
|
||||
UVD_STATUS__RBC_BUSY = 0x1,
|
||||
UVD_PGFSM_STATUS_UVDJ_PWR_ON = 0,
|
||||
};
|
||||
|
||||
enum internal_dpg_state {
|
||||
|
@ -87,6 +140,15 @@ struct dpg_pause_state {
|
|||
enum internal_dpg_state jpeg;
|
||||
};
|
||||
|
||||
struct amdgpu_vcn_reg{
|
||||
unsigned data0;
|
||||
unsigned data1;
|
||||
unsigned cmd;
|
||||
unsigned nop;
|
||||
unsigned scratch9;
|
||||
unsigned jpeg_pitch;
|
||||
};
|
||||
|
||||
struct amdgpu_vcn {
|
||||
struct amdgpu_bo *vcpu_bo;
|
||||
void *cpu_addr;
|
||||
|
@ -102,8 +164,15 @@ struct amdgpu_vcn {
|
|||
unsigned num_enc_rings;
|
||||
enum amd_powergating_state cur_state;
|
||||
struct dpg_pause_state pause_state;
|
||||
struct amdgpu_vcn_reg internal, external;
|
||||
int (*pause_dpg_mode)(struct amdgpu_device *adev,
|
||||
struct dpg_pause_state *new_state);
|
||||
|
||||
bool indirect_sram;
|
||||
struct amdgpu_bo *dpg_sram_bo;
|
||||
void *dpg_sram_cpu_addr;
|
||||
uint64_t dpg_sram_gpu_addr;
|
||||
uint32_t *dpg_sram_curr_addr;
|
||||
};
|
||||
|
||||
int amdgpu_vcn_sw_init(struct amdgpu_device *adev);
|
||||
|
|
|
@ -253,6 +253,7 @@ typedef struct amdgim_vf2pf_info_v2 amdgim_vf2pf_info ;
|
|||
struct amdgpu_virt {
|
||||
uint32_t caps;
|
||||
struct amdgpu_bo *csa_obj;
|
||||
void *csa_cpu_addr;
|
||||
bool chained_ib_support;
|
||||
uint32_t reg_val_offs;
|
||||
struct amdgpu_irq_src ack_irq;
|
||||
|
|
|
@ -1574,12 +1574,22 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev,
|
|||
flags &= ~AMDGPU_PTE_EXECUTABLE;
|
||||
flags |= mapping->flags & AMDGPU_PTE_EXECUTABLE;
|
||||
|
||||
flags &= ~AMDGPU_PTE_MTYPE_MASK;
|
||||
flags |= (mapping->flags & AMDGPU_PTE_MTYPE_MASK);
|
||||
if (adev->asic_type == CHIP_NAVI10) {
|
||||
flags &= ~AMDGPU_PTE_MTYPE_NV10_MASK;
|
||||
flags |= (mapping->flags & AMDGPU_PTE_MTYPE_NV10_MASK);
|
||||
} else {
|
||||
flags &= ~AMDGPU_PTE_MTYPE_VG10_MASK;
|
||||
flags |= (mapping->flags & AMDGPU_PTE_MTYPE_VG10_MASK);
|
||||
}
|
||||
|
||||
if ((mapping->flags & AMDGPU_PTE_PRT) &&
|
||||
(adev->asic_type >= CHIP_VEGA10)) {
|
||||
flags |= AMDGPU_PTE_PRT;
|
||||
if (adev->asic_type >= CHIP_NAVI10) {
|
||||
flags |= AMDGPU_PTE_SNOOPED;
|
||||
flags |= AMDGPU_PTE_LOG;
|
||||
flags |= AMDGPU_PTE_SYSTEM;
|
||||
}
|
||||
flags &= ~AMDGPU_PTE_VALID;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@ struct amdgpu_bo_list_entry;
|
|||
/* PDE is handled as PTE for VEGA10 */
|
||||
#define AMDGPU_PDE_PTE (1ULL << 54)
|
||||
|
||||
#define AMDGPU_PTE_LOG (1ULL << 55)
|
||||
|
||||
/* PTE is handled as PDE for VEGA10 (Translate Further) */
|
||||
#define AMDGPU_PTE_TF (1ULL << 56)
|
||||
|
||||
|
@ -75,8 +77,8 @@ struct amdgpu_bo_list_entry;
|
|||
|
||||
|
||||
/* For GFX9 */
|
||||
#define AMDGPU_PTE_MTYPE(a) ((uint64_t)a << 57)
|
||||
#define AMDGPU_PTE_MTYPE_MASK AMDGPU_PTE_MTYPE(3ULL)
|
||||
#define AMDGPU_PTE_MTYPE_VG10(a) ((uint64_t)(a) << 57)
|
||||
#define AMDGPU_PTE_MTYPE_VG10_MASK AMDGPU_PTE_MTYPE_VG10(3ULL)
|
||||
|
||||
#define AMDGPU_MTYPE_NC 0
|
||||
#define AMDGPU_MTYPE_CC 2
|
||||
|
@ -86,7 +88,11 @@ struct amdgpu_bo_list_entry;
|
|||
| AMDGPU_PTE_EXECUTABLE \
|
||||
| AMDGPU_PTE_READABLE \
|
||||
| AMDGPU_PTE_WRITEABLE \
|
||||
| AMDGPU_PTE_MTYPE(AMDGPU_MTYPE_CC))
|
||||
| AMDGPU_PTE_MTYPE_VG10(AMDGPU_MTYPE_CC))
|
||||
|
||||
/* NAVI10 only */
|
||||
#define AMDGPU_PTE_MTYPE_NV10(a) ((uint64_t)(a) << 48)
|
||||
#define AMDGPU_PTE_MTYPE_NV10_MASK AMDGPU_PTE_MTYPE_NV10(7ULL)
|
||||
|
||||
/* How to programm VM fault handling */
|
||||
#define AMDGPU_VM_FAULT_STOP_NEVER 0
|
||||
|
|
|
@ -275,7 +275,7 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
|
|||
struct drm_mm_node *nodes;
|
||||
enum drm_mm_insert_mode mode;
|
||||
unsigned long lpfn, num_nodes, pages_per_node, pages_left;
|
||||
uint64_t usage = 0, vis_usage = 0;
|
||||
uint64_t vis_usage = 0, mem_bytes;
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
|
@ -283,20 +283,34 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
|
|||
if (!lpfn)
|
||||
lpfn = man->size;
|
||||
|
||||
if (place->flags & TTM_PL_FLAG_CONTIGUOUS ||
|
||||
amdgpu_vram_page_split == -1) {
|
||||
/* bail out quickly if there's likely not enough VRAM for this BO */
|
||||
mem_bytes = (u64)mem->num_pages << PAGE_SHIFT;
|
||||
if (atomic64_add_return(mem_bytes, &mgr->usage) > adev->gmc.mc_vram_size) {
|
||||
atomic64_sub(mem_bytes, &mgr->usage);
|
||||
mem->mm_node = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
|
||||
pages_per_node = ~0ul;
|
||||
num_nodes = 1;
|
||||
} else {
|
||||
pages_per_node = max((uint32_t)amdgpu_vram_page_split,
|
||||
mem->page_alignment);
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
pages_per_node = HPAGE_PMD_NR;
|
||||
#else
|
||||
/* default to 2MB */
|
||||
pages_per_node = (2UL << (20UL - PAGE_SHIFT));
|
||||
#endif
|
||||
pages_per_node = max((uint32_t)pages_per_node, mem->page_alignment);
|
||||
num_nodes = DIV_ROUND_UP(mem->num_pages, pages_per_node);
|
||||
}
|
||||
|
||||
nodes = kvmalloc_array(num_nodes, sizeof(*nodes),
|
||||
nodes = kvmalloc_array((uint32_t)num_nodes, sizeof(*nodes),
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!nodes)
|
||||
if (!nodes) {
|
||||
atomic64_sub(mem_bytes, &mgr->usage);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mode = DRM_MM_INSERT_BEST;
|
||||
if (place->flags & TTM_PL_FLAG_TOPDOWN)
|
||||
|
@ -316,7 +330,6 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
|
|||
if (unlikely(r))
|
||||
break;
|
||||
|
||||
usage += nodes[i].size << PAGE_SHIFT;
|
||||
vis_usage += amdgpu_vram_mgr_vis_size(adev, &nodes[i]);
|
||||
amdgpu_vram_mgr_virt_start(mem, &nodes[i]);
|
||||
pages_left -= pages;
|
||||
|
@ -336,14 +349,12 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
|
|||
if (unlikely(r))
|
||||
goto error;
|
||||
|
||||
usage += nodes[i].size << PAGE_SHIFT;
|
||||
vis_usage += amdgpu_vram_mgr_vis_size(adev, &nodes[i]);
|
||||
amdgpu_vram_mgr_virt_start(mem, &nodes[i]);
|
||||
pages_left -= pages;
|
||||
}
|
||||
spin_unlock(&mgr->lock);
|
||||
|
||||
atomic64_add(usage, &mgr->usage);
|
||||
atomic64_add(vis_usage, &mgr->vis_usage);
|
||||
|
||||
mem->mm_node = nodes;
|
||||
|
@ -354,6 +365,7 @@ error:
|
|||
while (i--)
|
||||
drm_mm_remove_node(&nodes[i]);
|
||||
spin_unlock(&mgr->lock);
|
||||
atomic64_sub(mem->num_pages << PAGE_SHIFT, &mgr->usage);
|
||||
|
||||
kvfree(nodes);
|
||||
return r == -ENOSPC ? 0 : r;
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "athub_v2_0.h"
|
||||
|
||||
#include "athub/athub_2_0_0_offset.h"
|
||||
#include "athub/athub_2_0_0_sh_mask.h"
|
||||
#include "athub/athub_2_0_0_default.h"
|
||||
#include "navi10_enum.h"
|
||||
|
||||
#include "soc15_common.h"
|
||||
|
||||
static void
|
||||
athub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
uint32_t def, data;
|
||||
|
||||
def = data = RREG32_SOC15(ATHUB, 0, mmATHUB_MISC_CNTL);
|
||||
|
||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_MGCG))
|
||||
data |= ATHUB_MISC_CNTL__CG_ENABLE_MASK;
|
||||
else
|
||||
data &= ~ATHUB_MISC_CNTL__CG_ENABLE_MASK;
|
||||
|
||||
if (def != data)
|
||||
WREG32_SOC15(ATHUB, 0, mmATHUB_MISC_CNTL, data);
|
||||
}
|
||||
|
||||
static void
|
||||
athub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
uint32_t def, data;
|
||||
|
||||
def = data = RREG32_SOC15(ATHUB, 0, mmATHUB_MISC_CNTL);
|
||||
|
||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_LS) &&
|
||||
(adev->cg_flags & AMD_CG_SUPPORT_HDP_LS))
|
||||
data |= ATHUB_MISC_CNTL__CG_MEM_LS_ENABLE_MASK;
|
||||
else
|
||||
data &= ~ATHUB_MISC_CNTL__CG_MEM_LS_ENABLE_MASK;
|
||||
|
||||
if (def != data)
|
||||
WREG32_SOC15(ATHUB, 0, mmATHUB_MISC_CNTL, data);
|
||||
}
|
||||
|
||||
int athub_v2_0_set_clockgating(struct amdgpu_device *adev,
|
||||
enum amd_clockgating_state state)
|
||||
{
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_NAVI10:
|
||||
athub_v2_0_update_medium_grain_clock_gating(adev,
|
||||
state == AMD_CG_STATE_GATE ? true : false);
|
||||
athub_v2_0_update_medium_grain_light_sleep(adev,
|
||||
state == AMD_CG_STATE_GATE ? true : false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void athub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags)
|
||||
{
|
||||
int data;
|
||||
|
||||
/* AMD_CG_SUPPORT_ATHUB_MGCG */
|
||||
data = RREG32_SOC15(ATHUB, 0, mmATHUB_MISC_CNTL);
|
||||
if (data & ATHUB_MISC_CNTL__CG_ENABLE_MASK)
|
||||
*flags |= AMD_CG_SUPPORT_ATHUB_MGCG;
|
||||
|
||||
/* AMD_CG_SUPPORT_ATHUB_LS */
|
||||
if (data & ATHUB_MISC_CNTL__CG_MEM_LS_ENABLE_MASK)
|
||||
*flags |= AMD_CG_SUPPORT_ATHUB_LS;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#ifndef __ATHUB_V2_0_H__
|
||||
#define __ATHUB_V2_0_H__
|
||||
|
||||
int athub_v2_0_set_clockgating(struct amdgpu_device *adev,
|
||||
enum amd_clockgating_state state);
|
||||
void athub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,975 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
static const unsigned int gfx10_SECT_CONTEXT_def_1[] = {
|
||||
0x00000000, // DB_RENDER_CONTROL
|
||||
0x00000000, // DB_COUNT_CONTROL
|
||||
0x00000000, // DB_DEPTH_VIEW
|
||||
0x00000000, // DB_RENDER_OVERRIDE
|
||||
0x00000000, // DB_RENDER_OVERRIDE2
|
||||
0x00000000, // DB_HTILE_DATA_BASE
|
||||
0x00000000, // HOLE
|
||||
0x00000000, // DB_DEPTH_SIZE_XY
|
||||
0x00000000, // DB_DEPTH_BOUNDS_MIN
|
||||
0x00000000, // DB_DEPTH_BOUNDS_MAX
|
||||
0x00000000, // DB_STENCIL_CLEAR
|
||||
0x00000000, // DB_DEPTH_CLEAR
|
||||
0x00000000, // PA_SC_SCREEN_SCISSOR_TL
|
||||
0x40004000, // PA_SC_SCREEN_SCISSOR_BR
|
||||
0x00000000, // DB_DFSM_CONTROL
|
||||
0x00000000, // DB_DEPTH_INFO
|
||||
0x00000000, // DB_Z_INFO
|
||||
0x00000000, // DB_STENCIL_INFO
|
||||
0x00000000, // DB_Z_READ_BASE
|
||||
0x00000000, // DB_STENCIL_READ_BASE
|
||||
0x00000000, // DB_Z_WRITE_BASE
|
||||
0x00000000, // DB_STENCIL_WRITE_BASE
|
||||
0x00000000, // DB_DEPTH_SIZE
|
||||
0x00000000, // DB_DEPTH_SLICE
|
||||
0x00000000, // DB_Z_INFO2
|
||||
0x00000000, // DB_STENCIL_INFO2
|
||||
0x00000000, // DB_Z_READ_BASE_HI
|
||||
0x00000000, // DB_STENCIL_READ_BASE_HI
|
||||
0x00000000, // DB_Z_WRITE_BASE_HI
|
||||
0x00000000, // DB_STENCIL_WRITE_BASE_HI
|
||||
0x00000000, // DB_HTILE_DATA_BASE_HI
|
||||
0x00150055, // DB_RMI_L2_CACHE_CONTROL
|
||||
0x00000000, // TA_BC_BASE_ADDR
|
||||
0x00000000, // TA_BC_BASE_ADDR_HI
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0x00000000, // COHER_DEST_BASE_HI_0
|
||||
0x00000000, // COHER_DEST_BASE_HI_1
|
||||
0x00000000, // COHER_DEST_BASE_HI_2
|
||||
0x00000000, // COHER_DEST_BASE_HI_3
|
||||
0x00000000, // COHER_DEST_BASE_2
|
||||
0x00000000, // COHER_DEST_BASE_3
|
||||
0x00000000, // PA_SC_WINDOW_OFFSET
|
||||
0x80000000, // PA_SC_WINDOW_SCISSOR_TL
|
||||
0x40004000, // PA_SC_WINDOW_SCISSOR_BR
|
||||
0x0000ffff, // PA_SC_CLIPRECT_RULE
|
||||
0x00000000, // PA_SC_CLIPRECT_0_TL
|
||||
0x40004000, // PA_SC_CLIPRECT_0_BR
|
||||
0x00000000, // PA_SC_CLIPRECT_1_TL
|
||||
0x40004000, // PA_SC_CLIPRECT_1_BR
|
||||
0x00000000, // PA_SC_CLIPRECT_2_TL
|
||||
0x40004000, // PA_SC_CLIPRECT_2_BR
|
||||
0x00000000, // PA_SC_CLIPRECT_3_TL
|
||||
0x40004000, // PA_SC_CLIPRECT_3_BR
|
||||
0xaa99aaaa, // PA_SC_EDGERULE
|
||||
0x00000000, // PA_SU_HARDWARE_SCREEN_OFFSET
|
||||
0xffffffff, // CB_TARGET_MASK
|
||||
0xffffffff, // CB_SHADER_MASK
|
||||
0x80000000, // PA_SC_GENERIC_SCISSOR_TL
|
||||
0x40004000, // PA_SC_GENERIC_SCISSOR_BR
|
||||
0x00000000, // COHER_DEST_BASE_0
|
||||
0x00000000, // COHER_DEST_BASE_1
|
||||
0x80000000, // PA_SC_VPORT_SCISSOR_0_TL
|
||||
0x40004000, // PA_SC_VPORT_SCISSOR_0_BR
|
||||
0x80000000, // PA_SC_VPORT_SCISSOR_1_TL
|
||||
0x40004000, // PA_SC_VPORT_SCISSOR_1_BR
|
||||
0x80000000, // PA_SC_VPORT_SCISSOR_2_TL
|
||||
0x40004000, // PA_SC_VPORT_SCISSOR_2_BR
|
||||
0x80000000, // PA_SC_VPORT_SCISSOR_3_TL
|
||||
0x40004000, // PA_SC_VPORT_SCISSOR_3_BR
|
||||
0x80000000, // PA_SC_VPORT_SCISSOR_4_TL
|
||||
0x40004000, // PA_SC_VPORT_SCISSOR_4_BR
|
||||
0x80000000, // PA_SC_VPORT_SCISSOR_5_TL
|
||||
0x40004000, // PA_SC_VPORT_SCISSOR_5_BR
|
||||
0x80000000, // PA_SC_VPORT_SCISSOR_6_TL
|
||||
0x40004000, // PA_SC_VPORT_SCISSOR_6_BR
|
||||
0x80000000, // PA_SC_VPORT_SCISSOR_7_TL
|
||||
0x40004000, // PA_SC_VPORT_SCISSOR_7_BR
|
||||
0x80000000, // PA_SC_VPORT_SCISSOR_8_TL
|
||||
0x40004000, // PA_SC_VPORT_SCISSOR_8_BR
|
||||
0x80000000, // PA_SC_VPORT_SCISSOR_9_TL
|
||||
0x40004000, // PA_SC_VPORT_SCISSOR_9_BR
|
||||
0x80000000, // PA_SC_VPORT_SCISSOR_10_TL
|
||||
0x40004000, // PA_SC_VPORT_SCISSOR_10_BR
|
||||
0x80000000, // PA_SC_VPORT_SCISSOR_11_TL
|
||||
0x40004000, // PA_SC_VPORT_SCISSOR_11_BR
|
||||
0x80000000, // PA_SC_VPORT_SCISSOR_12_TL
|
||||
0x40004000, // PA_SC_VPORT_SCISSOR_12_BR
|
||||
0x80000000, // PA_SC_VPORT_SCISSOR_13_TL
|
||||
0x40004000, // PA_SC_VPORT_SCISSOR_13_BR
|
||||
0x80000000, // PA_SC_VPORT_SCISSOR_14_TL
|
||||
0x40004000, // PA_SC_VPORT_SCISSOR_14_BR
|
||||
0x80000000, // PA_SC_VPORT_SCISSOR_15_TL
|
||||
0x40004000, // PA_SC_VPORT_SCISSOR_15_BR
|
||||
0x00000000, // PA_SC_VPORT_ZMIN_0
|
||||
0x3f800000, // PA_SC_VPORT_ZMAX_0
|
||||
0x00000000, // PA_SC_VPORT_ZMIN_1
|
||||
0x3f800000, // PA_SC_VPORT_ZMAX_1
|
||||
0x00000000, // PA_SC_VPORT_ZMIN_2
|
||||
0x3f800000, // PA_SC_VPORT_ZMAX_2
|
||||
0x00000000, // PA_SC_VPORT_ZMIN_3
|
||||
0x3f800000, // PA_SC_VPORT_ZMAX_3
|
||||
0x00000000, // PA_SC_VPORT_ZMIN_4
|
||||
0x3f800000, // PA_SC_VPORT_ZMAX_4
|
||||
0x00000000, // PA_SC_VPORT_ZMIN_5
|
||||
0x3f800000, // PA_SC_VPORT_ZMAX_5
|
||||
0x00000000, // PA_SC_VPORT_ZMIN_6
|
||||
0x3f800000, // PA_SC_VPORT_ZMAX_6
|
||||
0x00000000, // PA_SC_VPORT_ZMIN_7
|
||||
0x3f800000, // PA_SC_VPORT_ZMAX_7
|
||||
0x00000000, // PA_SC_VPORT_ZMIN_8
|
||||
0x3f800000, // PA_SC_VPORT_ZMAX_8
|
||||
0x00000000, // PA_SC_VPORT_ZMIN_9
|
||||
0x3f800000, // PA_SC_VPORT_ZMAX_9
|
||||
0x00000000, // PA_SC_VPORT_ZMIN_10
|
||||
0x3f800000, // PA_SC_VPORT_ZMAX_10
|
||||
0x00000000, // PA_SC_VPORT_ZMIN_11
|
||||
0x3f800000, // PA_SC_VPORT_ZMAX_11
|
||||
0x00000000, // PA_SC_VPORT_ZMIN_12
|
||||
0x3f800000, // PA_SC_VPORT_ZMAX_12
|
||||
0x00000000, // PA_SC_VPORT_ZMIN_13
|
||||
0x3f800000, // PA_SC_VPORT_ZMAX_13
|
||||
0x00000000, // PA_SC_VPORT_ZMIN_14
|
||||
0x3f800000, // PA_SC_VPORT_ZMAX_14
|
||||
0x00000000, // PA_SC_VPORT_ZMIN_15
|
||||
0x3f800000, // PA_SC_VPORT_ZMAX_15
|
||||
0x00000000, // PA_SC_RASTER_CONFIG
|
||||
0x00000000, // PA_SC_RASTER_CONFIG_1
|
||||
0x00000000, // PA_SC_SCREEN_EXTENT_CONTROL
|
||||
};
|
||||
static const unsigned int gfx10_SECT_CONTEXT_def_2[] = {
|
||||
0x00000000, // CP_PERFMON_CNTX_CNTL
|
||||
0x00000000, // CP_RINGID
|
||||
0x00000000, // CP_VMID
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0x00000000, // PA_SC_RIGHT_VERT_GRID
|
||||
0x00000000, // PA_SC_LEFT_VERT_GRID
|
||||
0x00000000, // PA_SC_HORIZ_GRID
|
||||
0x00000000, // HOLE
|
||||
0x00000000, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0xffffffff, // VGT_MAX_VTX_INDX
|
||||
0x00000000, // VGT_MIN_VTX_INDX
|
||||
0x00000000, // VGT_INDX_OFFSET
|
||||
0x00000000, // VGT_MULTI_PRIM_IB_RESET_INDX
|
||||
0x00550055, // CB_RMI_GL2_CACHE_CONTROL
|
||||
0x00000000, // CB_BLEND_RED
|
||||
0x00000000, // CB_BLEND_GREEN
|
||||
0x00000000, // CB_BLEND_BLUE
|
||||
0x00000000, // CB_BLEND_ALPHA
|
||||
0x00000000, // CB_DCC_CONTROL
|
||||
0x00000000, // CB_COVERAGE_OUT_CONTROL
|
||||
0x00000000, // DB_STENCIL_CONTROL
|
||||
0x01000000, // DB_STENCILREFMASK
|
||||
0x01000000, // DB_STENCILREFMASK_BF
|
||||
0, // HOLE
|
||||
0x00000000, // PA_CL_VPORT_XSCALE
|
||||
0x00000000, // PA_CL_VPORT_XOFFSET
|
||||
0x00000000, // PA_CL_VPORT_YSCALE
|
||||
0x00000000, // PA_CL_VPORT_YOFFSET
|
||||
0x00000000, // PA_CL_VPORT_ZSCALE
|
||||
0x00000000, // PA_CL_VPORT_ZOFFSET
|
||||
0x00000000, // PA_CL_VPORT_XSCALE_1
|
||||
0x00000000, // PA_CL_VPORT_XOFFSET_1
|
||||
0x00000000, // PA_CL_VPORT_YSCALE_1
|
||||
0x00000000, // PA_CL_VPORT_YOFFSET_1
|
||||
0x00000000, // PA_CL_VPORT_ZSCALE_1
|
||||
0x00000000, // PA_CL_VPORT_ZOFFSET_1
|
||||
0x00000000, // PA_CL_VPORT_XSCALE_2
|
||||
0x00000000, // PA_CL_VPORT_XOFFSET_2
|
||||
0x00000000, // PA_CL_VPORT_YSCALE_2
|
||||
0x00000000, // PA_CL_VPORT_YOFFSET_2
|
||||
0x00000000, // PA_CL_VPORT_ZSCALE_2
|
||||
0x00000000, // PA_CL_VPORT_ZOFFSET_2
|
||||
0x00000000, // PA_CL_VPORT_XSCALE_3
|
||||
0x00000000, // PA_CL_VPORT_XOFFSET_3
|
||||
0x00000000, // PA_CL_VPORT_YSCALE_3
|
||||
0x00000000, // PA_CL_VPORT_YOFFSET_3
|
||||
0x00000000, // PA_CL_VPORT_ZSCALE_3
|
||||
0x00000000, // PA_CL_VPORT_ZOFFSET_3
|
||||
0x00000000, // PA_CL_VPORT_XSCALE_4
|
||||
0x00000000, // PA_CL_VPORT_XOFFSET_4
|
||||
0x00000000, // PA_CL_VPORT_YSCALE_4
|
||||
0x00000000, // PA_CL_VPORT_YOFFSET_4
|
||||
0x00000000, // PA_CL_VPORT_ZSCALE_4
|
||||
0x00000000, // PA_CL_VPORT_ZOFFSET_4
|
||||
0x00000000, // PA_CL_VPORT_XSCALE_5
|
||||
0x00000000, // PA_CL_VPORT_XOFFSET_5
|
||||
0x00000000, // PA_CL_VPORT_YSCALE_5
|
||||
0x00000000, // PA_CL_VPORT_YOFFSET_5
|
||||
0x00000000, // PA_CL_VPORT_ZSCALE_5
|
||||
0x00000000, // PA_CL_VPORT_ZOFFSET_5
|
||||
0x00000000, // PA_CL_VPORT_XSCALE_6
|
||||
0x00000000, // PA_CL_VPORT_XOFFSET_6
|
||||
0x00000000, // PA_CL_VPORT_YSCALE_6
|
||||
0x00000000, // PA_CL_VPORT_YOFFSET_6
|
||||
0x00000000, // PA_CL_VPORT_ZSCALE_6
|
||||
0x00000000, // PA_CL_VPORT_ZOFFSET_6
|
||||
0x00000000, // PA_CL_VPORT_XSCALE_7
|
||||
0x00000000, // PA_CL_VPORT_XOFFSET_7
|
||||
0x00000000, // PA_CL_VPORT_YSCALE_7
|
||||
0x00000000, // PA_CL_VPORT_YOFFSET_7
|
||||
0x00000000, // PA_CL_VPORT_ZSCALE_7
|
||||
0x00000000, // PA_CL_VPORT_ZOFFSET_7
|
||||
0x00000000, // PA_CL_VPORT_XSCALE_8
|
||||
0x00000000, // PA_CL_VPORT_XOFFSET_8
|
||||
0x00000000, // PA_CL_VPORT_YSCALE_8
|
||||
0x00000000, // PA_CL_VPORT_YOFFSET_8
|
||||
0x00000000, // PA_CL_VPORT_ZSCALE_8
|
||||
0x00000000, // PA_CL_VPORT_ZOFFSET_8
|
||||
0x00000000, // PA_CL_VPORT_XSCALE_9
|
||||
0x00000000, // PA_CL_VPORT_XOFFSET_9
|
||||
0x00000000, // PA_CL_VPORT_YSCALE_9
|
||||
0x00000000, // PA_CL_VPORT_YOFFSET_9
|
||||
0x00000000, // PA_CL_VPORT_ZSCALE_9
|
||||
0x00000000, // PA_CL_VPORT_ZOFFSET_9
|
||||
0x00000000, // PA_CL_VPORT_XSCALE_10
|
||||
0x00000000, // PA_CL_VPORT_XOFFSET_10
|
||||
0x00000000, // PA_CL_VPORT_YSCALE_10
|
||||
0x00000000, // PA_CL_VPORT_YOFFSET_10
|
||||
0x00000000, // PA_CL_VPORT_ZSCALE_10
|
||||
0x00000000, // PA_CL_VPORT_ZOFFSET_10
|
||||
0x00000000, // PA_CL_VPORT_XSCALE_11
|
||||
0x00000000, // PA_CL_VPORT_XOFFSET_11
|
||||
0x00000000, // PA_CL_VPORT_YSCALE_11
|
||||
0x00000000, // PA_CL_VPORT_YOFFSET_11
|
||||
0x00000000, // PA_CL_VPORT_ZSCALE_11
|
||||
0x00000000, // PA_CL_VPORT_ZOFFSET_11
|
||||
0x00000000, // PA_CL_VPORT_XSCALE_12
|
||||
0x00000000, // PA_CL_VPORT_XOFFSET_12
|
||||
0x00000000, // PA_CL_VPORT_YSCALE_12
|
||||
0x00000000, // PA_CL_VPORT_YOFFSET_12
|
||||
0x00000000, // PA_CL_VPORT_ZSCALE_12
|
||||
0x00000000, // PA_CL_VPORT_ZOFFSET_12
|
||||
0x00000000, // PA_CL_VPORT_XSCALE_13
|
||||
0x00000000, // PA_CL_VPORT_XOFFSET_13
|
||||
0x00000000, // PA_CL_VPORT_YSCALE_13
|
||||
0x00000000, // PA_CL_VPORT_YOFFSET_13
|
||||
0x00000000, // PA_CL_VPORT_ZSCALE_13
|
||||
0x00000000, // PA_CL_VPORT_ZOFFSET_13
|
||||
0x00000000, // PA_CL_VPORT_XSCALE_14
|
||||
0x00000000, // PA_CL_VPORT_XOFFSET_14
|
||||
0x00000000, // PA_CL_VPORT_YSCALE_14
|
||||
0x00000000, // PA_CL_VPORT_YOFFSET_14
|
||||
0x00000000, // PA_CL_VPORT_ZSCALE_14
|
||||
0x00000000, // PA_CL_VPORT_ZOFFSET_14
|
||||
0x00000000, // PA_CL_VPORT_XSCALE_15
|
||||
0x00000000, // PA_CL_VPORT_XOFFSET_15
|
||||
0x00000000, // PA_CL_VPORT_YSCALE_15
|
||||
0x00000000, // PA_CL_VPORT_YOFFSET_15
|
||||
0x00000000, // PA_CL_VPORT_ZSCALE_15
|
||||
0x00000000, // PA_CL_VPORT_ZOFFSET_15
|
||||
0x00000000, // PA_CL_UCP_0_X
|
||||
0x00000000, // PA_CL_UCP_0_Y
|
||||
0x00000000, // PA_CL_UCP_0_Z
|
||||
0x00000000, // PA_CL_UCP_0_W
|
||||
0x00000000, // PA_CL_UCP_1_X
|
||||
0x00000000, // PA_CL_UCP_1_Y
|
||||
0x00000000, // PA_CL_UCP_1_Z
|
||||
0x00000000, // PA_CL_UCP_1_W
|
||||
0x00000000, // PA_CL_UCP_2_X
|
||||
0x00000000, // PA_CL_UCP_2_Y
|
||||
0x00000000, // PA_CL_UCP_2_Z
|
||||
0x00000000, // PA_CL_UCP_2_W
|
||||
0x00000000, // PA_CL_UCP_3_X
|
||||
0x00000000, // PA_CL_UCP_3_Y
|
||||
0x00000000, // PA_CL_UCP_3_Z
|
||||
0x00000000, // PA_CL_UCP_3_W
|
||||
0x00000000, // PA_CL_UCP_4_X
|
||||
0x00000000, // PA_CL_UCP_4_Y
|
||||
0x00000000, // PA_CL_UCP_4_Z
|
||||
0x00000000, // PA_CL_UCP_4_W
|
||||
0x00000000, // PA_CL_UCP_5_X
|
||||
0x00000000, // PA_CL_UCP_5_Y
|
||||
0x00000000, // PA_CL_UCP_5_Z
|
||||
0x00000000, // PA_CL_UCP_5_W
|
||||
0x00000000, // PA_CL_PROG_NEAR_CLIP_Z
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_0
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_1
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_2
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_3
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_4
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_5
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_6
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_7
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_8
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_9
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_10
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_11
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_12
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_13
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_14
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_15
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_16
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_17
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_18
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_19
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_20
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_21
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_22
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_23
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_24
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_25
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_26
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_27
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_28
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_29
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_30
|
||||
0x00000000, // SPI_PS_INPUT_CNTL_31
|
||||
0x00000000, // SPI_VS_OUT_CONFIG
|
||||
0, // HOLE
|
||||
0x00000000, // SPI_PS_INPUT_ENA
|
||||
0x00000000, // SPI_PS_INPUT_ADDR
|
||||
0x00000000, // SPI_INTERP_CONTROL_0
|
||||
0x00000002, // SPI_PS_IN_CONTROL
|
||||
0, // HOLE
|
||||
0x00000000, // SPI_BARYC_CNTL
|
||||
0, // HOLE
|
||||
0x00000000, // SPI_TMPRING_SIZE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0x00000000, // SPI_SHADER_IDX_FORMAT
|
||||
0x00000000, // SPI_SHADER_POS_FORMAT
|
||||
0x00000000, // SPI_SHADER_Z_FORMAT
|
||||
0x00000000, // SPI_SHADER_COL_FORMAT
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0x00000000, // SX_PS_DOWNCONVERT
|
||||
0x00000000, // SX_BLEND_OPT_EPSILON
|
||||
0x00000000, // SX_BLEND_OPT_CONTROL
|
||||
0x00000000, // SX_MRT0_BLEND_OPT
|
||||
0x00000000, // SX_MRT1_BLEND_OPT
|
||||
0x00000000, // SX_MRT2_BLEND_OPT
|
||||
0x00000000, // SX_MRT3_BLEND_OPT
|
||||
0x00000000, // SX_MRT4_BLEND_OPT
|
||||
0x00000000, // SX_MRT5_BLEND_OPT
|
||||
0x00000000, // SX_MRT6_BLEND_OPT
|
||||
0x00000000, // SX_MRT7_BLEND_OPT
|
||||
0x00000000, // CB_BLEND0_CONTROL
|
||||
0x00000000, // CB_BLEND1_CONTROL
|
||||
0x00000000, // CB_BLEND2_CONTROL
|
||||
0x00000000, // CB_BLEND3_CONTROL
|
||||
0x00000000, // CB_BLEND4_CONTROL
|
||||
0x00000000, // CB_BLEND5_CONTROL
|
||||
0x00000000, // CB_BLEND6_CONTROL
|
||||
0x00000000, // CB_BLEND7_CONTROL
|
||||
};
|
||||
static const unsigned int gfx10_SECT_CONTEXT_def_3[] = {
|
||||
0x00000000, // PA_CL_POINT_X_RAD
|
||||
0x00000000, // PA_CL_POINT_Y_RAD
|
||||
0x00000000, // PA_CL_POINT_SIZE
|
||||
0x00000000, // PA_CL_POINT_CULL_RAD
|
||||
};
|
||||
static const unsigned int gfx10_SECT_CONTEXT_def_4[] = {
|
||||
0x00000000, // VGT_GS_MAX_PRIMS_PER_SUBGROUP
|
||||
0x00000000, // DB_DEPTH_CONTROL
|
||||
0x00000000, // DB_EQAA
|
||||
0x00000000, // CB_COLOR_CONTROL
|
||||
0x00000000, // DB_SHADER_CONTROL
|
||||
0x00090000, // PA_CL_CLIP_CNTL
|
||||
0x00000004, // PA_SU_SC_MODE_CNTL
|
||||
0x00000000, // PA_CL_VTE_CNTL
|
||||
0x00000000, // PA_CL_VS_OUT_CNTL
|
||||
0x00000000, // PA_CL_NANINF_CNTL
|
||||
0x00000000, // PA_SU_LINE_STIPPLE_CNTL
|
||||
0x00000000, // PA_SU_LINE_STIPPLE_SCALE
|
||||
0x00000000, // PA_SU_PRIM_FILTER_CNTL
|
||||
0x00000000, // PA_SU_SMALL_PRIM_FILTER_CNTL
|
||||
0x00000000, // PA_CL_OBJPRIM_ID_CNTL
|
||||
0x00000000, // PA_CL_NGG_CNTL
|
||||
0x00000000, // PA_SU_OVER_RASTERIZATION_CNTL
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0x00000000, // PA_SU_POINT_SIZE
|
||||
0x00000000, // PA_SU_POINT_MINMAX
|
||||
0x00000000, // PA_SU_LINE_CNTL
|
||||
0x00000000, // PA_SC_LINE_STIPPLE
|
||||
0x00000000, // VGT_OUTPUT_PATH_CNTL
|
||||
0x00000000, // VGT_HOS_CNTL
|
||||
0x00000000, // VGT_HOS_MAX_TESS_LEVEL
|
||||
0x00000000, // VGT_HOS_MIN_TESS_LEVEL
|
||||
0x00000000, // VGT_HOS_REUSE_DEPTH
|
||||
0x00000000, // VGT_GROUP_PRIM_TYPE
|
||||
0x00000000, // VGT_GROUP_FIRST_DECR
|
||||
0x00000000, // VGT_GROUP_DECR
|
||||
0x00000000, // VGT_GROUP_VECT_0_CNTL
|
||||
0x00000000, // VGT_GROUP_VECT_1_CNTL
|
||||
0x00000000, // VGT_GROUP_VECT_0_FMT_CNTL
|
||||
0x00000000, // VGT_GROUP_VECT_1_FMT_CNTL
|
||||
0x00000000, // VGT_GS_MODE
|
||||
0x00000000, // VGT_GS_ONCHIP_CNTL
|
||||
0x00000000, // PA_SC_MODE_CNTL_0
|
||||
0x00000000, // PA_SC_MODE_CNTL_1
|
||||
0x00000000, // VGT_ENHANCE
|
||||
0x00000100, // VGT_GS_PER_ES
|
||||
0x00000080, // VGT_ES_PER_GS
|
||||
0x00000002, // VGT_GS_PER_VS
|
||||
0x00000000, // VGT_GSVS_RING_OFFSET_1
|
||||
0x00000000, // VGT_GSVS_RING_OFFSET_2
|
||||
0x00000000, // VGT_GSVS_RING_OFFSET_3
|
||||
0x00000000, // VGT_GS_OUT_PRIM_TYPE
|
||||
0x00000000, // IA_ENHANCE
|
||||
};
|
||||
static const unsigned int gfx10_SECT_CONTEXT_def_5[] = {
|
||||
0x00000000, // WD_ENHANCE
|
||||
0x00000000, // VGT_PRIMITIVEID_EN
|
||||
};
|
||||
static const unsigned int gfx10_SECT_CONTEXT_def_6[] = {
|
||||
0x00000000, // VGT_PRIMITIVEID_RESET
|
||||
};
|
||||
static const unsigned int gfx10_SECT_CONTEXT_def_7[] = {
|
||||
0x00000000, // VGT_MULTI_PRIM_IB_RESET_EN
|
||||
0x00000000, // VGT_DRAW_PAYLOAD_CNTL
|
||||
0x00000000, // HOLE
|
||||
0x00000000, // VGT_INSTANCE_STEP_RATE_0
|
||||
0x00000000, // VGT_INSTANCE_STEP_RATE_1
|
||||
0x000000ff, // IA_MULTI_VGT_PARAM
|
||||
0x00000000, // VGT_ESGS_RING_ITEMSIZE
|
||||
0x00000000, // VGT_GSVS_RING_ITEMSIZE
|
||||
0x00000000, // VGT_REUSE_OFF
|
||||
0x00000000, // VGT_VTX_CNT_EN
|
||||
0x00000000, // DB_HTILE_SURFACE
|
||||
0x00000000, // DB_SRESULTS_COMPARE_STATE0
|
||||
0x00000000, // DB_SRESULTS_COMPARE_STATE1
|
||||
0x00000000, // DB_PRELOAD_CONTROL
|
||||
0, // HOLE
|
||||
0x00000000, // VGT_STRMOUT_BUFFER_SIZE_0
|
||||
0x00000000, // VGT_STRMOUT_VTX_STRIDE_0
|
||||
0, // HOLE
|
||||
0x00000000, // VGT_STRMOUT_BUFFER_OFFSET_0
|
||||
0x00000000, // VGT_STRMOUT_BUFFER_SIZE_1
|
||||
0x00000000, // VGT_STRMOUT_VTX_STRIDE_1
|
||||
0, // HOLE
|
||||
0x00000000, // VGT_STRMOUT_BUFFER_OFFSET_1
|
||||
0x00000000, // VGT_STRMOUT_BUFFER_SIZE_2
|
||||
0x00000000, // VGT_STRMOUT_VTX_STRIDE_2
|
||||
0, // HOLE
|
||||
0x00000000, // VGT_STRMOUT_BUFFER_OFFSET_2
|
||||
0x00000000, // VGT_STRMOUT_BUFFER_SIZE_3
|
||||
0x00000000, // VGT_STRMOUT_VTX_STRIDE_3
|
||||
0, // HOLE
|
||||
0x00000000, // VGT_STRMOUT_BUFFER_OFFSET_3
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0x00000000, // VGT_STRMOUT_DRAW_OPAQUE_OFFSET
|
||||
0x00000000, // VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE
|
||||
0x00000000, // VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE
|
||||
0, // HOLE
|
||||
0x00000000, // VGT_GS_MAX_VERT_OUT
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0, // HOLE
|
||||
0x00000000, // VGT_TESS_DISTRIBUTION
|
||||
0x00000000, // VGT_SHADER_STAGES_EN
|
||||
0x00000000, // VGT_LS_HS_CONFIG
|
||||
0x00000000, // VGT_GS_VERT_ITEMSIZE
|
||||
0x00000000, // VGT_GS_VERT_ITEMSIZE_1
|
||||
0x00000000, // VGT_GS_VERT_ITEMSIZE_2
|
||||
0x00000000, // VGT_GS_VERT_ITEMSIZE_3
|
||||
0x00000000, // VGT_TF_PARAM
|
||||
0x00000000, // DB_ALPHA_TO_MASK
|
||||
0x00000000, // VGT_DISPATCH_DRAW_INDEX
|
||||
0x00000000, // PA_SU_POLY_OFFSET_DB_FMT_CNTL
|
||||
0x00000000, // PA_SU_POLY_OFFSET_CLAMP
|
||||
0x00000000, // PA_SU_POLY_OFFSET_FRONT_SCALE
|
||||
0x00000000, // PA_SU_POLY_OFFSET_FRONT_OFFSET
|
||||
0x00000000, // PA_SU_POLY_OFFSET_BACK_SCALE
|
||||
0x00000000, // PA_SU_POLY_OFFSET_BACK_OFFSET
|
||||
0x00000000, // VGT_GS_INSTANCE_CNT
|
||||
0x00000000, // VGT_STRMOUT_CONFIG
|
||||
0x00000000, // VGT_STRMOUT_BUFFER_CONFIG
|
||||
};
|
||||
static const unsigned int gfx10_SECT_CONTEXT_def_8[] = {
|
||||
0x00000000, // PA_SC_CENTROID_PRIORITY_0
|
||||
0x00000000, // PA_SC_CENTROID_PRIORITY_1
|
||||
0x00001000, // PA_SC_LINE_CNTL
|
||||
0x00000000, // PA_SC_AA_CONFIG
|
||||
0x00000005, // PA_SU_VTX_CNTL
|
||||
0x3f800000, // PA_CL_GB_VERT_CLIP_ADJ
|
||||
0x3f800000, // PA_CL_GB_VERT_DISC_ADJ
|
||||
0x3f800000, // PA_CL_GB_HORZ_CLIP_ADJ
|
||||
0x3f800000, // PA_CL_GB_HORZ_DISC_ADJ
|
||||
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0
|
||||
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1
|
||||
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2
|
||||
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3
|
||||
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0
|
||||
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1
|
||||
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2
|
||||
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3
|
||||
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0
|
||||
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1
|
||||
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2
|
||||
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3
|
||||
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0
|
||||
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1
|
||||
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2
|
||||
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3
|
||||
0xffffffff, // PA_SC_AA_MASK_X0Y0_X1Y0
|
||||
0xffffffff, // PA_SC_AA_MASK_X0Y1_X1Y1
|
||||
0x00000000, // PA_SC_SHADER_CONTROL
|
||||
0x00000003, // PA_SC_BINNER_CNTL_0
|
||||
0x00000000, // PA_SC_BINNER_CNTL_1
|
||||
0x00100000, // PA_SC_CONSERVATIVE_RASTERIZATION_CNTL
|
||||
0x00000000, // PA_SC_NGG_MODE_CNTL
|
||||
0, // HOLE
|
||||
0x0000001e, // VGT_VERTEX_REUSE_BLOCK_CNTL
|
||||
0x00000020, // VGT_OUT_DEALLOC_CNTL
|
||||
0x00000000, // CB_COLOR0_BASE
|
||||
0x00000000, // CB_COLOR0_PITCH
|
||||
0x00000000, // CB_COLOR0_SLICE
|
||||
0x00000000, // CB_COLOR0_VIEW
|
||||
0x00000000, // CB_COLOR0_INFO
|
||||
0x00000000, // CB_COLOR0_ATTRIB
|
||||
0x00000000, // CB_COLOR0_DCC_CONTROL
|
||||
0x00000000, // CB_COLOR0_CMASK
|
||||
0x00000000, // CB_COLOR0_CMASK_SLICE
|
||||
0x00000000, // CB_COLOR0_FMASK
|
||||
0x00000000, // CB_COLOR0_FMASK_SLICE
|
||||
0x00000000, // CB_COLOR0_CLEAR_WORD0
|
||||
0x00000000, // CB_COLOR0_CLEAR_WORD1
|
||||
0x00000000, // CB_COLOR0_DCC_BASE
|
||||
0, // HOLE
|
||||
0x00000000, // CB_COLOR1_BASE
|
||||
0x00000000, // CB_COLOR1_PITCH
|
||||
0x00000000, // CB_COLOR1_SLICE
|
||||
0x00000000, // CB_COLOR1_VIEW
|
||||
0x00000000, // CB_COLOR1_INFO
|
||||
0x00000000, // CB_COLOR1_ATTRIB
|
||||
0x00000000, // CB_COLOR1_DCC_CONTROL
|
||||
0x00000000, // CB_COLOR1_CMASK
|
||||
0x00000000, // CB_COLOR1_CMASK_SLICE
|
||||
0x00000000, // CB_COLOR1_FMASK
|
||||
0x00000000, // CB_COLOR1_FMASK_SLICE
|
||||
0x00000000, // CB_COLOR1_CLEAR_WORD0
|
||||
0x00000000, // CB_COLOR1_CLEAR_WORD1
|
||||
0x00000000, // CB_COLOR1_DCC_BASE
|
||||
0, // HOLE
|
||||
0x00000000, // CB_COLOR2_BASE
|
||||
0x00000000, // CB_COLOR2_PITCH
|
||||
0x00000000, // CB_COLOR2_SLICE
|
||||
0x00000000, // CB_COLOR2_VIEW
|
||||
0x00000000, // CB_COLOR2_INFO
|
||||
0x00000000, // CB_COLOR2_ATTRIB
|
||||
0x00000000, // CB_COLOR2_DCC_CONTROL
|
||||
0x00000000, // CB_COLOR2_CMASK
|
||||
0x00000000, // CB_COLOR2_CMASK_SLICE
|
||||
0x00000000, // CB_COLOR2_FMASK
|
||||
0x00000000, // CB_COLOR2_FMASK_SLICE
|
||||
0x00000000, // CB_COLOR2_CLEAR_WORD0
|
||||
0x00000000, // CB_COLOR2_CLEAR_WORD1
|
||||
0x00000000, // CB_COLOR2_DCC_BASE
|
||||
0, // HOLE
|
||||
0x00000000, // CB_COLOR3_BASE
|
||||
0x00000000, // CB_COLOR3_PITCH
|
||||
0x00000000, // CB_COLOR3_SLICE
|
||||
0x00000000, // CB_COLOR3_VIEW
|
||||
0x00000000, // CB_COLOR3_INFO
|
||||
0x00000000, // CB_COLOR3_ATTRIB
|
||||
0x00000000, // CB_COLOR3_DCC_CONTROL
|
||||
0x00000000, // CB_COLOR3_CMASK
|
||||
0x00000000, // CB_COLOR3_CMASK_SLICE
|
||||
0x00000000, // CB_COLOR3_FMASK
|
||||
0x00000000, // CB_COLOR3_FMASK_SLICE
|
||||
0x00000000, // CB_COLOR3_CLEAR_WORD0
|
||||
0x00000000, // CB_COLOR3_CLEAR_WORD1
|
||||
0x00000000, // CB_COLOR3_DCC_BASE
|
||||
0, // HOLE
|
||||
0x00000000, // CB_COLOR4_BASE
|
||||
0x00000000, // CB_COLOR4_PITCH
|
||||
0x00000000, // CB_COLOR4_SLICE
|
||||
0x00000000, // CB_COLOR4_VIEW
|
||||
0x00000000, // CB_COLOR4_INFO
|
||||
0x00000000, // CB_COLOR4_ATTRIB
|
||||
0x00000000, // CB_COLOR4_DCC_CONTROL
|
||||
0x00000000, // CB_COLOR4_CMASK
|
||||
0x00000000, // CB_COLOR4_CMASK_SLICE
|
||||
0x00000000, // CB_COLOR4_FMASK
|
||||
0x00000000, // CB_COLOR4_FMASK_SLICE
|
||||
0x00000000, // CB_COLOR4_CLEAR_WORD0
|
||||
0x00000000, // CB_COLOR4_CLEAR_WORD1
|
||||
0x00000000, // CB_COLOR4_DCC_BASE
|
||||
0, // HOLE
|
||||
0x00000000, // CB_COLOR5_BASE
|
||||
0x00000000, // CB_COLOR5_PITCH
|
||||
0x00000000, // CB_COLOR5_SLICE
|
||||
0x00000000, // CB_COLOR5_VIEW
|
||||
0x00000000, // CB_COLOR5_INFO
|
||||
0x00000000, // CB_COLOR5_ATTRIB
|
||||
0x00000000, // CB_COLOR5_DCC_CONTROL
|
||||
0x00000000, // CB_COLOR5_CMASK
|
||||
0x00000000, // CB_COLOR5_CMASK_SLICE
|
||||
0x00000000, // CB_COLOR5_FMASK
|
||||
0x00000000, // CB_COLOR5_FMASK_SLICE
|
||||
0x00000000, // CB_COLOR5_CLEAR_WORD0
|
||||
0x00000000, // CB_COLOR5_CLEAR_WORD1
|
||||
0x00000000, // CB_COLOR5_DCC_BASE
|
||||
0, // HOLE
|
||||
0x00000000, // CB_COLOR6_BASE
|
||||
0x00000000, // CB_COLOR6_PITCH
|
||||
0x00000000, // CB_COLOR6_SLICE
|
||||
0x00000000, // CB_COLOR6_VIEW
|
||||
0x00000000, // CB_COLOR6_INFO
|
||||
0x00000000, // CB_COLOR6_ATTRIB
|
||||
0x00000000, // CB_COLOR6_DCC_CONTROL
|
||||
0x00000000, // CB_COLOR6_CMASK
|
||||
0x00000000, // CB_COLOR6_CMASK_SLICE
|
||||
0x00000000, // CB_COLOR6_FMASK
|
||||
0x00000000, // CB_COLOR6_FMASK_SLICE
|
||||
0x00000000, // CB_COLOR6_CLEAR_WORD0
|
||||
0x00000000, // CB_COLOR6_CLEAR_WORD1
|
||||
0x00000000, // CB_COLOR6_DCC_BASE
|
||||
0, // HOLE
|
||||
0x00000000, // CB_COLOR7_BASE
|
||||
0x00000000, // CB_COLOR7_PITCH
|
||||
0x00000000, // CB_COLOR7_SLICE
|
||||
0x00000000, // CB_COLOR7_VIEW
|
||||
0x00000000, // CB_COLOR7_INFO
|
||||
0x00000000, // CB_COLOR7_ATTRIB
|
||||
0x00000000, // CB_COLOR7_DCC_CONTROL
|
||||
0x00000000, // CB_COLOR7_CMASK
|
||||
0x00000000, // CB_COLOR7_CMASK_SLICE
|
||||
0x00000000, // CB_COLOR7_FMASK
|
||||
0x00000000, // CB_COLOR7_FMASK_SLICE
|
||||
0x00000000, // CB_COLOR7_CLEAR_WORD0
|
||||
0x00000000, // CB_COLOR7_CLEAR_WORD1
|
||||
0x00000000, // CB_COLOR7_DCC_BASE
|
||||
0, // HOLE
|
||||
0x00000000, // CB_COLOR0_BASE_EXT
|
||||
0x00000000, // CB_COLOR1_BASE_EXT
|
||||
0x00000000, // CB_COLOR2_BASE_EXT
|
||||
0x00000000, // CB_COLOR3_BASE_EXT
|
||||
0x00000000, // CB_COLOR4_BASE_EXT
|
||||
0x00000000, // CB_COLOR5_BASE_EXT
|
||||
0x00000000, // CB_COLOR6_BASE_EXT
|
||||
0x00000000, // CB_COLOR7_BASE_EXT
|
||||
0x00000000, // CB_COLOR0_CMASK_BASE_EXT
|
||||
0x00000000, // CB_COLOR1_CMASK_BASE_EXT
|
||||
0x00000000, // CB_COLOR2_CMASK_BASE_EXT
|
||||
0x00000000, // CB_COLOR3_CMASK_BASE_EXT
|
||||
0x00000000, // CB_COLOR4_CMASK_BASE_EXT
|
||||
0x00000000, // CB_COLOR5_CMASK_BASE_EXT
|
||||
0x00000000, // CB_COLOR6_CMASK_BASE_EXT
|
||||
0x00000000, // CB_COLOR7_CMASK_BASE_EXT
|
||||
0x00000000, // CB_COLOR0_FMASK_BASE_EXT
|
||||
0x00000000, // CB_COLOR1_FMASK_BASE_EXT
|
||||
0x00000000, // CB_COLOR2_FMASK_BASE_EXT
|
||||
0x00000000, // CB_COLOR3_FMASK_BASE_EXT
|
||||
0x00000000, // CB_COLOR4_FMASK_BASE_EXT
|
||||
0x00000000, // CB_COLOR5_FMASK_BASE_EXT
|
||||
0x00000000, // CB_COLOR6_FMASK_BASE_EXT
|
||||
0x00000000, // CB_COLOR7_FMASK_BASE_EXT
|
||||
0x00000000, // CB_COLOR0_DCC_BASE_EXT
|
||||
0x00000000, // CB_COLOR1_DCC_BASE_EXT
|
||||
0x00000000, // CB_COLOR2_DCC_BASE_EXT
|
||||
0x00000000, // CB_COLOR3_DCC_BASE_EXT
|
||||
0x00000000, // CB_COLOR4_DCC_BASE_EXT
|
||||
0x00000000, // CB_COLOR5_DCC_BASE_EXT
|
||||
0x00000000, // CB_COLOR6_DCC_BASE_EXT
|
||||
0x00000000, // CB_COLOR7_DCC_BASE_EXT
|
||||
0x00000000, // CB_COLOR0_ATTRIB2
|
||||
0x00000000, // CB_COLOR1_ATTRIB2
|
||||
0x00000000, // CB_COLOR2_ATTRIB2
|
||||
0x00000000, // CB_COLOR3_ATTRIB2
|
||||
0x00000000, // CB_COLOR4_ATTRIB2
|
||||
0x00000000, // CB_COLOR5_ATTRIB2
|
||||
0x00000000, // CB_COLOR6_ATTRIB2
|
||||
0x00000000, // CB_COLOR7_ATTRIB2
|
||||
0x00000000, // CB_COLOR0_ATTRIB3
|
||||
0x00000000, // CB_COLOR1_ATTRIB3
|
||||
0x00000000, // CB_COLOR2_ATTRIB3
|
||||
0x00000000, // CB_COLOR3_ATTRIB3
|
||||
0x00000000, // CB_COLOR4_ATTRIB3
|
||||
0x00000000, // CB_COLOR5_ATTRIB3
|
||||
0x00000000, // CB_COLOR6_ATTRIB3
|
||||
0x00000000, // CB_COLOR7_ATTRIB3
|
||||
};
|
||||
static const struct cs_extent_def gfx10_SECT_CONTEXT_defs[] = {
|
||||
{gfx10_SECT_CONTEXT_def_1, 0x0000a000, 215 },
|
||||
{gfx10_SECT_CONTEXT_def_2, 0x0000a0d8, 272 },
|
||||
{gfx10_SECT_CONTEXT_def_3, 0x0000a1f5, 4 },
|
||||
{gfx10_SECT_CONTEXT_def_4, 0x0000a1ff, 158 },
|
||||
{gfx10_SECT_CONTEXT_def_5, 0x0000a2a0, 2 },
|
||||
{gfx10_SECT_CONTEXT_def_6, 0x0000a2a3, 1 },
|
||||
{gfx10_SECT_CONTEXT_def_7, 0x0000a2a5, 66 },
|
||||
{gfx10_SECT_CONTEXT_def_8, 0x0000a2f5, 203 },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
static const struct cs_section_def gfx10_cs_data[] = {
|
||||
{ gfx10_SECT_CONTEXT_defs, SECT_CONTEXT },
|
||||
{ 0, SECT_NONE }
|
||||
};
|
|
@ -457,6 +457,7 @@ static int dce_virtual_hw_init(void *handle)
|
|||
case CHIP_VEGA10:
|
||||
case CHIP_VEGA12:
|
||||
case CHIP_VEGA20:
|
||||
case CHIP_NAVI10:
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Virtual display unsupported ASIC type: 0x%X\n", adev->asic_type);
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
static u32 df_v1_7_channel_number[] = {1, 2, 0, 4, 0, 8, 0, 16, 2};
|
||||
|
||||
static void df_v1_7_init (struct amdgpu_device *adev)
|
||||
static void df_v1_7_sw_init(struct amdgpu_device *adev)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ static void df_v1_7_enable_ecc_force_par_wr_rmw(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
const struct amdgpu_df_funcs df_v1_7_funcs = {
|
||||
.init = df_v1_7_init,
|
||||
.sw_init = df_v1_7_sw_init,
|
||||
.enable_broadcast_mode = df_v1_7_enable_broadcast_mode,
|
||||
.get_fb_channel_number = df_v1_7_get_fb_channel_number,
|
||||
.get_hbm_channel_number = df_v1_7_get_hbm_channel_number,
|
||||
|
|
|
@ -30,8 +30,104 @@
|
|||
static u32 df_v3_6_channel_number[] = {1, 2, 0, 4, 0, 8, 0,
|
||||
16, 32, 0, 0, 0, 2, 4, 8};
|
||||
|
||||
static void df_v3_6_init(struct amdgpu_device *adev)
|
||||
/* init df format attrs */
|
||||
AMDGPU_PMU_ATTR(event, "config:0-7");
|
||||
AMDGPU_PMU_ATTR(instance, "config:8-15");
|
||||
AMDGPU_PMU_ATTR(umask, "config:16-23");
|
||||
|
||||
/* df format attributes */
|
||||
static struct attribute *df_v3_6_format_attrs[] = {
|
||||
&pmu_attr_event.attr,
|
||||
&pmu_attr_instance.attr,
|
||||
&pmu_attr_umask.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* df format attribute group */
|
||||
static struct attribute_group df_v3_6_format_attr_group = {
|
||||
.name = "format",
|
||||
.attrs = df_v3_6_format_attrs,
|
||||
};
|
||||
|
||||
/* df event attrs */
|
||||
AMDGPU_PMU_ATTR(cake0_pcsout_txdata,
|
||||
"event=0x7,instance=0x46,umask=0x2");
|
||||
AMDGPU_PMU_ATTR(cake1_pcsout_txdata,
|
||||
"event=0x7,instance=0x47,umask=0x2");
|
||||
AMDGPU_PMU_ATTR(cake0_pcsout_txmeta,
|
||||
"event=0x7,instance=0x46,umask=0x4");
|
||||
AMDGPU_PMU_ATTR(cake1_pcsout_txmeta,
|
||||
"event=0x7,instance=0x47,umask=0x4");
|
||||
AMDGPU_PMU_ATTR(cake0_ftiinstat_reqalloc,
|
||||
"event=0xb,instance=0x46,umask=0x4");
|
||||
AMDGPU_PMU_ATTR(cake1_ftiinstat_reqalloc,
|
||||
"event=0xb,instance=0x47,umask=0x4");
|
||||
AMDGPU_PMU_ATTR(cake0_ftiinstat_rspalloc,
|
||||
"event=0xb,instance=0x46,umask=0x8");
|
||||
AMDGPU_PMU_ATTR(cake1_ftiinstat_rspalloc,
|
||||
"event=0xb,instance=0x47,umask=0x8");
|
||||
|
||||
/* df event attributes */
|
||||
static struct attribute *df_v3_6_event_attrs[] = {
|
||||
&pmu_attr_cake0_pcsout_txdata.attr,
|
||||
&pmu_attr_cake1_pcsout_txdata.attr,
|
||||
&pmu_attr_cake0_pcsout_txmeta.attr,
|
||||
&pmu_attr_cake1_pcsout_txmeta.attr,
|
||||
&pmu_attr_cake0_ftiinstat_reqalloc.attr,
|
||||
&pmu_attr_cake1_ftiinstat_reqalloc.attr,
|
||||
&pmu_attr_cake0_ftiinstat_rspalloc.attr,
|
||||
&pmu_attr_cake1_ftiinstat_rspalloc.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* df event attribute group */
|
||||
static struct attribute_group df_v3_6_event_attr_group = {
|
||||
.name = "events",
|
||||
.attrs = df_v3_6_event_attrs
|
||||
};
|
||||
|
||||
/* df event attr groups */
|
||||
const struct attribute_group *df_v3_6_attr_groups[] = {
|
||||
&df_v3_6_format_attr_group,
|
||||
&df_v3_6_event_attr_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* get the number of df counters available */
|
||||
static ssize_t df_v3_6_get_df_cntr_avail(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
struct drm_device *ddev;
|
||||
int i, count;
|
||||
|
||||
ddev = dev_get_drvdata(dev);
|
||||
adev = ddev->dev_private;
|
||||
count = 0;
|
||||
|
||||
for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
|
||||
if (adev->df_perfmon_config_assign_mask[i] == 0)
|
||||
count++;
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%i\n", count);
|
||||
}
|
||||
|
||||
/* device attr for available perfmon counters */
|
||||
static DEVICE_ATTR(df_cntr_avail, S_IRUGO, df_v3_6_get_df_cntr_avail, NULL);
|
||||
|
||||
/* init perfmons */
|
||||
static void df_v3_6_sw_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
ret = device_create_file(adev->dev, &dev_attr_df_cntr_avail);
|
||||
if (ret)
|
||||
DRM_ERROR("failed to create file for available df counters\n");
|
||||
|
||||
for (i = 0; i < AMDGPU_MAX_DF_PERFMONS; i++)
|
||||
adev->df_perfmon_config_assign_mask[i] = 0;
|
||||
}
|
||||
|
||||
static void df_v3_6_enable_broadcast_mode(struct amdgpu_device *adev,
|
||||
|
@ -105,28 +201,19 @@ static void df_v3_6_get_clockgating_state(struct amdgpu_device *adev,
|
|||
*flags |= AMD_CG_SUPPORT_DF_MGCG;
|
||||
}
|
||||
|
||||
/* hold counter assignment per gpu struct */
|
||||
struct df_v3_6_event_mask {
|
||||
struct amdgpu_device gpu;
|
||||
uint64_t config_assign_mask[AMDGPU_DF_MAX_COUNTERS];
|
||||
};
|
||||
|
||||
/* get assigned df perfmon ctr as int */
|
||||
static void df_v3_6_pmc_config_2_cntr(struct amdgpu_device *adev,
|
||||
uint64_t config,
|
||||
int *counter)
|
||||
static int df_v3_6_pmc_config_2_cntr(struct amdgpu_device *adev,
|
||||
uint64_t config)
|
||||
{
|
||||
struct df_v3_6_event_mask *mask;
|
||||
int i;
|
||||
|
||||
mask = container_of(adev, struct df_v3_6_event_mask, gpu);
|
||||
|
||||
for (i = 0; i < AMDGPU_DF_MAX_COUNTERS; i++) {
|
||||
if ((config & 0x0FFFFFFUL) == mask->config_assign_mask[i]) {
|
||||
*counter = i;
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
|
||||
if ((config & 0x0FFFFFFUL) ==
|
||||
adev->df_perfmon_config_assign_mask[i])
|
||||
return i;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* get address based on counter assignment */
|
||||
|
@ -136,10 +223,7 @@ static void df_v3_6_pmc_get_addr(struct amdgpu_device *adev,
|
|||
uint32_t *lo_base_addr,
|
||||
uint32_t *hi_base_addr)
|
||||
{
|
||||
|
||||
int target_cntr = -1;
|
||||
|
||||
df_v3_6_pmc_config_2_cntr(adev, config, &target_cntr);
|
||||
int target_cntr = df_v3_6_pmc_config_2_cntr(adev, config);
|
||||
|
||||
if (target_cntr < 0)
|
||||
return;
|
||||
|
@ -177,40 +261,38 @@ static void df_v3_6_pmc_get_read_settings(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
/* get control counter settings i.e. address and values to set */
|
||||
static void df_v3_6_pmc_get_ctrl_settings(struct amdgpu_device *adev,
|
||||
static int df_v3_6_pmc_get_ctrl_settings(struct amdgpu_device *adev,
|
||||
uint64_t config,
|
||||
uint32_t *lo_base_addr,
|
||||
uint32_t *hi_base_addr,
|
||||
uint32_t *lo_val,
|
||||
uint32_t *hi_val)
|
||||
{
|
||||
|
||||
uint32_t eventsel, instance, unitmask;
|
||||
uint32_t es_5_0, es_13_0, es_13_6, es_13_12, es_11_8, es_7_0;
|
||||
|
||||
df_v3_6_pmc_get_addr(adev, config, 1, lo_base_addr, hi_base_addr);
|
||||
|
||||
if (lo_val == NULL || hi_val == NULL)
|
||||
return;
|
||||
|
||||
if ((*lo_base_addr == 0) || (*hi_base_addr == 0)) {
|
||||
DRM_ERROR("DF PMC addressing not retrieved! Lo: %x, Hi: %x",
|
||||
DRM_ERROR("[DF PMC] addressing not retrieved! Lo: %x, Hi: %x",
|
||||
*lo_base_addr, *hi_base_addr);
|
||||
return;
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
eventsel = GET_EVENT(config);
|
||||
instance = GET_INSTANCE(config);
|
||||
unitmask = GET_UNITMASK(config);
|
||||
if (lo_val && hi_val) {
|
||||
uint32_t eventsel, instance, unitmask;
|
||||
uint32_t instance_10, instance_5432, instance_76;
|
||||
|
||||
es_5_0 = eventsel & 0x3FUL;
|
||||
es_13_6 = instance;
|
||||
es_13_0 = (es_13_6 << 6) + es_5_0;
|
||||
es_13_12 = (es_13_0 & 0x03000UL) >> 12;
|
||||
es_11_8 = (es_13_0 & 0x0F00UL) >> 8;
|
||||
es_7_0 = es_13_0 & 0x0FFUL;
|
||||
*lo_val = (es_7_0 & 0xFFUL) | ((unitmask & 0x0FUL) << 8);
|
||||
*hi_val = (es_11_8 | ((es_13_12)<<(29)));
|
||||
eventsel = DF_V3_6_GET_EVENT(config) & 0x3f;
|
||||
unitmask = DF_V3_6_GET_UNITMASK(config) & 0xf;
|
||||
instance = DF_V3_6_GET_INSTANCE(config);
|
||||
|
||||
instance_10 = instance & 0x3;
|
||||
instance_5432 = (instance >> 2) & 0xf;
|
||||
instance_76 = (instance >> 6) & 0x3;
|
||||
|
||||
*lo_val = (unitmask << 8) | (instance_10 << 6) | eventsel;
|
||||
*hi_val = (instance_76 << 29) | instance_5432;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* assign df performance counters for read */
|
||||
|
@ -218,26 +300,21 @@ static int df_v3_6_pmc_assign_cntr(struct amdgpu_device *adev,
|
|||
uint64_t config,
|
||||
int *is_assigned)
|
||||
{
|
||||
|
||||
struct df_v3_6_event_mask *mask;
|
||||
int i, target_cntr;
|
||||
|
||||
target_cntr = -1;
|
||||
|
||||
*is_assigned = 0;
|
||||
|
||||
df_v3_6_pmc_config_2_cntr(adev, config, &target_cntr);
|
||||
target_cntr = df_v3_6_pmc_config_2_cntr(adev, config);
|
||||
|
||||
if (target_cntr >= 0) {
|
||||
*is_assigned = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mask = container_of(adev, struct df_v3_6_event_mask, gpu);
|
||||
|
||||
for (i = 0; i < AMDGPU_DF_MAX_COUNTERS; i++) {
|
||||
if (mask->config_assign_mask[i] == 0ULL) {
|
||||
mask->config_assign_mask[i] = config & 0x0FFFFFFUL;
|
||||
for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
|
||||
if (adev->df_perfmon_config_assign_mask[i] == 0U) {
|
||||
adev->df_perfmon_config_assign_mask[i] =
|
||||
config & 0x0FFFFFFUL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -249,66 +326,17 @@ static int df_v3_6_pmc_assign_cntr(struct amdgpu_device *adev,
|
|||
static void df_v3_6_pmc_release_cntr(struct amdgpu_device *adev,
|
||||
uint64_t config)
|
||||
{
|
||||
|
||||
struct df_v3_6_event_mask *mask;
|
||||
int target_cntr;
|
||||
|
||||
target_cntr = -1;
|
||||
|
||||
df_v3_6_pmc_config_2_cntr(adev, config, &target_cntr);
|
||||
|
||||
mask = container_of(adev, struct df_v3_6_event_mask, gpu);
|
||||
int target_cntr = df_v3_6_pmc_config_2_cntr(adev, config);
|
||||
|
||||
if (target_cntr >= 0)
|
||||
mask->config_assign_mask[target_cntr] = 0ULL;
|
||||
|
||||
adev->df_perfmon_config_assign_mask[target_cntr] = 0ULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* get xgmi link counters via programmable data fabric (df) counters (max 4)
|
||||
* using cake tx event.
|
||||
*
|
||||
* @adev -> amdgpu device
|
||||
* @instance-> currently cake has 2 links to poll on vega20
|
||||
* @count -> counters to pass
|
||||
*
|
||||
*/
|
||||
|
||||
static void df_v3_6_get_xgmi_link_cntr(struct amdgpu_device *adev,
|
||||
int instance,
|
||||
uint64_t *count)
|
||||
{
|
||||
uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val;
|
||||
uint64_t config;
|
||||
|
||||
config = GET_INSTANCE_CONFIG(instance);
|
||||
|
||||
df_v3_6_pmc_get_read_settings(adev, config, &lo_base_addr,
|
||||
&hi_base_addr);
|
||||
|
||||
if ((lo_base_addr == 0) || (hi_base_addr == 0))
|
||||
return;
|
||||
|
||||
lo_val = RREG32_PCIE(lo_base_addr);
|
||||
hi_val = RREG32_PCIE(hi_base_addr);
|
||||
|
||||
*count = ((hi_val | 0ULL) << 32) | (lo_val | 0ULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* reset xgmi link counters
|
||||
*
|
||||
* @adev -> amdgpu device
|
||||
* @instance-> currently cake has 2 links to poll on vega20
|
||||
*
|
||||
*/
|
||||
static void df_v3_6_reset_xgmi_link_cntr(struct amdgpu_device *adev,
|
||||
int instance)
|
||||
static void df_v3_6_reset_perfmon_cntr(struct amdgpu_device *adev,
|
||||
uint64_t config)
|
||||
{
|
||||
uint32_t lo_base_addr, hi_base_addr;
|
||||
uint64_t config;
|
||||
|
||||
config = 0ULL | (0x7ULL) | ((0x46ULL + instance) << 8) | (0x2 << 16);
|
||||
|
||||
df_v3_6_pmc_get_read_settings(adev, config, &lo_base_addr,
|
||||
&hi_base_addr);
|
||||
|
@ -320,157 +348,69 @@ static void df_v3_6_reset_xgmi_link_cntr(struct amdgpu_device *adev,
|
|||
WREG32_PCIE(hi_base_addr, 0UL);
|
||||
}
|
||||
|
||||
/*
|
||||
* add xgmi link counters
|
||||
*
|
||||
* @adev -> amdgpu device
|
||||
* @instance-> currently cake has 2 links to poll on vega20
|
||||
*
|
||||
*/
|
||||
|
||||
static int df_v3_6_add_xgmi_link_cntr(struct amdgpu_device *adev,
|
||||
int instance)
|
||||
static int df_v3_6_add_perfmon_cntr(struct amdgpu_device *adev,
|
||||
uint64_t config)
|
||||
{
|
||||
uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val;
|
||||
uint64_t config;
|
||||
int ret, is_assigned;
|
||||
|
||||
if (instance < 0 || instance > 1)
|
||||
return -EINVAL;
|
||||
|
||||
config = GET_INSTANCE_CONFIG(instance);
|
||||
|
||||
ret = df_v3_6_pmc_assign_cntr(adev, config, &is_assigned);
|
||||
|
||||
if (ret || is_assigned)
|
||||
return ret;
|
||||
|
||||
df_v3_6_pmc_get_ctrl_settings(adev,
|
||||
ret = df_v3_6_pmc_get_ctrl_settings(adev,
|
||||
config,
|
||||
&lo_base_addr,
|
||||
&hi_base_addr,
|
||||
&lo_val,
|
||||
&hi_val);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x:%08x",
|
||||
config, lo_base_addr, hi_base_addr, lo_val, hi_val);
|
||||
|
||||
WREG32_PCIE(lo_base_addr, lo_val);
|
||||
WREG32_PCIE(hi_base_addr, hi_val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* start xgmi link counters
|
||||
*
|
||||
* @adev -> amdgpu device
|
||||
* @instance-> currently cake has 2 links to poll on vega20
|
||||
* @is_enable -> either resume or assign event via df perfmon
|
||||
*
|
||||
*/
|
||||
|
||||
static int df_v3_6_start_xgmi_link_cntr(struct amdgpu_device *adev,
|
||||
int instance,
|
||||
int is_enable)
|
||||
{
|
||||
uint32_t lo_base_addr, hi_base_addr, lo_val;
|
||||
uint64_t config;
|
||||
int ret;
|
||||
|
||||
if (instance < 0 || instance > 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (is_enable) {
|
||||
|
||||
ret = df_v3_6_add_xgmi_link_cntr(adev, instance);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
} else {
|
||||
|
||||
config = GET_INSTANCE_CONFIG(instance);
|
||||
|
||||
df_v3_6_pmc_get_ctrl_settings(adev,
|
||||
config,
|
||||
&lo_base_addr,
|
||||
&hi_base_addr,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (lo_base_addr == 0)
|
||||
return -EINVAL;
|
||||
|
||||
lo_val = RREG32_PCIE(lo_base_addr);
|
||||
|
||||
WREG32_PCIE(lo_base_addr, lo_val | (1ULL << 22));
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* start xgmi link counters
|
||||
*
|
||||
* @adev -> amdgpu device
|
||||
* @instance-> currently cake has 2 links to poll on vega20
|
||||
* @is_enable -> either pause or unassign event via df perfmon
|
||||
*
|
||||
*/
|
||||
|
||||
static int df_v3_6_stop_xgmi_link_cntr(struct amdgpu_device *adev,
|
||||
int instance,
|
||||
int is_disable)
|
||||
{
|
||||
|
||||
uint32_t lo_base_addr, hi_base_addr, lo_val;
|
||||
uint64_t config;
|
||||
|
||||
config = GET_INSTANCE_CONFIG(instance);
|
||||
|
||||
if (is_disable) {
|
||||
df_v3_6_reset_xgmi_link_cntr(adev, instance);
|
||||
df_v3_6_pmc_release_cntr(adev, config);
|
||||
} else {
|
||||
|
||||
df_v3_6_pmc_get_ctrl_settings(adev,
|
||||
config,
|
||||
&lo_base_addr,
|
||||
&hi_base_addr,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if ((lo_base_addr == 0) || (hi_base_addr == 0))
|
||||
return -EINVAL;
|
||||
|
||||
lo_val = RREG32_PCIE(lo_base_addr);
|
||||
|
||||
WREG32_PCIE(lo_base_addr, lo_val & ~(1ULL << 22));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int df_v3_6_pmc_start(struct amdgpu_device *adev, uint64_t config,
|
||||
int is_enable)
|
||||
{
|
||||
int xgmi_tx_link, ret = 0;
|
||||
uint32_t lo_base_addr, hi_base_addr, lo_val;
|
||||
int ret = 0;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA20:
|
||||
xgmi_tx_link = IS_DF_XGMI_0_TX(config) ? 0
|
||||
: (IS_DF_XGMI_1_TX(config) ? 1 : -1);
|
||||
|
||||
if (xgmi_tx_link >= 0)
|
||||
ret = df_v3_6_start_xgmi_link_cntr(adev, xgmi_tx_link,
|
||||
is_enable);
|
||||
df_v3_6_reset_perfmon_cntr(adev, config);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
if (is_enable) {
|
||||
ret = df_v3_6_add_perfmon_cntr(adev, config);
|
||||
} else {
|
||||
ret = df_v3_6_pmc_get_ctrl_settings(adev,
|
||||
config,
|
||||
&lo_base_addr,
|
||||
&hi_base_addr,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
lo_val = RREG32_PCIE(lo_base_addr);
|
||||
|
||||
DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x",
|
||||
config, lo_base_addr, hi_base_addr, lo_val);
|
||||
|
||||
WREG32_PCIE(lo_base_addr, lo_val | (1ULL << 22));
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -482,23 +422,32 @@ static int df_v3_6_pmc_start(struct amdgpu_device *adev, uint64_t config,
|
|||
static int df_v3_6_pmc_stop(struct amdgpu_device *adev, uint64_t config,
|
||||
int is_disable)
|
||||
{
|
||||
int xgmi_tx_link, ret = 0;
|
||||
uint32_t lo_base_addr, hi_base_addr, lo_val;
|
||||
int ret = 0;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA20:
|
||||
xgmi_tx_link = IS_DF_XGMI_0_TX(config) ? 0
|
||||
: (IS_DF_XGMI_1_TX(config) ? 1 : -1);
|
||||
ret = df_v3_6_pmc_get_ctrl_settings(adev,
|
||||
config,
|
||||
&lo_base_addr,
|
||||
&hi_base_addr,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (xgmi_tx_link >= 0) {
|
||||
ret = df_v3_6_stop_xgmi_link_cntr(adev,
|
||||
xgmi_tx_link,
|
||||
is_disable);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = 0;
|
||||
break;
|
||||
lo_val = RREG32_PCIE(lo_base_addr);
|
||||
|
||||
DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x",
|
||||
config, lo_base_addr, hi_base_addr, lo_val);
|
||||
|
||||
WREG32_PCIE(lo_base_addr, lo_val & ~(1ULL << 22));
|
||||
|
||||
if (is_disable)
|
||||
df_v3_6_pmc_release_cntr(adev, config);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -510,28 +459,38 @@ static void df_v3_6_pmc_get_count(struct amdgpu_device *adev,
|
|||
uint64_t config,
|
||||
uint64_t *count)
|
||||
{
|
||||
|
||||
int xgmi_tx_link;
|
||||
uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val;
|
||||
*count = 0;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA20:
|
||||
xgmi_tx_link = IS_DF_XGMI_0_TX(config) ? 0
|
||||
: (IS_DF_XGMI_1_TX(config) ? 1 : -1);
|
||||
|
||||
if (xgmi_tx_link >= 0) {
|
||||
df_v3_6_reset_xgmi_link_cntr(adev, xgmi_tx_link);
|
||||
df_v3_6_get_xgmi_link_cntr(adev, xgmi_tx_link, count);
|
||||
}
|
||||
df_v3_6_pmc_get_read_settings(adev, config, &lo_base_addr,
|
||||
&hi_base_addr);
|
||||
|
||||
if ((lo_base_addr == 0) || (hi_base_addr == 0))
|
||||
return;
|
||||
|
||||
lo_val = RREG32_PCIE(lo_base_addr);
|
||||
hi_val = RREG32_PCIE(hi_base_addr);
|
||||
|
||||
*count = ((hi_val | 0ULL) << 32) | (lo_val | 0ULL);
|
||||
|
||||
if (*count >= DF_V3_6_PERFMON_OVERFLOW)
|
||||
*count = 0;
|
||||
|
||||
DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x:%08x",
|
||||
config, lo_base_addr, hi_base_addr, lo_val, hi_val);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const struct amdgpu_df_funcs df_v3_6_funcs = {
|
||||
.init = df_v3_6_init,
|
||||
.sw_init = df_v3_6_sw_init,
|
||||
.enable_broadcast_mode = df_v3_6_enable_broadcast_mode,
|
||||
.get_fb_channel_number = df_v3_6_get_fb_channel_number,
|
||||
.get_hbm_channel_number = df_v3_6_get_hbm_channel_number,
|
||||
|
|
|
@ -36,22 +36,15 @@ enum DF_V3_6_MGCG {
|
|||
};
|
||||
|
||||
/* Defined in global_features.h as FTI_PERFMON_VISIBLE */
|
||||
#define AMDGPU_DF_MAX_COUNTERS 4
|
||||
#define DF_V3_6_MAX_COUNTERS 4
|
||||
|
||||
/* get flags from df perfmon config */
|
||||
#define GET_EVENT(x) (x & 0xFFUL)
|
||||
#define GET_INSTANCE(x) ((x >> 8) & 0xFFUL)
|
||||
#define GET_UNITMASK(x) ((x >> 16) & 0xFFUL)
|
||||
#define GET_INSTANCE_CONFIG(x) (0ULL | (0x07ULL) \
|
||||
| ((0x046ULL + x) << 8) \
|
||||
| (0x02 << 16))
|
||||
|
||||
/* df event conf macros */
|
||||
#define IS_DF_XGMI_0_TX(x) (GET_EVENT(x) == 0x7 \
|
||||
&& GET_INSTANCE(x) == 0x46 && GET_UNITMASK(x) == 0x2)
|
||||
#define IS_DF_XGMI_1_TX(x) (GET_EVENT(x) == 0x7 \
|
||||
&& GET_INSTANCE(x) == 0x47 && GET_UNITMASK(x) == 0x2)
|
||||
#define DF_V3_6_GET_EVENT(x) (x & 0xFFUL)
|
||||
#define DF_V3_6_GET_INSTANCE(x) ((x >> 8) & 0xFFUL)
|
||||
#define DF_V3_6_GET_UNITMASK(x) ((x >> 16) & 0xFFUL)
|
||||
#define DF_V3_6_PERFMON_OVERFLOW 0xFFFFFFFFFFFFULL
|
||||
|
||||
extern const struct attribute_group *df_v3_6_attr_groups[];
|
||||
extern const struct amdgpu_df_funcs df_v3_6_funcs;
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2019 dvanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __GFX_V10_0_H__
|
||||
#define __GFX_V10_0_H__
|
||||
|
||||
extern const struct amdgpu_ip_block_version gfx_v10_0_ip_block;
|
||||
|
||||
#endif
|
|
@ -3115,7 +3115,7 @@ static int gfx_v6_0_sw_init(void *handle)
|
|||
ring->ring_obj = NULL;
|
||||
sprintf(ring->name, "gfx");
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP);
|
||||
&adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -3350,7 +3350,7 @@ static int gfx_v6_0_set_eop_interrupt_state(struct amdgpu_device *adev,
|
|||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
switch (type) {
|
||||
case AMDGPU_CP_IRQ_GFX_EOP:
|
||||
case AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP:
|
||||
gfx_v6_0_set_gfx_eop_interrupt_state(adev, state);
|
||||
break;
|
||||
case AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP:
|
||||
|
|
|
@ -4462,7 +4462,7 @@ static int gfx_v7_0_sw_init(void *handle)
|
|||
ring->ring_obj = NULL;
|
||||
sprintf(ring->name, "gfx");
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP);
|
||||
&adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -4799,7 +4799,7 @@ static int gfx_v7_0_set_eop_interrupt_state(struct amdgpu_device *adev,
|
|||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
switch (type) {
|
||||
case AMDGPU_CP_IRQ_GFX_EOP:
|
||||
case AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP:
|
||||
gfx_v7_0_set_gfx_eop_interrupt_state(adev, state);
|
||||
break;
|
||||
case AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP:
|
||||
|
|
|
@ -2009,7 +2009,7 @@ static int gfx_v8_0_sw_init(void *handle)
|
|||
}
|
||||
|
||||
r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq,
|
||||
AMDGPU_CP_IRQ_GFX_EOP);
|
||||
AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -2046,7 +2046,7 @@ static int gfx_v8_0_sw_init(void *handle)
|
|||
return r;
|
||||
|
||||
/* create MQD for all compute queues as well as KIQ for SRIOV case */
|
||||
r = amdgpu_gfx_compute_mqd_sw_init(adev, sizeof(struct vi_mqd_allocation));
|
||||
r = amdgpu_gfx_mqd_sw_init(adev, sizeof(struct vi_mqd_allocation));
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -2069,7 +2069,7 @@ static int gfx_v8_0_sw_fini(void *handle)
|
|||
for (i = 0; i < adev->gfx.num_compute_rings; i++)
|
||||
amdgpu_ring_fini(&adev->gfx.compute_ring[i]);
|
||||
|
||||
amdgpu_gfx_compute_mqd_sw_fini(adev);
|
||||
amdgpu_gfx_mqd_sw_fini(adev);
|
||||
amdgpu_gfx_kiq_free_ring(&adev->gfx.kiq.ring, &adev->gfx.kiq.irq);
|
||||
amdgpu_gfx_kiq_fini(adev);
|
||||
|
||||
|
@ -6217,7 +6217,7 @@ static void gfx_v8_0_pipe_reserve_resources(struct amdgpu_device *adev,
|
|||
struct amdgpu_ring *iring;
|
||||
|
||||
mutex_lock(&adev->gfx.pipe_reserve_mutex);
|
||||
pipe = amdgpu_gfx_queue_to_bit(adev, ring->me, ring->pipe, 0);
|
||||
pipe = amdgpu_gfx_mec_queue_to_bit(adev, ring->me, ring->pipe, 0);
|
||||
if (acquire)
|
||||
set_bit(pipe, adev->gfx.pipe_reserve_bitmap);
|
||||
else
|
||||
|
@ -6236,20 +6236,20 @@ static void gfx_v8_0_pipe_reserve_resources(struct amdgpu_device *adev,
|
|||
/* Lower all pipes without a current reservation */
|
||||
for (i = 0; i < adev->gfx.num_gfx_rings; ++i) {
|
||||
iring = &adev->gfx.gfx_ring[i];
|
||||
pipe = amdgpu_gfx_queue_to_bit(adev,
|
||||
iring->me,
|
||||
iring->pipe,
|
||||
0);
|
||||
pipe = amdgpu_gfx_mec_queue_to_bit(adev,
|
||||
iring->me,
|
||||
iring->pipe,
|
||||
0);
|
||||
reserve = test_bit(pipe, adev->gfx.pipe_reserve_bitmap);
|
||||
gfx_v8_0_ring_set_pipe_percent(iring, reserve);
|
||||
}
|
||||
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; ++i) {
|
||||
iring = &adev->gfx.compute_ring[i];
|
||||
pipe = amdgpu_gfx_queue_to_bit(adev,
|
||||
iring->me,
|
||||
iring->pipe,
|
||||
0);
|
||||
pipe = amdgpu_gfx_mec_queue_to_bit(adev,
|
||||
iring->me,
|
||||
iring->pipe,
|
||||
0);
|
||||
reserve = test_bit(pipe, adev->gfx.pipe_reserve_bitmap);
|
||||
gfx_v8_0_ring_set_pipe_percent(iring, reserve);
|
||||
}
|
||||
|
@ -6537,7 +6537,7 @@ static int gfx_v8_0_set_eop_interrupt_state(struct amdgpu_device *adev,
|
|||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
switch (type) {
|
||||
case AMDGPU_CP_IRQ_GFX_EOP:
|
||||
case AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP:
|
||||
gfx_v8_0_set_gfx_eop_interrupt_state(adev, state);
|
||||
break;
|
||||
case AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP:
|
||||
|
|
|
@ -309,6 +309,7 @@ static int gfx_v9_0_get_cu_info(struct amdgpu_device *adev,
|
|||
static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev);
|
||||
static void gfx_v9_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, u32 sh_num, u32 instance);
|
||||
static void gfx_v9_0_ring_emit_de_meta(struct amdgpu_ring *ring);
|
||||
static u64 gfx_v9_0_ring_get_rptr_compute(struct amdgpu_ring *ring);
|
||||
|
||||
static void gfx_v9_0_init_golden_registers(struct amdgpu_device *adev)
|
||||
{
|
||||
|
@ -1724,7 +1725,7 @@ static int gfx_v9_0_sw_init(void *handle)
|
|||
ring->use_doorbell = true;
|
||||
ring->doorbell_index = adev->doorbell_index.gfx_ring0 << 1;
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP);
|
||||
&adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -1760,7 +1761,7 @@ static int gfx_v9_0_sw_init(void *handle)
|
|||
return r;
|
||||
|
||||
/* create MQD for all compute queues as wel as KIQ for SRIOV case */
|
||||
r = amdgpu_gfx_compute_mqd_sw_init(adev, sizeof(struct v9_mqd_allocation));
|
||||
r = amdgpu_gfx_mqd_sw_init(adev, sizeof(struct v9_mqd_allocation));
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -1802,7 +1803,7 @@ static int gfx_v9_0_sw_fini(void *handle)
|
|||
for (i = 0; i < adev->gfx.num_compute_rings; i++)
|
||||
amdgpu_ring_fini(&adev->gfx.compute_ring[i]);
|
||||
|
||||
amdgpu_gfx_compute_mqd_sw_fini(adev);
|
||||
amdgpu_gfx_mqd_sw_fini(adev);
|
||||
amdgpu_gfx_kiq_free_ring(&adev->gfx.kiq.ring, &adev->gfx.kiq.irq);
|
||||
amdgpu_gfx_kiq_fini(adev);
|
||||
|
||||
|
@ -3600,45 +3601,89 @@ static const struct soc15_reg_entry sgpr_init_regs[] = {
|
|||
};
|
||||
|
||||
static const struct soc15_reg_entry sec_ded_counter_registers[] = {
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCPC_EDC_SCRATCH_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCPC_EDC_UCODE_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCPF_EDC_ROQ_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCPF_EDC_TAG_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCPG_EDC_DMA_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCPG_EDC_TAG_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmDC_EDC_CSINVOC_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmDC_EDC_RESTORE_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmDC_EDC_STATE_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_GRBM_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_DED) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmSPI_EDC_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_DED_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_INFO) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_SEC_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTCP_ATC_EDC_GATCL1_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTD_EDC_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTA_EDC_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PHY_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PIPE_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTCI_EDC_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT2) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTCA_EDC_CNT) },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCPC_EDC_SCRATCH_CNT), 0, 1, 1},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCPC_EDC_UCODE_CNT), 0, 1, 1},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCPF_EDC_ROQ_CNT), 0, 1, 1},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCPF_EDC_TAG_CNT), 0, 1, 1},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCPG_EDC_DMA_CNT), 0, 1, 1},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCPG_EDC_TAG_CNT), 0, 1, 1},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmDC_EDC_CSINVOC_CNT), 0, 1, 1},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmDC_EDC_RESTORE_CNT), 0, 1, 1},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmDC_EDC_STATE_CNT), 0, 1, 1},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_CNT), 0, 1, 1},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_GRBM_CNT), 0, 1, 1},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_DED), 0, 1, 1},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmSPI_EDC_CNT), 0, 4, 1},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT), 0, 4, 6},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_DED_CNT), 0, 4, 16},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_INFO), 0, 4, 16},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_SEC_CNT), 0, 4, 16},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT), 0, 1, 16},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTCP_ATC_EDC_GATCL1_CNT), 0, 4, 16},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT), 0, 4, 16},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTD_EDC_CNT), 0, 4, 16},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2), 0, 4, 6},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT), 0, 4, 16},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTA_EDC_CNT), 0, 4, 16},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PHY_CNT), 0, 1, 1},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PIPE_CNT), 0, 1, 1},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT), 0, 1, 32},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2), 0, 1, 32},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTCI_EDC_CNT), 0, 1, 72},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT2), 0, 1, 16},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTCA_EDC_CNT), 0, 1, 2},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3), 0, 4, 6},
|
||||
};
|
||||
|
||||
static int gfx_v9_0_do_edc_gds_workarounds(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ring *ring = &adev->gfx.compute_ring[0];
|
||||
int i, r;
|
||||
|
||||
r = amdgpu_ring_alloc(ring, 7);
|
||||
if (r) {
|
||||
DRM_ERROR("amdgpu: GDS workarounds failed to lock ring %s (%d).\n",
|
||||
ring->name, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
WREG32_SOC15(GC, 0, mmGDS_VMID0_BASE, 0x00000000);
|
||||
WREG32_SOC15(GC, 0, mmGDS_VMID0_SIZE, adev->gds.gds_size);
|
||||
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_DMA_DATA, 5));
|
||||
amdgpu_ring_write(ring, (PACKET3_DMA_DATA_CP_SYNC |
|
||||
PACKET3_DMA_DATA_DST_SEL(1) |
|
||||
PACKET3_DMA_DATA_SRC_SEL(2) |
|
||||
PACKET3_DMA_DATA_ENGINE(0)));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
amdgpu_ring_write(ring, 0);
|
||||
amdgpu_ring_write(ring, 0);
|
||||
amdgpu_ring_write(ring, 0);
|
||||
amdgpu_ring_write(ring, PACKET3_DMA_DATA_CMD_RAW_WAIT |
|
||||
adev->gds.gds_size);
|
||||
|
||||
amdgpu_ring_commit(ring);
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
if (ring->wptr == gfx_v9_0_ring_get_rptr_compute(ring))
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
if (i >= adev->usec_timeout)
|
||||
r = -ETIMEDOUT;
|
||||
|
||||
WREG32_SOC15(GC, 0, mmGDS_VMID0_SIZE, 0x00000000);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int gfx_v9_0_do_edc_gpr_workarounds(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ring *ring = &adev->gfx.compute_ring[0];
|
||||
struct amdgpu_ib ib;
|
||||
struct dma_fence *f = NULL;
|
||||
int r, i, j;
|
||||
int r, i, j, k;
|
||||
unsigned total_size, vgpr_offset, sgpr_offset;
|
||||
u64 gpu_addr;
|
||||
|
||||
|
@ -3750,19 +3795,13 @@ static int gfx_v9_0_do_edc_gpr_workarounds(struct amdgpu_device *adev)
|
|||
|
||||
/* read back registers to clear the counters */
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
for (j = 0; j < 16; j++) {
|
||||
gfx_v9_0_select_se_sh(adev, 0x01, 0x0, j);
|
||||
for (i = 0; i < ARRAY_SIZE(sec_ded_counter_registers); i++)
|
||||
RREG32(SOC15_REG_ENTRY_OFFSET(sec_ded_counter_registers[i]));
|
||||
gfx_v9_0_select_se_sh(adev, 0x02, 0x0, j);
|
||||
for (i = 0; i < ARRAY_SIZE(sec_ded_counter_registers); i++)
|
||||
RREG32(SOC15_REG_ENTRY_OFFSET(sec_ded_counter_registers[i]));
|
||||
gfx_v9_0_select_se_sh(adev, 0x03, 0x0, j);
|
||||
for (i = 0; i < ARRAY_SIZE(sec_ded_counter_registers); i++)
|
||||
RREG32(SOC15_REG_ENTRY_OFFSET(sec_ded_counter_registers[i]));
|
||||
gfx_v9_0_select_se_sh(adev, 0x04, 0x0, j);
|
||||
for (i = 0; i < ARRAY_SIZE(sec_ded_counter_registers); i++)
|
||||
RREG32(SOC15_REG_ENTRY_OFFSET(sec_ded_counter_registers[i]));
|
||||
for (i = 0; i < ARRAY_SIZE(sec_ded_counter_registers); i++) {
|
||||
for (j = 0; j < sec_ded_counter_registers[i].se_num; j++) {
|
||||
for (k = 0; k < sec_ded_counter_registers[i].instance; k++) {
|
||||
gfx_v9_0_select_se_sh(adev, j, 0x0, k);
|
||||
RREG32(SOC15_REG_ENTRY_OFFSET(sec_ded_counter_registers[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, 0xe0000000);
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
@ -3815,6 +3854,10 @@ static int gfx_v9_0_ecc_late_init(void *handle)
|
|||
return 0;
|
||||
}
|
||||
|
||||
r = gfx_v9_0_do_edc_gds_workarounds(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* requires IBs so do in late init after IB pool is initialized */
|
||||
r = gfx_v9_0_do_edc_gpr_workarounds(adev);
|
||||
if (r)
|
||||
|
@ -3864,9 +3907,7 @@ static int gfx_v9_0_ecc_late_init(void *handle)
|
|||
if (r)
|
||||
goto interrupt;
|
||||
|
||||
r = amdgpu_ras_debugfs_create(adev, &fs_info);
|
||||
if (r)
|
||||
goto debugfs;
|
||||
amdgpu_ras_debugfs_create(adev, &fs_info);
|
||||
|
||||
r = amdgpu_ras_sysfs_create(adev, &fs_info);
|
||||
if (r)
|
||||
|
@ -3881,7 +3922,6 @@ irq:
|
|||
amdgpu_ras_sysfs_remove(adev, *ras_if);
|
||||
sysfs:
|
||||
amdgpu_ras_debugfs_remove(adev, *ras_if);
|
||||
debugfs:
|
||||
amdgpu_ras_interrupt_remove_handler(adev, &ih_info);
|
||||
interrupt:
|
||||
amdgpu_ras_feature_enable(adev, *ras_if, 0);
|
||||
|
@ -4542,7 +4582,7 @@ static void gfx_v9_0_pipe_reserve_resources(struct amdgpu_device *adev,
|
|||
struct amdgpu_ring *iring;
|
||||
|
||||
mutex_lock(&adev->gfx.pipe_reserve_mutex);
|
||||
pipe = amdgpu_gfx_queue_to_bit(adev, ring->me, ring->pipe, 0);
|
||||
pipe = amdgpu_gfx_mec_queue_to_bit(adev, ring->me, ring->pipe, 0);
|
||||
if (acquire)
|
||||
set_bit(pipe, adev->gfx.pipe_reserve_bitmap);
|
||||
else
|
||||
|
@ -4561,20 +4601,20 @@ static void gfx_v9_0_pipe_reserve_resources(struct amdgpu_device *adev,
|
|||
/* Lower all pipes without a current reservation */
|
||||
for (i = 0; i < adev->gfx.num_gfx_rings; ++i) {
|
||||
iring = &adev->gfx.gfx_ring[i];
|
||||
pipe = amdgpu_gfx_queue_to_bit(adev,
|
||||
iring->me,
|
||||
iring->pipe,
|
||||
0);
|
||||
pipe = amdgpu_gfx_mec_queue_to_bit(adev,
|
||||
iring->me,
|
||||
iring->pipe,
|
||||
0);
|
||||
reserve = test_bit(pipe, adev->gfx.pipe_reserve_bitmap);
|
||||
gfx_v9_0_ring_set_pipe_percent(iring, reserve);
|
||||
}
|
||||
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; ++i) {
|
||||
iring = &adev->gfx.compute_ring[i];
|
||||
pipe = amdgpu_gfx_queue_to_bit(adev,
|
||||
iring->me,
|
||||
iring->pipe,
|
||||
0);
|
||||
pipe = amdgpu_gfx_mec_queue_to_bit(adev,
|
||||
iring->me,
|
||||
iring->pipe,
|
||||
0);
|
||||
reserve = test_bit(pipe, adev->gfx.pipe_reserve_bitmap);
|
||||
gfx_v9_0_ring_set_pipe_percent(iring, reserve);
|
||||
}
|
||||
|
@ -4989,7 +5029,7 @@ static int gfx_v9_0_set_eop_interrupt_state(struct amdgpu_device *adev,
|
|||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
switch (type) {
|
||||
case AMDGPU_CP_IRQ_GFX_EOP:
|
||||
case AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP:
|
||||
gfx_v9_0_set_gfx_eop_interrupt_state(adev, state);
|
||||
break;
|
||||
case AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP:
|
||||
|
|
|
@ -0,0 +1,353 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "gfxhub_v2_0.h"
|
||||
|
||||
#include "gc/gc_10_1_0_offset.h"
|
||||
#include "gc/gc_10_1_0_sh_mask.h"
|
||||
#include "gc/gc_10_1_0_default.h"
|
||||
#include "navi10_enum.h"
|
||||
|
||||
#include "soc15_common.h"
|
||||
|
||||
u64 gfxhub_v2_0_get_fb_location(struct amdgpu_device *adev)
|
||||
{
|
||||
u64 base = RREG32_SOC15(GC, 0, mmGCMC_VM_FB_LOCATION_BASE);
|
||||
|
||||
base &= GCMC_VM_FB_LOCATION_BASE__FB_BASE_MASK;
|
||||
base <<= 24;
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
u64 gfxhub_v2_0_get_mc_fb_offset(struct amdgpu_device *adev)
|
||||
{
|
||||
return (u64)RREG32_SOC15(GC, 0, mmGCMC_VM_FB_OFFSET) << 24;
|
||||
}
|
||||
|
||||
static void gfxhub_v2_0_init_gart_pt_regs(struct amdgpu_device *adev)
|
||||
{
|
||||
uint64_t value = amdgpu_gmc_pd_addr(adev->gart.bo);
|
||||
|
||||
|
||||
WREG32_SOC15(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
|
||||
lower_32_bits(value));
|
||||
|
||||
WREG32_SOC15(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
|
||||
upper_32_bits(value));
|
||||
}
|
||||
|
||||
static void gfxhub_v2_0_init_gart_aperture_regs(struct amdgpu_device *adev)
|
||||
{
|
||||
gfxhub_v2_0_init_gart_pt_regs(adev);
|
||||
|
||||
WREG32_SOC15(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
|
||||
(u32)(adev->gmc.gart_start >> 12));
|
||||
WREG32_SOC15(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
|
||||
(u32)(adev->gmc.gart_start >> 44));
|
||||
|
||||
WREG32_SOC15(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
|
||||
(u32)(adev->gmc.gart_end >> 12));
|
||||
WREG32_SOC15(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
|
||||
(u32)(adev->gmc.gart_end >> 44));
|
||||
}
|
||||
|
||||
static void gfxhub_v2_0_init_system_aperture_regs(struct amdgpu_device *adev)
|
||||
{
|
||||
uint64_t value;
|
||||
|
||||
/* Disable AGP. */
|
||||
WREG32_SOC15(GC, 0, mmGCMC_VM_AGP_BASE, 0);
|
||||
WREG32_SOC15(GC, 0, mmGCMC_VM_AGP_TOP, 0);
|
||||
WREG32_SOC15(GC, 0, mmGCMC_VM_AGP_BOT, 0x00FFFFFF);
|
||||
|
||||
/* Program the system aperture low logical page number. */
|
||||
WREG32_SOC15(GC, 0, mmGCMC_VM_SYSTEM_APERTURE_LOW_ADDR,
|
||||
adev->gmc.vram_start >> 18);
|
||||
WREG32_SOC15(GC, 0, mmGCMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
|
||||
adev->gmc.vram_end >> 18);
|
||||
|
||||
/* Set default page address. */
|
||||
value = adev->vram_scratch.gpu_addr - adev->gmc.vram_start
|
||||
+ adev->vm_manager.vram_base_offset;
|
||||
WREG32_SOC15(GC, 0, mmGCMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
|
||||
(u32)(value >> 12));
|
||||
WREG32_SOC15(GC, 0, mmGCMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
|
||||
(u32)(value >> 44));
|
||||
|
||||
/* Program "protection fault". */
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
|
||||
(u32)(adev->dummy_page_addr >> 12));
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
|
||||
(u32)((u64)adev->dummy_page_addr >> 44));
|
||||
|
||||
WREG32_FIELD15(GC, 0, GCVM_L2_PROTECTION_FAULT_CNTL2,
|
||||
ACTIVE_PAGE_MIGRATION_PTE_READ_RETRY, 1);
|
||||
}
|
||||
|
||||
|
||||
static void gfxhub_v2_0_init_tlb_regs(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
/* Setup TLB control */
|
||||
tmp = RREG32_SOC15(GC, 0, mmGCMC_VM_MX_L1_TLB_CNTL);
|
||||
|
||||
tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, 3);
|
||||
tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL,
|
||||
ENABLE_ADVANCED_DRIVER_MODEL, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL,
|
||||
SYSTEM_APERTURE_UNMAPPED_ACCESS, 0);
|
||||
tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0);
|
||||
tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL,
|
||||
MTYPE, MTYPE_UC); /* UC, uncached */
|
||||
|
||||
WREG32_SOC15(GC, 0, mmGCMC_VM_MX_L1_TLB_CNTL, tmp);
|
||||
}
|
||||
|
||||
static void gfxhub_v2_0_init_cache_regs(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
/* Setup L2 cache */
|
||||
tmp = RREG32_SOC15(GC, 0, mmGCVM_L2_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, ENABLE_L2_CACHE, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING, 0);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL,
|
||||
ENABLE_DEFAULT_PAGE_OUT_TO_SYSTEM_MEMORY, 1);
|
||||
/* XXX for emulation, Refer to closed source code.*/
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL,
|
||||
L2_PDE0_CACHE_TAG_GENERATION_MODE, 0);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, PDE_FAULT_CLASSIFICATION, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, CONTEXT1_IDENTITY_ACCESS_MODE, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, IDENTITY_MODE_FRAGMENT_SIZE, 0);
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_CNTL, tmp);
|
||||
|
||||
tmp = RREG32_SOC15(GC, 0, mmGCVM_L2_CNTL2);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL2, INVALIDATE_L2_CACHE, 1);
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_CNTL2, tmp);
|
||||
|
||||
tmp = mmGCVM_L2_CNTL3_DEFAULT;
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_CNTL3, tmp);
|
||||
|
||||
tmp = mmGCVM_L2_CNTL4_DEFAULT;
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL4, VMC_TAP_PDE_REQUEST_PHYSICAL, 0);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL4, VMC_TAP_PTE_REQUEST_PHYSICAL, 0);
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_CNTL4, tmp);
|
||||
}
|
||||
|
||||
static void gfxhub_v2_0_enable_system_domain(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = RREG32_SOC15(GC, 0, mmGCVM_CONTEXT0_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT0_CNTL, ENABLE_CONTEXT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT0_CNTL, PAGE_TABLE_DEPTH, 0);
|
||||
WREG32_SOC15(GC, 0, mmGCVM_CONTEXT0_CNTL, tmp);
|
||||
}
|
||||
|
||||
static void gfxhub_v2_0_disable_identity_aperture(struct amdgpu_device *adev)
|
||||
{
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_LO32,
|
||||
0xFFFFFFFF);
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_HI32,
|
||||
0x0000000F);
|
||||
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_LO32,
|
||||
0);
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_HI32,
|
||||
0);
|
||||
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_LO32, 0);
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_HI32, 0);
|
||||
|
||||
}
|
||||
|
||||
static void gfxhub_v2_0_setup_vmid_config(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
uint32_t tmp;
|
||||
|
||||
for (i = 0; i <= 14; i++) {
|
||||
tmp = RREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT1_CNTL, i);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
|
||||
adev->vm_manager.num_level);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
|
||||
RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
|
||||
DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
|
||||
PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
|
||||
VALID_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
|
||||
READ_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
|
||||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
|
||||
PAGE_TABLE_BLOCK_SIZE,
|
||||
adev->vm_manager.block_size - 9);
|
||||
/* Send no-retry XNACK on fault to suppress VM fault storm. */
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
|
||||
RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0);
|
||||
WREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT1_CNTL, i, tmp);
|
||||
WREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32, i*2, 0);
|
||||
WREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT1_PAGE_TABLE_START_ADDR_HI32, i*2, 0);
|
||||
WREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT1_PAGE_TABLE_END_ADDR_LO32, i*2,
|
||||
lower_32_bits(adev->vm_manager.max_pfn - 1));
|
||||
WREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT1_PAGE_TABLE_END_ADDR_HI32, i*2,
|
||||
upper_32_bits(adev->vm_manager.max_pfn - 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void gfxhub_v2_0_program_invalidation(struct amdgpu_device *adev)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0 ; i < 18; ++i) {
|
||||
WREG32_SOC15_OFFSET(GC, 0, mmGCVM_INVALIDATE_ENG0_ADDR_RANGE_LO32,
|
||||
2 * i, 0xffffffff);
|
||||
WREG32_SOC15_OFFSET(GC, 0, mmGCVM_INVALIDATE_ENG0_ADDR_RANGE_HI32,
|
||||
2 * i, 0x1f);
|
||||
}
|
||||
}
|
||||
|
||||
int gfxhub_v2_0_gart_enable(struct amdgpu_device *adev)
|
||||
{
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
/*
|
||||
* GCMC_VM_FB_LOCATION_BASE/TOP is NULL for VF, becuase they are
|
||||
* VF copy registers so vbios post doesn't program them, for
|
||||
* SRIOV driver need to program them
|
||||
*/
|
||||
WREG32_SOC15(GC, 0, mmGCMC_VM_FB_LOCATION_BASE,
|
||||
adev->gmc.vram_start >> 24);
|
||||
WREG32_SOC15(GC, 0, mmGCMC_VM_FB_LOCATION_TOP,
|
||||
adev->gmc.vram_end >> 24);
|
||||
}
|
||||
|
||||
/* GART Enable. */
|
||||
gfxhub_v2_0_init_gart_aperture_regs(adev);
|
||||
gfxhub_v2_0_init_system_aperture_regs(adev);
|
||||
gfxhub_v2_0_init_tlb_regs(adev);
|
||||
gfxhub_v2_0_init_cache_regs(adev);
|
||||
|
||||
gfxhub_v2_0_enable_system_domain(adev);
|
||||
gfxhub_v2_0_disable_identity_aperture(adev);
|
||||
gfxhub_v2_0_setup_vmid_config(adev);
|
||||
gfxhub_v2_0_program_invalidation(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gfxhub_v2_0_gart_disable(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 tmp;
|
||||
u32 i;
|
||||
|
||||
/* Disable all tables */
|
||||
for (i = 0; i < 16; i++)
|
||||
WREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT0_CNTL, i, 0);
|
||||
|
||||
/* Setup TLB control */
|
||||
tmp = RREG32_SOC15(GC, 0, mmGCMC_VM_MX_L1_TLB_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 0);
|
||||
tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL,
|
||||
ENABLE_ADVANCED_DRIVER_MODEL, 0);
|
||||
WREG32_SOC15(GC, 0, mmGCMC_VM_MX_L1_TLB_CNTL, tmp);
|
||||
|
||||
/* Setup L2 cache */
|
||||
WREG32_FIELD15(GC, 0, GCVM_L2_CNTL, ENABLE_L2_CACHE, 0);
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_CNTL3, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* gfxhub_v2_0_set_fault_enable_default - update GART/VM fault handling
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @value: true redirects VM faults to the default page
|
||||
*/
|
||||
void gfxhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev,
|
||||
bool value)
|
||||
{
|
||||
u32 tmp;
|
||||
tmp = RREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
PDE1_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
PDE2_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
TRANSLATE_FURTHER_PROTECTION_FAULT_ENABLE_DEFAULT,
|
||||
value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
NACK_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
VALID_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
READ_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
|
||||
void gfxhub_v2_0_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB];
|
||||
|
||||
hub->ctx0_ptb_addr_lo32 =
|
||||
SOC15_REG_OFFSET(GC, 0,
|
||||
mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32);
|
||||
hub->ctx0_ptb_addr_hi32 =
|
||||
SOC15_REG_OFFSET(GC, 0,
|
||||
mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
|
||||
hub->vm_inv_eng0_req =
|
||||
SOC15_REG_OFFSET(GC, 0, mmGCVM_INVALIDATE_ENG0_REQ);
|
||||
hub->vm_inv_eng0_ack =
|
||||
SOC15_REG_OFFSET(GC, 0, mmGCVM_INVALIDATE_ENG0_ACK);
|
||||
hub->vm_context0_cntl =
|
||||
SOC15_REG_OFFSET(GC, 0, mmGCVM_CONTEXT0_CNTL);
|
||||
hub->vm_l2_pro_fault_status =
|
||||
SOC15_REG_OFFSET(GC, 0, mmGCVM_L2_PROTECTION_FAULT_STATUS);
|
||||
hub->vm_l2_pro_fault_cntl =
|
||||
SOC15_REG_OFFSET(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __GFXHUB_V2_0_H__
|
||||
#define __GFXHUB_V2_0_H__
|
||||
|
||||
u64 gfxhub_v2_0_get_fb_location(struct amdgpu_device *adev);
|
||||
int gfxhub_v2_0_gart_enable(struct amdgpu_device *adev);
|
||||
void gfxhub_v2_0_gart_disable(struct amdgpu_device *adev);
|
||||
void gfxhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev,
|
||||
bool value);
|
||||
void gfxhub_v2_0_init(struct amdgpu_device *adev);
|
||||
u64 gfxhub_v2_0_get_mc_fb_offset(struct amdgpu_device *adev);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,917 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/pci.h>
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_atomfirmware.h"
|
||||
#include "gmc_v10_0.h"
|
||||
|
||||
#include "hdp/hdp_5_0_0_offset.h"
|
||||
#include "hdp/hdp_5_0_0_sh_mask.h"
|
||||
#include "gc/gc_10_1_0_sh_mask.h"
|
||||
#include "mmhub/mmhub_2_0_0_sh_mask.h"
|
||||
#include "dcn/dcn_2_0_0_offset.h"
|
||||
#include "dcn/dcn_2_0_0_sh_mask.h"
|
||||
#include "oss/osssys_5_0_0_offset.h"
|
||||
#include "ivsrcid/vmc/irqsrcs_vmc_1_0.h"
|
||||
#include "navi10_enum.h"
|
||||
|
||||
#include "soc15.h"
|
||||
#include "soc15_common.h"
|
||||
|
||||
#include "nbio_v2_3.h"
|
||||
|
||||
#include "gfxhub_v2_0.h"
|
||||
#include "mmhub_v2_0.h"
|
||||
#include "athub_v2_0.h"
|
||||
/* XXX Move this macro to navi10 header file, which is like vid.h for VI.*/
|
||||
#define AMDGPU_NUM_OF_VMIDS 8
|
||||
|
||||
#if 0
|
||||
static const struct soc15_reg_golden golden_settings_navi10_hdp[] =
|
||||
{
|
||||
/* TODO add golden setting for hdp */
|
||||
};
|
||||
#endif
|
||||
|
||||
static int
|
||||
gmc_v10_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *src, unsigned type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
struct amdgpu_vmhub *hub;
|
||||
u32 tmp, reg, bits[AMDGPU_MAX_VMHUBS], i;
|
||||
|
||||
bits[AMDGPU_GFXHUB] = GCVM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
|
||||
GCVM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
|
||||
GCVM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
|
||||
GCVM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
|
||||
GCVM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
|
||||
GCVM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
|
||||
GCVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK;
|
||||
|
||||
bits[AMDGPU_MMHUB] = MMVM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
|
||||
MMVM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
|
||||
MMVM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
|
||||
MMVM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
|
||||
MMVM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
|
||||
MMVM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
|
||||
MMVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK;
|
||||
|
||||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
/* MM HUB */
|
||||
hub = &adev->vmhub[AMDGPU_MMHUB];
|
||||
for (i = 0; i < 16; i++) {
|
||||
reg = hub->vm_context0_cntl + i;
|
||||
tmp = RREG32(reg);
|
||||
tmp &= ~bits[AMDGPU_MMHUB];
|
||||
WREG32(reg, tmp);
|
||||
}
|
||||
|
||||
/* GFX HUB */
|
||||
hub = &adev->vmhub[AMDGPU_GFXHUB];
|
||||
for (i = 0; i < 16; i++) {
|
||||
reg = hub->vm_context0_cntl + i;
|
||||
tmp = RREG32(reg);
|
||||
tmp &= ~bits[AMDGPU_GFXHUB];
|
||||
WREG32(reg, tmp);
|
||||
}
|
||||
break;
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
/* MM HUB */
|
||||
hub = &adev->vmhub[AMDGPU_MMHUB];
|
||||
for (i = 0; i < 16; i++) {
|
||||
reg = hub->vm_context0_cntl + i;
|
||||
tmp = RREG32(reg);
|
||||
tmp |= bits[AMDGPU_MMHUB];
|
||||
WREG32(reg, tmp);
|
||||
}
|
||||
|
||||
/* GFX HUB */
|
||||
hub = &adev->vmhub[AMDGPU_GFXHUB];
|
||||
for (i = 0; i < 16; i++) {
|
||||
reg = hub->vm_context0_cntl + i;
|
||||
tmp = RREG32(reg);
|
||||
tmp |= bits[AMDGPU_GFXHUB];
|
||||
WREG32(reg, tmp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gmc_v10_0_process_interrupt(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
struct amdgpu_vmhub *hub = &adev->vmhub[entry->vmid_src];
|
||||
uint32_t status = 0;
|
||||
u64 addr;
|
||||
|
||||
addr = (u64)entry->src_data[0] << 12;
|
||||
addr |= ((u64)entry->src_data[1] & 0xf) << 44;
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
status = RREG32(hub->vm_l2_pro_fault_status);
|
||||
WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1);
|
||||
}
|
||||
|
||||
if (printk_ratelimit()) {
|
||||
dev_err(adev->dev,
|
||||
"[%s] VMC page fault (src_id:%u ring:%u vmid:%u pasid:%u)\n",
|
||||
entry->vmid_src ? "mmhub" : "gfxhub",
|
||||
entry->src_id, entry->ring_id, entry->vmid,
|
||||
entry->pasid);
|
||||
dev_err(adev->dev, " at page 0x%016llx from %d\n",
|
||||
addr, entry->client_id);
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
dev_err(adev->dev,
|
||||
"VM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
|
||||
status);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct amdgpu_irq_src_funcs gmc_v10_0_irq_funcs = {
|
||||
.set = gmc_v10_0_vm_fault_interrupt_state,
|
||||
.process = gmc_v10_0_process_interrupt,
|
||||
};
|
||||
|
||||
static void gmc_v10_0_set_irq_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->gmc.vm_fault.num_types = 1;
|
||||
adev->gmc.vm_fault.funcs = &gmc_v10_0_irq_funcs;
|
||||
}
|
||||
|
||||
static uint32_t gmc_v10_0_get_invalidate_req(unsigned int vmid,
|
||||
uint32_t flush_type)
|
||||
{
|
||||
u32 req = 0;
|
||||
|
||||
/* invalidate using legacy mode on vmid*/
|
||||
req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ,
|
||||
PER_VMID_INVALIDATE_REQ, 1 << vmid);
|
||||
req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, FLUSH_TYPE, flush_type);
|
||||
req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PTES, 1);
|
||||
req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE0, 1);
|
||||
req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE1, 1);
|
||||
req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE2, 1);
|
||||
req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L1_PTES, 1);
|
||||
req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ,
|
||||
CLEAR_PROTECTION_FAULT_STATUS_ADDR, 0);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
/*
|
||||
* GART
|
||||
* VMID 0 is the physical GPU addresses as used by the kernel.
|
||||
* VMIDs 1-15 are used for userspace clients and are handled
|
||||
* by the amdgpu vm/hsa code.
|
||||
*/
|
||||
|
||||
static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
|
||||
unsigned int vmhub, uint32_t flush_type)
|
||||
{
|
||||
struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
|
||||
u32 tmp = gmc_v10_0_get_invalidate_req(vmid, flush_type);
|
||||
/* Use register 17 for GART */
|
||||
const unsigned eng = 17;
|
||||
unsigned int i;
|
||||
|
||||
WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp);
|
||||
|
||||
/* Wait for ACK with a delay.*/
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_ack + eng);
|
||||
tmp &= 1 << vmid;
|
||||
if (tmp)
|
||||
break;
|
||||
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
if (i < adev->usec_timeout)
|
||||
return;
|
||||
|
||||
DRM_ERROR("Timeout waiting for VM flush ACK!\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* gmc_v10_0_flush_gpu_tlb - gart tlb flush callback
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @vmid: vm instance to flush
|
||||
*
|
||||
* Flush the TLB for the requested page table.
|
||||
*/
|
||||
static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint32_t flush_type)
|
||||
{
|
||||
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
|
||||
struct dma_fence *fence;
|
||||
struct amdgpu_job *job;
|
||||
|
||||
int r;
|
||||
|
||||
/* flush hdp cache */
|
||||
adev->nbio_funcs->hdp_flush(adev, NULL);
|
||||
|
||||
mutex_lock(&adev->mman.gtt_window_lock);
|
||||
|
||||
gmc_v10_0_flush_vm_hub(adev, vmid, AMDGPU_MMHUB, 0);
|
||||
if (!adev->mman.buffer_funcs_enabled || !adev->ib_pool_ready ||
|
||||
adev->asic_type != CHIP_NAVI10) {
|
||||
gmc_v10_0_flush_vm_hub(adev, vmid, AMDGPU_GFXHUB, 0);
|
||||
mutex_unlock(&adev->mman.gtt_window_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* The SDMA on Navi has a bug which can theoretically result in memory
|
||||
* corruption if an invalidation happens at the same time as an VA
|
||||
* translation. Avoid this by doing the invalidation from the SDMA
|
||||
* itself.
|
||||
*/
|
||||
r = amdgpu_job_alloc_with_ib(adev, 16 * 4, &job);
|
||||
if (r)
|
||||
goto error_alloc;
|
||||
|
||||
job->vm_pd_addr = amdgpu_gmc_pd_addr(adev->gart.bo);
|
||||
job->vm_needs_flush = true;
|
||||
amdgpu_ring_pad_ib(ring, &job->ibs[0]);
|
||||
r = amdgpu_job_submit(job, &adev->mman.entity,
|
||||
AMDGPU_FENCE_OWNER_UNDEFINED, &fence);
|
||||
if (r)
|
||||
goto error_submit;
|
||||
|
||||
mutex_unlock(&adev->mman.gtt_window_lock);
|
||||
|
||||
dma_fence_wait(fence, false);
|
||||
dma_fence_put(fence);
|
||||
|
||||
return;
|
||||
|
||||
error_submit:
|
||||
amdgpu_job_free(job);
|
||||
|
||||
error_alloc:
|
||||
mutex_unlock(&adev->mman.gtt_window_lock);
|
||||
DRM_ERROR("Error flushing GPU TLB using the SDMA (%d)!\n", r);
|
||||
}
|
||||
|
||||
static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
|
||||
unsigned vmid, uint64_t pd_addr)
|
||||
{
|
||||
struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub];
|
||||
uint32_t req = gmc_v10_0_get_invalidate_req(vmid, 0);
|
||||
unsigned eng = ring->vm_inv_eng;
|
||||
|
||||
amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 + (2 * vmid),
|
||||
lower_32_bits(pd_addr));
|
||||
|
||||
amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_hi32 + (2 * vmid),
|
||||
upper_32_bits(pd_addr));
|
||||
|
||||
amdgpu_ring_emit_wreg(ring, hub->vm_inv_eng0_req + eng, req);
|
||||
|
||||
/* wait for the invalidate to complete */
|
||||
amdgpu_ring_emit_reg_wait(ring, hub->vm_inv_eng0_ack + eng,
|
||||
1 << vmid, 1 << vmid);
|
||||
|
||||
return pd_addr;
|
||||
}
|
||||
|
||||
static void gmc_v10_0_emit_pasid_mapping(struct amdgpu_ring *ring, unsigned vmid,
|
||||
unsigned pasid)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
uint32_t reg;
|
||||
|
||||
if (ring->funcs->vmhub == AMDGPU_GFXHUB)
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_VMID_0_LUT) + vmid;
|
||||
else
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_VMID_0_LUT_MM) + vmid;
|
||||
|
||||
amdgpu_ring_emit_wreg(ring, reg, pasid);
|
||||
}
|
||||
|
||||
/*
|
||||
* PTE format on NAVI 10:
|
||||
* 63:59 reserved
|
||||
* 58:57 reserved
|
||||
* 56 F
|
||||
* 55 L
|
||||
* 54 reserved
|
||||
* 53:52 SW
|
||||
* 51 T
|
||||
* 50:48 mtype
|
||||
* 47:12 4k physical page base address
|
||||
* 11:7 fragment
|
||||
* 6 write
|
||||
* 5 read
|
||||
* 4 exe
|
||||
* 3 Z
|
||||
* 2 snooped
|
||||
* 1 system
|
||||
* 0 valid
|
||||
*
|
||||
* PDE format on NAVI 10:
|
||||
* 63:59 block fragment size
|
||||
* 58:55 reserved
|
||||
* 54 P
|
||||
* 53:48 reserved
|
||||
* 47:6 physical base address of PD or PTE
|
||||
* 5:3 reserved
|
||||
* 2 C
|
||||
* 1 system
|
||||
* 0 valid
|
||||
*/
|
||||
static uint64_t gmc_v10_0_get_vm_pte_flags(struct amdgpu_device *adev,
|
||||
uint32_t flags)
|
||||
{
|
||||
uint64_t pte_flag = 0;
|
||||
|
||||
if (flags & AMDGPU_VM_PAGE_EXECUTABLE)
|
||||
pte_flag |= AMDGPU_PTE_EXECUTABLE;
|
||||
if (flags & AMDGPU_VM_PAGE_READABLE)
|
||||
pte_flag |= AMDGPU_PTE_READABLE;
|
||||
if (flags & AMDGPU_VM_PAGE_WRITEABLE)
|
||||
pte_flag |= AMDGPU_PTE_WRITEABLE;
|
||||
|
||||
switch (flags & AMDGPU_VM_MTYPE_MASK) {
|
||||
case AMDGPU_VM_MTYPE_DEFAULT:
|
||||
pte_flag |= AMDGPU_PTE_MTYPE_NV10(MTYPE_NC);
|
||||
break;
|
||||
case AMDGPU_VM_MTYPE_NC:
|
||||
pte_flag |= AMDGPU_PTE_MTYPE_NV10(MTYPE_NC);
|
||||
break;
|
||||
case AMDGPU_VM_MTYPE_WC:
|
||||
pte_flag |= AMDGPU_PTE_MTYPE_NV10(MTYPE_WC);
|
||||
break;
|
||||
case AMDGPU_VM_MTYPE_CC:
|
||||
pte_flag |= AMDGPU_PTE_MTYPE_NV10(MTYPE_CC);
|
||||
break;
|
||||
case AMDGPU_VM_MTYPE_UC:
|
||||
pte_flag |= AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
|
||||
break;
|
||||
default:
|
||||
pte_flag |= AMDGPU_PTE_MTYPE_NV10(MTYPE_NC);
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags & AMDGPU_VM_PAGE_PRT)
|
||||
pte_flag |= AMDGPU_PTE_PRT;
|
||||
|
||||
return pte_flag;
|
||||
}
|
||||
|
||||
static void gmc_v10_0_get_vm_pde(struct amdgpu_device *adev, int level,
|
||||
uint64_t *addr, uint64_t *flags)
|
||||
{
|
||||
if (!(*flags & AMDGPU_PDE_PTE) && !(*flags & AMDGPU_PTE_SYSTEM))
|
||||
*addr = adev->vm_manager.vram_base_offset + *addr -
|
||||
adev->gmc.vram_start;
|
||||
BUG_ON(*addr & 0xFFFF00000000003FULL);
|
||||
|
||||
if (!adev->gmc.translate_further)
|
||||
return;
|
||||
|
||||
if (level == AMDGPU_VM_PDB1) {
|
||||
/* Set the block fragment size */
|
||||
if (!(*flags & AMDGPU_PDE_PTE))
|
||||
*flags |= AMDGPU_PDE_BFS(0x9);
|
||||
|
||||
} else if (level == AMDGPU_VM_PDB0) {
|
||||
if (*flags & AMDGPU_PDE_PTE)
|
||||
*flags &= ~AMDGPU_PDE_PTE;
|
||||
else
|
||||
*flags |= AMDGPU_PTE_TF;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct amdgpu_gmc_funcs gmc_v10_0_gmc_funcs = {
|
||||
.flush_gpu_tlb = gmc_v10_0_flush_gpu_tlb,
|
||||
.emit_flush_gpu_tlb = gmc_v10_0_emit_flush_gpu_tlb,
|
||||
.emit_pasid_mapping = gmc_v10_0_emit_pasid_mapping,
|
||||
.get_vm_pte_flags = gmc_v10_0_get_vm_pte_flags,
|
||||
.get_vm_pde = gmc_v10_0_get_vm_pde
|
||||
};
|
||||
|
||||
static void gmc_v10_0_set_gmc_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->gmc.gmc_funcs == NULL)
|
||||
adev->gmc.gmc_funcs = &gmc_v10_0_gmc_funcs;
|
||||
}
|
||||
|
||||
static int gmc_v10_0_early_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
gmc_v10_0_set_gmc_funcs(adev);
|
||||
gmc_v10_0_set_irq_funcs(adev);
|
||||
|
||||
adev->gmc.shared_aperture_start = 0x2000000000000000ULL;
|
||||
adev->gmc.shared_aperture_end =
|
||||
adev->gmc.shared_aperture_start + (4ULL << 30) - 1;
|
||||
adev->gmc.private_aperture_start = 0x1000000000000000ULL;
|
||||
adev->gmc.private_aperture_end =
|
||||
adev->gmc.private_aperture_start + (4ULL << 30) - 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gmc_v10_0_late_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
unsigned vm_inv_eng[AMDGPU_MAX_VMHUBS] = { 4, 4 };
|
||||
unsigned i;
|
||||
|
||||
for(i = 0; i < adev->num_rings; ++i) {
|
||||
struct amdgpu_ring *ring = adev->rings[i];
|
||||
unsigned vmhub = ring->funcs->vmhub;
|
||||
|
||||
ring->vm_inv_eng = vm_inv_eng[vmhub]++;
|
||||
dev_info(adev->dev, "ring %u(%s) uses VM inv eng %u on hub %u\n",
|
||||
ring->idx, ring->name, ring->vm_inv_eng,
|
||||
ring->funcs->vmhub);
|
||||
}
|
||||
|
||||
/* Engine 17 is used for GART flushes */
|
||||
for(i = 0; i < AMDGPU_MAX_VMHUBS; ++i)
|
||||
BUG_ON(vm_inv_eng[i] > 17);
|
||||
|
||||
return amdgpu_irq_get(adev, &adev->gmc.vm_fault, 0);
|
||||
}
|
||||
|
||||
static void gmc_v10_0_vram_gtt_location(struct amdgpu_device *adev,
|
||||
struct amdgpu_gmc *mc)
|
||||
{
|
||||
u64 base = 0;
|
||||
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
base = gfxhub_v2_0_get_fb_location(adev);
|
||||
|
||||
amdgpu_gmc_vram_location(adev, &adev->gmc, base);
|
||||
amdgpu_gmc_gart_location(adev, mc);
|
||||
|
||||
/* base offset of vram pages */
|
||||
adev->vm_manager.vram_base_offset = gfxhub_v2_0_get_mc_fb_offset(adev);
|
||||
}
|
||||
|
||||
/**
|
||||
* gmc_v10_0_mc_init - initialize the memory controller driver params
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Look up the amount of vram, vram width, and decide how to place
|
||||
* vram and gart within the GPU's physical address space.
|
||||
* Returns 0 for success.
|
||||
*/
|
||||
static int gmc_v10_0_mc_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int chansize, numchan;
|
||||
|
||||
if (!amdgpu_emu_mode)
|
||||
adev->gmc.vram_width = amdgpu_atomfirmware_get_vram_width(adev);
|
||||
else {
|
||||
/* hard code vram_width for emulation */
|
||||
chansize = 128;
|
||||
numchan = 1;
|
||||
adev->gmc.vram_width = numchan * chansize;
|
||||
}
|
||||
|
||||
/* Could aper size report 0 ? */
|
||||
adev->gmc.aper_base = pci_resource_start(adev->pdev, 0);
|
||||
adev->gmc.aper_size = pci_resource_len(adev->pdev, 0);
|
||||
|
||||
/* size in MB on si */
|
||||
adev->gmc.mc_vram_size =
|
||||
adev->nbio_funcs->get_memsize(adev) * 1024ULL * 1024ULL;
|
||||
adev->gmc.real_vram_size = adev->gmc.mc_vram_size;
|
||||
adev->gmc.visible_vram_size = adev->gmc.aper_size;
|
||||
|
||||
/* In case the PCI BAR is larger than the actual amount of vram */
|
||||
if (adev->gmc.visible_vram_size > adev->gmc.real_vram_size)
|
||||
adev->gmc.visible_vram_size = adev->gmc.real_vram_size;
|
||||
|
||||
/* set the gart size */
|
||||
if (amdgpu_gart_size == -1) {
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_NAVI10:
|
||||
default:
|
||||
adev->gmc.gart_size = 512ULL << 20;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
adev->gmc.gart_size = (u64)amdgpu_gart_size << 20;
|
||||
|
||||
gmc_v10_0_vram_gtt_location(adev, &adev->gmc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gmc_v10_0_gart_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (adev->gart.bo) {
|
||||
WARN(1, "NAVI10 PCIE GART already initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initialize common gart structure */
|
||||
r = amdgpu_gart_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
adev->gart.table_size = adev->gart.num_gpu_pages * 8;
|
||||
adev->gart.gart_pte_flags = AMDGPU_PTE_MTYPE_NV10(MTYPE_UC) |
|
||||
AMDGPU_PTE_EXECUTABLE;
|
||||
|
||||
return amdgpu_gart_table_vram_alloc(adev);
|
||||
}
|
||||
|
||||
static unsigned gmc_v10_0_get_vbios_fb_size(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL);
|
||||
unsigned size;
|
||||
|
||||
if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) {
|
||||
size = 9 * 1024 * 1024; /* reserve 8MB for vga emulator and 1 MB for FB */
|
||||
} else {
|
||||
u32 viewport;
|
||||
u32 pitch;
|
||||
|
||||
viewport = RREG32_SOC15(DCE, 0, mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION);
|
||||
pitch = RREG32_SOC15(DCE, 0, mmHUBPREQ0_DCSURF_SURFACE_PITCH);
|
||||
size = (REG_GET_FIELD(viewport,
|
||||
HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) *
|
||||
REG_GET_FIELD(pitch, HUBPREQ0_DCSURF_SURFACE_PITCH, PITCH) *
|
||||
4);
|
||||
}
|
||||
/* return 0 if the pre-OS buffer uses up most of vram */
|
||||
if ((adev->gmc.real_vram_size - size) < (8 * 1024 * 1024)) {
|
||||
DRM_ERROR("Warning: pre-OS buffer uses most of vram, \
|
||||
be aware of gart table overwrite\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int gmc_v10_0_sw_init(void *handle)
|
||||
{
|
||||
int r;
|
||||
int dma_bits;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
gfxhub_v2_0_init(adev);
|
||||
mmhub_v2_0_init(adev);
|
||||
|
||||
spin_lock_init(&adev->gmc.invalidate_lock);
|
||||
|
||||
adev->gmc.vram_type = amdgpu_atomfirmware_get_vram_type(adev);
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_NAVI10:
|
||||
/*
|
||||
* To fulfill 4-level page support,
|
||||
* vm size is 256TB (48bit), maximum size of Navi10,
|
||||
* block size 512 (9bit)
|
||||
*/
|
||||
amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* This interrupt is VMC page fault.*/
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VMC,
|
||||
VMC_1_0__SRCID__VM_FAULT,
|
||||
&adev->gmc.vm_fault);
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_UTCL2,
|
||||
UTCL2_1_0__SRCID__FAULT,
|
||||
&adev->gmc.vm_fault);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/*
|
||||
* Set the internal MC address mask This is the max address of the GPU's
|
||||
* internal address space.
|
||||
*/
|
||||
adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */
|
||||
|
||||
/*
|
||||
* Reserve 8M stolen memory for navi10 like vega10
|
||||
* TODO: will check if it's really needed on asic.
|
||||
*/
|
||||
if (amdgpu_emu_mode == 1)
|
||||
adev->gmc.stolen_size = 0;
|
||||
else
|
||||
adev->gmc.stolen_size = 9 * 1024 *1024;
|
||||
|
||||
/*
|
||||
* Set DMA mask + need_dma32 flags.
|
||||
* PCIE - can handle 44-bits.
|
||||
* IGP - can handle 44-bits
|
||||
* PCI - dma32 for legacy pci gart, 44 bits on navi10
|
||||
*/
|
||||
adev->need_dma32 = false;
|
||||
dma_bits = adev->need_dma32 ? 32 : 44;
|
||||
|
||||
r = pci_set_dma_mask(adev->pdev, DMA_BIT_MASK(dma_bits));
|
||||
if (r) {
|
||||
adev->need_dma32 = true;
|
||||
dma_bits = 32;
|
||||
printk(KERN_WARNING "amdgpu: No suitable DMA available.\n");
|
||||
}
|
||||
|
||||
r = pci_set_consistent_dma_mask(adev->pdev, DMA_BIT_MASK(dma_bits));
|
||||
if (r) {
|
||||
pci_set_consistent_dma_mask(adev->pdev, DMA_BIT_MASK(32));
|
||||
printk(KERN_WARNING "amdgpu: No coherent DMA available.\n");
|
||||
}
|
||||
|
||||
r = gmc_v10_0_mc_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
adev->gmc.stolen_size = gmc_v10_0_get_vbios_fb_size(adev);
|
||||
|
||||
/* Memory manager */
|
||||
r = amdgpu_bo_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = gmc_v10_0_gart_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/*
|
||||
* number of VMs
|
||||
* VMID 0 is reserved for System
|
||||
* amdgpu graphics/compute will use VMIDs 1-7
|
||||
* amdkfd will use VMIDs 8-15
|
||||
*/
|
||||
adev->vm_manager.id_mgr[AMDGPU_GFXHUB].num_ids = AMDGPU_NUM_OF_VMIDS;
|
||||
adev->vm_manager.id_mgr[AMDGPU_MMHUB].num_ids = AMDGPU_NUM_OF_VMIDS;
|
||||
|
||||
amdgpu_vm_manager_init(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gmc_v8_0_gart_fini - vm fini callback
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Tears down the driver GART/VM setup (CIK).
|
||||
*/
|
||||
static void gmc_v10_0_gart_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_gart_table_vram_free(adev);
|
||||
amdgpu_gart_fini(adev);
|
||||
}
|
||||
|
||||
static int gmc_v10_0_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_vm_manager_fini(adev);
|
||||
gmc_v10_0_gart_fini(adev);
|
||||
amdgpu_gem_force_release(adev);
|
||||
amdgpu_bo_fini(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gmc_v10_0_init_golden_registers(struct amdgpu_device *adev)
|
||||
{
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_NAVI10:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gmc_v10_0_gart_enable - gart enable
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*/
|
||||
static int gmc_v10_0_gart_enable(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
bool value;
|
||||
u32 tmp;
|
||||
|
||||
if (adev->gart.bo == NULL) {
|
||||
dev_err(adev->dev, "No VRAM object for PCIE GART.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = amdgpu_gart_table_vram_pin(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = gfxhub_v2_0_gart_enable(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mmhub_v2_0_gart_enable(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
tmp = RREG32_SOC15(HDP, 0, mmHDP_MISC_CNTL);
|
||||
tmp |= HDP_MISC_CNTL__FLUSH_INVALIDATE_CACHE_MASK;
|
||||
WREG32_SOC15(HDP, 0, mmHDP_MISC_CNTL, tmp);
|
||||
|
||||
tmp = RREG32_SOC15(HDP, 0, mmHDP_HOST_PATH_CNTL);
|
||||
WREG32_SOC15(HDP, 0, mmHDP_HOST_PATH_CNTL, tmp);
|
||||
|
||||
/* Flush HDP after it is initialized */
|
||||
adev->nbio_funcs->hdp_flush(adev, NULL);
|
||||
|
||||
value = (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS) ?
|
||||
false : true;
|
||||
|
||||
gfxhub_v2_0_set_fault_enable_default(adev, value);
|
||||
mmhub_v2_0_set_fault_enable_default(adev, value);
|
||||
gmc_v10_0_flush_gpu_tlb(adev, 0, 0);
|
||||
|
||||
DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
|
||||
(unsigned)(adev->gmc.gart_size >> 20),
|
||||
(unsigned long long)amdgpu_bo_gpu_offset(adev->gart.bo));
|
||||
|
||||
adev->gart.ready = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gmc_v10_0_hw_init(void *handle)
|
||||
{
|
||||
int r;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
/* The sequence of these two function calls matters.*/
|
||||
gmc_v10_0_init_golden_registers(adev);
|
||||
|
||||
r = gmc_v10_0_gart_enable(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gmc_v10_0_gart_disable - gart disable
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* This disables all VM page table.
|
||||
*/
|
||||
static void gmc_v10_0_gart_disable(struct amdgpu_device *adev)
|
||||
{
|
||||
gfxhub_v2_0_gart_disable(adev);
|
||||
mmhub_v2_0_gart_disable(adev);
|
||||
amdgpu_gart_table_vram_unpin(adev);
|
||||
}
|
||||
|
||||
static int gmc_v10_0_hw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
/* full access mode, so don't touch any GMC register */
|
||||
DRM_DEBUG("For SRIOV client, shouldn't do anything.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0);
|
||||
gmc_v10_0_gart_disable(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gmc_v10_0_suspend(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
gmc_v10_0_hw_fini(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gmc_v10_0_resume(void *handle)
|
||||
{
|
||||
int r;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
r = gmc_v10_0_hw_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
amdgpu_vmid_reset_all(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool gmc_v10_0_is_idle(void *handle)
|
||||
{
|
||||
/* MC is always ready in GMC v10.*/
|
||||
return true;
|
||||
}
|
||||
|
||||
static int gmc_v10_0_wait_for_idle(void *handle)
|
||||
{
|
||||
/* There is no need to wait for MC idle in GMC v10.*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gmc_v10_0_soft_reset(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gmc_v10_0_set_clockgating_state(void *handle,
|
||||
enum amd_clockgating_state state)
|
||||
{
|
||||
int r;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
r = mmhub_v2_0_set_clockgating(adev, state);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return athub_v2_0_set_clockgating(adev, state);
|
||||
}
|
||||
|
||||
static void gmc_v10_0_get_clockgating_state(void *handle, u32 *flags)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
mmhub_v2_0_get_clockgating(adev, flags);
|
||||
|
||||
athub_v2_0_get_clockgating(adev, flags);
|
||||
}
|
||||
|
||||
static int gmc_v10_0_set_powergating_state(void *handle,
|
||||
enum amd_powergating_state state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct amd_ip_funcs gmc_v10_0_ip_funcs = {
|
||||
.name = "gmc_v10_0",
|
||||
.early_init = gmc_v10_0_early_init,
|
||||
.late_init = gmc_v10_0_late_init,
|
||||
.sw_init = gmc_v10_0_sw_init,
|
||||
.sw_fini = gmc_v10_0_sw_fini,
|
||||
.hw_init = gmc_v10_0_hw_init,
|
||||
.hw_fini = gmc_v10_0_hw_fini,
|
||||
.suspend = gmc_v10_0_suspend,
|
||||
.resume = gmc_v10_0_resume,
|
||||
.is_idle = gmc_v10_0_is_idle,
|
||||
.wait_for_idle = gmc_v10_0_wait_for_idle,
|
||||
.soft_reset = gmc_v10_0_soft_reset,
|
||||
.set_clockgating_state = gmc_v10_0_set_clockgating_state,
|
||||
.set_powergating_state = gmc_v10_0_set_powergating_state,
|
||||
.get_clockgating_state = gmc_v10_0_get_clockgating_state,
|
||||
};
|
||||
|
||||
const struct amdgpu_ip_block_version gmc_v10_0_ip_block =
|
||||
{
|
||||
.type = AMD_IP_BLOCK_TYPE_GMC,
|
||||
.major = 10,
|
||||
.minor = 0,
|
||||
.rev = 0,
|
||||
.funcs = &gmc_v10_0_ip_funcs,
|
||||
};
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __GMC_V10_0_H__
|
||||
#define __GMC_V10_0_H__
|
||||
|
||||
extern const struct amd_ip_funcs gmc_v10_0_ip_funcs;
|
||||
extern const struct amdgpu_ip_block_version gmc_v10_0_ip_block;
|
||||
|
||||
#endif
|
|
@ -535,22 +535,22 @@ static uint64_t gmc_v9_0_get_vm_pte_flags(struct amdgpu_device *adev,
|
|||
|
||||
switch (flags & AMDGPU_VM_MTYPE_MASK) {
|
||||
case AMDGPU_VM_MTYPE_DEFAULT:
|
||||
pte_flag |= AMDGPU_PTE_MTYPE(MTYPE_NC);
|
||||
pte_flag |= AMDGPU_PTE_MTYPE_VG10(MTYPE_NC);
|
||||
break;
|
||||
case AMDGPU_VM_MTYPE_NC:
|
||||
pte_flag |= AMDGPU_PTE_MTYPE(MTYPE_NC);
|
||||
pte_flag |= AMDGPU_PTE_MTYPE_VG10(MTYPE_NC);
|
||||
break;
|
||||
case AMDGPU_VM_MTYPE_WC:
|
||||
pte_flag |= AMDGPU_PTE_MTYPE(MTYPE_WC);
|
||||
pte_flag |= AMDGPU_PTE_MTYPE_VG10(MTYPE_WC);
|
||||
break;
|
||||
case AMDGPU_VM_MTYPE_CC:
|
||||
pte_flag |= AMDGPU_PTE_MTYPE(MTYPE_CC);
|
||||
pte_flag |= AMDGPU_PTE_MTYPE_VG10(MTYPE_CC);
|
||||
break;
|
||||
case AMDGPU_VM_MTYPE_UC:
|
||||
pte_flag |= AMDGPU_PTE_MTYPE(MTYPE_UC);
|
||||
pte_flag |= AMDGPU_PTE_MTYPE_VG10(MTYPE_UC);
|
||||
break;
|
||||
default:
|
||||
pte_flag |= AMDGPU_PTE_MTYPE(MTYPE_NC);
|
||||
pte_flag |= AMDGPU_PTE_MTYPE_VG10(MTYPE_NC);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -733,9 +733,7 @@ static int gmc_v9_0_ecc_late_init(void *handle)
|
|||
if (r)
|
||||
goto interrupt;
|
||||
|
||||
r = amdgpu_ras_debugfs_create(adev, &fs_info);
|
||||
if (r)
|
||||
goto debugfs;
|
||||
amdgpu_ras_debugfs_create(adev, &fs_info);
|
||||
|
||||
r = amdgpu_ras_sysfs_create(adev, &fs_info);
|
||||
if (r)
|
||||
|
@ -750,7 +748,6 @@ irq:
|
|||
amdgpu_ras_sysfs_remove(adev, *ras_if);
|
||||
sysfs:
|
||||
amdgpu_ras_debugfs_remove(adev, *ras_if);
|
||||
debugfs:
|
||||
amdgpu_ras_interrupt_remove_handler(adev, &ih_info);
|
||||
interrupt:
|
||||
amdgpu_ras_feature_enable(adev, *ras_if, 0);
|
||||
|
@ -919,7 +916,7 @@ static int gmc_v9_0_gart_init(struct amdgpu_device *adev)
|
|||
if (r)
|
||||
return r;
|
||||
adev->gart.table_size = adev->gart.num_gpu_pages * 8;
|
||||
adev->gart.gart_pte_flags = AMDGPU_PTE_MTYPE(MTYPE_UC) |
|
||||
adev->gart.gart_pte_flags = AMDGPU_PTE_MTYPE_VG10(MTYPE_UC) |
|
||||
AMDGPU_PTE_EXECUTABLE;
|
||||
return amdgpu_gart_table_vram_alloc(adev);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,366 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
#include "amdgpu.h"
|
||||
#include "soc15_common.h"
|
||||
#include "nv.h"
|
||||
#include "gc/gc_10_1_0_offset.h"
|
||||
#include "gc/gc_10_1_0_sh_mask.h"
|
||||
|
||||
MODULE_FIRMWARE("amdgpu/navi10_mes.bin");
|
||||
|
||||
static int mes_v10_1_add_hw_queue(struct amdgpu_mes *mes,
|
||||
struct mes_add_queue_input *input)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mes_v10_1_remove_hw_queue(struct amdgpu_mes *mes,
|
||||
struct mes_remove_queue_input *input)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mes_v10_1_suspend_gang(struct amdgpu_mes *mes,
|
||||
struct mes_suspend_gang_input *input)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mes_v10_1_resume_gang(struct amdgpu_mes *mes,
|
||||
struct mes_resume_gang_input *input)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct amdgpu_mes_funcs mes_v10_1_funcs = {
|
||||
.add_hw_queue = mes_v10_1_add_hw_queue,
|
||||
.remove_hw_queue = mes_v10_1_remove_hw_queue,
|
||||
.suspend_gang = mes_v10_1_suspend_gang,
|
||||
.resume_gang = mes_v10_1_resume_gang,
|
||||
};
|
||||
|
||||
static int mes_v10_1_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
const char *chip_name;
|
||||
char fw_name[30];
|
||||
int err;
|
||||
const struct mes_firmware_header_v1_0 *mes_hdr;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_NAVI10:
|
||||
chip_name = "navi10";
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes.bin", chip_name);
|
||||
err = request_firmware(&adev->mes.fw, fw_name, adev->dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = amdgpu_ucode_validate(adev->mes.fw);
|
||||
if (err) {
|
||||
release_firmware(adev->mes.fw);
|
||||
adev->mes.fw = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
mes_hdr = (const struct mes_firmware_header_v1_0 *)adev->mes.fw->data;
|
||||
adev->mes.ucode_fw_version = le32_to_cpu(mes_hdr->mes_ucode_version);
|
||||
adev->mes.ucode_fw_version =
|
||||
le32_to_cpu(mes_hdr->mes_ucode_data_version);
|
||||
adev->mes.uc_start_addr =
|
||||
le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) |
|
||||
((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32);
|
||||
adev->mes.data_start_addr =
|
||||
le32_to_cpu(mes_hdr->mes_data_start_addr_lo) |
|
||||
((uint64_t)(le32_to_cpu(mes_hdr->mes_data_start_addr_hi)) << 32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mes_v10_1_free_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
release_firmware(adev->mes.fw);
|
||||
adev->mes.fw = NULL;
|
||||
}
|
||||
|
||||
static int mes_v10_1_allocate_ucode_buffer(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
const struct mes_firmware_header_v1_0 *mes_hdr;
|
||||
const __le32 *fw_data;
|
||||
unsigned fw_size;
|
||||
|
||||
mes_hdr = (const struct mes_firmware_header_v1_0 *)
|
||||
adev->mes.fw->data;
|
||||
|
||||
fw_data = (const __le32 *)(adev->mes.fw->data +
|
||||
le32_to_cpu(mes_hdr->mes_ucode_offset_bytes));
|
||||
fw_size = le32_to_cpu(mes_hdr->mes_ucode_size_bytes);
|
||||
|
||||
r = amdgpu_bo_create_reserved(adev, fw_size,
|
||||
PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->mes.ucode_fw_obj,
|
||||
&adev->mes.ucode_fw_gpu_addr,
|
||||
(void **)&adev->mes.ucode_fw_ptr);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "(%d) failed to create mes fw bo\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
memcpy(adev->mes.ucode_fw_ptr, fw_data, fw_size);
|
||||
|
||||
amdgpu_bo_kunmap(adev->mes.ucode_fw_obj);
|
||||
amdgpu_bo_unreserve(adev->mes.ucode_fw_obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mes_v10_1_allocate_ucode_data_buffer(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
const struct mes_firmware_header_v1_0 *mes_hdr;
|
||||
const __le32 *fw_data;
|
||||
unsigned fw_size;
|
||||
|
||||
mes_hdr = (const struct mes_firmware_header_v1_0 *)
|
||||
adev->mes.fw->data;
|
||||
|
||||
fw_data = (const __le32 *)(adev->mes.fw->data +
|
||||
le32_to_cpu(mes_hdr->mes_ucode_data_offset_bytes));
|
||||
fw_size = le32_to_cpu(mes_hdr->mes_ucode_data_size_bytes);
|
||||
|
||||
r = amdgpu_bo_create_reserved(adev, fw_size,
|
||||
64 * 1024, AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->mes.data_fw_obj,
|
||||
&adev->mes.data_fw_gpu_addr,
|
||||
(void **)&adev->mes.data_fw_ptr);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "(%d) failed to create mes data fw bo\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
memcpy(adev->mes.data_fw_ptr, fw_data, fw_size);
|
||||
|
||||
amdgpu_bo_kunmap(adev->mes.data_fw_obj);
|
||||
amdgpu_bo_unreserve(adev->mes.data_fw_obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mes_v10_1_free_ucode_buffers(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_bo_free_kernel(&adev->mes.data_fw_obj,
|
||||
&adev->mes.data_fw_gpu_addr,
|
||||
(void **)&adev->mes.data_fw_ptr);
|
||||
|
||||
amdgpu_bo_free_kernel(&adev->mes.ucode_fw_obj,
|
||||
&adev->mes.ucode_fw_gpu_addr,
|
||||
(void **)&adev->mes.ucode_fw_ptr);
|
||||
}
|
||||
|
||||
static void mes_v10_1_enable(struct amdgpu_device *adev, bool enable)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
|
||||
if (enable) {
|
||||
data = RREG32_SOC15(GC, 0, mmCP_MES_CNTL);
|
||||
data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE0_RESET, 1);
|
||||
WREG32_SOC15(GC, 0, mmCP_MES_CNTL, data);
|
||||
|
||||
/* set ucode start address */
|
||||
WREG32_SOC15(GC, 0, mmCP_MES_PRGRM_CNTR_START,
|
||||
(uint32_t)(adev->mes.uc_start_addr) >> 2);
|
||||
|
||||
/* clear BYPASS_UNCACHED to avoid hangs after interrupt. */
|
||||
data = RREG32_SOC15(GC, 0, mmCP_MES_DC_OP_CNTL);
|
||||
data = REG_SET_FIELD(data, CP_MES_DC_OP_CNTL,
|
||||
BYPASS_UNCACHED, 0);
|
||||
WREG32_SOC15(GC, 0, mmCP_MES_DC_OP_CNTL, data);
|
||||
|
||||
/* unhalt MES and activate pipe0 */
|
||||
data = REG_SET_FIELD(0, CP_MES_CNTL, MES_PIPE0_ACTIVE, 1);
|
||||
WREG32_SOC15(GC, 0, mmCP_MES_CNTL, data);
|
||||
} else {
|
||||
data = RREG32_SOC15(GC, 0, mmCP_MES_CNTL);
|
||||
data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE0_ACTIVE, 0);
|
||||
data = REG_SET_FIELD(data, CP_MES_CNTL,
|
||||
MES_INVALIDATE_ICACHE, 1);
|
||||
data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE0_RESET, 1);
|
||||
data = REG_SET_FIELD(data, CP_MES_CNTL, MES_HALT, 1);
|
||||
WREG32_SOC15(GC, 0, mmCP_MES_CNTL, data);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is for backdoor MES firmware */
|
||||
static int mes_v10_1_load_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
uint32_t data;
|
||||
|
||||
if (!adev->mes.fw)
|
||||
return -EINVAL;
|
||||
|
||||
r = mes_v10_1_allocate_ucode_buffer(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mes_v10_1_allocate_ucode_data_buffer(adev);
|
||||
if (r) {
|
||||
mes_v10_1_free_ucode_buffers(adev);
|
||||
return r;
|
||||
}
|
||||
|
||||
mes_v10_1_enable(adev, false);
|
||||
|
||||
WREG32_SOC15(GC, 0, mmCP_MES_IC_BASE_CNTL, 0);
|
||||
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
/* me=3, pipe=0, queue=0 */
|
||||
nv_grbm_select(adev, 3, 0, 0, 0);
|
||||
|
||||
/* set ucode start address */
|
||||
WREG32_SOC15(GC, 0, mmCP_MES_PRGRM_CNTR_START,
|
||||
(uint32_t)(adev->mes.uc_start_addr) >> 2);
|
||||
|
||||
/* set ucode fimrware address */
|
||||
WREG32_SOC15(GC, 0, mmCP_MES_IC_BASE_LO,
|
||||
lower_32_bits(adev->mes.ucode_fw_gpu_addr));
|
||||
WREG32_SOC15(GC, 0, mmCP_MES_IC_BASE_HI,
|
||||
upper_32_bits(adev->mes.ucode_fw_gpu_addr));
|
||||
|
||||
/* set ucode instruction cache boundary to 2M-1 */
|
||||
WREG32_SOC15(GC, 0, mmCP_MES_MIBOUND_LO, 0x1FFFFF);
|
||||
|
||||
/* set ucode data firmware address */
|
||||
WREG32_SOC15(GC, 0, mmCP_MES_MDBASE_LO,
|
||||
lower_32_bits(adev->mes.data_fw_gpu_addr));
|
||||
WREG32_SOC15(GC, 0, mmCP_MES_MDBASE_HI,
|
||||
upper_32_bits(adev->mes.data_fw_gpu_addr));
|
||||
|
||||
/* Set 0x3FFFF (256K-1) to CP_MES_MDBOUND_LO */
|
||||
WREG32_SOC15(GC, 0, mmCP_MES_MDBOUND_LO, 0x3FFFF);
|
||||
|
||||
/* invalidate ICACHE */
|
||||
data = RREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL);
|
||||
data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, PRIME_ICACHE, 0);
|
||||
data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, INVALIDATE_CACHE, 1);
|
||||
WREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL, data);
|
||||
|
||||
/* prime the ICACHE. */
|
||||
data = RREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL);
|
||||
data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, PRIME_ICACHE, 1);
|
||||
WREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL, data);
|
||||
|
||||
nv_grbm_select(adev, 0, 0, 0, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mes_v10_1_sw_init(void *handle)
|
||||
{
|
||||
int r;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
r = mes_v10_1_init_microcode(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mes_v10_1_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
mes_v10_1_free_microcode(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mes_v10_1_hw_init(void *handle)
|
||||
{
|
||||
int r;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) {
|
||||
r = mes_v10_1_load_microcode(adev);
|
||||
if (r) {
|
||||
DRM_ERROR("failed to MES fw, r=%d\n", r);
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
DRM_ERROR("only support direct fw loading on MES\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mes_v10_1_enable(adev, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mes_v10_1_hw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
mes_v10_1_enable(adev, false);
|
||||
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT)
|
||||
mes_v10_1_free_ucode_buffers(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mes_v10_1_suspend(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mes_v10_1_resume(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct amd_ip_funcs mes_v10_1_ip_funcs = {
|
||||
.name = "mes_v10_1",
|
||||
.sw_init = mes_v10_1_sw_init,
|
||||
.sw_fini = mes_v10_1_sw_fini,
|
||||
.hw_init = mes_v10_1_hw_init,
|
||||
.hw_fini = mes_v10_1_hw_fini,
|
||||
.suspend = mes_v10_1_suspend,
|
||||
.resume = mes_v10_1_resume,
|
||||
};
|
||||
|
||||
const struct amdgpu_ip_block_version mes_v10_1_ip_block = {
|
||||
.type = AMD_IP_BLOCK_TYPE_MES,
|
||||
.major = 10,
|
||||
.minor = 1,
|
||||
.rev = 0,
|
||||
.funcs = &mes_v10_1_ip_funcs,
|
||||
};
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MES_V10_1_H__
|
||||
#define __MES_v10_1_H__
|
||||
|
||||
extern const struct amdgpu_ip_block_version mes_v10_1_ip_block;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,444 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "mmhub_v2_0.h"
|
||||
|
||||
#include "mmhub/mmhub_2_0_0_offset.h"
|
||||
#include "mmhub/mmhub_2_0_0_sh_mask.h"
|
||||
#include "mmhub/mmhub_2_0_0_default.h"
|
||||
#include "navi10_enum.h"
|
||||
|
||||
#include "soc15_common.h"
|
||||
|
||||
static void mmhub_v2_0_init_gart_pt_regs(struct amdgpu_device *adev)
|
||||
{
|
||||
uint64_t value = amdgpu_gmc_pd_addr(adev->gart.bo);
|
||||
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
|
||||
lower_32_bits(value));
|
||||
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
|
||||
upper_32_bits(value));
|
||||
}
|
||||
|
||||
static void mmhub_v2_0_init_gart_aperture_regs(struct amdgpu_device *adev)
|
||||
{
|
||||
mmhub_v2_0_init_gart_pt_regs(adev);
|
||||
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
|
||||
(u32)(adev->gmc.gart_start >> 12));
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
|
||||
(u32)(adev->gmc.gart_start >> 44));
|
||||
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
|
||||
(u32)(adev->gmc.gart_end >> 12));
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
|
||||
(u32)(adev->gmc.gart_end >> 44));
|
||||
}
|
||||
|
||||
static void mmhub_v2_0_init_system_aperture_regs(struct amdgpu_device *adev)
|
||||
{
|
||||
uint64_t value;
|
||||
uint32_t tmp;
|
||||
|
||||
/* Disable AGP. */
|
||||
WREG32_SOC15(MMHUB, 0, mmMMMC_VM_AGP_BASE, 0);
|
||||
WREG32_SOC15(MMHUB, 0, mmMMMC_VM_AGP_TOP, 0);
|
||||
WREG32_SOC15(MMHUB, 0, mmMMMC_VM_AGP_BOT, 0x00FFFFFF);
|
||||
|
||||
/* Program the system aperture low logical page number. */
|
||||
WREG32_SOC15(MMHUB, 0, mmMMMC_VM_SYSTEM_APERTURE_LOW_ADDR,
|
||||
adev->gmc.vram_start >> 18);
|
||||
WREG32_SOC15(MMHUB, 0, mmMMMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
|
||||
adev->gmc.vram_end >> 18);
|
||||
|
||||
/* Set default page address. */
|
||||
value = adev->vram_scratch.gpu_addr - adev->gmc.vram_start +
|
||||
adev->vm_manager.vram_base_offset;
|
||||
WREG32_SOC15(MMHUB, 0, mmMMMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
|
||||
(u32)(value >> 12));
|
||||
WREG32_SOC15(MMHUB, 0, mmMMMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
|
||||
(u32)(value >> 44));
|
||||
|
||||
/* Program "protection fault". */
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
|
||||
(u32)(adev->dummy_page_addr >> 12));
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
|
||||
(u32)((u64)adev->dummy_page_addr >> 44));
|
||||
|
||||
tmp = RREG32_SOC15(MMHUB, 0, mmMMVM_L2_PROTECTION_FAULT_CNTL2);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL2,
|
||||
ACTIVE_PAGE_MIGRATION_PTE_READ_RETRY, 1);
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_L2_PROTECTION_FAULT_CNTL2, tmp);
|
||||
}
|
||||
|
||||
static void mmhub_v2_0_init_tlb_regs(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
/* Setup TLB control */
|
||||
tmp = RREG32_SOC15(MMHUB, 0, mmMMMC_VM_MX_L1_TLB_CNTL);
|
||||
|
||||
tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 1);
|
||||
tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, 3);
|
||||
tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL,
|
||||
ENABLE_ADVANCED_DRIVER_MODEL, 1);
|
||||
tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL,
|
||||
SYSTEM_APERTURE_UNMAPPED_ACCESS, 0);
|
||||
tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0);
|
||||
tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL,
|
||||
MTYPE, MTYPE_UC); /* UC, uncached */
|
||||
|
||||
WREG32_SOC15(MMHUB, 0, mmMMMC_VM_MX_L1_TLB_CNTL, tmp);
|
||||
}
|
||||
|
||||
static void mmhub_v2_0_init_cache_regs(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
/* Setup L2 cache */
|
||||
tmp = RREG32_SOC15(MMHUB, 0, mmMMVM_L2_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, ENABLE_L2_CACHE, 1);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING, 0);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL,
|
||||
ENABLE_DEFAULT_PAGE_OUT_TO_SYSTEM_MEMORY, 1);
|
||||
/* XXX for emulation, Refer to closed source code.*/
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, L2_PDE0_CACHE_TAG_GENERATION_MODE,
|
||||
0);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, PDE_FAULT_CLASSIFICATION, 1);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, CONTEXT1_IDENTITY_ACCESS_MODE, 1);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, IDENTITY_MODE_FRAGMENT_SIZE, 0);
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_L2_CNTL, tmp);
|
||||
|
||||
tmp = RREG32_SOC15(MMHUB, 0, mmMMVM_L2_CNTL2);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS, 1);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL2, INVALIDATE_L2_CACHE, 1);
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_L2_CNTL2, tmp);
|
||||
|
||||
tmp = mmMMVM_L2_CNTL3_DEFAULT;
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_L2_CNTL3, tmp);
|
||||
|
||||
tmp = mmMMVM_L2_CNTL4_DEFAULT;
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL4, VMC_TAP_PDE_REQUEST_PHYSICAL, 0);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL4, VMC_TAP_PTE_REQUEST_PHYSICAL, 0);
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_L2_CNTL4, tmp);
|
||||
}
|
||||
|
||||
static void mmhub_v2_0_enable_system_domain(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = RREG32_SOC15(MMHUB, 0, mmMMVM_CONTEXT0_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT0_CNTL, ENABLE_CONTEXT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT0_CNTL, PAGE_TABLE_DEPTH, 0);
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_CONTEXT0_CNTL, tmp);
|
||||
}
|
||||
|
||||
static void mmhub_v2_0_disable_identity_aperture(struct amdgpu_device *adev)
|
||||
{
|
||||
WREG32_SOC15(MMHUB, 0,
|
||||
mmMMVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_LO32,
|
||||
0xFFFFFFFF);
|
||||
WREG32_SOC15(MMHUB, 0,
|
||||
mmMMVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_HI32,
|
||||
0x0000000F);
|
||||
|
||||
WREG32_SOC15(MMHUB, 0,
|
||||
mmMMVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_LO32, 0);
|
||||
WREG32_SOC15(MMHUB, 0,
|
||||
mmMMVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_HI32, 0);
|
||||
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_LO32,
|
||||
0);
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_HI32,
|
||||
0);
|
||||
}
|
||||
|
||||
static void mmhub_v2_0_setup_vmid_config(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
uint32_t tmp;
|
||||
|
||||
for (i = 0; i <= 14; i++) {
|
||||
tmp = RREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_CONTEXT1_CNTL, i);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
|
||||
adev->vm_manager.num_level);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
|
||||
RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
|
||||
DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT,
|
||||
1);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
|
||||
PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
|
||||
VALID_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
|
||||
READ_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
|
||||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
|
||||
PAGE_TABLE_BLOCK_SIZE,
|
||||
adev->vm_manager.block_size - 9);
|
||||
/* Send no-retry XNACK on fault to suppress VM fault storm. */
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
|
||||
RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0);
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_CONTEXT1_CNTL, i, tmp);
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32, i*2, 0);
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_CONTEXT1_PAGE_TABLE_START_ADDR_HI32, i*2, 0);
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_CONTEXT1_PAGE_TABLE_END_ADDR_LO32, i*2,
|
||||
lower_32_bits(adev->vm_manager.max_pfn - 1));
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_CONTEXT1_PAGE_TABLE_END_ADDR_HI32, i*2,
|
||||
upper_32_bits(adev->vm_manager.max_pfn - 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void mmhub_v2_0_program_invalidation(struct amdgpu_device *adev)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 18; ++i) {
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_INVALIDATE_ENG0_ADDR_RANGE_LO32,
|
||||
2 * i, 0xffffffff);
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_INVALIDATE_ENG0_ADDR_RANGE_HI32,
|
||||
2 * i, 0x1f);
|
||||
}
|
||||
}
|
||||
|
||||
int mmhub_v2_0_gart_enable(struct amdgpu_device *adev)
|
||||
{
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
/*
|
||||
* MMMC_VM_FB_LOCATION_BASE/TOP is NULL for VF, becuase they are
|
||||
* VF copy registers so vbios post doesn't program them, for
|
||||
* SRIOV driver need to program them
|
||||
*/
|
||||
WREG32_SOC15(MMHUB, 0, mmMMMC_VM_FB_LOCATION_BASE,
|
||||
adev->gmc.vram_start >> 24);
|
||||
WREG32_SOC15(MMHUB, 0, mmMMMC_VM_FB_LOCATION_TOP,
|
||||
adev->gmc.vram_end >> 24);
|
||||
}
|
||||
|
||||
/* GART Enable. */
|
||||
mmhub_v2_0_init_gart_aperture_regs(adev);
|
||||
mmhub_v2_0_init_system_aperture_regs(adev);
|
||||
mmhub_v2_0_init_tlb_regs(adev);
|
||||
mmhub_v2_0_init_cache_regs(adev);
|
||||
|
||||
mmhub_v2_0_enable_system_domain(adev);
|
||||
mmhub_v2_0_disable_identity_aperture(adev);
|
||||
mmhub_v2_0_setup_vmid_config(adev);
|
||||
mmhub_v2_0_program_invalidation(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mmhub_v2_0_gart_disable(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 tmp;
|
||||
u32 i;
|
||||
|
||||
/* Disable all tables */
|
||||
for (i = 0; i < 16; i++)
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_CONTEXT0_CNTL, i, 0);
|
||||
|
||||
/* Setup TLB control */
|
||||
tmp = RREG32_SOC15(MMHUB, 0, mmMMMC_VM_MX_L1_TLB_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 0);
|
||||
tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL,
|
||||
ENABLE_ADVANCED_DRIVER_MODEL, 0);
|
||||
WREG32_SOC15(MMHUB, 0, mmMMMC_VM_MX_L1_TLB_CNTL, tmp);
|
||||
|
||||
/* Setup L2 cache */
|
||||
tmp = RREG32_SOC15(MMHUB, 0, mmMMVM_L2_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, ENABLE_L2_CACHE, 0);
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_L2_CNTL, tmp);
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_L2_CNTL3, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* mmhub_v2_0_set_fault_enable_default - update GART/VM fault handling
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @value: true redirects VM faults to the default page
|
||||
*/
|
||||
void mmhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, bool value)
|
||||
{
|
||||
u32 tmp;
|
||||
tmp = RREG32_SOC15(MMHUB, 0, mmMMVM_L2_PROTECTION_FAULT_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
|
||||
RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
|
||||
PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
|
||||
PDE1_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
|
||||
PDE2_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
|
||||
TRANSLATE_FURTHER_PROTECTION_FAULT_ENABLE_DEFAULT,
|
||||
value);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
|
||||
NACK_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
|
||||
DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
|
||||
VALID_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
|
||||
READ_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
|
||||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
WREG32_SOC15(MMHUB, 0, mmMMVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
|
||||
void mmhub_v2_0_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB];
|
||||
|
||||
hub->ctx0_ptb_addr_lo32 =
|
||||
SOC15_REG_OFFSET(MMHUB, 0,
|
||||
mmMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32);
|
||||
hub->ctx0_ptb_addr_hi32 =
|
||||
SOC15_REG_OFFSET(MMHUB, 0,
|
||||
mmMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
|
||||
hub->vm_inv_eng0_req =
|
||||
SOC15_REG_OFFSET(MMHUB, 0, mmMMVM_INVALIDATE_ENG0_REQ);
|
||||
hub->vm_inv_eng0_ack =
|
||||
SOC15_REG_OFFSET(MMHUB, 0, mmMMVM_INVALIDATE_ENG0_ACK);
|
||||
hub->vm_context0_cntl =
|
||||
SOC15_REG_OFFSET(MMHUB, 0, mmMMVM_CONTEXT0_CNTL);
|
||||
hub->vm_l2_pro_fault_status =
|
||||
SOC15_REG_OFFSET(MMHUB, 0, mmMMVM_L2_PROTECTION_FAULT_STATUS);
|
||||
hub->vm_l2_pro_fault_cntl =
|
||||
SOC15_REG_OFFSET(MMHUB, 0, mmMMVM_L2_PROTECTION_FAULT_CNTL);
|
||||
|
||||
}
|
||||
|
||||
static void mmhub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
uint32_t def, data, def1, data1;
|
||||
|
||||
def = data = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG);
|
||||
|
||||
def1 = data1 = RREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2);
|
||||
|
||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_MGCG)) {
|
||||
data |= MM_ATC_L2_MISC_CG__ENABLE_MASK;
|
||||
|
||||
data1 &= ~(DAGB0_CNTL_MISC2__DISABLE_WRREQ_CG_MASK |
|
||||
DAGB0_CNTL_MISC2__DISABLE_WRRET_CG_MASK |
|
||||
DAGB0_CNTL_MISC2__DISABLE_RDREQ_CG_MASK |
|
||||
DAGB0_CNTL_MISC2__DISABLE_RDRET_CG_MASK |
|
||||
DAGB0_CNTL_MISC2__DISABLE_TLBWR_CG_MASK |
|
||||
DAGB0_CNTL_MISC2__DISABLE_TLBRD_CG_MASK);
|
||||
|
||||
} else {
|
||||
data &= ~MM_ATC_L2_MISC_CG__ENABLE_MASK;
|
||||
|
||||
data1 |= (DAGB0_CNTL_MISC2__DISABLE_WRREQ_CG_MASK |
|
||||
DAGB0_CNTL_MISC2__DISABLE_WRRET_CG_MASK |
|
||||
DAGB0_CNTL_MISC2__DISABLE_RDREQ_CG_MASK |
|
||||
DAGB0_CNTL_MISC2__DISABLE_RDRET_CG_MASK |
|
||||
DAGB0_CNTL_MISC2__DISABLE_TLBWR_CG_MASK |
|
||||
DAGB0_CNTL_MISC2__DISABLE_TLBRD_CG_MASK);
|
||||
}
|
||||
|
||||
if (def != data)
|
||||
WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG, data);
|
||||
|
||||
if (def1 != data1)
|
||||
WREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2, data1);
|
||||
}
|
||||
|
||||
static void mmhub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
uint32_t def, data;
|
||||
|
||||
def = data = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG);
|
||||
|
||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_LS))
|
||||
data |= MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK;
|
||||
else
|
||||
data &= ~MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK;
|
||||
|
||||
if (def != data)
|
||||
WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG, data);
|
||||
}
|
||||
|
||||
int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev,
|
||||
enum amd_clockgating_state state)
|
||||
{
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_NAVI10:
|
||||
mmhub_v2_0_update_medium_grain_clock_gating(adev,
|
||||
state == AMD_CG_STATE_GATE ? true : false);
|
||||
mmhub_v2_0_update_medium_grain_light_sleep(adev,
|
||||
state == AMD_CG_STATE_GATE ? true : false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags)
|
||||
{
|
||||
int data, data1;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
*flags = 0;
|
||||
|
||||
data = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG);
|
||||
|
||||
data1 = RREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2);
|
||||
|
||||
/* AMD_CG_SUPPORT_MC_MGCG */
|
||||
if ((data & MM_ATC_L2_MISC_CG__ENABLE_MASK) &&
|
||||
!(data1 & (DAGB0_CNTL_MISC2__DISABLE_WRREQ_CG_MASK |
|
||||
DAGB0_CNTL_MISC2__DISABLE_WRRET_CG_MASK |
|
||||
DAGB0_CNTL_MISC2__DISABLE_RDREQ_CG_MASK |
|
||||
DAGB0_CNTL_MISC2__DISABLE_RDRET_CG_MASK |
|
||||
DAGB0_CNTL_MISC2__DISABLE_TLBWR_CG_MASK |
|
||||
DAGB0_CNTL_MISC2__DISABLE_TLBRD_CG_MASK)))
|
||||
*flags |= AMD_CG_SUPPORT_MC_MGCG;
|
||||
|
||||
/* AMD_CG_SUPPORT_MC_LS */
|
||||
if (data & MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK)
|
||||
*flags |= AMD_CG_SUPPORT_MC_LS;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#ifndef __MMHUB_V2_0_H__
|
||||
#define __MMHUB_V2_0_H__
|
||||
|
||||
int mmhub_v2_0_gart_enable(struct amdgpu_device *adev);
|
||||
void mmhub_v2_0_gart_disable(struct amdgpu_device *adev);
|
||||
void mmhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev,
|
||||
bool value);
|
||||
void mmhub_v2_0_init(struct amdgpu_device *adev);
|
||||
int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev,
|
||||
enum amd_clockgating_state state);
|
||||
void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags);
|
||||
|
||||
#endif
|
|
@ -451,19 +451,16 @@ void xgpu_ai_mailbox_put_irq(struct amdgpu_device *adev)
|
|||
|
||||
static void xgpu_ai_init_reg_access_mode(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t rlc_fw_ver = RREG32_SOC15(GC, 0, mmRLC_GPM_GENERAL_6);
|
||||
uint32_t sos_fw_ver = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_58);
|
||||
|
||||
adev->virt.reg_access_mode = AMDGPU_VIRT_REG_ACCESS_LEGACY;
|
||||
|
||||
if (rlc_fw_ver >= 0x5d)
|
||||
adev->virt.reg_access_mode |= AMDGPU_VIRT_REG_ACCESS_RLC;
|
||||
/* Enable L1 security reg access mode by defaul, as non-security VF
|
||||
* will no longer be supported.
|
||||
*/
|
||||
adev->virt.reg_access_mode |= AMDGPU_VIRT_REG_ACCESS_RLC;
|
||||
|
||||
if (sos_fw_ver >= 0x80455)
|
||||
adev->virt.reg_access_mode |= AMDGPU_VIRT_REG_ACCESS_PSP_PRG_IH;
|
||||
adev->virt.reg_access_mode |= AMDGPU_VIRT_REG_ACCESS_PSP_PRG_IH;
|
||||
|
||||
if (sos_fw_ver >= 0x8045b)
|
||||
adev->virt.reg_access_mode |= AMDGPU_VIRT_REG_SKIP_SEETING;
|
||||
adev->virt.reg_access_mode |= AMDGPU_VIRT_REG_SKIP_SEETING;
|
||||
}
|
||||
|
||||
const struct amdgpu_virt_ops xgpu_ai_virt_ops = {
|
||||
|
|
|
@ -0,0 +1,486 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_ih.h"
|
||||
|
||||
#include "oss/osssys_5_0_0_offset.h"
|
||||
#include "oss/osssys_5_0_0_sh_mask.h"
|
||||
|
||||
#include "soc15_common.h"
|
||||
#include "navi10_ih.h"
|
||||
|
||||
|
||||
static void navi10_ih_set_interrupt_funcs(struct amdgpu_device *adev);
|
||||
|
||||
/**
|
||||
* navi10_ih_enable_interrupts - Enable the interrupt ring buffer
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Enable the interrupt ring buffer (NAVI10).
|
||||
*/
|
||||
static void navi10_ih_enable_interrupts(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
|
||||
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_ENABLE, 1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 1);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
|
||||
adev->irq.ih.enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* navi10_ih_disable_interrupts - Disable the interrupt ring buffer
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Disable the interrupt ring buffer (NAVI10).
|
||||
*/
|
||||
static void navi10_ih_disable_interrupts(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
|
||||
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_ENABLE, 0);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
|
||||
/* set rptr, wptr to 0 */
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);
|
||||
adev->irq.ih.enabled = false;
|
||||
adev->irq.ih.rptr = 0;
|
||||
}
|
||||
|
||||
static uint32_t navi10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
|
||||
{
|
||||
int rb_bufsz = order_base_2(ih->ring_size / 4);
|
||||
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
|
||||
MC_SPACE, ih->use_bus_addr ? 1 : 4);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
|
||||
WPTR_OVERFLOW_CLEAR, 1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
|
||||
WPTR_OVERFLOW_ENABLE, 1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
|
||||
/* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register
|
||||
* value is written to memory
|
||||
*/
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
|
||||
WPTR_WRITEBACK_ENABLE, 1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
|
||||
|
||||
return ih_rb_cntl;
|
||||
}
|
||||
|
||||
/**
|
||||
* navi10_ih_irq_init - init and enable the interrupt ring
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Allocate a ring buffer for the interrupt controller,
|
||||
* enable the RLC, disable interrupts, enable the IH
|
||||
* ring buffer and enable it (NAVI).
|
||||
* Called at device load and reume.
|
||||
* Returns 0 for success, errors for failure.
|
||||
*/
|
||||
static int navi10_ih_irq_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ih_ring *ih = &adev->irq.ih;
|
||||
int ret = 0;
|
||||
u32 ih_rb_cntl, ih_doorbell_rtpr, ih_chicken;
|
||||
u32 tmp;
|
||||
|
||||
/* disable irqs */
|
||||
navi10_ih_disable_interrupts(adev);
|
||||
|
||||
adev->nbio_funcs->ih_control(adev);
|
||||
|
||||
/* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, ih->gpu_addr >> 8);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, (ih->gpu_addr >> 40) & 0xff);
|
||||
|
||||
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
|
||||
ih_rb_cntl = navi10_ih_rb_cntl(ih, ih_rb_cntl);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM,
|
||||
!!adev->irq.msi_enabled);
|
||||
|
||||
if (unlikely(adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT)) {
|
||||
if (ih->use_bus_addr) {
|
||||
ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN);
|
||||
ih_chicken = REG_SET_FIELD(ih_chicken,
|
||||
IH_CHICKEN, MC_SPACE_GPA_ENABLE, 1);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN, ih_chicken);
|
||||
}
|
||||
}
|
||||
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
|
||||
|
||||
/* set the writeback address whether it's enabled or not */
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_LO,
|
||||
lower_32_bits(ih->wptr_addr));
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_HI,
|
||||
upper_32_bits(ih->wptr_addr) & 0xFFFF);
|
||||
|
||||
/* set rptr, wptr to 0 */
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);
|
||||
|
||||
ih_doorbell_rtpr = RREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR);
|
||||
if (ih->use_doorbell) {
|
||||
ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
|
||||
IH_DOORBELL_RPTR, OFFSET,
|
||||
ih->doorbell_index);
|
||||
ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
|
||||
IH_DOORBELL_RPTR, ENABLE, 1);
|
||||
} else {
|
||||
ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
|
||||
IH_DOORBELL_RPTR, ENABLE, 0);
|
||||
}
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR, ih_doorbell_rtpr);
|
||||
|
||||
adev->nbio_funcs->ih_doorbell_range(adev, ih->use_doorbell,
|
||||
ih->doorbell_index);
|
||||
|
||||
tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, IH_STORM_CLIENT_LIST_CNTL,
|
||||
CLIENT18_IS_STORM_CLIENT, 1);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL, tmp);
|
||||
|
||||
tmp = RREG32_SOC15(OSSSYS, 0, mmIH_INT_FLOOD_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, IH_INT_FLOOD_CNTL, FLOOD_CNTL_ENABLE, 1);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_INT_FLOOD_CNTL, tmp);
|
||||
|
||||
pci_set_master(adev->pdev);
|
||||
|
||||
/* enable interrupts */
|
||||
navi10_ih_enable_interrupts(adev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* navi10_ih_irq_disable - disable interrupts
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Disable interrupts on the hw (NAVI10).
|
||||
*/
|
||||
static void navi10_ih_irq_disable(struct amdgpu_device *adev)
|
||||
{
|
||||
navi10_ih_disable_interrupts(adev);
|
||||
|
||||
/* Wait and acknowledge irq */
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* navi10_ih_get_wptr - get the IH ring buffer wptr
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Get the IH ring buffer wptr from either the register
|
||||
* or the writeback memory buffer (NAVI10). Also check for
|
||||
* ring buffer overflow and deal with it.
|
||||
* Returns the value of the wptr.
|
||||
*/
|
||||
static u32 navi10_ih_get_wptr(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
u32 wptr, reg, tmp;
|
||||
|
||||
wptr = le32_to_cpu(*ih->wptr_cpu);
|
||||
|
||||
if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
|
||||
goto out;
|
||||
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR);
|
||||
wptr = RREG32_NO_KIQ(reg);
|
||||
if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
|
||||
goto out;
|
||||
wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
|
||||
|
||||
/* When a ring buffer overflow happen start parsing interrupt
|
||||
* from the last not overwritten vector (wptr + 32). Hopefully
|
||||
* this should allow us to catch up.
|
||||
*/
|
||||
tmp = (wptr + 32) & ih->ptr_mask;
|
||||
dev_warn(adev->dev, "IH ring buffer overflow "
|
||||
"(0x%08X, 0x%08X, 0x%08X)\n",
|
||||
wptr, ih->rptr, tmp);
|
||||
ih->rptr = tmp;
|
||||
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL);
|
||||
tmp = RREG32_NO_KIQ(reg);
|
||||
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
|
||||
WREG32_NO_KIQ(reg, tmp);
|
||||
out:
|
||||
return (wptr & ih->ptr_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* navi10_ih_decode_iv - decode an interrupt vector
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Decodes the interrupt vector at the current rptr
|
||||
* position and also advance the position.
|
||||
*/
|
||||
static void navi10_ih_decode_iv(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
/* wptr/rptr are in bytes! */
|
||||
u32 ring_index = ih->rptr >> 2;
|
||||
uint32_t dw[8];
|
||||
|
||||
dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
|
||||
dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
|
||||
dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
|
||||
dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
|
||||
dw[4] = le32_to_cpu(ih->ring[ring_index + 4]);
|
||||
dw[5] = le32_to_cpu(ih->ring[ring_index + 5]);
|
||||
dw[6] = le32_to_cpu(ih->ring[ring_index + 6]);
|
||||
dw[7] = le32_to_cpu(ih->ring[ring_index + 7]);
|
||||
|
||||
entry->client_id = dw[0] & 0xff;
|
||||
entry->src_id = (dw[0] >> 8) & 0xff;
|
||||
entry->ring_id = (dw[0] >> 16) & 0xff;
|
||||
entry->vmid = (dw[0] >> 24) & 0xf;
|
||||
entry->vmid_src = (dw[0] >> 31);
|
||||
entry->timestamp = dw[1] | ((u64)(dw[2] & 0xffff) << 32);
|
||||
entry->timestamp_src = dw[2] >> 31;
|
||||
entry->pasid = dw[3] & 0xffff;
|
||||
entry->pasid_src = dw[3] >> 31;
|
||||
entry->src_data[0] = dw[4];
|
||||
entry->src_data[1] = dw[5];
|
||||
entry->src_data[2] = dw[6];
|
||||
entry->src_data[3] = dw[7];
|
||||
|
||||
/* wptr/rptr are in bytes! */
|
||||
ih->rptr += 32;
|
||||
}
|
||||
|
||||
/**
|
||||
* navi10_ih_set_rptr - set the IH ring buffer rptr
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Set the IH ring buffer rptr.
|
||||
*/
|
||||
static void navi10_ih_set_rptr(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
if (ih->use_doorbell) {
|
||||
/* XXX check if swapping is necessary on BE */
|
||||
*ih->rptr_cpu = ih->rptr;
|
||||
WDOORBELL32(ih->doorbell_index, ih->rptr);
|
||||
} else
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, ih->rptr);
|
||||
}
|
||||
|
||||
static int navi10_ih_early_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
navi10_ih_set_interrupt_funcs(adev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int navi10_ih_sw_init(void *handle)
|
||||
{
|
||||
int r;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
bool use_bus_addr;
|
||||
|
||||
/* use gpu virtual address for ih ring
|
||||
* until ih_checken is programmed to allow
|
||||
* use bus address for ih ring by psp bl */
|
||||
use_bus_addr =
|
||||
(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) ? false : true;
|
||||
r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, use_bus_addr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
adev->irq.ih.use_doorbell = true;
|
||||
adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1;
|
||||
|
||||
r = amdgpu_irq_init(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int navi10_ih_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_irq_fini(adev);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int navi10_ih_hw_init(void *handle)
|
||||
{
|
||||
int r;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
r = navi10_ih_irq_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int navi10_ih_hw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
navi10_ih_irq_disable(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int navi10_ih_suspend(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
return navi10_ih_hw_fini(adev);
|
||||
}
|
||||
|
||||
static int navi10_ih_resume(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
return navi10_ih_hw_init(adev);
|
||||
}
|
||||
|
||||
static bool navi10_ih_is_idle(void *handle)
|
||||
{
|
||||
/* todo */
|
||||
return true;
|
||||
}
|
||||
|
||||
static int navi10_ih_wait_for_idle(void *handle)
|
||||
{
|
||||
/* todo */
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int navi10_ih_soft_reset(void *handle)
|
||||
{
|
||||
/* todo */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void navi10_ih_update_clockgating_state(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
uint32_t data, def, field_val;
|
||||
|
||||
if (adev->cg_flags & AMD_CG_SUPPORT_IH_CG) {
|
||||
def = data = RREG32_SOC15(OSSSYS, 0, mmIH_CLK_CTRL);
|
||||
field_val = enable ? 0 : 1;
|
||||
data = REG_SET_FIELD(data, IH_CLK_CTRL,
|
||||
DBUS_MUX_CLK_SOFT_OVERRIDE, field_val);
|
||||
data = REG_SET_FIELD(data, IH_CLK_CTRL,
|
||||
OSSSYS_SHARE_CLK_SOFT_OVERRIDE, field_val);
|
||||
data = REG_SET_FIELD(data, IH_CLK_CTRL,
|
||||
LIMIT_SMN_CLK_SOFT_OVERRIDE, field_val);
|
||||
data = REG_SET_FIELD(data, IH_CLK_CTRL,
|
||||
DYN_CLK_SOFT_OVERRIDE, field_val);
|
||||
data = REG_SET_FIELD(data, IH_CLK_CTRL,
|
||||
REG_CLK_SOFT_OVERRIDE, field_val);
|
||||
if (def != data)
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_CLK_CTRL, data);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int navi10_ih_set_clockgating_state(void *handle,
|
||||
enum amd_clockgating_state state)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
navi10_ih_update_clockgating_state(adev,
|
||||
state == AMD_CG_STATE_GATE ? true : false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int navi10_ih_set_powergating_state(void *handle,
|
||||
enum amd_powergating_state state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void navi10_ih_get_clockgating_state(void *handle, u32 *flags)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (!RREG32_SOC15(OSSSYS, 0, mmIH_CLK_CTRL))
|
||||
*flags |= AMD_CG_SUPPORT_IH_CG;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static const struct amd_ip_funcs navi10_ih_ip_funcs = {
|
||||
.name = "navi10_ih",
|
||||
.early_init = navi10_ih_early_init,
|
||||
.late_init = NULL,
|
||||
.sw_init = navi10_ih_sw_init,
|
||||
.sw_fini = navi10_ih_sw_fini,
|
||||
.hw_init = navi10_ih_hw_init,
|
||||
.hw_fini = navi10_ih_hw_fini,
|
||||
.suspend = navi10_ih_suspend,
|
||||
.resume = navi10_ih_resume,
|
||||
.is_idle = navi10_ih_is_idle,
|
||||
.wait_for_idle = navi10_ih_wait_for_idle,
|
||||
.soft_reset = navi10_ih_soft_reset,
|
||||
.set_clockgating_state = navi10_ih_set_clockgating_state,
|
||||
.set_powergating_state = navi10_ih_set_powergating_state,
|
||||
.get_clockgating_state = navi10_ih_get_clockgating_state,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ih_funcs navi10_ih_funcs = {
|
||||
.get_wptr = navi10_ih_get_wptr,
|
||||
.decode_iv = navi10_ih_decode_iv,
|
||||
.set_rptr = navi10_ih_set_rptr
|
||||
};
|
||||
|
||||
static void navi10_ih_set_interrupt_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->irq.ih_funcs == NULL)
|
||||
adev->irq.ih_funcs = &navi10_ih_funcs;
|
||||
}
|
||||
|
||||
const struct amdgpu_ip_block_version navi10_ih_ip_block =
|
||||
{
|
||||
.type = AMD_IP_BLOCK_TYPE_IH,
|
||||
.major = 5,
|
||||
.minor = 0,
|
||||
.rev = 0,
|
||||
.funcs = &navi10_ih_ip_funcs,
|
||||
};
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __NAVI10_IH_H__
|
||||
#define __NAVI10_IH_H__
|
||||
|
||||
extern const struct amdgpu_ip_block_version navi10_ih_ip_block;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright 2018 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include "amdgpu.h"
|
||||
#include "nv.h"
|
||||
|
||||
#include "soc15_common.h"
|
||||
#include "soc15_hw_ip.h"
|
||||
#include "navi10_ip_offset.h"
|
||||
|
||||
int navi10_reg_base_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int r, i;
|
||||
|
||||
if (amdgpu_discovery) {
|
||||
r = amdgpu_discovery_reg_base_init(adev);
|
||||
if (r) {
|
||||
DRM_WARN("failed to init reg base from ip discovery table, "
|
||||
"fallback to legacy init method\n");
|
||||
goto legacy_init;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
legacy_init:
|
||||
for (i = 0 ; i < MAX_INSTANCE ; ++i) {
|
||||
adev->reg_offset[GC_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
|
||||
adev->reg_offset[HDP_HWIP][i] = (uint32_t *)(&(HDP_BASE.instance[i]));
|
||||
adev->reg_offset[MMHUB_HWIP][i] = (uint32_t *)(&(MMHUB_BASE.instance[i]));
|
||||
adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i]));
|
||||
adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i]));
|
||||
adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i]));
|
||||
adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i]));
|
||||
adev->reg_offset[VCN_HWIP][i] = (uint32_t *)(&(VCN_BASE.instance[i]));
|
||||
adev->reg_offset[DF_HWIP][i] = (uint32_t *)(&(DF_BASE.instance[i]));
|
||||
adev->reg_offset[DCE_HWIP][i] = (uint32_t *)(&(DCN_BASE.instance[i]));
|
||||
adev->reg_offset[OSSSYS_HWIP][i] = (uint32_t *)(&(OSSSYS_BASE.instance[i]));
|
||||
adev->reg_offset[SDMA0_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
|
||||
adev->reg_offset[SDMA1_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
|
||||
adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
|
||||
adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i]));
|
||||
adev->reg_offset[CLK_HWIP][i] = (uint32_t *)(&(CLK_BASE.instance[i]));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,334 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_atombios.h"
|
||||
#include "nbio_v2_3.h"
|
||||
|
||||
#include "nbio/nbio_2_3_default.h"
|
||||
#include "nbio/nbio_2_3_offset.h"
|
||||
#include "nbio/nbio_2_3_sh_mask.h"
|
||||
|
||||
#define smnPCIE_CONFIG_CNTL 0x11180044
|
||||
#define smnCPM_CONTROL 0x11180460
|
||||
#define smnPCIE_CNTL2 0x11180070
|
||||
|
||||
static u32 nbio_v2_3_get_rev_id(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 tmp = RREG32_SOC15(NBIO, 0, mmRCC_DEV0_EPF0_STRAP0);
|
||||
|
||||
tmp &= RCC_DEV0_EPF0_STRAP0__STRAP_ATI_REV_ID_DEV0_F0_MASK;
|
||||
tmp >>= RCC_DEV0_EPF0_STRAP0__STRAP_ATI_REV_ID_DEV0_F0__SHIFT;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static void nbio_v2_3_mc_access_enable(struct amdgpu_device *adev, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
WREG32_SOC15(NBIO, 0, mmBIF_FB_EN,
|
||||
BIF_FB_EN__FB_READ_EN_MASK |
|
||||
BIF_FB_EN__FB_WRITE_EN_MASK);
|
||||
else
|
||||
WREG32_SOC15(NBIO, 0, mmBIF_FB_EN, 0);
|
||||
}
|
||||
|
||||
static void nbio_v2_3_hdp_flush(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring)
|
||||
{
|
||||
if (!ring || !ring->funcs->emit_wreg)
|
||||
WREG32_SOC15_NO_KIQ(NBIO, 0, mmBIF_BX_PF_HDP_MEM_COHERENCY_FLUSH_CNTL, 0);
|
||||
else
|
||||
amdgpu_ring_emit_wreg(ring, SOC15_REG_OFFSET(
|
||||
NBIO, 0, mmBIF_BX_PF_HDP_MEM_COHERENCY_FLUSH_CNTL), 0);
|
||||
}
|
||||
|
||||
static u32 nbio_v2_3_get_memsize(struct amdgpu_device *adev)
|
||||
{
|
||||
return RREG32_SOC15(NBIO, 0, mmRCC_DEV0_EPF0_RCC_CONFIG_MEMSIZE);
|
||||
}
|
||||
|
||||
static void nbio_v2_3_sdma_doorbell_range(struct amdgpu_device *adev, int instance,
|
||||
bool use_doorbell, int doorbell_index,
|
||||
int doorbell_size)
|
||||
{
|
||||
u32 reg = instance == 0 ? SOC15_REG_OFFSET(NBIO, 0, mmBIF_SDMA0_DOORBELL_RANGE) :
|
||||
SOC15_REG_OFFSET(NBIO, 0, mmBIF_SDMA1_DOORBELL_RANGE);
|
||||
|
||||
u32 doorbell_range = RREG32(reg);
|
||||
|
||||
if (use_doorbell) {
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range,
|
||||
BIF_SDMA0_DOORBELL_RANGE, OFFSET,
|
||||
doorbell_index);
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range,
|
||||
BIF_SDMA0_DOORBELL_RANGE, SIZE,
|
||||
doorbell_size);
|
||||
} else
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range,
|
||||
BIF_SDMA0_DOORBELL_RANGE, SIZE,
|
||||
0);
|
||||
|
||||
WREG32(reg, doorbell_range);
|
||||
}
|
||||
|
||||
static void nbio_v2_3_vcn_doorbell_range(struct amdgpu_device *adev, bool use_doorbell,
|
||||
int doorbell_index)
|
||||
{
|
||||
u32 reg = SOC15_REG_OFFSET(NBIO, 0, mmBIF_MMSCH0_DOORBELL_RANGE);
|
||||
|
||||
u32 doorbell_range = RREG32(reg);
|
||||
|
||||
if (use_doorbell) {
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range,
|
||||
BIF_MMSCH0_DOORBELL_RANGE, OFFSET,
|
||||
doorbell_index);
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range,
|
||||
BIF_MMSCH0_DOORBELL_RANGE, SIZE, 8);
|
||||
} else
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range,
|
||||
BIF_MMSCH0_DOORBELL_RANGE, SIZE, 0);
|
||||
|
||||
WREG32(reg, doorbell_range);
|
||||
}
|
||||
|
||||
static void nbio_v2_3_enable_doorbell_aperture(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
WREG32_FIELD15(NBIO, 0, RCC_DEV0_EPF0_RCC_DOORBELL_APER_EN, BIF_DOORBELL_APER_EN,
|
||||
enable ? 1 : 0);
|
||||
}
|
||||
|
||||
static void nbio_v2_3_enable_doorbell_selfring_aperture(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
u32 tmp = 0;
|
||||
|
||||
if (enable) {
|
||||
tmp = REG_SET_FIELD(tmp, BIF_BX_PF_DOORBELL_SELFRING_GPA_APER_CNTL,
|
||||
DOORBELL_SELFRING_GPA_APER_EN, 1) |
|
||||
REG_SET_FIELD(tmp, BIF_BX_PF_DOORBELL_SELFRING_GPA_APER_CNTL,
|
||||
DOORBELL_SELFRING_GPA_APER_MODE, 1) |
|
||||
REG_SET_FIELD(tmp, BIF_BX_PF_DOORBELL_SELFRING_GPA_APER_CNTL,
|
||||
DOORBELL_SELFRING_GPA_APER_SIZE, 0);
|
||||
|
||||
WREG32_SOC15(NBIO, 0, mmBIF_BX_PF_DOORBELL_SELFRING_GPA_APER_BASE_LOW,
|
||||
lower_32_bits(adev->doorbell.base));
|
||||
WREG32_SOC15(NBIO, 0, mmBIF_BX_PF_DOORBELL_SELFRING_GPA_APER_BASE_HIGH,
|
||||
upper_32_bits(adev->doorbell.base));
|
||||
}
|
||||
|
||||
WREG32_SOC15(NBIO, 0, mmBIF_BX_PF_DOORBELL_SELFRING_GPA_APER_CNTL,
|
||||
tmp);
|
||||
}
|
||||
|
||||
|
||||
static void nbio_v2_3_ih_doorbell_range(struct amdgpu_device *adev,
|
||||
bool use_doorbell, int doorbell_index)
|
||||
{
|
||||
u32 ih_doorbell_range = RREG32_SOC15(NBIO, 0, mmBIF_IH_DOORBELL_RANGE);
|
||||
|
||||
if (use_doorbell) {
|
||||
ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range,
|
||||
BIF_IH_DOORBELL_RANGE, OFFSET,
|
||||
doorbell_index);
|
||||
ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range,
|
||||
BIF_IH_DOORBELL_RANGE, SIZE,
|
||||
2);
|
||||
} else
|
||||
ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range,
|
||||
BIF_IH_DOORBELL_RANGE, SIZE,
|
||||
0);
|
||||
|
||||
WREG32_SOC15(NBIO, 0, mmBIF_IH_DOORBELL_RANGE, ih_doorbell_range);
|
||||
}
|
||||
|
||||
static void nbio_v2_3_ih_control(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 interrupt_cntl;
|
||||
|
||||
/* setup interrupt control */
|
||||
WREG32_SOC15(NBIO, 0, mmINTERRUPT_CNTL2, adev->dummy_page_addr >> 8);
|
||||
|
||||
interrupt_cntl = RREG32_SOC15(NBIO, 0, mmINTERRUPT_CNTL);
|
||||
/*
|
||||
* INTERRUPT_CNTL__IH_DUMMY_RD_OVERRIDE_MASK=0 - dummy read disabled with msi, enabled without msi
|
||||
* INTERRUPT_CNTL__IH_DUMMY_RD_OVERRIDE_MASK=1 - dummy read controlled by IH_DUMMY_RD_EN
|
||||
*/
|
||||
interrupt_cntl = REG_SET_FIELD(interrupt_cntl, INTERRUPT_CNTL,
|
||||
IH_DUMMY_RD_OVERRIDE, 0);
|
||||
|
||||
/* INTERRUPT_CNTL__IH_REQ_NONSNOOP_EN_MASK=1 if ring is in non-cacheable memory, e.g., vram */
|
||||
interrupt_cntl = REG_SET_FIELD(interrupt_cntl, INTERRUPT_CNTL,
|
||||
IH_REQ_NONSNOOP_EN, 0);
|
||||
|
||||
WREG32_SOC15(NBIO, 0, mmINTERRUPT_CNTL, interrupt_cntl);
|
||||
}
|
||||
|
||||
static void nbio_v2_3_update_medium_grain_clock_gating(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
uint32_t def, data;
|
||||
|
||||
def = data = RREG32_PCIE(smnCPM_CONTROL);
|
||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_BIF_MGCG)) {
|
||||
data |= (CPM_CONTROL__LCLK_DYN_GATE_ENABLE_MASK |
|
||||
CPM_CONTROL__TXCLK_DYN_GATE_ENABLE_MASK |
|
||||
CPM_CONTROL__TXCLK_LCNT_GATE_ENABLE_MASK |
|
||||
CPM_CONTROL__TXCLK_REGS_GATE_ENABLE_MASK |
|
||||
CPM_CONTROL__TXCLK_PRBS_GATE_ENABLE_MASK |
|
||||
CPM_CONTROL__REFCLK_REGS_GATE_ENABLE_MASK);
|
||||
} else {
|
||||
data &= ~(CPM_CONTROL__LCLK_DYN_GATE_ENABLE_MASK |
|
||||
CPM_CONTROL__TXCLK_DYN_GATE_ENABLE_MASK |
|
||||
CPM_CONTROL__TXCLK_LCNT_GATE_ENABLE_MASK |
|
||||
CPM_CONTROL__TXCLK_REGS_GATE_ENABLE_MASK |
|
||||
CPM_CONTROL__TXCLK_PRBS_GATE_ENABLE_MASK |
|
||||
CPM_CONTROL__REFCLK_REGS_GATE_ENABLE_MASK);
|
||||
}
|
||||
|
||||
if (def != data)
|
||||
WREG32_PCIE(smnCPM_CONTROL, data);
|
||||
}
|
||||
|
||||
static void nbio_v2_3_update_medium_grain_light_sleep(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
uint32_t def, data;
|
||||
|
||||
def = data = RREG32_PCIE(smnPCIE_CNTL2);
|
||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_BIF_LS)) {
|
||||
data |= (PCIE_CNTL2__SLV_MEM_LS_EN_MASK |
|
||||
PCIE_CNTL2__MST_MEM_LS_EN_MASK |
|
||||
PCIE_CNTL2__REPLAY_MEM_LS_EN_MASK);
|
||||
} else {
|
||||
data &= ~(PCIE_CNTL2__SLV_MEM_LS_EN_MASK |
|
||||
PCIE_CNTL2__MST_MEM_LS_EN_MASK |
|
||||
PCIE_CNTL2__REPLAY_MEM_LS_EN_MASK);
|
||||
}
|
||||
|
||||
if (def != data)
|
||||
WREG32_PCIE(smnPCIE_CNTL2, data);
|
||||
}
|
||||
|
||||
static void nbio_v2_3_get_clockgating_state(struct amdgpu_device *adev,
|
||||
u32 *flags)
|
||||
{
|
||||
int data;
|
||||
|
||||
/* AMD_CG_SUPPORT_BIF_MGCG */
|
||||
data = RREG32_PCIE(smnCPM_CONTROL);
|
||||
if (data & CPM_CONTROL__LCLK_DYN_GATE_ENABLE_MASK)
|
||||
*flags |= AMD_CG_SUPPORT_BIF_MGCG;
|
||||
|
||||
/* AMD_CG_SUPPORT_BIF_LS */
|
||||
data = RREG32_PCIE(smnPCIE_CNTL2);
|
||||
if (data & PCIE_CNTL2__SLV_MEM_LS_EN_MASK)
|
||||
*flags |= AMD_CG_SUPPORT_BIF_LS;
|
||||
}
|
||||
|
||||
static u32 nbio_v2_3_get_hdp_flush_req_offset(struct amdgpu_device *adev)
|
||||
{
|
||||
return SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_GPU_HDP_FLUSH_REQ);
|
||||
}
|
||||
|
||||
static u32 nbio_v2_3_get_hdp_flush_done_offset(struct amdgpu_device *adev)
|
||||
{
|
||||
return SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_GPU_HDP_FLUSH_DONE);
|
||||
}
|
||||
|
||||
static u32 nbio_v2_3_get_pcie_index_offset(struct amdgpu_device *adev)
|
||||
{
|
||||
return SOC15_REG_OFFSET(NBIO, 0, mmPCIE_INDEX2);
|
||||
}
|
||||
|
||||
static u32 nbio_v2_3_get_pcie_data_offset(struct amdgpu_device *adev)
|
||||
{
|
||||
return SOC15_REG_OFFSET(NBIO, 0, mmPCIE_DATA2);
|
||||
}
|
||||
|
||||
const struct nbio_hdp_flush_reg nbio_v2_3_hdp_flush_reg = {
|
||||
.ref_and_mask_cp0 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP0_MASK,
|
||||
.ref_and_mask_cp1 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP1_MASK,
|
||||
.ref_and_mask_cp2 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP2_MASK,
|
||||
.ref_and_mask_cp3 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP3_MASK,
|
||||
.ref_and_mask_cp4 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP4_MASK,
|
||||
.ref_and_mask_cp5 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP5_MASK,
|
||||
.ref_and_mask_cp6 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP6_MASK,
|
||||
.ref_and_mask_cp7 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP7_MASK,
|
||||
.ref_and_mask_cp8 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP8_MASK,
|
||||
.ref_and_mask_cp9 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP9_MASK,
|
||||
.ref_and_mask_sdma0 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__SDMA0_MASK,
|
||||
.ref_and_mask_sdma1 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__SDMA1_MASK,
|
||||
};
|
||||
|
||||
static void nbio_v2_3_detect_hw_virt(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
reg = RREG32_SOC15(NBIO, 0, mmRCC_DEV0_EPF0_RCC_IOV_FUNC_IDENTIFIER);
|
||||
if (reg & 1)
|
||||
adev->virt.caps |= AMDGPU_SRIOV_CAPS_IS_VF;
|
||||
|
||||
if (reg & 0x80000000)
|
||||
adev->virt.caps |= AMDGPU_SRIOV_CAPS_ENABLE_IOV;
|
||||
|
||||
if (!reg) {
|
||||
if (is_virtual_machine()) /* passthrough mode exclus sriov mod */
|
||||
adev->virt.caps |= AMDGPU_PASSTHROUGH_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
static void nbio_v2_3_init_registers(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t def, data;
|
||||
|
||||
def = data = RREG32_PCIE(smnPCIE_CONFIG_CNTL);
|
||||
data = REG_SET_FIELD(data, PCIE_CONFIG_CNTL, CI_SWUS_MAX_READ_REQUEST_SIZE_MODE, 1);
|
||||
data = REG_SET_FIELD(data, PCIE_CONFIG_CNTL, CI_SWUS_MAX_READ_REQUEST_SIZE_PRIV, 1);
|
||||
|
||||
if (def != data)
|
||||
WREG32_PCIE(smnPCIE_CONFIG_CNTL, data);
|
||||
}
|
||||
|
||||
const struct amdgpu_nbio_funcs nbio_v2_3_funcs = {
|
||||
.hdp_flush_reg = &nbio_v2_3_hdp_flush_reg,
|
||||
.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_pcie_index_offset = nbio_v2_3_get_pcie_index_offset,
|
||||
.get_pcie_data_offset = nbio_v2_3_get_pcie_data_offset,
|
||||
.get_rev_id = nbio_v2_3_get_rev_id,
|
||||
.mc_access_enable = nbio_v2_3_mc_access_enable,
|
||||
.hdp_flush = nbio_v2_3_hdp_flush,
|
||||
.get_memsize = nbio_v2_3_get_memsize,
|
||||
.sdma_doorbell_range = nbio_v2_3_sdma_doorbell_range,
|
||||
.vcn_doorbell_range = nbio_v2_3_vcn_doorbell_range,
|
||||
.enable_doorbell_aperture = nbio_v2_3_enable_doorbell_aperture,
|
||||
.enable_doorbell_selfring_aperture = nbio_v2_3_enable_doorbell_selfring_aperture,
|
||||
.ih_doorbell_range = nbio_v2_3_ih_doorbell_range,
|
||||
.update_medium_grain_clock_gating = nbio_v2_3_update_medium_grain_clock_gating,
|
||||
.update_medium_grain_light_sleep = nbio_v2_3_update_medium_grain_light_sleep,
|
||||
.get_clockgating_state = nbio_v2_3_get_clockgating_state,
|
||||
.ih_control = nbio_v2_3_ih_control,
|
||||
.init_registers = nbio_v2_3_init_registers,
|
||||
.detect_hw_virt = nbio_v2_3_detect_hw_virt,
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __NBIO_V2_3_H__
|
||||
#define __NBIO_V2_3_H__
|
||||
|
||||
#include "soc15_common.h"
|
||||
|
||||
extern const struct amdgpu_nbio_funcs nbio_v2_3_funcs;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,778 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <drm/drmP.h>
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_atombios.h"
|
||||
#include "amdgpu_ih.h"
|
||||
#include "amdgpu_uvd.h"
|
||||
#include "amdgpu_vce.h"
|
||||
#include "amdgpu_ucode.h"
|
||||
#include "amdgpu_psp.h"
|
||||
#include "atom.h"
|
||||
#include "amd_pcie.h"
|
||||
|
||||
#include "gc/gc_10_1_0_offset.h"
|
||||
#include "gc/gc_10_1_0_sh_mask.h"
|
||||
#include "hdp/hdp_5_0_0_offset.h"
|
||||
#include "hdp/hdp_5_0_0_sh_mask.h"
|
||||
|
||||
#include "soc15.h"
|
||||
#include "soc15_common.h"
|
||||
#include "gmc_v10_0.h"
|
||||
#include "gfxhub_v2_0.h"
|
||||
#include "mmhub_v2_0.h"
|
||||
#include "nv.h"
|
||||
#include "navi10_ih.h"
|
||||
#include "gfx_v10_0.h"
|
||||
#include "sdma_v5_0.h"
|
||||
#include "vcn_v2_0.h"
|
||||
#include "dce_virtual.h"
|
||||
#include "mes_v10_1.h"
|
||||
|
||||
static const struct amd_ip_funcs nv_common_ip_funcs;
|
||||
|
||||
/*
|
||||
* Indirect registers accessor
|
||||
*/
|
||||
static u32 nv_pcie_rreg(struct amdgpu_device *adev, u32 reg)
|
||||
{
|
||||
unsigned long flags, address, data;
|
||||
u32 r;
|
||||
address = adev->nbio_funcs->get_pcie_index_offset(adev);
|
||||
data = adev->nbio_funcs->get_pcie_data_offset(adev);
|
||||
|
||||
spin_lock_irqsave(&adev->pcie_idx_lock, flags);
|
||||
WREG32(address, reg);
|
||||
(void)RREG32(address);
|
||||
r = RREG32(data);
|
||||
spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void nv_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags, address, data;
|
||||
|
||||
address = adev->nbio_funcs->get_pcie_index_offset(adev);
|
||||
data = adev->nbio_funcs->get_pcie_data_offset(adev);
|
||||
|
||||
spin_lock_irqsave(&adev->pcie_idx_lock, flags);
|
||||
WREG32(address, reg);
|
||||
(void)RREG32(address);
|
||||
WREG32(data, v);
|
||||
(void)RREG32(data);
|
||||
spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
|
||||
}
|
||||
|
||||
static u32 nv_didt_rreg(struct amdgpu_device *adev, u32 reg)
|
||||
{
|
||||
unsigned long flags, address, data;
|
||||
u32 r;
|
||||
|
||||
address = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_INDEX);
|
||||
data = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_DATA);
|
||||
|
||||
spin_lock_irqsave(&adev->didt_idx_lock, flags);
|
||||
WREG32(address, (reg));
|
||||
r = RREG32(data);
|
||||
spin_unlock_irqrestore(&adev->didt_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void nv_didt_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags, address, data;
|
||||
|
||||
address = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_INDEX);
|
||||
data = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_DATA);
|
||||
|
||||
spin_lock_irqsave(&adev->didt_idx_lock, flags);
|
||||
WREG32(address, (reg));
|
||||
WREG32(data, (v));
|
||||
spin_unlock_irqrestore(&adev->didt_idx_lock, flags);
|
||||
}
|
||||
|
||||
static u32 nv_get_config_memsize(struct amdgpu_device *adev)
|
||||
{
|
||||
return adev->nbio_funcs->get_memsize(adev);
|
||||
}
|
||||
|
||||
static u32 nv_get_xclk(struct amdgpu_device *adev)
|
||||
{
|
||||
return adev->clock.spll.reference_freq;
|
||||
}
|
||||
|
||||
|
||||
void nv_grbm_select(struct amdgpu_device *adev,
|
||||
u32 me, u32 pipe, u32 queue, u32 vmid)
|
||||
{
|
||||
u32 grbm_gfx_cntl = 0;
|
||||
grbm_gfx_cntl = REG_SET_FIELD(grbm_gfx_cntl, GRBM_GFX_CNTL, PIPEID, pipe);
|
||||
grbm_gfx_cntl = REG_SET_FIELD(grbm_gfx_cntl, GRBM_GFX_CNTL, MEID, me);
|
||||
grbm_gfx_cntl = REG_SET_FIELD(grbm_gfx_cntl, GRBM_GFX_CNTL, VMID, vmid);
|
||||
grbm_gfx_cntl = REG_SET_FIELD(grbm_gfx_cntl, GRBM_GFX_CNTL, QUEUEID, queue);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_CNTL), grbm_gfx_cntl);
|
||||
}
|
||||
|
||||
static void nv_vga_set_state(struct amdgpu_device *adev, bool state)
|
||||
{
|
||||
/* todo */
|
||||
}
|
||||
|
||||
static bool nv_read_disabled_bios(struct amdgpu_device *adev)
|
||||
{
|
||||
/* todo */
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool nv_read_bios_from_rom(struct amdgpu_device *adev,
|
||||
u8 *bios, u32 length_bytes)
|
||||
{
|
||||
/* TODO: will implement it when SMU header is available */
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct soc15_allowed_register_entry nv_allowed_read_registers[] = {
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS)},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS2)},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS_SE0)},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS_SE1)},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS_SE2)},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS_SE3)},
|
||||
#if 0 /* TODO: will set it when SDMA header is available */
|
||||
{ SOC15_REG_ENTRY(SDMA0, 0, mmSDMA0_STATUS_REG)},
|
||||
{ SOC15_REG_ENTRY(SDMA1, 0, mmSDMA1_STATUS_REG)},
|
||||
#endif
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCP_STAT)},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCP_STALLED_STAT1)},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCP_STALLED_STAT2)},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCP_STALLED_STAT3)},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCP_CPF_BUSY_STAT)},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCP_CPF_STALLED_STAT1)},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCP_CPF_STATUS)},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCP_CPC_STALLED_STAT1)},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCP_CPC_STATUS)},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGB_ADDR_CONFIG)},
|
||||
};
|
||||
|
||||
static uint32_t nv_read_indexed_register(struct amdgpu_device *adev, u32 se_num,
|
||||
u32 sh_num, u32 reg_offset)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
if (se_num != 0xffffffff || sh_num != 0xffffffff)
|
||||
amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff);
|
||||
|
||||
val = RREG32(reg_offset);
|
||||
|
||||
if (se_num != 0xffffffff || sh_num != 0xffffffff)
|
||||
amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
return val;
|
||||
}
|
||||
|
||||
static uint32_t nv_get_register_value(struct amdgpu_device *adev,
|
||||
bool indexed, u32 se_num,
|
||||
u32 sh_num, u32 reg_offset)
|
||||
{
|
||||
if (indexed) {
|
||||
return nv_read_indexed_register(adev, se_num, sh_num, reg_offset);
|
||||
} else {
|
||||
if (reg_offset == SOC15_REG_OFFSET(GC, 0, mmGB_ADDR_CONFIG))
|
||||
return adev->gfx.config.gb_addr_config;
|
||||
return RREG32(reg_offset);
|
||||
}
|
||||
}
|
||||
|
||||
static int nv_read_register(struct amdgpu_device *adev, u32 se_num,
|
||||
u32 sh_num, u32 reg_offset, u32 *value)
|
||||
{
|
||||
uint32_t i;
|
||||
struct soc15_allowed_register_entry *en;
|
||||
|
||||
*value = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(nv_allowed_read_registers); i++) {
|
||||
en = &nv_allowed_read_registers[i];
|
||||
if (reg_offset !=
|
||||
(adev->reg_offset[en->hwip][en->inst][en->seg] + en->reg_offset))
|
||||
continue;
|
||||
|
||||
*value = nv_get_register_value(adev,
|
||||
nv_allowed_read_registers[i].grbm_indexed,
|
||||
se_num, sh_num, reg_offset);
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void nv_gpu_pci_config_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
dev_info(adev->dev, "GPU pci config reset\n");
|
||||
|
||||
/* disable BM */
|
||||
pci_clear_master(adev->pdev);
|
||||
/* reset */
|
||||
amdgpu_pci_config_reset(adev);
|
||||
|
||||
udelay(100);
|
||||
|
||||
/* wait for asic to come out of reset */
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
u32 memsize = nbio_v2_3_get_memsize(adev);
|
||||
if (memsize != 0xffffffff)
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
static int nv_asic_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
|
||||
/* FIXME: it doesn't work since vega10 */
|
||||
#if 0
|
||||
amdgpu_atombios_scratch_regs_engine_hung(adev, true);
|
||||
|
||||
nv_gpu_pci_config_reset(adev);
|
||||
|
||||
amdgpu_atombios_scratch_regs_engine_hung(adev, false);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nv_set_uvd_clocks(struct amdgpu_device *adev, u32 vclk, u32 dclk)
|
||||
{
|
||||
/* todo */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nv_set_vce_clocks(struct amdgpu_device *adev, u32 evclk, u32 ecclk)
|
||||
{
|
||||
/* todo */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nv_pcie_gen3_enable(struct amdgpu_device *adev)
|
||||
{
|
||||
if (pci_is_root_bus(adev->pdev->bus))
|
||||
return;
|
||||
|
||||
if (amdgpu_pcie_gen2 == 0)
|
||||
return;
|
||||
|
||||
if (!(adev->pm.pcie_gen_mask & (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 |
|
||||
CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)))
|
||||
return;
|
||||
|
||||
/* todo */
|
||||
}
|
||||
|
||||
static void nv_program_aspm(struct amdgpu_device *adev)
|
||||
{
|
||||
|
||||
if (amdgpu_aspm == 0)
|
||||
return;
|
||||
|
||||
/* todo */
|
||||
}
|
||||
|
||||
static void nv_enable_doorbell_aperture(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
adev->nbio_funcs->enable_doorbell_aperture(adev, enable);
|
||||
adev->nbio_funcs->enable_doorbell_selfring_aperture(adev, enable);
|
||||
}
|
||||
|
||||
static const struct amdgpu_ip_block_version nv_common_ip_block =
|
||||
{
|
||||
.type = AMD_IP_BLOCK_TYPE_COMMON,
|
||||
.major = 1,
|
||||
.minor = 0,
|
||||
.rev = 0,
|
||||
.funcs = &nv_common_ip_funcs,
|
||||
};
|
||||
|
||||
int nv_set_ip_blocks(struct amdgpu_device *adev)
|
||||
{
|
||||
/* Set IP register base before any HW register access */
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_NAVI10:
|
||||
navi10_reg_base_init(adev);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
adev->nbio_funcs = &nbio_v2_3_funcs;
|
||||
|
||||
adev->nbio_funcs->detect_hw_virt(adev);
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_NAVI10:
|
||||
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
|
||||
is_support_sw_smu(adev))
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
|
||||
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
|
||||
else if (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_device_ip_block_add(adev, &dm_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v5_0_ip_block);
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT &&
|
||||
is_support_sw_smu(adev))
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
|
||||
if (adev->enable_mes)
|
||||
amdgpu_device_ip_block_add(adev, &mes_v10_1_ip_block);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t nv_get_rev_id(struct amdgpu_device *adev)
|
||||
{
|
||||
return adev->nbio_funcs->get_rev_id(adev);
|
||||
}
|
||||
|
||||
static void nv_flush_hdp(struct amdgpu_device *adev, struct amdgpu_ring *ring)
|
||||
{
|
||||
adev->nbio_funcs->hdp_flush(adev, ring);
|
||||
}
|
||||
|
||||
static void nv_invalidate_hdp(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring)
|
||||
{
|
||||
if (!ring || !ring->funcs->emit_wreg) {
|
||||
WREG32_SOC15_NO_KIQ(NBIO, 0, mmHDP_READ_CACHE_INVALIDATE, 1);
|
||||
} else {
|
||||
amdgpu_ring_emit_wreg(ring, SOC15_REG_OFFSET(
|
||||
HDP, 0, mmHDP_READ_CACHE_INVALIDATE), 1);
|
||||
}
|
||||
}
|
||||
|
||||
static bool nv_need_full_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void nv_get_pcie_usage(struct amdgpu_device *adev,
|
||||
uint64_t *count0,
|
||||
uint64_t *count1)
|
||||
{
|
||||
/*TODO*/
|
||||
}
|
||||
|
||||
static bool nv_need_reset_on_init(struct amdgpu_device *adev)
|
||||
{
|
||||
#if 0
|
||||
u32 sol_reg;
|
||||
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return false;
|
||||
|
||||
/* Check sOS sign of life register to confirm sys driver and sOS
|
||||
* are already been loaded.
|
||||
*/
|
||||
sol_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81);
|
||||
if (sol_reg)
|
||||
return true;
|
||||
#endif
|
||||
/* TODO: re-enable it when mode1 reset is functional */
|
||||
return false;
|
||||
}
|
||||
|
||||
static void nv_init_doorbell_index(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->doorbell_index.kiq = AMDGPU_NAVI10_DOORBELL_KIQ;
|
||||
adev->doorbell_index.mec_ring0 = AMDGPU_NAVI10_DOORBELL_MEC_RING0;
|
||||
adev->doorbell_index.mec_ring1 = AMDGPU_NAVI10_DOORBELL_MEC_RING1;
|
||||
adev->doorbell_index.mec_ring2 = AMDGPU_NAVI10_DOORBELL_MEC_RING2;
|
||||
adev->doorbell_index.mec_ring3 = AMDGPU_NAVI10_DOORBELL_MEC_RING3;
|
||||
adev->doorbell_index.mec_ring4 = AMDGPU_NAVI10_DOORBELL_MEC_RING4;
|
||||
adev->doorbell_index.mec_ring5 = AMDGPU_NAVI10_DOORBELL_MEC_RING5;
|
||||
adev->doorbell_index.mec_ring6 = AMDGPU_NAVI10_DOORBELL_MEC_RING6;
|
||||
adev->doorbell_index.mec_ring7 = AMDGPU_NAVI10_DOORBELL_MEC_RING7;
|
||||
adev->doorbell_index.userqueue_start = AMDGPU_NAVI10_DOORBELL_USERQUEUE_START;
|
||||
adev->doorbell_index.userqueue_end = AMDGPU_NAVI10_DOORBELL_USERQUEUE_END;
|
||||
adev->doorbell_index.gfx_ring0 = AMDGPU_NAVI10_DOORBELL_GFX_RING0;
|
||||
adev->doorbell_index.gfx_ring1 = AMDGPU_NAVI10_DOORBELL_GFX_RING1;
|
||||
adev->doorbell_index.sdma_engine[0] = AMDGPU_NAVI10_DOORBELL_sDMA_ENGINE0;
|
||||
adev->doorbell_index.sdma_engine[1] = AMDGPU_NAVI10_DOORBELL_sDMA_ENGINE1;
|
||||
adev->doorbell_index.ih = AMDGPU_NAVI10_DOORBELL_IH;
|
||||
adev->doorbell_index.vcn.vcn_ring0_1 = AMDGPU_NAVI10_DOORBELL64_VCN0_1;
|
||||
adev->doorbell_index.vcn.vcn_ring2_3 = AMDGPU_NAVI10_DOORBELL64_VCN2_3;
|
||||
adev->doorbell_index.vcn.vcn_ring4_5 = AMDGPU_NAVI10_DOORBELL64_VCN4_5;
|
||||
adev->doorbell_index.vcn.vcn_ring6_7 = AMDGPU_NAVI10_DOORBELL64_VCN6_7;
|
||||
adev->doorbell_index.first_non_cp = AMDGPU_NAVI10_DOORBELL64_FIRST_NON_CP;
|
||||
adev->doorbell_index.last_non_cp = AMDGPU_NAVI10_DOORBELL64_LAST_NON_CP;
|
||||
|
||||
adev->doorbell_index.max_assignment = AMDGPU_NAVI10_DOORBELL_MAX_ASSIGNMENT << 1;
|
||||
adev->doorbell_index.sdma_doorbell_range = 20;
|
||||
}
|
||||
|
||||
static const struct amdgpu_asic_funcs nv_asic_funcs =
|
||||
{
|
||||
.read_disabled_bios = &nv_read_disabled_bios,
|
||||
.read_bios_from_rom = &nv_read_bios_from_rom,
|
||||
.read_register = &nv_read_register,
|
||||
.reset = &nv_asic_reset,
|
||||
.set_vga_state = &nv_vga_set_state,
|
||||
.get_xclk = &nv_get_xclk,
|
||||
.set_uvd_clocks = &nv_set_uvd_clocks,
|
||||
.set_vce_clocks = &nv_set_vce_clocks,
|
||||
.get_config_memsize = &nv_get_config_memsize,
|
||||
.flush_hdp = &nv_flush_hdp,
|
||||
.invalidate_hdp = &nv_invalidate_hdp,
|
||||
.init_doorbell_index = &nv_init_doorbell_index,
|
||||
.need_full_reset = &nv_need_full_reset,
|
||||
.get_pcie_usage = &nv_get_pcie_usage,
|
||||
.need_reset_on_init = &nv_need_reset_on_init,
|
||||
};
|
||||
|
||||
static int nv_common_early_init(void *handle)
|
||||
{
|
||||
bool psp_enabled = false;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
adev->smc_rreg = NULL;
|
||||
adev->smc_wreg = NULL;
|
||||
adev->pcie_rreg = &nv_pcie_rreg;
|
||||
adev->pcie_wreg = &nv_pcie_wreg;
|
||||
|
||||
/* TODO: will add them during VCN v2 implementation */
|
||||
adev->uvd_ctx_rreg = NULL;
|
||||
adev->uvd_ctx_wreg = NULL;
|
||||
|
||||
adev->didt_rreg = &nv_didt_rreg;
|
||||
adev->didt_wreg = &nv_didt_wreg;
|
||||
|
||||
adev->asic_funcs = &nv_asic_funcs;
|
||||
|
||||
if (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_PSP) &&
|
||||
(amdgpu_ip_block_mask & (1 << AMD_IP_BLOCK_TYPE_PSP)))
|
||||
psp_enabled = true;
|
||||
|
||||
adev->rev_id = nv_get_rev_id(adev);
|
||||
adev->external_rev_id = 0xff;
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_NAVI10:
|
||||
adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
|
||||
AMD_CG_SUPPORT_GFX_CGCG |
|
||||
AMD_CG_SUPPORT_IH_CG |
|
||||
AMD_CG_SUPPORT_HDP_MGCG |
|
||||
AMD_CG_SUPPORT_HDP_LS |
|
||||
AMD_CG_SUPPORT_SDMA_MGCG |
|
||||
AMD_CG_SUPPORT_SDMA_LS |
|
||||
AMD_CG_SUPPORT_MC_MGCG |
|
||||
AMD_CG_SUPPORT_MC_LS |
|
||||
AMD_CG_SUPPORT_ATHUB_MGCG |
|
||||
AMD_CG_SUPPORT_ATHUB_LS |
|
||||
AMD_CG_SUPPORT_VCN_MGCG |
|
||||
AMD_CG_SUPPORT_BIF_MGCG |
|
||||
AMD_CG_SUPPORT_BIF_LS;
|
||||
adev->pg_flags = AMD_PG_SUPPORT_VCN |
|
||||
AMD_PG_SUPPORT_VCN_DPG |
|
||||
AMD_PG_SUPPORT_MMHUB |
|
||||
AMD_PG_SUPPORT_ATHUB;
|
||||
adev->external_rev_id = adev->rev_id + 0x1;
|
||||
break;
|
||||
default:
|
||||
/* FIXME: not supported yet */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nv_common_late_init(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nv_common_sw_init(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nv_common_sw_fini(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nv_common_hw_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
/* enable pcie gen2/3 link */
|
||||
nv_pcie_gen3_enable(adev);
|
||||
/* enable aspm */
|
||||
nv_program_aspm(adev);
|
||||
/* setup nbio registers */
|
||||
adev->nbio_funcs->init_registers(adev);
|
||||
/* enable the doorbell aperture */
|
||||
nv_enable_doorbell_aperture(adev, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nv_common_hw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
/* disable the doorbell aperture */
|
||||
nv_enable_doorbell_aperture(adev, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nv_common_suspend(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
return nv_common_hw_fini(adev);
|
||||
}
|
||||
|
||||
static int nv_common_resume(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
return nv_common_hw_init(adev);
|
||||
}
|
||||
|
||||
static bool nv_common_is_idle(void *handle)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static int nv_common_wait_for_idle(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nv_common_soft_reset(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nv_update_hdp_mem_power_gating(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
uint32_t hdp_clk_cntl, hdp_clk_cntl1;
|
||||
uint32_t hdp_mem_pwr_cntl;
|
||||
|
||||
if (!(adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS |
|
||||
AMD_CG_SUPPORT_HDP_DS |
|
||||
AMD_CG_SUPPORT_HDP_SD)))
|
||||
return;
|
||||
|
||||
hdp_clk_cntl = hdp_clk_cntl1 = RREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL);
|
||||
hdp_mem_pwr_cntl = RREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL);
|
||||
|
||||
/* Before doing clock/power mode switch,
|
||||
* forced on IPH & RC clock */
|
||||
hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL,
|
||||
IPH_MEM_CLK_SOFT_OVERRIDE, 1);
|
||||
hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL,
|
||||
RC_MEM_CLK_SOFT_OVERRIDE, 1);
|
||||
WREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL, hdp_clk_cntl);
|
||||
|
||||
/* HDP 5.0 doesn't support dynamic power mode switch,
|
||||
* disable clock and power gating before any changing */
|
||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
|
||||
IPH_MEM_POWER_CTRL_EN, 0);
|
||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
|
||||
IPH_MEM_POWER_LS_EN, 0);
|
||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
|
||||
IPH_MEM_POWER_DS_EN, 0);
|
||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
|
||||
IPH_MEM_POWER_SD_EN, 0);
|
||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
|
||||
RC_MEM_POWER_CTRL_EN, 0);
|
||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
|
||||
RC_MEM_POWER_LS_EN, 0);
|
||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
|
||||
RC_MEM_POWER_DS_EN, 0);
|
||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
|
||||
RC_MEM_POWER_SD_EN, 0);
|
||||
WREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL, hdp_mem_pwr_cntl);
|
||||
|
||||
/* only one clock gating mode (LS/DS/SD) can be enabled */
|
||||
if (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS) {
|
||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
||||
HDP_MEM_POWER_CTRL,
|
||||
IPH_MEM_POWER_LS_EN, enable);
|
||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
||||
HDP_MEM_POWER_CTRL,
|
||||
RC_MEM_POWER_LS_EN, enable);
|
||||
} else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_DS) {
|
||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
||||
HDP_MEM_POWER_CTRL,
|
||||
IPH_MEM_POWER_DS_EN, enable);
|
||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
||||
HDP_MEM_POWER_CTRL,
|
||||
RC_MEM_POWER_DS_EN, enable);
|
||||
} else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_SD) {
|
||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
||||
HDP_MEM_POWER_CTRL,
|
||||
IPH_MEM_POWER_SD_EN, enable);
|
||||
/* RC should not use shut down mode, fallback to ds */
|
||||
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
|
||||
HDP_MEM_POWER_CTRL,
|
||||
RC_MEM_POWER_DS_EN, enable);
|
||||
}
|
||||
|
||||
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 nv_update_hdp_clock_gating(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
uint32_t hdp_clk_cntl;
|
||||
|
||||
if (!(adev->cg_flags & AMD_CG_SUPPORT_HDP_MGCG))
|
||||
return;
|
||||
|
||||
hdp_clk_cntl = RREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL);
|
||||
|
||||
if (enable) {
|
||||
hdp_clk_cntl &=
|
||||
~(uint32_t)
|
||||
(HDP_CLK_CNTL__IPH_MEM_CLK_SOFT_OVERRIDE_MASK |
|
||||
HDP_CLK_CNTL__RC_MEM_CLK_SOFT_OVERRIDE_MASK |
|
||||
HDP_CLK_CNTL__DBUS_CLK_SOFT_OVERRIDE_MASK |
|
||||
HDP_CLK_CNTL__DYN_CLK_SOFT_OVERRIDE_MASK |
|
||||
HDP_CLK_CNTL__XDP_REG_CLK_SOFT_OVERRIDE_MASK |
|
||||
HDP_CLK_CNTL__HDP_REG_CLK_SOFT_OVERRIDE_MASK);
|
||||
} else {
|
||||
hdp_clk_cntl |= HDP_CLK_CNTL__IPH_MEM_CLK_SOFT_OVERRIDE_MASK |
|
||||
HDP_CLK_CNTL__RC_MEM_CLK_SOFT_OVERRIDE_MASK |
|
||||
HDP_CLK_CNTL__DBUS_CLK_SOFT_OVERRIDE_MASK |
|
||||
HDP_CLK_CNTL__DYN_CLK_SOFT_OVERRIDE_MASK |
|
||||
HDP_CLK_CNTL__XDP_REG_CLK_SOFT_OVERRIDE_MASK |
|
||||
HDP_CLK_CNTL__HDP_REG_CLK_SOFT_OVERRIDE_MASK;
|
||||
}
|
||||
|
||||
WREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL, hdp_clk_cntl);
|
||||
}
|
||||
|
||||
static int nv_common_set_clockgating_state(void *handle,
|
||||
enum amd_clockgating_state state)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_NAVI10:
|
||||
adev->nbio_funcs->update_medium_grain_clock_gating(adev,
|
||||
state == AMD_CG_STATE_GATE ? true : false);
|
||||
adev->nbio_funcs->update_medium_grain_light_sleep(adev,
|
||||
state == AMD_CG_STATE_GATE ? true : false);
|
||||
nv_update_hdp_mem_power_gating(adev,
|
||||
state == AMD_CG_STATE_GATE ? true : false);
|
||||
nv_update_hdp_clock_gating(adev,
|
||||
state == AMD_CG_STATE_GATE ? true : false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nv_common_set_powergating_state(void *handle,
|
||||
enum amd_powergating_state state)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nv_common_get_clockgating_state(void *handle, u32 *flags)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
uint32_t tmp;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
*flags = 0;
|
||||
|
||||
adev->nbio_funcs->get_clockgating_state(adev, flags);
|
||||
|
||||
/* AMD_CG_SUPPORT_HDP_MGCG */
|
||||
tmp = RREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL);
|
||||
if (!(tmp & (HDP_CLK_CNTL__IPH_MEM_CLK_SOFT_OVERRIDE_MASK |
|
||||
HDP_CLK_CNTL__RC_MEM_CLK_SOFT_OVERRIDE_MASK |
|
||||
HDP_CLK_CNTL__DBUS_CLK_SOFT_OVERRIDE_MASK |
|
||||
HDP_CLK_CNTL__DYN_CLK_SOFT_OVERRIDE_MASK |
|
||||
HDP_CLK_CNTL__XDP_REG_CLK_SOFT_OVERRIDE_MASK |
|
||||
HDP_CLK_CNTL__HDP_REG_CLK_SOFT_OVERRIDE_MASK)))
|
||||
*flags |= AMD_CG_SUPPORT_HDP_MGCG;
|
||||
|
||||
/* AMD_CG_SUPPORT_HDP_LS/DS/SD */
|
||||
tmp = RREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL);
|
||||
if (tmp & HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK)
|
||||
*flags |= AMD_CG_SUPPORT_HDP_LS;
|
||||
else if (tmp & HDP_MEM_POWER_CTRL__IPH_MEM_POWER_DS_EN_MASK)
|
||||
*flags |= AMD_CG_SUPPORT_HDP_DS;
|
||||
else if (tmp & HDP_MEM_POWER_CTRL__IPH_MEM_POWER_SD_EN_MASK)
|
||||
*flags |= AMD_CG_SUPPORT_HDP_SD;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static const struct amd_ip_funcs nv_common_ip_funcs = {
|
||||
.name = "nv_common",
|
||||
.early_init = nv_common_early_init,
|
||||
.late_init = nv_common_late_init,
|
||||
.sw_init = nv_common_sw_init,
|
||||
.sw_fini = nv_common_sw_fini,
|
||||
.hw_init = nv_common_hw_init,
|
||||
.hw_fini = nv_common_hw_fini,
|
||||
.suspend = nv_common_suspend,
|
||||
.resume = nv_common_resume,
|
||||
.is_idle = nv_common_is_idle,
|
||||
.wait_for_idle = nv_common_wait_for_idle,
|
||||
.soft_reset = nv_common_soft_reset,
|
||||
.set_clockgating_state = nv_common_set_clockgating_state,
|
||||
.set_powergating_state = nv_common_set_powergating_state,
|
||||
.get_clockgating_state = nv_common_get_clockgating_state,
|
||||
};
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __NV_H__
|
||||
#define __NV_H__
|
||||
|
||||
#include "nbio_v2_3.h"
|
||||
|
||||
void nv_grbm_select(struct amdgpu_device *adev,
|
||||
u32 me, u32 pipe, u32 queue, u32 vmid);
|
||||
int nv_set_ip_blocks(struct amdgpu_device *adev);
|
||||
int navi10_reg_base_init(struct amdgpu_device *adev);
|
||||
#endif
|
|
@ -0,0 +1,418 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NVD_H
|
||||
#define NVD_H
|
||||
|
||||
/**
|
||||
* Navi's PM4 definitions
|
||||
*/
|
||||
#define PACKET_TYPE0 0
|
||||
#define PACKET_TYPE1 1
|
||||
#define PACKET_TYPE2 2
|
||||
#define PACKET_TYPE3 3
|
||||
|
||||
#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
|
||||
#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
|
||||
#define CP_PACKET0_GET_REG(h) ((h) & 0xFFFF)
|
||||
#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
|
||||
#define PACKET0(reg, n) ((PACKET_TYPE0 << 30) | \
|
||||
((reg) & 0xFFFF) | \
|
||||
((n) & 0x3FFF) << 16)
|
||||
#define CP_PACKET2 0x80000000
|
||||
#define PACKET2_PAD_SHIFT 0
|
||||
#define PACKET2_PAD_MASK (0x3fffffff << 0)
|
||||
|
||||
#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
|
||||
|
||||
#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \
|
||||
(((op) & 0xFF) << 8) | \
|
||||
((n) & 0x3FFF) << 16)
|
||||
|
||||
#define PACKET3_COMPUTE(op, n) (PACKET3(op, n) | 1 << 1)
|
||||
|
||||
/* Packet 3 types */
|
||||
#define PACKET3_NOP 0x10
|
||||
#define PACKET3_SET_BASE 0x11
|
||||
#define PACKET3_BASE_INDEX(x) ((x) << 0)
|
||||
#define CE_PARTITION_BASE 3
|
||||
#define PACKET3_CLEAR_STATE 0x12
|
||||
#define PACKET3_INDEX_BUFFER_SIZE 0x13
|
||||
#define PACKET3_DISPATCH_DIRECT 0x15
|
||||
#define PACKET3_DISPATCH_INDIRECT 0x16
|
||||
#define PACKET3_INDIRECT_BUFFER_END 0x17
|
||||
#define PACKET3_INDIRECT_BUFFER_CNST_END 0x19
|
||||
#define PACKET3_ATOMIC_GDS 0x1D
|
||||
#define PACKET3_ATOMIC_MEM 0x1E
|
||||
#define PACKET3_OCCLUSION_QUERY 0x1F
|
||||
#define PACKET3_SET_PREDICATION 0x20
|
||||
#define PACKET3_REG_RMW 0x21
|
||||
#define PACKET3_COND_EXEC 0x22
|
||||
#define PACKET3_PRED_EXEC 0x23
|
||||
#define PACKET3_DRAW_INDIRECT 0x24
|
||||
#define PACKET3_DRAW_INDEX_INDIRECT 0x25
|
||||
#define PACKET3_INDEX_BASE 0x26
|
||||
#define PACKET3_DRAW_INDEX_2 0x27
|
||||
#define PACKET3_CONTEXT_CONTROL 0x28
|
||||
#define PACKET3_INDEX_TYPE 0x2A
|
||||
#define PACKET3_DRAW_INDIRECT_MULTI 0x2C
|
||||
#define PACKET3_DRAW_INDEX_AUTO 0x2D
|
||||
#define PACKET3_NUM_INSTANCES 0x2F
|
||||
#define PACKET3_DRAW_INDEX_MULTI_AUTO 0x30
|
||||
#define PACKET3_INDIRECT_BUFFER_PRIV 0x32
|
||||
#define PACKET3_INDIRECT_BUFFER_CNST 0x33
|
||||
#define PACKET3_COND_INDIRECT_BUFFER_CNST 0x33
|
||||
#define PACKET3_STRMOUT_BUFFER_UPDATE 0x34
|
||||
#define PACKET3_DRAW_INDEX_OFFSET_2 0x35
|
||||
#define PACKET3_DRAW_PREAMBLE 0x36
|
||||
#define PACKET3_WRITE_DATA 0x37
|
||||
#define WRITE_DATA_DST_SEL(x) ((x) << 8)
|
||||
/* 0 - register
|
||||
* 1 - memory (sync - via GRBM)
|
||||
* 2 - gl2
|
||||
* 3 - gds
|
||||
* 4 - reserved
|
||||
* 5 - memory (async - direct)
|
||||
*/
|
||||
#define WR_ONE_ADDR (1 << 16)
|
||||
#define WR_CONFIRM (1 << 20)
|
||||
#define WRITE_DATA_CACHE_POLICY(x) ((x) << 25)
|
||||
/* 0 - LRU
|
||||
* 1 - Stream
|
||||
*/
|
||||
#define WRITE_DATA_ENGINE_SEL(x) ((x) << 30)
|
||||
/* 0 - me
|
||||
* 1 - pfp
|
||||
* 2 - ce
|
||||
*/
|
||||
#define PACKET3_DRAW_INDEX_INDIRECT_MULTI 0x38
|
||||
#define PACKET3_MEM_SEMAPHORE 0x39
|
||||
# define PACKET3_SEM_USE_MAILBOX (0x1 << 16)
|
||||
# define PACKET3_SEM_SEL_SIGNAL_TYPE (0x1 << 20) /* 0 = increment, 1 = write 1 */
|
||||
# define PACKET3_SEM_SEL_SIGNAL (0x6 << 29)
|
||||
# define PACKET3_SEM_SEL_WAIT (0x7 << 29)
|
||||
#define PACKET3_DRAW_INDEX_MULTI_INST 0x3A
|
||||
#define PACKET3_COPY_DW 0x3B
|
||||
#define PACKET3_WAIT_REG_MEM 0x3C
|
||||
#define WAIT_REG_MEM_FUNCTION(x) ((x) << 0)
|
||||
/* 0 - always
|
||||
* 1 - <
|
||||
* 2 - <=
|
||||
* 3 - ==
|
||||
* 4 - !=
|
||||
* 5 - >=
|
||||
* 6 - >
|
||||
*/
|
||||
#define WAIT_REG_MEM_MEM_SPACE(x) ((x) << 4)
|
||||
/* 0 - reg
|
||||
* 1 - mem
|
||||
*/
|
||||
#define WAIT_REG_MEM_OPERATION(x) ((x) << 6)
|
||||
/* 0 - wait_reg_mem
|
||||
* 1 - wr_wait_wr_reg
|
||||
*/
|
||||
#define WAIT_REG_MEM_ENGINE(x) ((x) << 8)
|
||||
/* 0 - me
|
||||
* 1 - pfp
|
||||
*/
|
||||
#define PACKET3_INDIRECT_BUFFER 0x3F
|
||||
#define INDIRECT_BUFFER_VALID (1 << 23)
|
||||
#define INDIRECT_BUFFER_CACHE_POLICY(x) ((x) << 28)
|
||||
/* 0 - LRU
|
||||
* 1 - Stream
|
||||
* 2 - Bypass
|
||||
*/
|
||||
#define INDIRECT_BUFFER_PRE_ENB(x) ((x) << 21)
|
||||
#define INDIRECT_BUFFER_PRE_RESUME(x) ((x) << 30)
|
||||
#define PACKET3_COND_INDIRECT_BUFFER 0x3F
|
||||
#define PACKET3_COPY_DATA 0x40
|
||||
#define PACKET3_CP_DMA 0x41
|
||||
#define PACKET3_PFP_SYNC_ME 0x42
|
||||
#define PACKET3_SURFACE_SYNC 0x43
|
||||
#define PACKET3_ME_INITIALIZE 0x44
|
||||
#define PACKET3_COND_WRITE 0x45
|
||||
#define PACKET3_EVENT_WRITE 0x46
|
||||
#define EVENT_TYPE(x) ((x) << 0)
|
||||
#define EVENT_INDEX(x) ((x) << 8)
|
||||
/* 0 - any non-TS event
|
||||
* 1 - ZPASS_DONE, PIXEL_PIPE_STAT_*
|
||||
* 2 - SAMPLE_PIPELINESTAT
|
||||
* 3 - SAMPLE_STREAMOUTSTAT*
|
||||
* 4 - *S_PARTIAL_FLUSH
|
||||
*/
|
||||
#define PACKET3_EVENT_WRITE_EOP 0x47
|
||||
#define PACKET3_EVENT_WRITE_EOS 0x48
|
||||
#define PACKET3_RELEASE_MEM 0x49
|
||||
#define PACKET3_RELEASE_MEM_EVENT_TYPE(x) ((x) << 0)
|
||||
#define PACKET3_RELEASE_MEM_EVENT_INDEX(x) ((x) << 8)
|
||||
#define PACKET3_RELEASE_MEM_GCR_GLM_WB (1 << 12)
|
||||
#define PACKET3_RELEASE_MEM_GCR_GLM_INV (1 << 13)
|
||||
#define PACKET3_RELEASE_MEM_GCR_GLV_INV (1 << 14)
|
||||
#define PACKET3_RELEASE_MEM_GCR_GL1_INV (1 << 15)
|
||||
#define PACKET3_RELEASE_MEM_GCR_GL2_US (1 << 16)
|
||||
#define PACKET3_RELEASE_MEM_GCR_GL2_RANGE (1 << 17)
|
||||
#define PACKET3_RELEASE_MEM_GCR_GL2_DISCARD (1 << 19)
|
||||
#define PACKET3_RELEASE_MEM_GCR_GL2_INV (1 << 20)
|
||||
#define PACKET3_RELEASE_MEM_GCR_GL2_WB (1 << 21)
|
||||
#define PACKET3_RELEASE_MEM_GCR_SEQ (1 << 22)
|
||||
#define PACKET3_RELEASE_MEM_CACHE_POLICY(x) ((x) << 25)
|
||||
/* 0 - cache_policy__me_release_mem__lru
|
||||
* 1 - cache_policy__me_release_mem__stream
|
||||
* 2 - cache_policy__me_release_mem__noa
|
||||
* 3 - cache_policy__me_release_mem__bypass
|
||||
*/
|
||||
#define PACKET3_RELEASE_MEM_EXECUTE (1 << 28)
|
||||
|
||||
#define PACKET3_RELEASE_MEM_DATA_SEL(x) ((x) << 29)
|
||||
/* 0 - discard
|
||||
* 1 - send low 32bit data
|
||||
* 2 - send 64bit data
|
||||
* 3 - send 64bit GPU counter value
|
||||
* 4 - send 64bit sys counter value
|
||||
*/
|
||||
#define PACKET3_RELEASE_MEM_INT_SEL(x) ((x) << 24)
|
||||
/* 0 - none
|
||||
* 1 - interrupt only (DATA_SEL = 0)
|
||||
* 2 - interrupt when data write is confirmed
|
||||
*/
|
||||
#define PACKET3_RELEASE_MEM_DST_SEL(x) ((x) << 16)
|
||||
/* 0 - MC
|
||||
* 1 - TC/L2
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#define PACKET3_PREAMBLE_CNTL 0x4A
|
||||
# define PACKET3_PREAMBLE_BEGIN_CLEAR_STATE (2 << 28)
|
||||
# define PACKET3_PREAMBLE_END_CLEAR_STATE (3 << 28)
|
||||
#define PACKET3_DMA_DATA 0x50
|
||||
/* 1. header
|
||||
* 2. CONTROL
|
||||
* 3. SRC_ADDR_LO or DATA [31:0]
|
||||
* 4. SRC_ADDR_HI [31:0]
|
||||
* 5. DST_ADDR_LO [31:0]
|
||||
* 6. DST_ADDR_HI [7:0]
|
||||
* 7. COMMAND [31:26] | BYTE_COUNT [25:0]
|
||||
*/
|
||||
/* CONTROL */
|
||||
# define PACKET3_DMA_DATA_ENGINE(x) ((x) << 0)
|
||||
/* 0 - ME
|
||||
* 1 - PFP
|
||||
*/
|
||||
# define PACKET3_DMA_DATA_SRC_CACHE_POLICY(x) ((x) << 13)
|
||||
/* 0 - LRU
|
||||
* 1 - Stream
|
||||
*/
|
||||
# define PACKET3_DMA_DATA_DST_SEL(x) ((x) << 20)
|
||||
/* 0 - DST_ADDR using DAS
|
||||
* 1 - GDS
|
||||
* 3 - DST_ADDR using L2
|
||||
*/
|
||||
# define PACKET3_DMA_DATA_DST_CACHE_POLICY(x) ((x) << 25)
|
||||
/* 0 - LRU
|
||||
* 1 - Stream
|
||||
*/
|
||||
# define PACKET3_DMA_DATA_SRC_SEL(x) ((x) << 29)
|
||||
/* 0 - SRC_ADDR using SAS
|
||||
* 1 - GDS
|
||||
* 2 - DATA
|
||||
* 3 - SRC_ADDR using L2
|
||||
*/
|
||||
# define PACKET3_DMA_DATA_CP_SYNC (1 << 31)
|
||||
/* COMMAND */
|
||||
# define PACKET3_DMA_DATA_CMD_SAS (1 << 26)
|
||||
/* 0 - memory
|
||||
* 1 - register
|
||||
*/
|
||||
# define PACKET3_DMA_DATA_CMD_DAS (1 << 27)
|
||||
/* 0 - memory
|
||||
* 1 - register
|
||||
*/
|
||||
# define PACKET3_DMA_DATA_CMD_SAIC (1 << 28)
|
||||
# define PACKET3_DMA_DATA_CMD_DAIC (1 << 29)
|
||||
# define PACKET3_DMA_DATA_CMD_RAW_WAIT (1 << 30)
|
||||
#define PACKET3_CONTEXT_REG_RMW 0x51
|
||||
#define PACKET3_GFX_CNTX_UPDATE 0x52
|
||||
#define PACKET3_BLK_CNTX_UPDATE 0x53
|
||||
#define PACKET3_INCR_UPDT_STATE 0x55
|
||||
#define PACKET3_ACQUIRE_MEM 0x58
|
||||
#define PACKET3_REWIND 0x59
|
||||
#define PACKET3_INTERRUPT 0x5A
|
||||
#define PACKET3_GEN_PDEPTE 0x5B
|
||||
#define PACKET3_INDIRECT_BUFFER_PASID 0x5C
|
||||
#define PACKET3_PRIME_UTCL2 0x5D
|
||||
#define PACKET3_LOAD_UCONFIG_REG 0x5E
|
||||
#define PACKET3_LOAD_SH_REG 0x5F
|
||||
#define PACKET3_LOAD_CONFIG_REG 0x60
|
||||
#define PACKET3_LOAD_CONTEXT_REG 0x61
|
||||
#define PACKET3_LOAD_COMPUTE_STATE 0x62
|
||||
#define PACKET3_LOAD_SH_REG_INDEX 0x63
|
||||
#define PACKET3_SET_CONFIG_REG 0x68
|
||||
#define PACKET3_SET_CONFIG_REG_START 0x00002000
|
||||
#define PACKET3_SET_CONFIG_REG_END 0x00002c00
|
||||
#define PACKET3_SET_CONTEXT_REG 0x69
|
||||
#define PACKET3_SET_CONTEXT_REG_START 0x0000a000
|
||||
#define PACKET3_SET_CONTEXT_REG_END 0x0000a400
|
||||
#define PACKET3_SET_CONTEXT_REG_INDEX 0x6A
|
||||
#define PACKET3_SET_VGPR_REG_DI_MULTI 0x71
|
||||
#define PACKET3_SET_SH_REG_DI 0x72
|
||||
#define PACKET3_SET_CONTEXT_REG_INDIRECT 0x73
|
||||
#define PACKET3_SET_SH_REG_DI_MULTI 0x74
|
||||
#define PACKET3_GFX_PIPE_LOCK 0x75
|
||||
#define PACKET3_SET_SH_REG 0x76
|
||||
#define PACKET3_SET_SH_REG_START 0x00002c00
|
||||
#define PACKET3_SET_SH_REG_END 0x00003000
|
||||
#define PACKET3_SET_SH_REG_OFFSET 0x77
|
||||
#define PACKET3_SET_QUEUE_REG 0x78
|
||||
#define PACKET3_SET_UCONFIG_REG 0x79
|
||||
#define PACKET3_SET_UCONFIG_REG_START 0x0000c000
|
||||
#define PACKET3_SET_UCONFIG_REG_END 0x0000c400
|
||||
#define PACKET3_SET_UCONFIG_REG_INDEX 0x7A
|
||||
#define PACKET3_FORWARD_HEADER 0x7C
|
||||
#define PACKET3_SCRATCH_RAM_WRITE 0x7D
|
||||
#define PACKET3_SCRATCH_RAM_READ 0x7E
|
||||
#define PACKET3_LOAD_CONST_RAM 0x80
|
||||
#define PACKET3_WRITE_CONST_RAM 0x81
|
||||
#define PACKET3_DUMP_CONST_RAM 0x83
|
||||
#define PACKET3_INCREMENT_CE_COUNTER 0x84
|
||||
#define PACKET3_INCREMENT_DE_COUNTER 0x85
|
||||
#define PACKET3_WAIT_ON_CE_COUNTER 0x86
|
||||
#define PACKET3_WAIT_ON_DE_COUNTER_DIFF 0x88
|
||||
#define PACKET3_SWITCH_BUFFER 0x8B
|
||||
#define PACKET3_DISPATCH_DRAW_PREAMBLE 0x8C
|
||||
#define PACKET3_DISPATCH_DRAW_PREAMBLE_ACE 0x8C
|
||||
#define PACKET3_DISPATCH_DRAW 0x8D
|
||||
#define PACKET3_DISPATCH_DRAW_ACE 0x8D
|
||||
#define PACKET3_GET_LOD_STATS 0x8E
|
||||
#define PACKET3_DRAW_MULTI_PREAMBLE 0x8F
|
||||
#define PACKET3_FRAME_CONTROL 0x90
|
||||
# define FRAME_CMD(x) ((x) << 28)
|
||||
/*
|
||||
* x=0: tmz_begin
|
||||
* x=1: tmz_end
|
||||
*/
|
||||
#define PACKET3_INDEX_ATTRIBUTES_INDIRECT 0x91
|
||||
#define PACKET3_WAIT_REG_MEM64 0x93
|
||||
#define PACKET3_COND_PREEMPT 0x94
|
||||
#define PACKET3_HDP_FLUSH 0x95
|
||||
#define PACKET3_COPY_DATA_RB 0x96
|
||||
#define PACKET3_INVALIDATE_TLBS 0x98
|
||||
# define PACKET3_INVALIDATE_TLBS_DST_SEL(x) ((x) << 0)
|
||||
# define PACKET3_INVALIDATE_TLBS_ALL_HUB(x) ((x) << 4)
|
||||
# define PACKET3_INVALIDATE_TLBS_PASID(x) ((x) << 5)
|
||||
#define PACKET3_AQL_PACKET 0x99
|
||||
#define PACKET3_DMA_DATA_FILL_MULTI 0x9A
|
||||
#define PACKET3_SET_SH_REG_INDEX 0x9B
|
||||
#define PACKET3_DRAW_INDIRECT_COUNT_MULTI 0x9C
|
||||
#define PACKET3_DRAW_INDEX_INDIRECT_COUNT_MULTI 0x9D
|
||||
#define PACKET3_DUMP_CONST_RAM_OFFSET 0x9E
|
||||
#define PACKET3_LOAD_CONTEXT_REG_INDEX 0x9F
|
||||
#define PACKET3_SET_RESOURCES 0xA0
|
||||
/* 1. header
|
||||
* 2. CONTROL
|
||||
* 3. QUEUE_MASK_LO [31:0]
|
||||
* 4. QUEUE_MASK_HI [31:0]
|
||||
* 5. GWS_MASK_LO [31:0]
|
||||
* 6. GWS_MASK_HI [31:0]
|
||||
* 7. OAC_MASK [15:0]
|
||||
* 8. GDS_HEAP_SIZE [16:11] | GDS_HEAP_BASE [5:0]
|
||||
*/
|
||||
# define PACKET3_SET_RESOURCES_VMID_MASK(x) ((x) << 0)
|
||||
# define PACKET3_SET_RESOURCES_UNMAP_LATENTY(x) ((x) << 16)
|
||||
# define PACKET3_SET_RESOURCES_QUEUE_TYPE(x) ((x) << 29)
|
||||
#define PACKET3_MAP_PROCESS 0xA1
|
||||
#define PACKET3_MAP_QUEUES 0xA2
|
||||
/* 1. header
|
||||
* 2. CONTROL
|
||||
* 3. CONTROL2
|
||||
* 4. MQD_ADDR_LO [31:0]
|
||||
* 5. MQD_ADDR_HI [31:0]
|
||||
* 6. WPTR_ADDR_LO [31:0]
|
||||
* 7. WPTR_ADDR_HI [31:0]
|
||||
*/
|
||||
/* CONTROL */
|
||||
# define PACKET3_MAP_QUEUES_QUEUE_SEL(x) ((x) << 4)
|
||||
# define PACKET3_MAP_QUEUES_VMID(x) ((x) << 8)
|
||||
# define PACKET3_MAP_QUEUES_QUEUE(x) ((x) << 13)
|
||||
# define PACKET3_MAP_QUEUES_PIPE(x) ((x) << 16)
|
||||
# define PACKET3_MAP_QUEUES_ME(x) ((x) << 18)
|
||||
# define PACKET3_MAP_QUEUES_QUEUE_TYPE(x) ((x) << 21)
|
||||
# define PACKET3_MAP_QUEUES_ALLOC_FORMAT(x) ((x) << 24)
|
||||
# define PACKET3_MAP_QUEUES_ENGINE_SEL(x) ((x) << 26)
|
||||
# define PACKET3_MAP_QUEUES_NUM_QUEUES(x) ((x) << 29)
|
||||
/* CONTROL2 */
|
||||
# define PACKET3_MAP_QUEUES_CHECK_DISABLE(x) ((x) << 1)
|
||||
# define PACKET3_MAP_QUEUES_DOORBELL_OFFSET(x) ((x) << 2)
|
||||
#define PACKET3_UNMAP_QUEUES 0xA3
|
||||
/* 1. header
|
||||
* 2. CONTROL
|
||||
* 3. CONTROL2
|
||||
* 4. CONTROL3
|
||||
* 5. CONTROL4
|
||||
* 6. CONTROL5
|
||||
*/
|
||||
/* CONTROL */
|
||||
# define PACKET3_UNMAP_QUEUES_ACTION(x) ((x) << 0)
|
||||
/* 0 - PREEMPT_QUEUES
|
||||
* 1 - RESET_QUEUES
|
||||
* 2 - DISABLE_PROCESS_QUEUES
|
||||
* 3 - PREEMPT_QUEUES_NO_UNMAP
|
||||
*/
|
||||
# define PACKET3_UNMAP_QUEUES_QUEUE_SEL(x) ((x) << 4)
|
||||
# define PACKET3_UNMAP_QUEUES_ENGINE_SEL(x) ((x) << 26)
|
||||
# define PACKET3_UNMAP_QUEUES_NUM_QUEUES(x) ((x) << 29)
|
||||
/* CONTROL2a */
|
||||
# define PACKET3_UNMAP_QUEUES_PASID(x) ((x) << 0)
|
||||
/* CONTROL2b */
|
||||
# define PACKET3_UNMAP_QUEUES_DOORBELL_OFFSET0(x) ((x) << 2)
|
||||
/* CONTROL3a */
|
||||
# define PACKET3_UNMAP_QUEUES_DOORBELL_OFFSET1(x) ((x) << 2)
|
||||
/* CONTROL3b */
|
||||
# define PACKET3_UNMAP_QUEUES_RB_WPTR(x) ((x) << 0)
|
||||
/* CONTROL4 */
|
||||
# define PACKET3_UNMAP_QUEUES_DOORBELL_OFFSET2(x) ((x) << 2)
|
||||
/* CONTROL5 */
|
||||
# define PACKET3_UNMAP_QUEUES_DOORBELL_OFFSET3(x) ((x) << 2)
|
||||
#define PACKET3_QUERY_STATUS 0xA4
|
||||
/* 1. header
|
||||
* 2. CONTROL
|
||||
* 3. CONTROL2
|
||||
* 4. ADDR_LO [31:0]
|
||||
* 5. ADDR_HI [31:0]
|
||||
* 6. DATA_LO [31:0]
|
||||
* 7. DATA_HI [31:0]
|
||||
*/
|
||||
/* CONTROL */
|
||||
# define PACKET3_QUERY_STATUS_CONTEXT_ID(x) ((x) << 0)
|
||||
# define PACKET3_QUERY_STATUS_INTERRUPT_SEL(x) ((x) << 28)
|
||||
# define PACKET3_QUERY_STATUS_COMMAND(x) ((x) << 30)
|
||||
/* CONTROL2a */
|
||||
# define PACKET3_QUERY_STATUS_PASID(x) ((x) << 0)
|
||||
/* CONTROL2b */
|
||||
# define PACKET3_QUERY_STATUS_DOORBELL_OFFSET(x) ((x) << 2)
|
||||
# define PACKET3_QUERY_STATUS_ENG_SEL(x) ((x) << 25)
|
||||
#define PACKET3_RUN_LIST 0xA5
|
||||
#define PACKET3_MAP_PROCESS_VM 0xA6
|
||||
|
||||
|
||||
#endif
|
|
@ -80,6 +80,18 @@ struct psp_gfx_ctrl
|
|||
*/
|
||||
#define GFX_FLAG_RESPONSE 0x80000000
|
||||
|
||||
/* Gbr IH registers ID */
|
||||
enum ih_reg_id {
|
||||
IH_RB = 0, // IH_RB_CNTL
|
||||
IH_RB_RNG1 = 1, // IH_RB_CNTL_RING1
|
||||
IH_RB_RNG2 = 2, // IH_RB_CNTL_RING2
|
||||
};
|
||||
|
||||
/* Command to setup Gibraltar IH register */
|
||||
struct psp_gfx_cmd_gbr_ih_reg {
|
||||
uint32_t reg_value; /* Value to be set to the IH_RB_CNTL... register*/
|
||||
enum ih_reg_id reg_id; /* ID of the register */
|
||||
};
|
||||
|
||||
/* TEE Gfx Command IDs for the ring buffer interface. */
|
||||
enum psp_gfx_cmd_id
|
||||
|
@ -95,9 +107,11 @@ enum psp_gfx_cmd_id
|
|||
GFX_CMD_ID_SETUP_VMR = 0x00000009, /* setup VMR region */
|
||||
GFX_CMD_ID_DESTROY_VMR = 0x0000000A, /* destroy VMR region */
|
||||
GFX_CMD_ID_PROG_REG = 0x0000000B, /* program regs */
|
||||
/* IDs upto 0x1F are reserved for older programs (Raven, Vega 10/12/20) */
|
||||
GFX_CMD_ID_LOAD_TOC = 0x00000020, /* Load TOC and obtain TMR size */
|
||||
GFX_CMD_ID_AUTOLOAD_RLC = 0x00000021, /* Indicates all graphics fw loaded, start RLC autoload */
|
||||
};
|
||||
|
||||
|
||||
/* Command to load Trusted Application binary into PSP OS. */
|
||||
struct psp_gfx_cmd_load_ta
|
||||
{
|
||||
|
@ -169,33 +183,59 @@ struct psp_gfx_cmd_setup_tmr
|
|||
|
||||
|
||||
/* FW types for GFX_CMD_ID_LOAD_IP_FW command. Limit 31. */
|
||||
enum psp_gfx_fw_type
|
||||
{
|
||||
GFX_FW_TYPE_NONE = 0,
|
||||
GFX_FW_TYPE_CP_ME = 1,
|
||||
GFX_FW_TYPE_CP_PFP = 2,
|
||||
GFX_FW_TYPE_CP_CE = 3,
|
||||
GFX_FW_TYPE_CP_MEC = 4,
|
||||
GFX_FW_TYPE_CP_MEC_ME1 = 5,
|
||||
GFX_FW_TYPE_CP_MEC_ME2 = 6,
|
||||
GFX_FW_TYPE_RLC_V = 7,
|
||||
GFX_FW_TYPE_RLC_G = 8,
|
||||
GFX_FW_TYPE_SDMA0 = 9,
|
||||
GFX_FW_TYPE_SDMA1 = 10,
|
||||
GFX_FW_TYPE_DMCU_ERAM = 11,
|
||||
GFX_FW_TYPE_DMCU_ISR = 12,
|
||||
GFX_FW_TYPE_VCN = 13,
|
||||
GFX_FW_TYPE_UVD = 14,
|
||||
GFX_FW_TYPE_VCE = 15,
|
||||
GFX_FW_TYPE_ISP = 16,
|
||||
GFX_FW_TYPE_ACP = 17,
|
||||
GFX_FW_TYPE_SMU = 18,
|
||||
GFX_FW_TYPE_MMSCH = 19,
|
||||
GFX_FW_TYPE_RLC_RESTORE_LIST_GPM_MEM = 20,
|
||||
GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_MEM = 21,
|
||||
GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_CNTL = 22,
|
||||
GFX_FW_TYPE_UVD1 = 23,
|
||||
GFX_FW_TYPE_MAX = 24
|
||||
enum psp_gfx_fw_type {
|
||||
GFX_FW_TYPE_NONE = 0, /* */
|
||||
GFX_FW_TYPE_CP_ME = 1, /* CP-ME VG + RV */
|
||||
GFX_FW_TYPE_CP_PFP = 2, /* CP-PFP VG + RV */
|
||||
GFX_FW_TYPE_CP_CE = 3, /* CP-CE VG + RV */
|
||||
GFX_FW_TYPE_CP_MEC = 4, /* CP-MEC FW VG + RV */
|
||||
GFX_FW_TYPE_CP_MEC_ME1 = 5, /* CP-MEC Jump Table 1 VG + RV */
|
||||
GFX_FW_TYPE_CP_MEC_ME2 = 6, /* CP-MEC Jump Table 2 VG */
|
||||
GFX_FW_TYPE_RLC_V = 7, /* RLC-V VG */
|
||||
GFX_FW_TYPE_RLC_G = 8, /* RLC-G VG + RV */
|
||||
GFX_FW_TYPE_SDMA0 = 9, /* SDMA0 VG + RV */
|
||||
GFX_FW_TYPE_SDMA1 = 10, /* SDMA1 VG */
|
||||
GFX_FW_TYPE_DMCU_ERAM = 11, /* DMCU-ERAM VG + RV */
|
||||
GFX_FW_TYPE_DMCU_ISR = 12, /* DMCU-ISR VG + RV */
|
||||
GFX_FW_TYPE_VCN = 13, /* VCN RV */
|
||||
GFX_FW_TYPE_UVD = 14, /* UVD VG */
|
||||
GFX_FW_TYPE_VCE = 15, /* VCE VG */
|
||||
GFX_FW_TYPE_ISP = 16, /* ISP RV */
|
||||
GFX_FW_TYPE_ACP = 17, /* ACP RV */
|
||||
GFX_FW_TYPE_SMU = 18, /* SMU VG */
|
||||
GFX_FW_TYPE_MMSCH = 19, /* MMSCH VG */
|
||||
GFX_FW_TYPE_RLC_RESTORE_LIST_GPM_MEM = 20, /* RLC GPM VG + RV */
|
||||
GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_MEM = 21, /* RLC SRM VG + RV */
|
||||
GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_CNTL = 22, /* RLC CNTL VG + RV */
|
||||
GFX_FW_TYPE_UVD1 = 23, /* UVD1 VG-20 */
|
||||
GFX_FW_TYPE_TOC = 24, /* TOC NV-10 */
|
||||
GFX_FW_TYPE_RLC_P = 25, /* RLC P NV */
|
||||
GFX_FW_TYPE_RLX6 = 26, /* RLX6 NV */
|
||||
GFX_FW_TYPE_GLOBAL_TAP_DELAYS = 27, /* GLOBAL TAP DELAYS NV */
|
||||
GFX_FW_TYPE_SE0_TAP_DELAYS = 28, /* SE0 TAP DELAYS NV */
|
||||
GFX_FW_TYPE_SE1_TAP_DELAYS = 29, /* SE1 TAP DELAYS NV */
|
||||
GFX_FW_TYPE_GLOBAL_SE0_SE1_SKEW_DELAYS = 30, /* GLOBAL SE0/1 SKEW DELAYS NV */
|
||||
GFX_FW_TYPE_SDMA0_JT = 31, /* SDMA0 JT NV */
|
||||
GFX_FW_TYPE_SDMA1_JT = 32, /* SDNA1 JT NV */
|
||||
GFX_FW_TYPE_CP_MES = 33, /* CP MES NV */
|
||||
GFX_FW_TYPE_MES_STACK = 34, /* MES STACK NV */
|
||||
GFX_FW_TYPE_RLC_SRM_DRAM_SR = 35, /* RLC SRM DRAM NV */
|
||||
GFX_FW_TYPE_RLCG_SCRATCH_SR = 36, /* RLCG SCRATCH NV */
|
||||
GFX_FW_TYPE_RLCP_SCRATCH_SR = 37, /* RLCP SCRATCH NV */
|
||||
GFX_FW_TYPE_RLCV_SCRATCH_SR = 38, /* RLCV SCRATCH NV */
|
||||
GFX_FW_TYPE_RLX6_DRAM_SR = 39, /* RLX6 DRAM NV */
|
||||
GFX_FW_TYPE_SDMA0_PG_CONTEXT = 40, /* SDMA0 PG CONTEXT NV */
|
||||
GFX_FW_TYPE_SDMA1_PG_CONTEXT = 41, /* SDMA1 PG CONTEXT NV */
|
||||
GFX_FW_TYPE_GLOBAL_MUX_SELECT_RAM = 42, /* GLOBAL MUX SEL RAM NV */
|
||||
GFX_FW_TYPE_SE0_MUX_SELECT_RAM = 43, /* SE0 MUX SEL RAM NV */
|
||||
GFX_FW_TYPE_SE1_MUX_SELECT_RAM = 44, /* SE1 MUX SEL RAM NV */
|
||||
GFX_FW_TYPE_ACCUM_CTRL_RAM = 45, /* ACCUM CTRL RAM NV */
|
||||
GFX_FW_TYPE_RLCP_CAM = 46, /* RLCP CAM NV */
|
||||
GFX_FW_TYPE_RLC_SPP_CAM_EXT = 47, /* RLC SPP CAM EXT NV */
|
||||
GFX_FW_TYPE_RLX6_DRAM_BOOT = 48, /* RLX6 DRAM BOOT NV */
|
||||
GFX_FW_TYPE_VCN0_RAM = 49, /* VCN_RAM NV */
|
||||
GFX_FW_TYPE_VCN1_RAM = 50, /* VCN_RAM NV */
|
||||
GFX_FW_TYPE_MAX
|
||||
};
|
||||
|
||||
/* Command to load HW IP FW. */
|
||||
|
@ -224,6 +264,14 @@ struct psp_gfx_cmd_reg_prog {
|
|||
uint32_t reg_id;
|
||||
};
|
||||
|
||||
/* Command to load TOC */
|
||||
struct psp_gfx_cmd_load_toc
|
||||
{
|
||||
uint32_t toc_phy_addr_lo; /* bits [31:0] of GPU Virtual address of FW location (must be 4 KB aligned) */
|
||||
uint32_t toc_phy_addr_hi; /* bits [63:32] of GPU Virtual address of FW location */
|
||||
uint32_t toc_size; /* FW buffer size in bytes */
|
||||
};
|
||||
|
||||
/* All GFX ring buffer commands. */
|
||||
union psp_gfx_commands
|
||||
{
|
||||
|
@ -234,21 +282,23 @@ union psp_gfx_commands
|
|||
struct psp_gfx_cmd_load_ip_fw cmd_load_ip_fw;
|
||||
struct psp_gfx_cmd_save_restore_ip_fw cmd_save_restore_ip_fw;
|
||||
struct psp_gfx_cmd_reg_prog cmd_setup_reg_prog;
|
||||
struct psp_gfx_cmd_setup_tmr cmd_setup_vmr;
|
||||
struct psp_gfx_cmd_load_toc cmd_load_toc;
|
||||
};
|
||||
|
||||
|
||||
/* Structure of GFX Response buffer.
|
||||
* For GPCOM I/F it is part of GFX_CMD_RESP buffer, for RBI
|
||||
* it is separate buffer.
|
||||
*/
|
||||
struct psp_gfx_resp
|
||||
{
|
||||
uint32_t status; /* +0 status of command execution */
|
||||
uint32_t session_id; /* +4 session ID in response to LoadTa command */
|
||||
uint32_t fw_addr_lo; /* +8 bits [31:0] of FW address within TMR (in response to cmd_load_ip_fw command) */
|
||||
uint32_t fw_addr_hi; /* +12 bits [63:32] of FW address within TMR (in response to cmd_load_ip_fw command) */
|
||||
uint32_t status; /* +0 status of command execution */
|
||||
uint32_t session_id; /* +4 session ID in response to LoadTa command */
|
||||
uint32_t fw_addr_lo; /* +8 bits [31:0] of FW address within TMR (in response to cmd_load_ip_fw command) */
|
||||
uint32_t fw_addr_hi; /* +12 bits [63:32] of FW address within TMR (in response to cmd_load_ip_fw command) */
|
||||
uint32_t tmr_size; /* +16 size of the TMR to be reserved including MM fw and Gfx fw in response to cmd_load_toc command */
|
||||
|
||||
uint32_t reserved[4];
|
||||
uint32_t reserved[3];
|
||||
|
||||
/* total 32 bytes */
|
||||
};
|
||||
|
|
|
@ -41,9 +41,16 @@
|
|||
MODULE_FIRMWARE("amdgpu/vega20_sos.bin");
|
||||
MODULE_FIRMWARE("amdgpu/vega20_asd.bin");
|
||||
MODULE_FIRMWARE("amdgpu/vega20_ta.bin");
|
||||
MODULE_FIRMWARE("amdgpu/navi10_sos.bin");
|
||||
MODULE_FIRMWARE("amdgpu/navi10_asd.bin");
|
||||
|
||||
/* address block */
|
||||
#define smnMP1_FIRMWARE_FLAGS 0x3010024
|
||||
/* navi10 reg offset define */
|
||||
#define mmRLC_GPM_UCODE_ADDR_NV10 0x5b61
|
||||
#define mmRLC_GPM_UCODE_DATA_NV10 0x5b62
|
||||
#define mmSDMA0_UCODE_ADDR_NV10 0x5880
|
||||
#define mmSDMA0_UCODE_DATA_NV10 0x5881
|
||||
|
||||
static int psp_v11_0_init_microcode(struct psp_context *psp)
|
||||
{
|
||||
|
@ -52,6 +59,7 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
|
|||
char fw_name[30];
|
||||
int err = 0;
|
||||
const struct psp_firmware_header_v1_0 *sos_hdr;
|
||||
const struct psp_firmware_header_v1_1 *sos_hdr_v1_1;
|
||||
const struct psp_firmware_header_v1_0 *asd_hdr;
|
||||
const struct ta_firmware_header_v1_0 *ta_hdr;
|
||||
|
||||
|
@ -61,6 +69,9 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
|
|||
case CHIP_VEGA20:
|
||||
chip_name = "vega20";
|
||||
break;
|
||||
case CHIP_NAVI10:
|
||||
chip_name = "navi10";
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
@ -75,15 +86,31 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
|
|||
goto out;
|
||||
|
||||
sos_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.sos_fw->data;
|
||||
adev->psp.sos_fw_version = le32_to_cpu(sos_hdr->header.ucode_version);
|
||||
adev->psp.sos_feature_version = le32_to_cpu(sos_hdr->ucode_feature_version);
|
||||
adev->psp.sos_bin_size = le32_to_cpu(sos_hdr->sos_size_bytes);
|
||||
adev->psp.sys_bin_size = le32_to_cpu(sos_hdr->header.ucode_size_bytes) -
|
||||
le32_to_cpu(sos_hdr->sos_size_bytes);
|
||||
adev->psp.sys_start_addr = (uint8_t *)sos_hdr +
|
||||
amdgpu_ucode_print_psp_hdr(&sos_hdr->header);
|
||||
|
||||
switch (sos_hdr->header.header_version_major) {
|
||||
case 1:
|
||||
adev->psp.sos_fw_version = le32_to_cpu(sos_hdr->header.ucode_version);
|
||||
adev->psp.sos_feature_version = le32_to_cpu(sos_hdr->ucode_feature_version);
|
||||
adev->psp.sos_bin_size = le32_to_cpu(sos_hdr->sos_size_bytes);
|
||||
adev->psp.sys_bin_size = le32_to_cpu(sos_hdr->sos_offset_bytes);
|
||||
adev->psp.sys_start_addr = (uint8_t *)sos_hdr +
|
||||
le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes);
|
||||
adev->psp.sos_start_addr = (uint8_t *)adev->psp.sys_start_addr +
|
||||
adev->psp.sos_start_addr = (uint8_t *)adev->psp.sys_start_addr +
|
||||
le32_to_cpu(sos_hdr->sos_offset_bytes);
|
||||
if (sos_hdr->header.header_version_minor == 1) {
|
||||
sos_hdr_v1_1 = (const struct psp_firmware_header_v1_1 *)adev->psp.sos_fw->data;
|
||||
adev->psp.toc_bin_size = le32_to_cpu(sos_hdr_v1_1->toc_size_bytes);
|
||||
adev->psp.toc_start_addr = (uint8_t *)adev->psp.sys_start_addr +
|
||||
le32_to_cpu(sos_hdr_v1_1->toc_offset_bytes);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(adev->dev,
|
||||
"Unsupported psp sos firmware\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_asd.bin", chip_name);
|
||||
err = request_firmware(&adev->psp.asd_fw, fw_name, adev->dev);
|
||||
|
@ -101,30 +128,36 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
|
|||
adev->psp.asd_start_addr = (uint8_t *)asd_hdr +
|
||||
le32_to_cpu(asd_hdr->header.ucode_array_offset_bytes);
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
|
||||
err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
|
||||
if (err) {
|
||||
release_firmware(adev->psp.ta_fw);
|
||||
adev->psp.ta_fw = NULL;
|
||||
dev_info(adev->dev,
|
||||
"psp v11.0: Failed to load firmware \"%s\"\n", fw_name);
|
||||
} else {
|
||||
err = amdgpu_ucode_validate(adev->psp.ta_fw);
|
||||
if (err)
|
||||
goto out2;
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA20:
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
|
||||
err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
|
||||
if (err) {
|
||||
release_firmware(adev->psp.ta_fw);
|
||||
adev->psp.ta_fw = NULL;
|
||||
dev_info(adev->dev,
|
||||
"psp v11.0: Failed to load firmware \"%s\"\n", fw_name);
|
||||
} else {
|
||||
err = amdgpu_ucode_validate(adev->psp.ta_fw);
|
||||
if (err)
|
||||
goto out2;
|
||||
|
||||
ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
|
||||
adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version);
|
||||
adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes);
|
||||
adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr +
|
||||
le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
|
||||
|
||||
adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
|
||||
|
||||
adev->psp.ta_ras_ucode_version = le32_to_cpu(ta_hdr->ta_ras_ucode_version);
|
||||
adev->psp.ta_ras_ucode_size = le32_to_cpu(ta_hdr->ta_ras_size_bytes);
|
||||
adev->psp.ta_ras_start_addr = (uint8_t *)adev->psp.ta_xgmi_start_addr +
|
||||
le32_to_cpu(ta_hdr->ta_ras_offset_bytes);
|
||||
ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
|
||||
adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version);
|
||||
adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes);
|
||||
adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr +
|
||||
le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
|
||||
adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
|
||||
adev->psp.ta_ras_ucode_version = le32_to_cpu(ta_hdr->ta_ras_ucode_version);
|
||||
adev->psp.ta_ras_ucode_size = le32_to_cpu(ta_hdr->ta_ras_size_bytes);
|
||||
adev->psp.ta_ras_start_addr = (uint8_t *)adev->psp.ta_xgmi_start_addr +
|
||||
le32_to_cpu(ta_hdr->ta_ras_offset_bytes);
|
||||
}
|
||||
break;
|
||||
case CHIP_NAVI10:
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -501,14 +534,24 @@ psp_v11_0_sram_map(struct amdgpu_device *adev,
|
|||
|
||||
case AMDGPU_UCODE_ID_RLC_G:
|
||||
*sram_offset = 0x2000;
|
||||
*sram_addr_reg_offset = SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_ADDR);
|
||||
*sram_data_reg_offset = SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_DATA);
|
||||
if (adev->asic_type != CHIP_NAVI10) {
|
||||
*sram_addr_reg_offset = SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_ADDR);
|
||||
*sram_data_reg_offset = SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_DATA);
|
||||
} else {
|
||||
*sram_addr_reg_offset = adev->reg_offset[GC_HWIP][0][1] + mmRLC_GPM_UCODE_ADDR_NV10;
|
||||
*sram_data_reg_offset = adev->reg_offset[GC_HWIP][0][1] + mmRLC_GPM_UCODE_DATA_NV10;
|
||||
}
|
||||
break;
|
||||
|
||||
case AMDGPU_UCODE_ID_SDMA0:
|
||||
*sram_offset = 0x0;
|
||||
*sram_addr_reg_offset = SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_UCODE_ADDR);
|
||||
*sram_data_reg_offset = SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_UCODE_DATA);
|
||||
if (adev->asic_type != CHIP_NAVI10) {
|
||||
*sram_addr_reg_offset = SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_UCODE_ADDR);
|
||||
*sram_data_reg_offset = SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_UCODE_DATA);
|
||||
} else {
|
||||
*sram_addr_reg_offset = adev->reg_offset[GC_HWIP][0][1] + mmSDMA0_UCODE_ADDR_NV10;
|
||||
*sram_data_reg_offset = adev->reg_offset[GC_HWIP][0][1] + mmSDMA0_UCODE_DATA_NV10;
|
||||
}
|
||||
break;
|
||||
|
||||
/* TODO: needs to confirm */
|
||||
|
@ -772,6 +815,11 @@ static int psp_v11_0_ras_cure_posion(struct psp_context *psp, uint64_t *mode_ptr
|
|||
#endif
|
||||
}
|
||||
|
||||
static int psp_v11_0_rlc_autoload_start(struct psp_context *psp)
|
||||
{
|
||||
return psp_rlc_autoload_start(psp);
|
||||
}
|
||||
|
||||
static const struct psp_funcs psp_v11_0_funcs = {
|
||||
.init_microcode = psp_v11_0_init_microcode,
|
||||
.bootloader_load_sysdrv = psp_v11_0_bootloader_load_sysdrv,
|
||||
|
@ -790,6 +838,7 @@ static const struct psp_funcs psp_v11_0_funcs = {
|
|||
.support_vmr_ring = psp_v11_0_support_vmr_ring,
|
||||
.ras_trigger_error = psp_v11_0_ras_trigger_error,
|
||||
.ras_cure_posion = psp_v11_0_ras_cure_posion,
|
||||
.rlc_autoload_start = psp_v11_0_rlc_autoload_start,
|
||||
};
|
||||
|
||||
void psp_v11_0_set_psp_funcs(struct psp_context *psp)
|
||||
|
|
|
@ -1095,7 +1095,7 @@ static int sdma_v4_0_load_microcode(struct amdgpu_device *adev)
|
|||
static int sdma_v4_0_start(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ring *ring;
|
||||
int i, r;
|
||||
int i, r = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
sdma_v4_0_ctx_switch_enable(adev, false);
|
||||
|
@ -1569,9 +1569,7 @@ static int sdma_v4_0_late_init(void *handle)
|
|||
if (r)
|
||||
goto interrupt;
|
||||
|
||||
r = amdgpu_ras_debugfs_create(adev, &fs_info);
|
||||
if (r)
|
||||
goto debugfs;
|
||||
amdgpu_ras_debugfs_create(adev, &fs_info);
|
||||
|
||||
r = amdgpu_ras_sysfs_create(adev, &fs_info);
|
||||
if (r)
|
||||
|
@ -1592,7 +1590,6 @@ irq:
|
|||
amdgpu_ras_sysfs_remove(adev, *ras_if);
|
||||
sysfs:
|
||||
amdgpu_ras_debugfs_remove(adev, *ras_if);
|
||||
debugfs:
|
||||
amdgpu_ras_interrupt_remove_handler(adev, &ih_info);
|
||||
interrupt:
|
||||
amdgpu_ras_feature_enable(adev, *ras_if, 0);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SDMA_V5_0_H__
|
||||
#define __SDMA_V5_0_H__
|
||||
|
||||
enum sdma_v5_0_utcl2_cache_read_policy {
|
||||
CACHE_READ_POLICY_L2__LRU = 0x00000000,
|
||||
CACHE_READ_POLICY_L2__STREAM = 0x00000001,
|
||||
CACHE_READ_POLICY_L2__NOA = 0x00000002,
|
||||
CACHE_READ_POLICY_L2__DEFAULT = CACHE_READ_POLICY_L2__NOA,
|
||||
};
|
||||
|
||||
enum sdma_v5_0_utcl2_cache_write_policy {
|
||||
CACHE_WRITE_POLICY_L2__LRU = 0x00000000,
|
||||
CACHE_WRITE_POLICY_L2__STREAM = 0x00000001,
|
||||
CACHE_WRITE_POLICY_L2__NOA = 0x00000002,
|
||||
CACHE_WRITE_POLICY_L2__BYPASS = 0x00000003,
|
||||
CACHE_WRITE_POLICY_L2__DEFAULT = CACHE_WRITE_POLICY_L2__BYPASS,
|
||||
};
|
||||
|
||||
extern const struct amd_ip_funcs sdma_v5_0_ip_funcs;
|
||||
extern const struct amdgpu_ip_block_version sdma_v5_0_ip_block;
|
||||
|
||||
#endif /* __SDMA_V5_0_H__ */
|
|
@ -1340,8 +1340,8 @@ static void si_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
|
|||
/* This reports 0 on APUs, so return to avoid writing/reading registers
|
||||
* that may or may not be different from their GPU counterparts
|
||||
*/
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return;
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return;
|
||||
|
||||
/* Set the 2 events that we wish to watch, defined above */
|
||||
/* Reg 40 is # received msgs, Reg 104 is # of posted requests sent */
|
||||
|
|
|
@ -275,15 +275,6 @@ static bool soc15_read_bios_from_rom(struct amdgpu_device *adev,
|
|||
return true;
|
||||
}
|
||||
|
||||
struct soc15_allowed_register_entry {
|
||||
uint32_t hwip;
|
||||
uint32_t inst;
|
||||
uint32_t seg;
|
||||
uint32_t reg_offset;
|
||||
bool grbm_indexed;
|
||||
};
|
||||
|
||||
|
||||
static struct soc15_allowed_register_entry soc15_allowed_read_registers[] = {
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS)},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS2)},
|
||||
|
@ -388,7 +379,7 @@ void soc15_program_register_sequence(struct amdgpu_device *adev,
|
|||
} else {
|
||||
tmp = RREG32(reg);
|
||||
tmp &= ~(entry->and_mask);
|
||||
tmp |= entry->or_mask;
|
||||
tmp |= (entry->or_mask & entry->and_mask);
|
||||
}
|
||||
|
||||
if (reg == SOC15_REG_OFFSET(GC, 0, mmPA_SC_BINNER_EVENT_CNTL_3) ||
|
||||
|
@ -722,8 +713,8 @@ static void soc15_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
|
|||
/* This reports 0 on APUs, so return to avoid writing/reading registers
|
||||
* that may or may not be different from their GPU counterparts
|
||||
*/
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return;
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return;
|
||||
|
||||
/* Set the 2 events that we wish to watch, defined above */
|
||||
/* Reg 40 is # received msgs, Reg 104 is # of posted requests sent */
|
||||
|
@ -1035,6 +1026,8 @@ static int soc15_common_sw_init(void *handle)
|
|||
if (amdgpu_sriov_vf(adev))
|
||||
xgpu_ai_mailbox_add_irq_id(adev);
|
||||
|
||||
adev->df_funcs->sw_init(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1081,6 +1074,7 @@ static int soc15_common_hw_init(void *handle)
|
|||
*/
|
||||
if (adev->nbio_funcs->remap_hdp_registers)
|
||||
adev->nbio_funcs->remap_hdp_registers(adev);
|
||||
|
||||
/* enable the doorbell aperture */
|
||||
soc15_enable_doorbell_aperture(adev, true);
|
||||
/* HW doorbell routing policy: doorbell writing not
|
||||
|
|
|
@ -48,6 +48,16 @@ struct soc15_reg_entry {
|
|||
uint32_t seg;
|
||||
uint32_t reg_offset;
|
||||
uint32_t reg_value;
|
||||
uint32_t se_num;
|
||||
uint32_t instance;
|
||||
};
|
||||
|
||||
struct soc15_allowed_register_entry {
|
||||
uint32_t hwip;
|
||||
uint32_t inst;
|
||||
uint32_t seg;
|
||||
uint32_t reg_offset;
|
||||
bool grbm_indexed;
|
||||
};
|
||||
|
||||
#define SOC15_REG_ENTRY(ip, inst, reg) ip##_HWIP, inst, reg##_BASE_IDX, reg
|
||||
|
|
|
@ -1,29 +1,26 @@
|
|||
/****************************************************************************\
|
||||
*
|
||||
* File Name ta_ras_if.h
|
||||
* Project AMD PSP SW IP Module
|
||||
*
|
||||
* Description Interface to the RAS Trusted Application
|
||||
*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TA_RAS_IF_H
|
||||
#define _TA_RAS_IF_H
|
||||
|
||||
|
@ -31,8 +28,8 @@
|
|||
#define RSP_ID_MASK (1U << 31)
|
||||
#define RSP_ID(cmdId) (((uint32_t)(cmdId)) | RSP_ID_MASK)
|
||||
|
||||
#define TA_NUM_BLOCK_MAX 14
|
||||
|
||||
/* RAS related enumerations */
|
||||
/**********************************************************/
|
||||
enum ras_command {
|
||||
TA_RAS_COMMAND__ENABLE_FEATURES = 0,
|
||||
TA_RAS_COMMAND__DISABLE_FEATURES,
|
||||
|
@ -45,7 +42,12 @@ enum ta_ras_status {
|
|||
TA_RAS_STATUS__ERROR_INVALID_PARAMETER = 0x02,
|
||||
TA_RAS_STATUS__ERROR_RAS_NOT_AVAILABLE = 0x03,
|
||||
TA_RAS_STATUS__ERROR_RAS_DUPLICATE_CMD = 0x04,
|
||||
TA_RAS_STATUS__ERROR_INJECTION_FAILED = 0x05
|
||||
TA_RAS_STATUS__ERROR_INJECTION_FAILED = 0x05,
|
||||
TA_RAS_STATUS__ERROR_ASD_READ_WRITE = 0x06,
|
||||
TA_RAS_STATUS__ERROR_TOGGLE_DF_CSTATE = 0x07,
|
||||
TA_RAS_STATUS__ERROR_TIMEOUT = 0x08,
|
||||
TA_RAS_STATUS__ERROR_BLOCK_DISABLED = 0x09,
|
||||
TA_RAS_STATUS__ERROR_GENERIC = 0x10,
|
||||
};
|
||||
|
||||
enum ta_ras_block {
|
||||
|
@ -62,47 +64,55 @@ enum ta_ras_block {
|
|||
TA_RAS_BLOCK__SEM,
|
||||
TA_RAS_BLOCK__MP0,
|
||||
TA_RAS_BLOCK__MP1,
|
||||
TA_RAS_BLOCK__FUSE = (TA_NUM_BLOCK_MAX - 1),
|
||||
TA_RAS_BLOCK__FUSE,
|
||||
TA_NUM_BLOCK_MAX
|
||||
};
|
||||
|
||||
enum ta_ras_error_type {
|
||||
TA_RAS_ERROR__NONE = 0,
|
||||
TA_RAS_ERROR__PARITY = 1,
|
||||
TA_RAS_ERROR__SINGLE_CORRECTABLE = 2,
|
||||
TA_RAS_ERROR__MULTI_UNCORRECTABLE = 4,
|
||||
TA_RAS_ERROR__POISON = 8
|
||||
TA_RAS_ERROR__NONE = 0,
|
||||
TA_RAS_ERROR__PARITY = 1,
|
||||
TA_RAS_ERROR__SINGLE_CORRECTABLE = 2,
|
||||
TA_RAS_ERROR__MULTI_UNCORRECTABLE = 4,
|
||||
TA_RAS_ERROR__POISON = 8,
|
||||
};
|
||||
|
||||
/* Input/output structures for RAS commands */
|
||||
/**********************************************************/
|
||||
|
||||
struct ta_ras_enable_features_input {
|
||||
enum ta_ras_block block_id;
|
||||
enum ta_ras_error_type error_type;
|
||||
enum ta_ras_block block_id;
|
||||
enum ta_ras_error_type error_type;
|
||||
};
|
||||
|
||||
struct ta_ras_disable_features_input {
|
||||
enum ta_ras_block block_id;
|
||||
enum ta_ras_error_type error_type;
|
||||
enum ta_ras_block block_id;
|
||||
enum ta_ras_error_type error_type;
|
||||
};
|
||||
|
||||
struct ta_ras_trigger_error_input {
|
||||
enum ta_ras_block block_id;
|
||||
enum ta_ras_error_type inject_error_type;
|
||||
uint32_t sub_block_index;
|
||||
uint64_t address;
|
||||
uint64_t value;
|
||||
enum ta_ras_block block_id; // ras-block. i.e. umc, gfx
|
||||
enum ta_ras_error_type inject_error_type; // type of error. i.e. single_correctable
|
||||
uint32_t sub_block_index; // mem block. i.e. hbm, sram etc.
|
||||
uint64_t address; // explicit address of error
|
||||
uint64_t value; // method if error injection. i.e persistent, coherent etc.
|
||||
};
|
||||
|
||||
/* Common input structure for RAS callbacks */
|
||||
/**********************************************************/
|
||||
union ta_ras_cmd_input {
|
||||
struct ta_ras_enable_features_input enable_features;
|
||||
struct ta_ras_disable_features_input disable_features;
|
||||
struct ta_ras_trigger_error_input trigger_error;
|
||||
};
|
||||
|
||||
/* Shared Memory structures */
|
||||
/**********************************************************/
|
||||
struct ta_ras_shared_memory {
|
||||
uint32_t cmd_id;
|
||||
uint32_t resp_id;
|
||||
enum ta_ras_status ras_status;
|
||||
uint32_t reserved;
|
||||
union ta_ras_cmd_input ras_in_message;
|
||||
uint32_t cmd_id;
|
||||
uint32_t resp_id;
|
||||
enum ta_ras_status ras_status;
|
||||
uint32_t reserved;
|
||||
union ta_ras_cmd_input ras_in_message;
|
||||
};
|
||||
|
||||
#endif // TL_RAS_IF_H_
|
||||
|
|
|
@ -128,6 +128,17 @@ static int vcn_v1_0_sw_init(void *handle)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
adev->vcn.internal.scratch9 = adev->vcn.external.scratch9 =
|
||||
SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9);
|
||||
adev->vcn.internal.data0 = adev->vcn.external.data0 =
|
||||
SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0);
|
||||
adev->vcn.internal.data1 = adev->vcn.external.data1 =
|
||||
SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1);
|
||||
adev->vcn.internal.cmd = adev->vcn.external.cmd =
|
||||
SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD);
|
||||
adev->vcn.internal.nop = adev->vcn.external.nop =
|
||||
SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP);
|
||||
|
||||
for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
|
||||
ring = &adev->vcn.ring_enc[i];
|
||||
sprintf(ring->name, "vcn_enc%d", i);
|
||||
|
@ -143,6 +154,8 @@ static int vcn_v1_0_sw_init(void *handle)
|
|||
return r;
|
||||
|
||||
adev->vcn.pause_dpg_mode = vcn_v1_0_pause_dpg_mode;
|
||||
adev->vcn.internal.jpeg_pitch = adev->vcn.external.jpeg_pitch =
|
||||
SOC15_REG_OFFSET(UVD, 0, mmUVD_JPEG_PITCH);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2018 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __VCN_V2_0_H__
|
||||
#define __VCN_V2_0_H__
|
||||
|
||||
extern const struct amdgpu_ip_block_version vcn_v2_0_ip_block;
|
||||
|
||||
#endif /* __VCN_V2_0_H__ */
|
|
@ -36,16 +36,19 @@ AMDKFD_FILES := $(AMDKFD_PATH)/kfd_module.o \
|
|||
$(AMDKFD_PATH)/kfd_mqd_manager_cik.o \
|
||||
$(AMDKFD_PATH)/kfd_mqd_manager_vi.o \
|
||||
$(AMDKFD_PATH)/kfd_mqd_manager_v9.o \
|
||||
$(AMDKFD_PATH)/kfd_mqd_manager_v10.o \
|
||||
$(AMDKFD_PATH)/kfd_kernel_queue.o \
|
||||
$(AMDKFD_PATH)/kfd_kernel_queue_cik.o \
|
||||
$(AMDKFD_PATH)/kfd_kernel_queue_vi.o \
|
||||
$(AMDKFD_PATH)/kfd_kernel_queue_v9.o \
|
||||
$(AMDKFD_PATH)/kfd_kernel_queue_v10.o \
|
||||
$(AMDKFD_PATH)/kfd_packet_manager.o \
|
||||
$(AMDKFD_PATH)/kfd_process_queue_manager.o \
|
||||
$(AMDKFD_PATH)/kfd_device_queue_manager.o \
|
||||
$(AMDKFD_PATH)/kfd_device_queue_manager_cik.o \
|
||||
$(AMDKFD_PATH)/kfd_device_queue_manager_vi.o \
|
||||
$(AMDKFD_PATH)/kfd_device_queue_manager_v9.o \
|
||||
$(AMDKFD_PATH)/kfd_device_queue_manager_v10.o \
|
||||
$(AMDKFD_PATH)/kfd_interrupt.o \
|
||||
$(AMDKFD_PATH)/kfd_events.o \
|
||||
$(AMDKFD_PATH)/cik_event_interrupt.o \
|
||||
|
|
|
@ -561,3 +561,302 @@ static const uint32_t cwsr_trap_gfx9_hex[] = {
|
|||
0xbf8a0000, 0x95806f6c,
|
||||
0xbf810000, 0x00000000,
|
||||
};
|
||||
|
||||
static const uint32_t cwsr_trap_gfx10_hex[] = {
|
||||
0xbf820001, 0xbf82012e,
|
||||
0xb0804004, 0xb970f802,
|
||||
0x8a708670, 0xb971f803,
|
||||
0x8771ff71, 0x00000400,
|
||||
0xbf850008, 0xb971f803,
|
||||
0x8771ff71, 0x000001ff,
|
||||
0xbf850001, 0x806c846c,
|
||||
0x876dff6d, 0x0000ffff,
|
||||
0xbe80226c, 0xb971f803,
|
||||
0x8771ff71, 0x00000100,
|
||||
0xbf840006, 0xbef60380,
|
||||
0xb9f60203, 0x876dff6d,
|
||||
0x0000ffff, 0x80ec886c,
|
||||
0x82ed806d, 0xbef60380,
|
||||
0xb9f60283, 0xb973f816,
|
||||
0xb9762c07, 0x8f769c76,
|
||||
0x886d766d, 0xb97603c7,
|
||||
0x8f769b76, 0x886d766d,
|
||||
0xb976f807, 0x8776ff76,
|
||||
0x00007fff, 0xb9f6f807,
|
||||
0xbeee037e, 0xbeef037f,
|
||||
0xbefe0480, 0xbf900004,
|
||||
0xbf8e0002, 0xbf88fffe,
|
||||
0xbef4037e, 0x8775ff7f,
|
||||
0x0000ffff, 0x8875ff75,
|
||||
0x00040000, 0xbef60380,
|
||||
0xbef703ff, 0x00807fac,
|
||||
0x8776ff7f, 0x08000000,
|
||||
0x90768376, 0x88777677,
|
||||
0x8776ff7f, 0x70000000,
|
||||
0x90768176, 0x88777677,
|
||||
0xbefb037c, 0xbefa0380,
|
||||
0xb97202dc, 0x8872727f,
|
||||
0xbefe03c1, 0x877c8172,
|
||||
0xbf06817c, 0xbf850002,
|
||||
0xbeff0380, 0xbf820001,
|
||||
0xbeff03c1, 0xb9712a05,
|
||||
0x80718171, 0x8f718271,
|
||||
0x877c8172, 0xbf06817c,
|
||||
0xbf85000d, 0x8f768771,
|
||||
0xbef603ff, 0x01000000,
|
||||
0xbefc0380, 0x7e008700,
|
||||
0xe0704000, 0x7a5d0000,
|
||||
0x807c817c, 0x807aff7a,
|
||||
0x00000080, 0xbf0a717c,
|
||||
0xbf85fff8, 0xbf82001b,
|
||||
0x8f768871, 0xbef603ff,
|
||||
0x01000000, 0xbefc0380,
|
||||
0x7e008700, 0xe0704000,
|
||||
0x7a5d0000, 0x807c817c,
|
||||
0x807aff7a, 0x00000100,
|
||||
0xbf0a717c, 0xbf85fff8,
|
||||
0xb9711e06, 0x8771c171,
|
||||
0xbf84000c, 0x8f718371,
|
||||
0x80717c71, 0xbefe03c1,
|
||||
0xbeff0380, 0x7e008700,
|
||||
0xe0704000, 0x7a5d0000,
|
||||
0x807c817c, 0x807aff7a,
|
||||
0x00000080, 0xbf0a717c,
|
||||
0xbf85fff8, 0xbf8a0000,
|
||||
0x8776ff72, 0x04000000,
|
||||
0xbf84002b, 0xbefe03c1,
|
||||
0x877c8172, 0xbf06817c,
|
||||
0xbf850002, 0xbeff0380,
|
||||
0xbf820001, 0xbeff03c1,
|
||||
0xb9714306, 0x8771c171,
|
||||
0xbf840021, 0x8f718671,
|
||||
0x8f718271, 0xbef60371,
|
||||
0xbef603ff, 0x01000000,
|
||||
0xd7650000, 0x000100c1,
|
||||
0xd7660000, 0x000200c1,
|
||||
0x16000084, 0x877c8172,
|
||||
0xbf06817c, 0xbefc0380,
|
||||
0xbf85000a, 0x807cff7c,
|
||||
0x00000080, 0x807aff7a,
|
||||
0x00000080, 0xd5250000,
|
||||
0x0001ff00, 0x00000080,
|
||||
0xbf0a717c, 0xbf85fff7,
|
||||
0xbf820009, 0x807cff7c,
|
||||
0x00000100, 0x807aff7a,
|
||||
0x00000100, 0xd5250000,
|
||||
0x0001ff00, 0x00000100,
|
||||
0xbf0a717c, 0xbf85fff7,
|
||||
0x877c8172, 0xbf06817c,
|
||||
0xbf850003, 0x8f7687ff,
|
||||
0x0000006a, 0xbf820002,
|
||||
0x8f7688ff, 0x0000006a,
|
||||
0xbef603ff, 0x01000000,
|
||||
0x877c8172, 0xbf06817c,
|
||||
0xbefc0380, 0xbf800000,
|
||||
0xbf85000b, 0xbe802e00,
|
||||
0x7e000200, 0xe0704000,
|
||||
0x7a5d0000, 0x807aff7a,
|
||||
0x00000080, 0x807c817c,
|
||||
0xbf0aff7c, 0x0000006a,
|
||||
0xbf85fff6, 0xbf82000a,
|
||||
0xbe802e00, 0x7e000200,
|
||||
0xe0704000, 0x7a5d0000,
|
||||
0x807aff7a, 0x00000100,
|
||||
0x807c817c, 0xbf0aff7c,
|
||||
0x0000006a, 0xbf85fff6,
|
||||
0xbef60384, 0xbef603ff,
|
||||
0x01000000, 0x877c8172,
|
||||
0xbf06817c, 0xbf850030,
|
||||
0x7e00027b, 0xe0704000,
|
||||
0x7a5d0000, 0x807aff7a,
|
||||
0x00000080, 0x7e00026c,
|
||||
0xe0704000, 0x7a5d0000,
|
||||
0x807aff7a, 0x00000080,
|
||||
0x7e00026d, 0xe0704000,
|
||||
0x7a5d0000, 0x807aff7a,
|
||||
0x00000080, 0x7e00026e,
|
||||
0xe0704000, 0x7a5d0000,
|
||||
0x807aff7a, 0x00000080,
|
||||
0x7e00026f, 0xe0704000,
|
||||
0x7a5d0000, 0x807aff7a,
|
||||
0x00000080, 0x7e000270,
|
||||
0xe0704000, 0x7a5d0000,
|
||||
0x807aff7a, 0x00000080,
|
||||
0xb971f803, 0x7e000271,
|
||||
0xe0704000, 0x7a5d0000,
|
||||
0x807aff7a, 0x00000080,
|
||||
0x7e000273, 0xe0704000,
|
||||
0x7a5d0000, 0x807aff7a,
|
||||
0x00000080, 0xb97bf801,
|
||||
0x7e00027b, 0xe0704000,
|
||||
0x7a5d0000, 0x807aff7a,
|
||||
0x00000080, 0xbf82002f,
|
||||
0x7e00027b, 0xe0704000,
|
||||
0x7a5d0000, 0x807aff7a,
|
||||
0x00000100, 0x7e00026c,
|
||||
0xe0704000, 0x7a5d0000,
|
||||
0x807aff7a, 0x00000100,
|
||||
0x7e00026d, 0xe0704000,
|
||||
0x7a5d0000, 0x807aff7a,
|
||||
0x00000100, 0x7e00026e,
|
||||
0xe0704000, 0x7a5d0000,
|
||||
0x807aff7a, 0x00000100,
|
||||
0x7e00026f, 0xe0704000,
|
||||
0x7a5d0000, 0x807aff7a,
|
||||
0x00000100, 0x7e000270,
|
||||
0xe0704000, 0x7a5d0000,
|
||||
0x807aff7a, 0x00000100,
|
||||
0xb971f803, 0x7e000271,
|
||||
0xe0704000, 0x7a5d0000,
|
||||
0x807aff7a, 0x00000100,
|
||||
0x7e000273, 0xe0704000,
|
||||
0x7a5d0000, 0x807aff7a,
|
||||
0x00000100, 0xb97bf801,
|
||||
0x7e00027b, 0xe0704000,
|
||||
0x7a5d0000, 0x807aff7a,
|
||||
0x00000100, 0xbf820119,
|
||||
0xbef4037e, 0x8775ff7f,
|
||||
0x0000ffff, 0x8875ff75,
|
||||
0x00040000, 0xbef60380,
|
||||
0xbef703ff, 0x00807fac,
|
||||
0x8772ff7f, 0x08000000,
|
||||
0x90728372, 0x88777277,
|
||||
0x8772ff7f, 0x70000000,
|
||||
0x90728172, 0x88777277,
|
||||
0xb97902dc, 0x8879797f,
|
||||
0xbef80380, 0xbefe03c1,
|
||||
0x877c8179, 0xbf06817c,
|
||||
0xbf850002, 0xbeff0380,
|
||||
0xbf820001, 0xbeff03c1,
|
||||
0xb96f2a05, 0x806f816f,
|
||||
0x8f6f826f, 0x877c8179,
|
||||
0xbf06817c, 0xbf850013,
|
||||
0x8f76876f, 0xbef603ff,
|
||||
0x01000000, 0xbef20378,
|
||||
0x8078ff78, 0x00000080,
|
||||
0xbefc0381, 0xe0304000,
|
||||
0x785d0000, 0xbf8c3f70,
|
||||
0x7e008500, 0x807c817c,
|
||||
0x8078ff78, 0x00000080,
|
||||
0xbf0a6f7c, 0xbf85fff7,
|
||||
0xe0304000, 0x725d0000,
|
||||
0xbf820023, 0x8f76886f,
|
||||
0xbef603ff, 0x01000000,
|
||||
0xbef20378, 0x8078ff78,
|
||||
0x00000100, 0xbefc0381,
|
||||
0xe0304000, 0x785d0000,
|
||||
0xbf8c3f70, 0x7e008500,
|
||||
0x807c817c, 0x8078ff78,
|
||||
0x00000100, 0xbf0a6f7c,
|
||||
0xbf85fff7, 0xb96f1e06,
|
||||
0x876fc16f, 0xbf84000e,
|
||||
0x8f6f836f, 0x806f7c6f,
|
||||
0xbefe03c1, 0xbeff0380,
|
||||
0xe0304000, 0x785d0000,
|
||||
0xbf8c3f70, 0x7e008500,
|
||||
0x807c817c, 0x8078ff78,
|
||||
0x00000080, 0xbf0a6f7c,
|
||||
0xbf85fff7, 0xbeff03c1,
|
||||
0xe0304000, 0x725d0000,
|
||||
0x8772ff79, 0x04000000,
|
||||
0xbf840020, 0xbefe03c1,
|
||||
0x877c8179, 0xbf06817c,
|
||||
0xbf850002, 0xbeff0380,
|
||||
0xbf820001, 0xbeff03c1,
|
||||
0xb96f4306, 0x876fc16f,
|
||||
0xbf840016, 0x8f6f866f,
|
||||
0x8f6f826f, 0xbef6036f,
|
||||
0xbef603ff, 0x01000000,
|
||||
0x877c8172, 0xbf06817c,
|
||||
0xbefc0380, 0xbf850007,
|
||||
0x807cff7c, 0x00000080,
|
||||
0x8078ff78, 0x00000080,
|
||||
0xbf0a6f7c, 0xbf85fffa,
|
||||
0xbf820006, 0x807cff7c,
|
||||
0x00000100, 0x8078ff78,
|
||||
0x00000100, 0xbf0a6f7c,
|
||||
0xbf85fffa, 0x877c8179,
|
||||
0xbf06817c, 0xbf850003,
|
||||
0x8f7687ff, 0x0000006a,
|
||||
0xbf820002, 0x8f7688ff,
|
||||
0x0000006a, 0xbef603ff,
|
||||
0x01000000, 0x877c8179,
|
||||
0xbf06817c, 0xbf850012,
|
||||
0xf4211cba, 0xf0000000,
|
||||
0x8078ff78, 0x00000080,
|
||||
0xbefc0381, 0xf421003a,
|
||||
0xf0000000, 0x8078ff78,
|
||||
0x00000080, 0xbf8cc07f,
|
||||
0xbe803000, 0xbf800000,
|
||||
0x807c817c, 0xbf0aff7c,
|
||||
0x0000006a, 0xbf85fff5,
|
||||
0xbe800372, 0xbf820011,
|
||||
0xf4211cba, 0xf0000000,
|
||||
0x8078ff78, 0x00000100,
|
||||
0xbefc0381, 0xf421003a,
|
||||
0xf0000000, 0x8078ff78,
|
||||
0x00000100, 0xbf8cc07f,
|
||||
0xbe803000, 0xbf800000,
|
||||
0x807c817c, 0xbf0aff7c,
|
||||
0x0000006a, 0xbf85fff5,
|
||||
0xbe800372, 0xbef60384,
|
||||
0xbef603ff, 0x01000000,
|
||||
0x877c8179, 0xbf06817c,
|
||||
0xbf850025, 0xf4211bfa,
|
||||
0xf0000000, 0x8078ff78,
|
||||
0x00000080, 0xf4211b3a,
|
||||
0xf0000000, 0x8078ff78,
|
||||
0x00000080, 0xf4211b7a,
|
||||
0xf0000000, 0x8078ff78,
|
||||
0x00000080, 0xf4211eba,
|
||||
0xf0000000, 0x8078ff78,
|
||||
0x00000080, 0xf4211efa,
|
||||
0xf0000000, 0x8078ff78,
|
||||
0x00000080, 0xf4211c3a,
|
||||
0xf0000000, 0x8078ff78,
|
||||
0x00000080, 0xf4211c7a,
|
||||
0xf0000000, 0x8078ff78,
|
||||
0x00000080, 0xf4211cfa,
|
||||
0xf0000000, 0x8078ff78,
|
||||
0x00000080, 0xf4211e7a,
|
||||
0xf0000000, 0x8078ff78,
|
||||
0x00000080, 0xbf820024,
|
||||
0xf4211bfa, 0xf0000000,
|
||||
0x8078ff78, 0x00000100,
|
||||
0xf4211b3a, 0xf0000000,
|
||||
0x8078ff78, 0x00000100,
|
||||
0xf4211b7a, 0xf0000000,
|
||||
0x8078ff78, 0x00000100,
|
||||
0xf4211eba, 0xf0000000,
|
||||
0x8078ff78, 0x00000100,
|
||||
0xf4211efa, 0xf0000000,
|
||||
0x8078ff78, 0x00000100,
|
||||
0xf4211c3a, 0xf0000000,
|
||||
0x8078ff78, 0x00000100,
|
||||
0xf4211c7a, 0xf0000000,
|
||||
0x8078ff78, 0x00000100,
|
||||
0xf4211cfa, 0xf0000000,
|
||||
0x8078ff78, 0x00000100,
|
||||
0xf4211e7a, 0xf0000000,
|
||||
0x8078ff78, 0x00000100,
|
||||
0xbf8cc07f, 0x876dff6d,
|
||||
0x0000ffff, 0xbefc036f,
|
||||
0xbefe037a, 0xbeff037b,
|
||||
0x876f71ff, 0x000003ff,
|
||||
0xb9ef4803, 0xb9f3f816,
|
||||
0x876f71ff, 0xfffff800,
|
||||
0x906f8b6f, 0xb9efa2c3,
|
||||
0xb9f9f801, 0x876fff6d,
|
||||
0xf0000000, 0x906f9c6f,
|
||||
0x8f6f906f, 0xbef20380,
|
||||
0x88726f72, 0x876fff6d,
|
||||
0x08000000, 0x906f9b6f,
|
||||
0x8f6f8f6f, 0x88726f72,
|
||||
0x876fff70, 0x00800000,
|
||||
0x906f976f, 0xb9f2f807,
|
||||
0xb9f0f802, 0xbf8a0000,
|
||||
0xbe80226c, 0xbf810000,
|
||||
0xbf9f0000, 0xbf9f0000,
|
||||
0xbf9f0000, 0xbf9f0000,
|
||||
0xbf9f0000, 0x00000000,
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue