Merge tag 'amd-drm-next-7.3-2026-07-29' of https://gitlab.freedesktop.org/agd5f/linux into drm-next

amd-drm-next-7.3-2026-07-29:

amdgpu:
- VCN 5.3 fix
- UserQ fixes
- GEM close optimization
- HDMI AV mute fix
- UML build fixes
- GFXOFF residency metrics fixes
- SMU 15 fixes
- debug_vm fix
- PSP 15 fixes
- NBIO 7.11.5 fix
- pptable use after free fix
- gpu metrics fetch fix
- DC viewport fix
- DML2.1 fix
- i2c retimer spam fix
- UMD profile pstate fix
- Power metrics format cleanup
- GTT size fix on APUs
- DC context logging fix
- Misc fixes
- IB pool clean up and fixes
- DCN 4.2 updates
- Old BUG() and BUG_ON() removal
- RAS updates
- PASID management updates
- DC MCIF ARB updates
- More DC KUNIT tests
- Refactor dc_validation_set
- Introduce dc_state_get_status unified status accessor
- Apple Studio Display fixes
- DML updates
- DC writeback fixes
- MES updates
- PTL updates
- DC code restructuring
- DC FRL fixes
- Add modifiers for GFX6-8
- Resume fix for MacBookPro15,1

amdkfd:
- Various bounds checking fixes
- Mutex locking fix
- Clean up debug runlist printing
- SR-IOV fixes
- Avoid topology_lock in kfd_mmap
- Fix signal reset event
- SVM eviction fixes

radeon:
- Fix for unset CONFIG_ACPI

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

From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patch.msgid.link/20260729201801.4073097-1-alexander.deucher@amd.com
This commit is contained in:
Dave Airlie
2026-07-31 15:44:43 +10:00
291 changed files with 16581 additions and 3538 deletions

View File

@@ -223,6 +223,7 @@ extern int amdgpu_smartshift_bias;
extern int amdgpu_use_xgmi_p2p;
extern int amdgpu_mtype_local;
extern int amdgpu_enforce_isolation;
extern uint amdgpu_debug_mask;
#ifdef CONFIG_HSA_AMD
extern int sched_policy;
extern bool debug_evictions;

View File

@@ -39,6 +39,7 @@
#if IS_ENABLED(CONFIG_HSA_AMD)
#include "kfd_priv.h"
#endif
#include "kfd_svm.h"
/* Total memory size in system memory and all GPU VRAM. Used to
* estimate worst case amount of memory to reserve for page tables
@@ -711,7 +712,8 @@ int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
goto err;
}
ret = amdgpu_job_alloc(adev, NULL, NULL, NULL, 1, &job, 0);
ret = amdgpu_job_alloc(adev, NULL, NULL, NULL, 1, 0, GFP_KERNEL,
&job);
if (ret)
goto err;
@@ -971,3 +973,24 @@ int amdgpu_amdkfd_reset_mes_queue(struct amdgpu_device *adev,
return kgd2kfd_reset_mes_queue(adev->kfd.dev, node_id, queue_type,
pipe, queue, db);
}
int amdgpu_amdkfd_evict_svm_bo(struct amdgpu_bo *bo)
{
struct dma_resv_iter cursor;
struct dma_fence *fence;
int r = 0;
dma_resv_iter_begin(&cursor, bo->tbo.base.resv, DMA_RESV_USAGE_BOOKKEEP);
dma_resv_for_each_fence_unlocked(&cursor, fence) {
struct amdgpu_amdkfd_fence *f = to_amdgpu_amdkfd_fence(fence);
if (f && f->svm_bo) {
r = svm_range_evict_svm_bo(f->svm_bo);
if (r)
break;
}
}
dma_resv_iter_end(&cursor);
return r;
}

View File

@@ -286,6 +286,7 @@ int amdgpu_amdkfd_reset_mes_queue(struct amdgpu_device *adev,
int queue_type,
int pipe, int queue,
unsigned int db);
int amdgpu_amdkfd_evict_svm_bo(struct amdgpu_bo *bo);
/* Read user wptr from a specified user address space with page fault
* disabled. The memory must be pinned and mapped to the hardware when

View File

@@ -92,7 +92,7 @@ struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f)
return NULL;
fence = container_of(f, struct amdgpu_amdkfd_fence, base);
if (f->ops == &amdkfd_fence_ops)
if (rcu_access_pointer(f->ops) == &amdkfd_fence_ops)
return fence;
return NULL;
@@ -135,9 +135,6 @@ static bool amdkfd_fence_enable_signaling(struct dma_fence *f)
if (!fence->svm_bo) {
if (!kgd2kfd_schedule_evict_and_restore_process(fence->mm, fence->context_id, f))
return true;
} else {
if (!svm_range_schedule_evict_svm_bo(fence))
return true;
}
return false;
}

View File

@@ -3104,7 +3104,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu *
process_info->eviction_fence = new_fence;
replace_eviction_fence(ef, dma_fence_get(&new_fence->base));
} else {
WARN_ONCE(*ef != &process_info->eviction_fence->base,
WARN_ONCE(rcu_access_pointer(*ef) != &process_info->eviction_fence->base,
"KFD eviction fence doesn't match KGD process_info");
}

View File

@@ -519,7 +519,7 @@ int amdgpu_cper_deferred_init(struct amdgpu_device *adev)
int amdgpu_cper_fini(struct amdgpu_device *adev)
{
if (amdgpu_sriov_vf(adev))
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_ras_cper_en(adev))
return 0;
adev->cper.enabled = false;

View File

@@ -267,8 +267,8 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
for (i = 0; i < p->gang_size; ++i) {
ret = amdgpu_job_alloc(p->adev, vm, p->entities[i], vm,
num_ibs[i], &p->jobs[i],
p->filp->client_id);
num_ibs[i], p->filp->client_id,
GFP_KERNEL, &p->jobs[i]);
if (ret)
goto free_all_kdata;
switch (p->adev->enforce_isolation[fpriv->xcp_id]) {
@@ -1171,19 +1171,6 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
job->vm_pd_addr = amdgpu_gmc_pd_addr(vm->root.bo);
}
if (adev->debug_vm) {
/* Invalidate all BOs to test for userspace bugs */
amdgpu_bo_list_for_each_entry(e, p->bo_list) {
struct amdgpu_bo *bo = e->bo;
/* ignore duplicates */
if (!bo)
continue;
amdgpu_vm_bo_invalidate(bo, false);
}
}
return 0;
}
@@ -1371,6 +1358,8 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
/* Cleanup the parser structure */
static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser)
{
struct amdgpu_device *adev = parser->adev;
struct amdgpu_bo_list_entry *e;
unsigned int i;
amdgpu_sync_free(&parser->sync);
@@ -1386,8 +1375,21 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser)
if (parser->ctx)
amdgpu_ctx_put(parser->ctx);
if (parser->bo_list)
if (parser->bo_list) {
if (adev->debug_vm) {
/* Invalidate all BOs to test for userspace bugs */
amdgpu_bo_list_for_each_entry(e, parser->bo_list) {
struct amdgpu_bo *bo = e->bo;
/* ignore duplicates */
if (!bo)
continue;
amdgpu_vm_bo_invalidate(bo, false);
}
}
amdgpu_bo_list_put(parser->bo_list);
}
for (i = 0; i < parser->nchunks; i++)
kvfree(parser->chunks[i].kdata);

View File

@@ -44,6 +44,11 @@
#if defined(CONFIG_DEBUG_FS)
/* Encode milliwatts in the raw Q24.8 sensor report format used by UMR. */
#define AMDGPU_DEBUGFS_PWR_MW_TO_Q24_8(power_mw) \
DIV_ROUND_CLOSEST_ULL((u64)(power_mw) * BIT(8), \
MILLIWATT_PER_WATT)
/**
* amdgpu_debugfs_process_reg_op - Handle MMIO register reads/writes
*
@@ -1105,6 +1110,10 @@ static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf,
return r;
}
if (idx == AMDGPU_PP_SENSOR_GPU_AVG_POWER ||
idx == AMDGPU_PP_SENSOR_GPU_INPUT_POWER)
values[0] = AMDGPU_DEBUGFS_PWR_MW_TO_Q24_8(values[0]);
if (size > valuesize) {
amdgpu_virt_disable_access_debugfs(adev);
return -EINVAL;
@@ -1320,8 +1329,8 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf,
* @size: Number of bytes to read
* @pos: Offset to seek to
*
* Read the last residency value logged. It doesn't auto update, one needs to
* stop logging before getting the current value.
* Read a live GFXOFF residency sample from firmware. One needs to start logging
* before getting the current value.
*/
static ssize_t amdgpu_debugfs_gfxoff_residency_read(struct file *f, char __user *buf,
size_t size, loff_t *pos)

View File

@@ -745,6 +745,64 @@ void amdgpu_device_mm_access(struct amdgpu_device *adev, loff_t pos,
drm_dev_exit(idx);
}
#ifdef CONFIG_64BIT
/*
* During early SR-IOV VF init, host-provided init data can live in FB before
* the normal VRAM aperture mapping is ready. Use a temporary BAR0 mapping for
* reads only, and verify it matches the VRAM aperture when aperture information
* is already available.
*/
static int amdgpu_device_read_fb_via_bar0(struct amdgpu_device *adev,
u64 offset, void *buf, size_t size)
{
resource_size_t aper_base, aper_size, bar_start, bar_size, map_base;
void __iomem *vram;
size_t map_offset, map_size;
unsigned long flags;
u64 end;
if (!buf || !size)
return -EINVAL;
flags = pci_resource_flags(adev->pdev, 0);
if ((flags & IORESOURCE_UNSET) || !(flags & IORESOURCE_MEM))
return -EINVAL;
bar_start = pci_resource_start(adev->pdev, 0);
bar_size = pci_resource_len(adev->pdev, 0);
if (!bar_size)
return -ENODEV;
aper_base = adev->gmc.aper_base;
aper_size = adev->gmc.visible_vram_size ? adev->gmc.visible_vram_size :
adev->gmc.aper_size;
if (aper_base || aper_size) {
if (aper_base != bar_start || aper_size > bar_size)
return -EINVAL;
} else {
aper_base = bar_start;
aper_size = bar_size;
}
if (check_add_overflow(offset, size, &end) || end > aper_size)
return -EINVAL;
map_offset = offset_in_page(offset);
map_base = aper_base + (offset & PAGE_MASK);
map_size = PAGE_ALIGN(map_offset + size);
vram = ioremap_wc(map_base, map_size);
if (!vram)
return -ENOMEM;
memcpy_fromio(buf, (u8 __iomem *)vram + map_offset, size);
iounmap(vram);
return 0;
}
#endif
/**
* amdgpu_device_aper_access - access vram by vram aperture
*
@@ -764,8 +822,12 @@ size_t amdgpu_device_aper_access(struct amdgpu_device *adev, loff_t pos,
size_t count = 0;
uint64_t last;
if (!adev->mman.aper_base_kaddr)
if (!adev->mman.aper_base_kaddr) {
/* Writes still require the regular aperture/MM path. */
if (!write && !amdgpu_device_read_fb_via_bar0(adev, pos, buf, size))
return size;
return 0;
}
last = min(pos + size, adev->gmc.visible_vram_size);
if (last > pos) {
@@ -1862,16 +1924,25 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
{
struct amdgpu_ip_block *ip_block;
struct pci_dev *parent;
bool total, skip_bios;
bool total, skip_bios, early_full_gpu_access = false;
uint32_t bios_flags;
int i, r;
amdgpu_device_enable_virtual_display(adev);
if (amdgpu_sriov_vf(adev)) {
r = amdgpu_virt_request_full_gpu(adev, true);
if (r)
return r;
/*
* Legacy hosts do not provide init data before early init, so
* keep the original early full GPU access request for them. Newer
* hosts publish the init data through VF FB, which lets us defer
* full GPU access until after non-GPU early init work is done.
*/
early_full_gpu_access = (adev->virt.req_init_data_ver == 0);
if (early_full_gpu_access) {
r = amdgpu_virt_request_full_gpu(adev, true);
if (r)
return r;
}
r = amdgpu_virt_init_critical_region(adev);
if (r)
@@ -2034,6 +2105,13 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
if (!total)
return -ENODEV;
/* Request full GPU access only for the remaining SR-IOV init work. */
if (amdgpu_sriov_vf(adev) && !early_full_gpu_access) {
r = amdgpu_virt_request_full_gpu(adev, true);
if (r)
return r;
}
if (adev->gmc.xgmi.supported)
amdgpu_xgmi_early_init(adev);

View File

@@ -2529,6 +2529,7 @@ static int amdgpu_discovery_set_psp_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &psp_v14_0_ip_block);
break;
case IP_VERSION(15, 0, 0):
case IP_VERSION(15, 0, 5):
case IP_VERSION(15, 0, 9):
amdgpu_device_ip_block_add(adev, &psp_v15_0_ip_block);
break;

View File

@@ -746,7 +746,7 @@ static int convert_tiling_flags_to_modifier_gfx12(struct amdgpu_framebuffer *afb
return 0;
}
static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb)
static int convert_tiling_flags_to_modifier_gfx9(struct amdgpu_framebuffer *afb)
{
struct amdgpu_device *adev = drm_to_adev(afb->base.dev);
uint64_t modifier = 0;
@@ -940,25 +940,85 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb)
return 0;
}
/* Mirrors the is_displayable check in radeonsi's gfx6_compute_surface */
static int convert_tiling_flags_to_modifier_gfx6(struct amdgpu_framebuffer *afb)
{
const uint32_t array_mode = AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE);
const uint32_t pipe_config = AMDGPU_TILING_GET(afb->tiling_flags, PIPE_CONFIG);
const uint32_t tile_split = AMDGPU_TILING_GET(afb->tiling_flags, TILE_SPLIT);
const uint32_t micro_tile_mode = AMDGPU_TILING_GET(afb->tiling_flags, MICRO_TILE_MODE);
const uint32_t bank_width = AMDGPU_TILING_GET(afb->tiling_flags, BANK_WIDTH);
const uint32_t bank_height = AMDGPU_TILING_GET(afb->tiling_flags, BANK_HEIGHT);
const uint32_t macro_tile_aspect = AMDGPU_TILING_GET(afb->tiling_flags, MACRO_TILE_ASPECT);
const uint32_t num_banks = AMDGPU_TILING_GET(afb->tiling_flags, NUM_BANKS);
struct amdgpu_device *adev = drm_to_adev(afb->base.dev);
uint64_t modifier = 0;
switch (array_mode) {
case DC_ARRAY_LINEAR_GENERAL:
case DC_ARRAY_LINEAR_ALLIGNED:
modifier = DRM_FORMAT_MOD_LINEAR;
break;
case DC_ARRAY_2D_TILED_THIN1:
/* Macro tiled modes only */
modifier |=
AMD_FMT_MOD_SET(PIPE_CONFIG, pipe_config) |
AMD_FMT_MOD_SET(TILE_SPLIT, tile_split) |
AMD_FMT_MOD_SET(BANK_WIDTH, bank_width) |
AMD_FMT_MOD_SET(BANK_HEIGHT, bank_height) |
AMD_FMT_MOD_SET(MACRO_TILE_ASPECT, macro_tile_aspect) |
AMD_FMT_MOD_SET(NUM_BANKS, num_banks);
fallthrough;
case DC_ARRAY_1D_TILED_THIN1:
/* Micro and macro tiled modes */
modifier |=
AMD_FMT_MOD |
AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX6) |
AMD_FMT_MOD_SET(TILE, array_mode) |
AMD_FMT_MOD_SET(MICROTILE, micro_tile_mode);
break;
default:
drm_dbg_kms(&adev->ddev, "array mode 0x%x not supported\n", array_mode);
return -EINVAL;
}
afb->base.modifier = modifier;
afb->base.flags |= DRM_MODE_FB_MODIFIERS;
return 0;
}
static int check_tiling_flags_gfx6(struct amdgpu_framebuffer *afb)
{
u64 micro_tile_mode;
const u64 array_mode = AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE);
const u64 micro_tile_mode = AMDGPU_TILING_GET(afb->tiling_flags, MICRO_TILE_MODE);
if (AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) == 1) /* LINEAR_ALIGNED */
/* LINEAR_GENERAL, LINEAR_ALIGNED */
if (array_mode == 0 || array_mode == 1)
return 0;
micro_tile_mode = AMDGPU_TILING_GET(afb->tiling_flags, MICRO_TILE_MODE);
switch (micro_tile_mode) {
case 0: /* DISPLAY */
case 3: /* RENDER */
return 0;
default:
/* 1D_TILED_THIN1, 2D_TILED_THIN1 */
if (array_mode != 2 && array_mode != 4) {
drm_dbg_kms(afb->base.dev,
"Array mode %llu not supported for scanout\n",
array_mode);
return -EINVAL;
}
/*
* For now, only allow DISPLAY micro tile mode.
* THIN, DEPTH and THICK modes are not displayable.
* ROTATED has never been supported by Linux or Mesa.
*/
if (micro_tile_mode != 0) {
drm_dbg_kms(afb->base.dev,
"Micro tile mode %llu not supported for scanout\n",
micro_tile_mode);
return -EINVAL;
}
return 0;
}
static void get_block_dimensions(unsigned int block_log2, unsigned int cpp,
@@ -1053,6 +1113,85 @@ static int amdgpu_display_verify_plane(struct amdgpu_framebuffer *rfb, int plane
return 0;
}
static int amdgpu_display_verify_sizes_gfx6(struct drm_device *dev,
const u64 modifier,
unsigned int *out_block_width,
unsigned int *out_block_height)
{
const u32 display_micro_tile_pitch = 32; /* required by DCE */
const u32 micro_tile_width = 8;
const u32 micro_tile_height = 8;
const u32 micro_tile_mode = AMD_FMT_MOD_GET(MICROTILE, modifier);
const u32 array_mode = AMD_FMT_MOD_GET(TILE, modifier);
u32 num_banks, bank_width, bank_height, pipe_config, macro_tile_aspect;
u32 num_pipes;
if (AMD_FMT_MOD_GET(DCC, modifier)) {
drm_dbg_kms(dev, "DCC is not displayable on GFX6-8\n");
return -EINVAL;
}
if (array_mode != AMD_FMT_MOD_TILE_GFX6_1D_TILED_THIN1 &&
array_mode != AMD_FMT_MOD_TILE_GFX6_2D_TILED_THIN1) {
drm_dbg_kms(dev, "Array mode %u not supported for scanout\n", array_mode);
return -EINVAL;
}
if (micro_tile_mode != AMD_FMT_MOD_MICROTILE_DISPLAY) {
drm_dbg_kms(dev, "Microtile mode %u not supported for scanout\n", micro_tile_mode);
return -EINVAL;
}
num_banks = 2 << AMD_FMT_MOD_GET(NUM_BANKS, modifier);
bank_width = 1 << AMD_FMT_MOD_GET(BANK_WIDTH, modifier);
bank_height = 1 << AMD_FMT_MOD_GET(BANK_HEIGHT, modifier);
pipe_config = AMD_FMT_MOD_GET(PIPE_CONFIG, modifier);
macro_tile_aspect = 1 << AMD_FMT_MOD_GET(MACRO_TILE_ASPECT, modifier);
switch (pipe_config) {
case AMD_FMT_MOD_PIPE_CONFIG_P16_32x32_8x16:
case AMD_FMT_MOD_PIPE_CONFIG_P16_32x32_16x16:
num_pipes = 16;
break;
case AMD_FMT_MOD_PIPE_CONFIG_P8_16x16_8x16:
case AMD_FMT_MOD_PIPE_CONFIG_P8_16x32_8x16:
case AMD_FMT_MOD_PIPE_CONFIG_P8_32x32_8x16:
case AMD_FMT_MOD_PIPE_CONFIG_P8_16x32_16x16:
case AMD_FMT_MOD_PIPE_CONFIG_P8_32x32_16x16:
case AMD_FMT_MOD_PIPE_CONFIG_P8_32x32_16x32:
case AMD_FMT_MOD_PIPE_CONFIG_P8_32x64_32x32:
num_pipes = 8;
break;
case AMD_FMT_MOD_PIPE_CONFIG_P4_8x16:
case AMD_FMT_MOD_PIPE_CONFIG_P4_16x16:
case AMD_FMT_MOD_PIPE_CONFIG_P4_16x32:
case AMD_FMT_MOD_PIPE_CONFIG_P4_32x32:
num_pipes = 4;
break;
case AMD_FMT_MOD_PIPE_CONFIG_P2:
num_pipes = 2;
break;
default:
drm_dbg_kms(dev, "Pipe config %u invalid\n", pipe_config);
return -EINVAL;
}
/* For reference, see SiLib::InitEquationTable() in addrlib */
if (array_mode < AMD_FMT_MOD_TILE_GFX6_2D_TILED_THIN1) {
*out_block_width = display_micro_tile_pitch;
*out_block_height = micro_tile_height;
} else {
/* Assume non-PRT macro tiling modes */
*out_block_width = num_pipes * micro_tile_width *
bank_width * macro_tile_aspect;
*out_block_height = micro_tile_height * bank_height *
num_banks / macro_tile_aspect;
}
return 0;
}
static int amdgpu_display_verify_sizes(struct amdgpu_framebuffer *rfb)
{
@@ -1093,7 +1232,7 @@ static int amdgpu_display_verify_sizes(struct amdgpu_framebuffer *rfb)
get_block_dimensions(block_size_log2, format_info->cpp[i],
&block_width, &block_height);
} else {
} else if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) >= AMD_FMT_MOD_TILE_VER_GFX9) {
int swizzle = AMD_FMT_MOD_GET(TILE, modifier);
switch ((swizzle & ~3) + 1) {
@@ -1120,6 +1259,18 @@ static int amdgpu_display_verify_sizes(struct amdgpu_framebuffer *rfb)
get_block_dimensions(block_size_log2, format_info->cpp[i],
&block_width, &block_height);
} else if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) == AMD_FMT_MOD_TILE_VER_GFX6) {
ret = amdgpu_display_verify_sizes_gfx6(rfb->base.dev, modifier,
&block_width, &block_height);
if (ret)
return ret;
/* amdgpu_display_verify_plane() assumes the block size is a power of 2 */
WARN_ON(!is_power_of_2(block_width));
WARN_ON(!is_power_of_2(block_height));
WARN_ON(!is_power_of_2(format_info->cpp[i]));
block_size_log2 = ilog2(block_width * block_height * format_info->cpp[i]);
}
ret = amdgpu_display_verify_plane(rfb, i, format_info,
@@ -1271,8 +1422,10 @@ static int amdgpu_display_framebuffer_init(struct drm_device *dev,
!(rfb->base.flags & DRM_MODE_FB_MODIFIERS)) {
if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 0, 0))
ret = convert_tiling_flags_to_modifier_gfx12(rfb);
else if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(9, 0, 0))
ret = convert_tiling_flags_to_modifier_gfx9(rfb);
else
ret = convert_tiling_flags_to_modifier(rfb);
ret = convert_tiling_flags_to_modifier_gfx6(rfb);
if (ret) {
drm_dbg_kms(dev, "Failed to convert tiling flags 0x%llX to a modifier",

View File

@@ -1838,357 +1838,357 @@ static const u16 amdgpu_unsupported_pciidlist[] = {
};
static const struct pci_device_id pciidlist[] = {
{0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
{0x1002, 0x6784, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
{0x1002, 0x6788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
{0x1002, 0x678A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
{0x1002, 0x6790, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
{0x1002, 0x6791, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
{0x1002, 0x6792, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
{0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
{0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
{0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
{0x1002, 0x679B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
{0x1002, 0x679E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
{0x1002, 0x679F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
{0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|AMD_IS_MOBILITY},
{0x1002, 0x6801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|AMD_IS_MOBILITY},
{0x1002, 0x6802, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|AMD_IS_MOBILITY},
{0x1002, 0x6806, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN},
{0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN},
{0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN},
{0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN},
{0x1002, 0x6811, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN},
{0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN},
{0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN},
{0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN},
{0x1002, 0x6819, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN},
{0x1002, 0x6600, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY},
{0x1002, 0x6601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY},
{0x1002, 0x6602, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY},
{0x1002, 0x6603, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY},
{0x1002, 0x6604, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY},
{0x1002, 0x6605, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY},
{0x1002, 0x6606, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY},
{0x1002, 0x6607, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY},
{0x1002, 0x6608, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND},
{0x1002, 0x6610, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND},
{0x1002, 0x6611, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND},
{0x1002, 0x6613, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND},
{0x1002, 0x6617, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY},
{0x1002, 0x6620, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY},
{0x1002, 0x6621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY},
{0x1002, 0x6623, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY},
{0x1002, 0x6631, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND},
{0x1002, 0x6820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY},
{0x1002, 0x6821, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY},
{0x1002, 0x6822, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY},
{0x1002, 0x6823, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY},
{0x1002, 0x6824, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY},
{0x1002, 0x6825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY},
{0x1002, 0x6826, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY},
{0x1002, 0x6827, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY},
{0x1002, 0x6828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE},
{0x1002, 0x6829, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE},
{0x1002, 0x682A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY},
{0x1002, 0x682B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY},
{0x1002, 0x682C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE},
{0x1002, 0x682D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY},
{0x1002, 0x682F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY},
{0x1002, 0x6830, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY},
{0x1002, 0x6831, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY},
{0x1002, 0x6835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE},
{0x1002, 0x6837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE},
{0x1002, 0x6838, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE},
{0x1002, 0x6839, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE},
{0x1002, 0x683B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE},
{0x1002, 0x683D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE},
{0x1002, 0x683F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE},
{0x1002, 0x6660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY},
{0x1002, 0x6663, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY},
{0x1002, 0x6664, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY},
{0x1002, 0x6665, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY},
{0x1002, 0x6667, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY},
{0x1002, 0x666F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY},
{ PCI_DEVICE(0x1002, 0x6780), .driver_data = CHIP_TAHITI },
{ PCI_DEVICE(0x1002, 0x6784), .driver_data = CHIP_TAHITI },
{ PCI_DEVICE(0x1002, 0x6788), .driver_data = CHIP_TAHITI },
{ PCI_DEVICE(0x1002, 0x678A), .driver_data = CHIP_TAHITI },
{ PCI_DEVICE(0x1002, 0x6790), .driver_data = CHIP_TAHITI },
{ PCI_DEVICE(0x1002, 0x6791), .driver_data = CHIP_TAHITI },
{ PCI_DEVICE(0x1002, 0x6792), .driver_data = CHIP_TAHITI },
{ PCI_DEVICE(0x1002, 0x6798), .driver_data = CHIP_TAHITI },
{ PCI_DEVICE(0x1002, 0x6799), .driver_data = CHIP_TAHITI },
{ PCI_DEVICE(0x1002, 0x679A), .driver_data = CHIP_TAHITI },
{ PCI_DEVICE(0x1002, 0x679B), .driver_data = CHIP_TAHITI },
{ PCI_DEVICE(0x1002, 0x679E), .driver_data = CHIP_TAHITI },
{ PCI_DEVICE(0x1002, 0x679F), .driver_data = CHIP_TAHITI },
{ PCI_DEVICE(0x1002, 0x6800), .driver_data = CHIP_PITCAIRN|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6801), .driver_data = CHIP_PITCAIRN|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6802), .driver_data = CHIP_PITCAIRN|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6806), .driver_data = CHIP_PITCAIRN },
{ PCI_DEVICE(0x1002, 0x6808), .driver_data = CHIP_PITCAIRN },
{ PCI_DEVICE(0x1002, 0x6809), .driver_data = CHIP_PITCAIRN },
{ PCI_DEVICE(0x1002, 0x6810), .driver_data = CHIP_PITCAIRN },
{ PCI_DEVICE(0x1002, 0x6811), .driver_data = CHIP_PITCAIRN },
{ PCI_DEVICE(0x1002, 0x6816), .driver_data = CHIP_PITCAIRN },
{ PCI_DEVICE(0x1002, 0x6817), .driver_data = CHIP_PITCAIRN },
{ PCI_DEVICE(0x1002, 0x6818), .driver_data = CHIP_PITCAIRN },
{ PCI_DEVICE(0x1002, 0x6819), .driver_data = CHIP_PITCAIRN },
{ PCI_DEVICE(0x1002, 0x6600), .driver_data = CHIP_OLAND|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6601), .driver_data = CHIP_OLAND|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6602), .driver_data = CHIP_OLAND|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6603), .driver_data = CHIP_OLAND|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6604), .driver_data = CHIP_OLAND|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6605), .driver_data = CHIP_OLAND|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6606), .driver_data = CHIP_OLAND|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6607), .driver_data = CHIP_OLAND|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6608), .driver_data = CHIP_OLAND },
{ PCI_DEVICE(0x1002, 0x6610), .driver_data = CHIP_OLAND },
{ PCI_DEVICE(0x1002, 0x6611), .driver_data = CHIP_OLAND },
{ PCI_DEVICE(0x1002, 0x6613), .driver_data = CHIP_OLAND },
{ PCI_DEVICE(0x1002, 0x6617), .driver_data = CHIP_OLAND|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6620), .driver_data = CHIP_OLAND|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6621), .driver_data = CHIP_OLAND|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6623), .driver_data = CHIP_OLAND|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6631), .driver_data = CHIP_OLAND },
{ PCI_DEVICE(0x1002, 0x6820), .driver_data = CHIP_VERDE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6821), .driver_data = CHIP_VERDE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6822), .driver_data = CHIP_VERDE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6823), .driver_data = CHIP_VERDE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6824), .driver_data = CHIP_VERDE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6825), .driver_data = CHIP_VERDE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6826), .driver_data = CHIP_VERDE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6827), .driver_data = CHIP_VERDE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6828), .driver_data = CHIP_VERDE },
{ PCI_DEVICE(0x1002, 0x6829), .driver_data = CHIP_VERDE },
{ PCI_DEVICE(0x1002, 0x682A), .driver_data = CHIP_VERDE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x682B), .driver_data = CHIP_VERDE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x682C), .driver_data = CHIP_VERDE },
{ PCI_DEVICE(0x1002, 0x682D), .driver_data = CHIP_VERDE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x682F), .driver_data = CHIP_VERDE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6830), .driver_data = CHIP_VERDE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6831), .driver_data = CHIP_VERDE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6835), .driver_data = CHIP_VERDE },
{ PCI_DEVICE(0x1002, 0x6837), .driver_data = CHIP_VERDE },
{ PCI_DEVICE(0x1002, 0x6838), .driver_data = CHIP_VERDE },
{ PCI_DEVICE(0x1002, 0x6839), .driver_data = CHIP_VERDE },
{ PCI_DEVICE(0x1002, 0x683B), .driver_data = CHIP_VERDE },
{ PCI_DEVICE(0x1002, 0x683D), .driver_data = CHIP_VERDE },
{ PCI_DEVICE(0x1002, 0x683F), .driver_data = CHIP_VERDE },
{ PCI_DEVICE(0x1002, 0x6660), .driver_data = CHIP_HAINAN|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6663), .driver_data = CHIP_HAINAN|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6664), .driver_data = CHIP_HAINAN|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6665), .driver_data = CHIP_HAINAN|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6667), .driver_data = CHIP_HAINAN|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x666F), .driver_data = CHIP_HAINAN|AMD_IS_MOBILITY },
/* Kaveri */
{0x1002, 0x1304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x1305, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_APU},
{0x1002, 0x1306, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x1307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_APU},
{0x1002, 0x1309, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x130A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x130B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x130C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x130D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x130E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x130F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_APU},
{0x1002, 0x1310, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_APU},
{0x1002, 0x1311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_APU},
{0x1002, 0x1312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_APU},
{0x1002, 0x1313, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_APU},
{0x1002, 0x1315, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_APU},
{0x1002, 0x1316, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_APU},
{0x1002, 0x1317, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x1318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x131B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_APU},
{0x1002, 0x131C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_APU},
{0x1002, 0x131D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_APU},
{ PCI_DEVICE(0x1002, 0x1304), .driver_data = CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x1305), .driver_data = CHIP_KAVERI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x1306), .driver_data = CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x1307), .driver_data = CHIP_KAVERI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x1309), .driver_data = CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x130A), .driver_data = CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x130B), .driver_data = CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x130C), .driver_data = CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x130D), .driver_data = CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x130E), .driver_data = CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x130F), .driver_data = CHIP_KAVERI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x1310), .driver_data = CHIP_KAVERI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x1311), .driver_data = CHIP_KAVERI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x1312), .driver_data = CHIP_KAVERI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x1313), .driver_data = CHIP_KAVERI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x1315), .driver_data = CHIP_KAVERI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x1316), .driver_data = CHIP_KAVERI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x1317), .driver_data = CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x1318), .driver_data = CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x131B), .driver_data = CHIP_KAVERI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x131C), .driver_data = CHIP_KAVERI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x131D), .driver_data = CHIP_KAVERI|AMD_IS_APU },
/* Bonaire */
{0x1002, 0x6640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|AMD_IS_MOBILITY},
{0x1002, 0x6641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|AMD_IS_MOBILITY},
{0x1002, 0x6646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|AMD_IS_MOBILITY},
{0x1002, 0x6647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|AMD_IS_MOBILITY},
{0x1002, 0x6649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE},
{0x1002, 0x664D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE},
{0x1002, 0x6650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE},
{0x1002, 0x6651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE},
{0x1002, 0x6658, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE},
{0x1002, 0x665c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE},
{0x1002, 0x665d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE},
{0x1002, 0x665f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE},
{ PCI_DEVICE(0x1002, 0x6640), .driver_data = CHIP_BONAIRE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6641), .driver_data = CHIP_BONAIRE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6646), .driver_data = CHIP_BONAIRE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6647), .driver_data = CHIP_BONAIRE|AMD_IS_MOBILITY },
{ PCI_DEVICE(0x1002, 0x6649), .driver_data = CHIP_BONAIRE },
{ PCI_DEVICE(0x1002, 0x664D), .driver_data = CHIP_BONAIRE },
{ PCI_DEVICE(0x1002, 0x6650), .driver_data = CHIP_BONAIRE },
{ PCI_DEVICE(0x1002, 0x6651), .driver_data = CHIP_BONAIRE },
{ PCI_DEVICE(0x1002, 0x6658), .driver_data = CHIP_BONAIRE },
{ PCI_DEVICE(0x1002, 0x665c), .driver_data = CHIP_BONAIRE },
{ PCI_DEVICE(0x1002, 0x665d), .driver_data = CHIP_BONAIRE },
{ PCI_DEVICE(0x1002, 0x665f), .driver_data = CHIP_BONAIRE },
/* Hawaii */
{0x1002, 0x67A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII},
{0x1002, 0x67A1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII},
{0x1002, 0x67A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII},
{0x1002, 0x67A8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII},
{0x1002, 0x67A9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII},
{0x1002, 0x67AA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII},
{0x1002, 0x67B0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII},
{0x1002, 0x67B1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII},
{0x1002, 0x67B8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII},
{0x1002, 0x67B9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII},
{0x1002, 0x67BA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII},
{0x1002, 0x67BE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII},
{ PCI_DEVICE(0x1002, 0x67A0), .driver_data = CHIP_HAWAII },
{ PCI_DEVICE(0x1002, 0x67A1), .driver_data = CHIP_HAWAII },
{ PCI_DEVICE(0x1002, 0x67A2), .driver_data = CHIP_HAWAII },
{ PCI_DEVICE(0x1002, 0x67A8), .driver_data = CHIP_HAWAII },
{ PCI_DEVICE(0x1002, 0x67A9), .driver_data = CHIP_HAWAII },
{ PCI_DEVICE(0x1002, 0x67AA), .driver_data = CHIP_HAWAII },
{ PCI_DEVICE(0x1002, 0x67B0), .driver_data = CHIP_HAWAII },
{ PCI_DEVICE(0x1002, 0x67B1), .driver_data = CHIP_HAWAII },
{ PCI_DEVICE(0x1002, 0x67B8), .driver_data = CHIP_HAWAII },
{ PCI_DEVICE(0x1002, 0x67B9), .driver_data = CHIP_HAWAII },
{ PCI_DEVICE(0x1002, 0x67BA), .driver_data = CHIP_HAWAII },
{ PCI_DEVICE(0x1002, 0x67BE), .driver_data = CHIP_HAWAII },
/* Kabini */
{0x1002, 0x9830, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x9831, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|AMD_IS_APU},
{0x1002, 0x9832, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x9833, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|AMD_IS_APU},
{0x1002, 0x9834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x9835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|AMD_IS_APU},
{0x1002, 0x9836, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x9837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|AMD_IS_APU},
{0x1002, 0x9838, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x9839, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x983a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|AMD_IS_APU},
{0x1002, 0x983b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x983c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|AMD_IS_APU},
{0x1002, 0x983d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|AMD_IS_APU},
{0x1002, 0x983e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|AMD_IS_APU},
{0x1002, 0x983f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|AMD_IS_APU},
{ PCI_DEVICE(0x1002, 0x9830), .driver_data = CHIP_KABINI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9831), .driver_data = CHIP_KABINI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9832), .driver_data = CHIP_KABINI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9833), .driver_data = CHIP_KABINI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9834), .driver_data = CHIP_KABINI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9835), .driver_data = CHIP_KABINI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9836), .driver_data = CHIP_KABINI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9837), .driver_data = CHIP_KABINI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9838), .driver_data = CHIP_KABINI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9839), .driver_data = CHIP_KABINI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x983a), .driver_data = CHIP_KABINI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x983b), .driver_data = CHIP_KABINI|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x983c), .driver_data = CHIP_KABINI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x983d), .driver_data = CHIP_KABINI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x983e), .driver_data = CHIP_KABINI|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x983f), .driver_data = CHIP_KABINI|AMD_IS_APU },
/* mullins */
{0x1002, 0x9850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x9851, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x9852, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x9853, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x9854, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x9855, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x9856, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x9857, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x9858, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x9859, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x985A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x985B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x985C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x985D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x985E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
{0x1002, 0x985F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
{ PCI_DEVICE(0x1002, 0x9850), .driver_data = CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9851), .driver_data = CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9852), .driver_data = CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9853), .driver_data = CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9854), .driver_data = CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9855), .driver_data = CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9856), .driver_data = CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9857), .driver_data = CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9858), .driver_data = CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9859), .driver_data = CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x985A), .driver_data = CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x985B), .driver_data = CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x985C), .driver_data = CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x985D), .driver_data = CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x985E), .driver_data = CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x985F), .driver_data = CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU },
/* topaz */
{0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
{0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
{0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
{0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
{0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
{ PCI_DEVICE(0x1002, 0x6900), .driver_data = CHIP_TOPAZ },
{ PCI_DEVICE(0x1002, 0x6901), .driver_data = CHIP_TOPAZ },
{ PCI_DEVICE(0x1002, 0x6902), .driver_data = CHIP_TOPAZ },
{ PCI_DEVICE(0x1002, 0x6903), .driver_data = CHIP_TOPAZ },
{ PCI_DEVICE(0x1002, 0x6907), .driver_data = CHIP_TOPAZ },
/* tonga */
{0x1002, 0x6920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
{0x1002, 0x6921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
{0x1002, 0x6928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
{0x1002, 0x6929, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
{0x1002, 0x692B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
{0x1002, 0x692F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
{0x1002, 0x6930, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
{0x1002, 0x6938, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
{0x1002, 0x6939, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
{0x1002, 0x693B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
{ PCI_DEVICE(0x1002, 0x6920), .driver_data = CHIP_TONGA },
{ PCI_DEVICE(0x1002, 0x6921), .driver_data = CHIP_TONGA },
{ PCI_DEVICE(0x1002, 0x6928), .driver_data = CHIP_TONGA },
{ PCI_DEVICE(0x1002, 0x6929), .driver_data = CHIP_TONGA },
{ PCI_DEVICE(0x1002, 0x692B), .driver_data = CHIP_TONGA },
{ PCI_DEVICE(0x1002, 0x692F), .driver_data = CHIP_TONGA },
{ PCI_DEVICE(0x1002, 0x6930), .driver_data = CHIP_TONGA },
{ PCI_DEVICE(0x1002, 0x6938), .driver_data = CHIP_TONGA },
{ PCI_DEVICE(0x1002, 0x6939), .driver_data = CHIP_TONGA },
{ PCI_DEVICE(0x1002, 0x693B), .driver_data = CHIP_TONGA },
/* fiji */
{0x1002, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_FIJI},
{0x1002, 0x730F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_FIJI},
{ PCI_DEVICE(0x1002, 0x7300), .driver_data = CHIP_FIJI },
{ PCI_DEVICE(0x1002, 0x730F), .driver_data = CHIP_FIJI },
/* carrizo */
{0x1002, 0x9870, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU},
{0x1002, 0x9874, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU},
{0x1002, 0x9875, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU},
{0x1002, 0x9876, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU},
{0x1002, 0x9877, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU},
{ PCI_DEVICE(0x1002, 0x9870), .driver_data = CHIP_CARRIZO|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9874), .driver_data = CHIP_CARRIZO|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9875), .driver_data = CHIP_CARRIZO|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9876), .driver_data = CHIP_CARRIZO|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x9877), .driver_data = CHIP_CARRIZO|AMD_IS_APU },
/* stoney */
{0x1002, 0x98E4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_STONEY|AMD_IS_APU},
{ PCI_DEVICE(0x1002, 0x98E4), .driver_data = CHIP_STONEY|AMD_IS_APU },
/* Polaris11 */
{0x1002, 0x67E0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
{0x1002, 0x67E3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
{0x1002, 0x67E8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
{0x1002, 0x67EB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
{0x1002, 0x67EF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
{0x1002, 0x67FF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
{0x1002, 0x67E1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
{0x1002, 0x67E7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
{0x1002, 0x67E9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
{ PCI_DEVICE(0x1002, 0x67E0), .driver_data = CHIP_POLARIS11 },
{ PCI_DEVICE(0x1002, 0x67E3), .driver_data = CHIP_POLARIS11 },
{ PCI_DEVICE(0x1002, 0x67E8), .driver_data = CHIP_POLARIS11 },
{ PCI_DEVICE(0x1002, 0x67EB), .driver_data = CHIP_POLARIS11 },
{ PCI_DEVICE(0x1002, 0x67EF), .driver_data = CHIP_POLARIS11 },
{ PCI_DEVICE(0x1002, 0x67FF), .driver_data = CHIP_POLARIS11 },
{ PCI_DEVICE(0x1002, 0x67E1), .driver_data = CHIP_POLARIS11 },
{ PCI_DEVICE(0x1002, 0x67E7), .driver_data = CHIP_POLARIS11 },
{ PCI_DEVICE(0x1002, 0x67E9), .driver_data = CHIP_POLARIS11 },
/* Polaris10 */
{0x1002, 0x67C0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x67C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x67C2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x67C4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x67C7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x67D0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x67D4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x67DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x67C8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x67C9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x67CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x67CC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x67CF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x6FDF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{ PCI_DEVICE(0x1002, 0x67C0), .driver_data = CHIP_POLARIS10 },
{ PCI_DEVICE(0x1002, 0x67C1), .driver_data = CHIP_POLARIS10 },
{ PCI_DEVICE(0x1002, 0x67C2), .driver_data = CHIP_POLARIS10 },
{ PCI_DEVICE(0x1002, 0x67C4), .driver_data = CHIP_POLARIS10 },
{ PCI_DEVICE(0x1002, 0x67C7), .driver_data = CHIP_POLARIS10 },
{ PCI_DEVICE(0x1002, 0x67D0), .driver_data = CHIP_POLARIS10 },
{ PCI_DEVICE(0x1002, 0x67D4), .driver_data = CHIP_POLARIS10 },
{ PCI_DEVICE(0x1002, 0x67DF), .driver_data = CHIP_POLARIS10 },
{ PCI_DEVICE(0x1002, 0x67C8), .driver_data = CHIP_POLARIS10 },
{ PCI_DEVICE(0x1002, 0x67C9), .driver_data = CHIP_POLARIS10 },
{ PCI_DEVICE(0x1002, 0x67CA), .driver_data = CHIP_POLARIS10 },
{ PCI_DEVICE(0x1002, 0x67CC), .driver_data = CHIP_POLARIS10 },
{ PCI_DEVICE(0x1002, 0x67CF), .driver_data = CHIP_POLARIS10 },
{ PCI_DEVICE(0x1002, 0x6FDF), .driver_data = CHIP_POLARIS10 },
/* Polaris12 */
{0x1002, 0x6980, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x6981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x6985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x6986, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x6987, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x698F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x6995, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x6997, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x699F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{ PCI_DEVICE(0x1002, 0x6980), .driver_data = CHIP_POLARIS12 },
{ PCI_DEVICE(0x1002, 0x6981), .driver_data = CHIP_POLARIS12 },
{ PCI_DEVICE(0x1002, 0x6985), .driver_data = CHIP_POLARIS12 },
{ PCI_DEVICE(0x1002, 0x6986), .driver_data = CHIP_POLARIS12 },
{ PCI_DEVICE(0x1002, 0x6987), .driver_data = CHIP_POLARIS12 },
{ PCI_DEVICE(0x1002, 0x698F), .driver_data = CHIP_POLARIS12 },
{ PCI_DEVICE(0x1002, 0x6995), .driver_data = CHIP_POLARIS12 },
{ PCI_DEVICE(0x1002, 0x6997), .driver_data = CHIP_POLARIS12 },
{ PCI_DEVICE(0x1002, 0x699F), .driver_data = CHIP_POLARIS12 },
/* VEGAM */
{0x1002, 0x694C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGAM},
{0x1002, 0x694E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGAM},
{0x1002, 0x694F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGAM},
{ PCI_DEVICE(0x1002, 0x694C), .driver_data = CHIP_VEGAM },
{ PCI_DEVICE(0x1002, 0x694E), .driver_data = CHIP_VEGAM },
{ PCI_DEVICE(0x1002, 0x694F), .driver_data = CHIP_VEGAM },
/* Vega 10 */
{0x1002, 0x6860, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
{0x1002, 0x6861, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
{0x1002, 0x6862, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
{0x1002, 0x6863, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
{0x1002, 0x6864, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
{0x1002, 0x6867, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
{0x1002, 0x6868, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
{0x1002, 0x6869, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
{0x1002, 0x686a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
{0x1002, 0x686b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
{0x1002, 0x686c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
{0x1002, 0x686d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
{0x1002, 0x686e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
{0x1002, 0x686f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
{0x1002, 0x687f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
{ PCI_DEVICE(0x1002, 0x6860), .driver_data = CHIP_VEGA10 },
{ PCI_DEVICE(0x1002, 0x6861), .driver_data = CHIP_VEGA10 },
{ PCI_DEVICE(0x1002, 0x6862), .driver_data = CHIP_VEGA10 },
{ PCI_DEVICE(0x1002, 0x6863), .driver_data = CHIP_VEGA10 },
{ PCI_DEVICE(0x1002, 0x6864), .driver_data = CHIP_VEGA10 },
{ PCI_DEVICE(0x1002, 0x6867), .driver_data = CHIP_VEGA10 },
{ PCI_DEVICE(0x1002, 0x6868), .driver_data = CHIP_VEGA10 },
{ PCI_DEVICE(0x1002, 0x6869), .driver_data = CHIP_VEGA10 },
{ PCI_DEVICE(0x1002, 0x686a), .driver_data = CHIP_VEGA10 },
{ PCI_DEVICE(0x1002, 0x686b), .driver_data = CHIP_VEGA10 },
{ PCI_DEVICE(0x1002, 0x686c), .driver_data = CHIP_VEGA10 },
{ PCI_DEVICE(0x1002, 0x686d), .driver_data = CHIP_VEGA10 },
{ PCI_DEVICE(0x1002, 0x686e), .driver_data = CHIP_VEGA10 },
{ PCI_DEVICE(0x1002, 0x686f), .driver_data = CHIP_VEGA10 },
{ PCI_DEVICE(0x1002, 0x687f), .driver_data = CHIP_VEGA10 },
/* Vega 12 */
{0x1002, 0x69A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA12},
{0x1002, 0x69A1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA12},
{0x1002, 0x69A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA12},
{0x1002, 0x69A3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA12},
{0x1002, 0x69AF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA12},
{ PCI_DEVICE(0x1002, 0x69A0), .driver_data = CHIP_VEGA12 },
{ PCI_DEVICE(0x1002, 0x69A1), .driver_data = CHIP_VEGA12 },
{ PCI_DEVICE(0x1002, 0x69A2), .driver_data = CHIP_VEGA12 },
{ PCI_DEVICE(0x1002, 0x69A3), .driver_data = CHIP_VEGA12 },
{ PCI_DEVICE(0x1002, 0x69AF), .driver_data = CHIP_VEGA12 },
/* Vega 20 */
{0x1002, 0x66A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA20},
{0x1002, 0x66A1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA20},
{0x1002, 0x66A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA20},
{0x1002, 0x66A3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA20},
{0x1002, 0x66A4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA20},
{0x1002, 0x66A7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA20},
{0x1002, 0x66AF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA20},
{ PCI_DEVICE(0x1002, 0x66A0), .driver_data = CHIP_VEGA20 },
{ PCI_DEVICE(0x1002, 0x66A1), .driver_data = CHIP_VEGA20 },
{ PCI_DEVICE(0x1002, 0x66A2), .driver_data = CHIP_VEGA20 },
{ PCI_DEVICE(0x1002, 0x66A3), .driver_data = CHIP_VEGA20 },
{ PCI_DEVICE(0x1002, 0x66A4), .driver_data = CHIP_VEGA20 },
{ PCI_DEVICE(0x1002, 0x66A7), .driver_data = CHIP_VEGA20 },
{ PCI_DEVICE(0x1002, 0x66AF), .driver_data = CHIP_VEGA20 },
/* 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},
{ PCI_DEVICE(0x1002, 0x15dd), .driver_data = CHIP_RAVEN|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x15d8), .driver_data = CHIP_RAVEN|AMD_IS_APU },
/* Arcturus */
{0x1002, 0x738C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS},
{0x1002, 0x7388, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS},
{0x1002, 0x738E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS},
{0x1002, 0x7390, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS},
{ PCI_DEVICE(0x1002, 0x738C), .driver_data = CHIP_ARCTURUS },
{ PCI_DEVICE(0x1002, 0x7388), .driver_data = CHIP_ARCTURUS },
{ PCI_DEVICE(0x1002, 0x738E), .driver_data = CHIP_ARCTURUS },
{ PCI_DEVICE(0x1002, 0x7390), .driver_data = CHIP_ARCTURUS },
/* 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, 0x731E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
{0x1002, 0x731F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
{ PCI_DEVICE(0x1002, 0x7310), .driver_data = CHIP_NAVI10 },
{ PCI_DEVICE(0x1002, 0x7312), .driver_data = CHIP_NAVI10 },
{ PCI_DEVICE(0x1002, 0x7318), .driver_data = CHIP_NAVI10 },
{ PCI_DEVICE(0x1002, 0x7319), .driver_data = CHIP_NAVI10 },
{ PCI_DEVICE(0x1002, 0x731A), .driver_data = CHIP_NAVI10 },
{ PCI_DEVICE(0x1002, 0x731B), .driver_data = CHIP_NAVI10 },
{ PCI_DEVICE(0x1002, 0x731E), .driver_data = CHIP_NAVI10 },
{ PCI_DEVICE(0x1002, 0x731F), .driver_data = CHIP_NAVI10 },
/* Navi14 */
{0x1002, 0x7340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI14},
{0x1002, 0x7341, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI14},
{0x1002, 0x7347, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI14},
{0x1002, 0x734F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI14},
{ PCI_DEVICE(0x1002, 0x7340), .driver_data = CHIP_NAVI14 },
{ PCI_DEVICE(0x1002, 0x7341), .driver_data = CHIP_NAVI14 },
{ PCI_DEVICE(0x1002, 0x7347), .driver_data = CHIP_NAVI14 },
{ PCI_DEVICE(0x1002, 0x734F), .driver_data = CHIP_NAVI14 },
/* Renoir */
{0x1002, 0x15E7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RENOIR|AMD_IS_APU},
{0x1002, 0x1636, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RENOIR|AMD_IS_APU},
{0x1002, 0x1638, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RENOIR|AMD_IS_APU},
{0x1002, 0x164C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RENOIR|AMD_IS_APU},
{ PCI_DEVICE(0x1002, 0x15E7), .driver_data = CHIP_RENOIR|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x1636), .driver_data = CHIP_RENOIR|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x1638), .driver_data = CHIP_RENOIR|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x164C), .driver_data = CHIP_RENOIR|AMD_IS_APU },
/* Navi12 */
{0x1002, 0x7360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12},
{0x1002, 0x7362, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12},
{ PCI_DEVICE(0x1002, 0x7360), .driver_data = CHIP_NAVI12 },
{ PCI_DEVICE(0x1002, 0x7362), .driver_data = CHIP_NAVI12 },
/* Sienna_Cichlid */
{0x1002, 0x73A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
{0x1002, 0x73A1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
{0x1002, 0x73A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
{0x1002, 0x73A3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
{0x1002, 0x73A5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
{0x1002, 0x73A8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
{0x1002, 0x73A9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
{0x1002, 0x73AB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
{0x1002, 0x73AC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
{0x1002, 0x73AD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
{0x1002, 0x73AE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
{0x1002, 0x73AF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
{0x1002, 0x73BF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
{ PCI_DEVICE(0x1002, 0x73A0), .driver_data = CHIP_SIENNA_CICHLID },
{ PCI_DEVICE(0x1002, 0x73A1), .driver_data = CHIP_SIENNA_CICHLID },
{ PCI_DEVICE(0x1002, 0x73A2), .driver_data = CHIP_SIENNA_CICHLID },
{ PCI_DEVICE(0x1002, 0x73A3), .driver_data = CHIP_SIENNA_CICHLID },
{ PCI_DEVICE(0x1002, 0x73A5), .driver_data = CHIP_SIENNA_CICHLID },
{ PCI_DEVICE(0x1002, 0x73A8), .driver_data = CHIP_SIENNA_CICHLID },
{ PCI_DEVICE(0x1002, 0x73A9), .driver_data = CHIP_SIENNA_CICHLID },
{ PCI_DEVICE(0x1002, 0x73AB), .driver_data = CHIP_SIENNA_CICHLID },
{ PCI_DEVICE(0x1002, 0x73AC), .driver_data = CHIP_SIENNA_CICHLID },
{ PCI_DEVICE(0x1002, 0x73AD), .driver_data = CHIP_SIENNA_CICHLID },
{ PCI_DEVICE(0x1002, 0x73AE), .driver_data = CHIP_SIENNA_CICHLID },
{ PCI_DEVICE(0x1002, 0x73AF), .driver_data = CHIP_SIENNA_CICHLID },
{ PCI_DEVICE(0x1002, 0x73BF), .driver_data = CHIP_SIENNA_CICHLID },
/* Yellow Carp */
{0x1002, 0x164D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_YELLOW_CARP|AMD_IS_APU},
{0x1002, 0x1681, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_YELLOW_CARP|AMD_IS_APU},
{ PCI_DEVICE(0x1002, 0x164D), .driver_data = CHIP_YELLOW_CARP|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x1681), .driver_data = CHIP_YELLOW_CARP|AMD_IS_APU },
/* Navy_Flounder */
{0x1002, 0x73C0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVY_FLOUNDER},
{0x1002, 0x73C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVY_FLOUNDER},
{0x1002, 0x73C3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVY_FLOUNDER},
{0x1002, 0x73DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVY_FLOUNDER},
{0x1002, 0x73DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVY_FLOUNDER},
{0x1002, 0x73DC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVY_FLOUNDER},
{0x1002, 0x73DD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVY_FLOUNDER},
{0x1002, 0x73DE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVY_FLOUNDER},
{0x1002, 0x73DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVY_FLOUNDER},
{ PCI_DEVICE(0x1002, 0x73C0), .driver_data = CHIP_NAVY_FLOUNDER },
{ PCI_DEVICE(0x1002, 0x73C1), .driver_data = CHIP_NAVY_FLOUNDER },
{ PCI_DEVICE(0x1002, 0x73C3), .driver_data = CHIP_NAVY_FLOUNDER },
{ PCI_DEVICE(0x1002, 0x73DA), .driver_data = CHIP_NAVY_FLOUNDER },
{ PCI_DEVICE(0x1002, 0x73DB), .driver_data = CHIP_NAVY_FLOUNDER },
{ PCI_DEVICE(0x1002, 0x73DC), .driver_data = CHIP_NAVY_FLOUNDER },
{ PCI_DEVICE(0x1002, 0x73DD), .driver_data = CHIP_NAVY_FLOUNDER },
{ PCI_DEVICE(0x1002, 0x73DE), .driver_data = CHIP_NAVY_FLOUNDER },
{ PCI_DEVICE(0x1002, 0x73DF), .driver_data = CHIP_NAVY_FLOUNDER },
/* DIMGREY_CAVEFISH */
{0x1002, 0x73E0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
{0x1002, 0x73E1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
{0x1002, 0x73E2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
{0x1002, 0x73E3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
{0x1002, 0x73E8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
{0x1002, 0x73E9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
{0x1002, 0x73EA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
{0x1002, 0x73EB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
{0x1002, 0x73EC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
{0x1002, 0x73ED, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
{0x1002, 0x73EF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
{0x1002, 0x73FF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
{ PCI_DEVICE(0x1002, 0x73E0), .driver_data = CHIP_DIMGREY_CAVEFISH },
{ PCI_DEVICE(0x1002, 0x73E1), .driver_data = CHIP_DIMGREY_CAVEFISH },
{ PCI_DEVICE(0x1002, 0x73E2), .driver_data = CHIP_DIMGREY_CAVEFISH },
{ PCI_DEVICE(0x1002, 0x73E3), .driver_data = CHIP_DIMGREY_CAVEFISH },
{ PCI_DEVICE(0x1002, 0x73E8), .driver_data = CHIP_DIMGREY_CAVEFISH },
{ PCI_DEVICE(0x1002, 0x73E9), .driver_data = CHIP_DIMGREY_CAVEFISH },
{ PCI_DEVICE(0x1002, 0x73EA), .driver_data = CHIP_DIMGREY_CAVEFISH },
{ PCI_DEVICE(0x1002, 0x73EB), .driver_data = CHIP_DIMGREY_CAVEFISH },
{ PCI_DEVICE(0x1002, 0x73EC), .driver_data = CHIP_DIMGREY_CAVEFISH },
{ PCI_DEVICE(0x1002, 0x73ED), .driver_data = CHIP_DIMGREY_CAVEFISH },
{ PCI_DEVICE(0x1002, 0x73EF), .driver_data = CHIP_DIMGREY_CAVEFISH },
{ PCI_DEVICE(0x1002, 0x73FF), .driver_data = CHIP_DIMGREY_CAVEFISH },
/* Aldebaran */
{0x1002, 0x7408, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN},
{0x1002, 0x740C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN},
{0x1002, 0x740F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN},
{0x1002, 0x7410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN},
{ PCI_DEVICE(0x1002, 0x7408), .driver_data = CHIP_ALDEBARAN },
{ PCI_DEVICE(0x1002, 0x740C), .driver_data = CHIP_ALDEBARAN },
{ PCI_DEVICE(0x1002, 0x740F), .driver_data = CHIP_ALDEBARAN },
{ PCI_DEVICE(0x1002, 0x7410), .driver_data = CHIP_ALDEBARAN },
/* CYAN_SKILLFISH */
{0x1002, 0x13DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
{0x1002, 0x13F9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
{0x1002, 0x13FA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
{0x1002, 0x13FB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
{0x1002, 0x13FC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
{0x1002, 0x13FE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
{0x1002, 0x143F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
{ PCI_DEVICE(0x1002, 0x13DB), .driver_data = CHIP_CYAN_SKILLFISH|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x13F9), .driver_data = CHIP_CYAN_SKILLFISH|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x13FA), .driver_data = CHIP_CYAN_SKILLFISH|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x13FB), .driver_data = CHIP_CYAN_SKILLFISH|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x13FC), .driver_data = CHIP_CYAN_SKILLFISH|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x13FE), .driver_data = CHIP_CYAN_SKILLFISH|AMD_IS_APU },
{ PCI_DEVICE(0x1002, 0x143F), .driver_data = CHIP_CYAN_SKILLFISH|AMD_IS_APU },
/* BEIGE_GOBY */
{0x1002, 0x7420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
{0x1002, 0x7421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
{0x1002, 0x7422, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
{0x1002, 0x7423, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
{0x1002, 0x7424, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
{0x1002, 0x743F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
{ PCI_DEVICE(0x1002, 0x7420), .driver_data = CHIP_BEIGE_GOBY },
{ PCI_DEVICE(0x1002, 0x7421), .driver_data = CHIP_BEIGE_GOBY },
{ PCI_DEVICE(0x1002, 0x7422), .driver_data = CHIP_BEIGE_GOBY },
{ PCI_DEVICE(0x1002, 0x7423), .driver_data = CHIP_BEIGE_GOBY },
{ PCI_DEVICE(0x1002, 0x7424), .driver_data = CHIP_BEIGE_GOBY },
{ PCI_DEVICE(0x1002, 0x743F), .driver_data = CHIP_BEIGE_GOBY },
{ PCI_DEVICE(0x1002, PCI_ANY_ID),
.class = PCI_CLASS_DISPLAY_VGA << 8,
@@ -2205,7 +2205,7 @@ static const struct pci_device_id pciidlist[] = {
.class_mask = 0xffffff,
.driver_data = CHIP_IP_DISCOVERY },
{0, 0, 0}
{ }
};
MODULE_DEVICE_TABLE(pci, pciidlist);
@@ -2920,6 +2920,19 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
return 0;
}
static void amdgpu_restore_umd_profile_pstate_after_runpm(struct amdgpu_device *adev)
{
enum amd_dpm_forced_level level;
uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
level = amdgpu_dpm_get_performance_level(adev);
if (level & profile_mode_mask)
amdgpu_asic_update_umd_stable_pstate(adev, true);
}
static int amdgpu_pmops_runtime_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
@@ -2964,6 +2977,8 @@ static int amdgpu_pmops_runtime_resume(struct device *dev)
if (adev->pm.rpm_mode == AMDGPU_RUNPM_PX)
drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;
amdgpu_restore_umd_profile_pstate_after_runpm(adev);
adev->in_runpm = false;
return 0;
}

View File

@@ -1713,8 +1713,9 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
owner = (void *)(unsigned long)atomic_inc_return(&counter);
r = amdgpu_job_alloc_with_ib(ring->adev, &entity, owner,
ib_size_dw * sizeof(uint32_t), 0, &job,
AMDGPU_KERNEL_JOB_ID_CLEANER_SHADER);
ib_size_dw * sizeof(uint32_t), 0,
AMDGPU_KERNEL_JOB_ID_CLEANER_SHADER,
&job);
if (r)
goto err;

View File

@@ -761,7 +761,8 @@ void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
r = amdgpu_job_alloc_with_ib(ring->adev, &adev->mman.default_entity.base,
AMDGPU_FENCE_OWNER_UNDEFINED,
16 * 4, AMDGPU_IB_POOL_IMMEDIATE,
&job, AMDGPU_KERNEL_JOB_ID_FLUSH_GPU_TLB);
AMDGPU_KERNEL_JOB_ID_FLUSH_GPU_TLB,
&job);
if (r)
goto error_alloc;

View File

@@ -351,6 +351,30 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
*/
int amdgpu_ib_pool_init(struct amdgpu_device *adev)
{
const int sizes[AMDGPU_IB_POOL_MAX] = {
[AMDGPU_IB_POOL_DELAYED] = SZ_1M,
[AMDGPU_IB_POOL_IMMEDIATE] = SZ_128K,
[AMDGPU_IB_POOL_DIRECT] = SZ_512K
};
const gfp_t gfp_flags[AMDGPU_IB_POOL_MAX] = {
/*
* For normal page table updates and recoverable retry faults
* (for SVM), further restricted by the VM eviction lock to not
* wait for memory reclaim.
*/
[AMDGPU_IB_POOL_DELAYED] = GFP_KERNEL,
/*
* For redirecting unrecoverable retry faults to the dummy page
* or set the PRT bits. dma_fence submissions might depend on
* that so we need the emmergency reserves.
*/
[AMDGPU_IB_POOL_IMMEDIATE] = GFP_ATOMIC,
/*
* For IB tests during GPU resets. Only very small and temporary
* allocation to allow dma_fences to signal.
*/
[AMDGPU_IB_POOL_DIRECT] = GFP_ATOMIC
};
int r, i;
if (adev->ib_pool_ready)
@@ -358,8 +382,7 @@ int amdgpu_ib_pool_init(struct amdgpu_device *adev)
for (i = 0; i < AMDGPU_IB_POOL_MAX; i++) {
r = amdgpu_sa_bo_manager_init(adev, &adev->ib_pools[i],
AMDGPU_IB_POOL_SIZE, 256,
AMDGPU_GEM_DOMAIN_GTT);
sizes[i], gfp_flags[i]);
if (r)
goto error;
}
@@ -393,6 +416,17 @@ void amdgpu_ib_pool_fini(struct amdgpu_device *adev)
adev->ib_pool_ready = false;
}
/**
* amdgpu_ib_pool_gfp_flags - Returns the gfp flags to use for each pool
* @adev: amdgpu device pointer
* @type: the IB pool type
*/
gfp_t amdgpu_ib_pool_gfp_flags(struct amdgpu_device *adev,
enum amdgpu_ib_pool_type type)
{
return adev->ib_pools[type].gfp_flags;
}
/**
* amdgpu_ib_ring_tests - test IBs on the rings
*

View File

@@ -51,16 +51,16 @@ struct amdgpu_pasid_cb {
/**
* amdgpu_pasid_alloc - Allocate a PASID
* @bits: Maximum width of the PASID in bits, must be at least 1
* @bits: Number of PASID bits supported by the hardware
* @fpriv: DRM file private to associate with the PASID
*
* Uses kernel's IDR cyclic allocator (same as PID allocation).
* Uses the kernel's XArray cyclic allocator.
* Allocates sequentially with automatic wrap-around.
*
* Returns a positive integer on success. Returns %-EINVAL if bits==0.
* Returns %-ENOSPC if no PASID was available. Returns %-ENOMEM on
* memory allocation failure.
* Returns:
* Allocated PASID on success or a negative error code on failure.
*/
int amdgpu_pasid_alloc(unsigned int bits)
int amdgpu_pasid_alloc(unsigned int bits, struct amdgpu_fpriv *fpriv)
{
u32 pasid;
int r;
@@ -68,9 +68,9 @@ int amdgpu_pasid_alloc(unsigned int bits)
if (bits == 0)
return -EINVAL;
r = xa_alloc_cyclic_irq(&amdgpu_pasid_xa, &pasid, xa_mk_value(0),
XA_LIMIT(1, (1U << bits) - 1),
&amdgpu_pasid_xa_next, GFP_KERNEL);
r = xa_alloc_cyclic_irq(&amdgpu_pasid_xa, &pasid, fpriv,
XA_LIMIT(1, (1U << bits) - 1),
&amdgpu_pasid_xa_next, GFP_KERNEL);
if (r < 0)
return r;
@@ -106,6 +106,71 @@ static void amdgpu_pasid_free_cb(struct dma_fence *fence,
kfree(cb);
}
/**
* amdgpu_pasid_clear_owner - Clear the owner associated with a PASID
* @pasid: PASID whose owner should be cleared
*
* Replace the stored owner with NULL while keeping the PASID allocated.
*
* This is used by the delayed PASID free path so that future PASID
* lookups cannot resolve a stale DRM file-private object while the PASID
* is still waiting for outstanding fences before being released.
*/
static void amdgpu_pasid_clear_owner(u32 pasid)
{
unsigned long flags;
if (!pasid)
return;
xa_lock_irqsave(&amdgpu_pasid_xa, flags);
__xa_store(&amdgpu_pasid_xa, pasid, NULL, GFP_ATOMIC);
xa_unlock_irqrestore(&amdgpu_pasid_xa, flags);
}
/**
* amdgpu_pasid_lock - acquire the global PASID xarray lock
* @flags: storage for interrupt state
*
* Acquire the global PASID xarray lock with interrupts disabled.
* The saved interrupt state must be passed to
* amdgpu_pasid_unlock().
*/
void amdgpu_pasid_lock(unsigned long *flags)
{
xa_lock_irqsave(&amdgpu_pasid_xa, *flags);
}
/**
* amdgpu_pasid_unlock - release the global PASID xarray lock
* @flags: interrupt state returned by amdgpu_pasid_lock()
*
* Release the global PASID xarray lock and restore the previous
* interrupt state.
*/
void amdgpu_pasid_unlock(unsigned long flags)
{
xa_unlock_irqrestore(&amdgpu_pasid_xa, flags);
}
/**
* amdgpu_pasid_get_fpriv_locked - get the DRM owner of a PASID
* @pasid: PASID to resolve
*
* The caller must hold the PASID XArray lock.
*
* Returns:
* Pointer to the owning DRM file private, or %NULL if the PASID has no
* current owner.
*
* The returned pointer is only valid while the PASID lock remains held
* and must not be retained after calling amdgpu_pasid_unlock().
*/
struct amdgpu_fpriv *amdgpu_pasid_get_fpriv_locked(u32 pasid)
{
return xa_load(&amdgpu_pasid_xa, pasid);
}
/**
* amdgpu_pasid_free_delayed - free pasid when fences signal
*
@@ -121,6 +186,8 @@ void amdgpu_pasid_free_delayed(struct dma_resv *resv,
struct dma_fence *fence;
int r;
amdgpu_pasid_clear_owner(pasid);
r = dma_resv_get_singleton(resv, DMA_RESV_USAGE_BOOKKEEP, &fence);
if (r)
goto fallback;

View File

@@ -34,6 +34,7 @@
#define AMDGPU_NUM_VMID 16
struct amdgpu_device;
struct amdgpu_fpriv;
struct amdgpu_vm;
struct amdgpu_ring;
struct amdgpu_sync;
@@ -70,7 +71,10 @@ struct amdgpu_vmid_mgr {
bool reserved_vmid;
};
int amdgpu_pasid_alloc(unsigned int bits);
int amdgpu_pasid_alloc(unsigned int bits, struct amdgpu_fpriv *fpriv);
void amdgpu_pasid_lock(unsigned long *flags);
void amdgpu_pasid_unlock(unsigned long flags);
struct amdgpu_fpriv *amdgpu_pasid_get_fpriv_locked(u32 pasid);
void amdgpu_pasid_free(u32 pasid);
void amdgpu_pasid_free_delayed(struct dma_resv *resv,
u32 pasid);

View File

@@ -198,8 +198,8 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
struct drm_sched_entity *entity, void *owner,
unsigned int num_ibs, struct amdgpu_job **job,
u64 drm_client_id)
unsigned int num_ibs, u64 drm_client_id,
gfp_t gfp_flags, struct amdgpu_job **job)
{
struct amdgpu_fence *af;
int r;
@@ -207,18 +207,18 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
if (num_ibs == 0)
return -EINVAL;
*job = kzalloc_flex(**job, ibs, num_ibs);
*job = kzalloc_flex(**job, ibs, num_ibs, gfp_flags);
if (!*job)
return -ENOMEM;
af = kzalloc_obj(struct amdgpu_fence);
af = kzalloc_obj(struct amdgpu_fence, gfp_flags);
if (!af) {
r = -ENOMEM;
goto err_job;
}
(*job)->hw_fence = af;
af = kzalloc_obj(struct amdgpu_fence);
af = kzalloc_obj(struct amdgpu_fence, gfp_flags);
if (!af) {
r = -ENOMEM;
goto err_fence;
@@ -252,12 +252,13 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev,
struct drm_sched_entity *entity, void *owner,
size_t size, enum amdgpu_ib_pool_type pool_type,
struct amdgpu_job **job, u64 k_job_id)
u64 k_job_id, struct amdgpu_job **job)
{
int r;
r = amdgpu_job_alloc(adev, NULL, entity, owner, 1, job,
k_job_id);
r = amdgpu_job_alloc(adev, NULL, entity, owner, 1, k_job_id,
amdgpu_ib_pool_gfp_flags(adev, pool_type),
job);
if (r)
return r;

View File

@@ -115,13 +115,13 @@ static inline struct amdgpu_ring *amdgpu_job_ring(struct amdgpu_job *job)
int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
struct drm_sched_entity *entity, void *owner,
unsigned int num_ibs, struct amdgpu_job **job,
u64 drm_client_id);
unsigned int num_ibs, u64 drm_client_id,
gfp_t gfp_flags, struct amdgpu_job **job);
int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev,
struct drm_sched_entity *entity, void *owner,
size_t size, enum amdgpu_ib_pool_type pool_type,
struct amdgpu_job **job,
u64 k_job_id);
u64 k_job_id,
struct amdgpu_job **job);
void amdgpu_job_set_resources(struct amdgpu_job *job, struct amdgpu_bo *gds,
struct amdgpu_bo *gws, struct amdgpu_bo *oa);
void amdgpu_job_free_resources(struct amdgpu_job *job);

View File

@@ -197,8 +197,9 @@ static int amdgpu_jpeg_dec_set_reg(struct amdgpu_ring *ring, uint32_t handle,
int i, r;
r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,
AMDGPU_IB_POOL_DIRECT, &job,
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST);
AMDGPU_IB_POOL_DIRECT,
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST,
&job);
if (r)
return r;

View File

@@ -1211,7 +1211,7 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
return -EINVAL;
}
}
ui32 >>= 8;
ui32 /= MILLIWATT_PER_WATT;
break;
case AMDGPU_INFO_SENSOR_GPU_INPUT_POWER:
/* get input GPU power */
@@ -1220,7 +1220,7 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
(void *)&ui32, &ui32_size)) {
return -EINVAL;
}
ui32 >>= 8;
ui32 /= MILLIWATT_PER_WATT;
break;
case AMDGPU_INFO_SENSOR_VDDNB:
/* get VDDNB in millivolts */
@@ -1376,11 +1376,11 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
memset(&gpuvm_fault, 0, sizeof(gpuvm_fault));
xa_lock_irqsave(&adev->vm_manager.pasids, flags);
amdgpu_pasid_lock(&flags);
gpuvm_fault.addr = vm->fault_info.addr;
gpuvm_fault.status = vm->fault_info.status;
gpuvm_fault.vmhub = vm->fault_info.vmhub;
xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
amdgpu_pasid_unlock(flags);
return copy_to_user(out, &gpuvm_fault,
min((size_t)size, sizeof(gpuvm_fault))) ? -EFAULT : 0;
@@ -1465,7 +1465,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
struct amdgpu_device *adev = drm_to_adev(dev);
struct amdgpu_fpriv *fpriv;
struct drm_exec exec;
int r, pasid;
int r, pasid = 0;
/* Ensure IB tests are run on ring */
flush_delayed_work(&adev->delayed_init_work);
@@ -1488,22 +1488,23 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
goto out_suspend;
}
pasid = amdgpu_pasid_alloc(16);
if (pasid < 0) {
dev_warn(adev->dev, "No more PASIDs available!");
pasid = 0;
}
r = amdgpu_xcp_open_device(adev, fpriv, file_priv);
if (r)
goto error_pasid;
amdgpu_debugfs_vm_init(file_priv);
r = amdgpu_vm_init(adev, &fpriv->vm, fpriv->xcp_id, pasid);
r = amdgpu_vm_init(adev, &fpriv->vm, fpriv->xcp_id);
if (r)
goto error_pasid;
pasid = amdgpu_pasid_alloc(16, fpriv);
if (pasid < 0) {
dev_warn(adev->dev, "No more PASIDs available!");
pasid = 0;
}
fpriv->vm.pasid = pasid;
drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0);
drm_exec_until_all_locked(&exec) {
r = amdgpu_vm_lock_pd(&fpriv->vm, &exec, 0);
@@ -1547,12 +1548,14 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
goto out_suspend;
error_vm:
if (pasid) {
amdgpu_pasid_free(pasid);
pasid = 0;
}
amdgpu_vm_fini(adev, &fpriv->vm);
error_pasid:
if (pasid)
amdgpu_pasid_free(pasid);
kfree(fpriv);
out_suspend:
@@ -1608,10 +1611,11 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
}
amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr);
amdgpu_vm_fini(adev, &fpriv->vm);
if (pasid)
amdgpu_pasid_free_delayed(pd->tbo.base.resv, pasid);
amdgpu_vm_fini(adev, &fpriv->vm);
amdgpu_bo_unref(&pd);
xa_for_each(&fpriv->bo_list_handles, handle, list)

View File

@@ -952,9 +952,11 @@ int amdgpu_mes_rs64mem_init(struct amdgpu_mes *mes)
return 0;
}
/**
* amdgpu_mes_rs64mem_fini - tear down RS64 local memory management
*/
/**
* amdgpu_mes_rs64mem_fini - tear down RS64 local memory management
*
* @mes: MES instance
*/
void amdgpu_mes_rs64mem_fini(struct amdgpu_mes *mes)
{
if (mes->ctx_array_size_bo) {
@@ -1038,9 +1040,10 @@ int amdgpu_mes_rs64mem_setup_bitmaps(struct amdgpu_mes *mes)
* amdgpu_mes_alloc_proc_ctx_index - allocate a process context slot
*
* @mes: MES instance
* @queue: Usermode queue receiving the allocated process context index
*
* Returns 0 on success, -ENOSPC if all slots are used (caller should
* fall back to system memory path).
* Returns 0 on success, -ENOSPC if all slots are used, or
* -EOPNOTSUPP if RS64 local memory is unavailable.
*/
int amdgpu_mes_alloc_proc_ctx_index(struct amdgpu_mes *mes,
struct amdgpu_usermode_queue *queue)
@@ -1064,9 +1067,12 @@ int amdgpu_mes_alloc_proc_ctx_index(struct amdgpu_mes *mes,
return 0;
}
/**
* amdgpu_mes_free_proc_ctx_index - free a process context slot
*/
/**
* amdgpu_mes_free_proc_ctx_index - free a process context slot
*
* @mes: MES instance
* @queue: Usermode queue whose process context index is released
*/
void amdgpu_mes_free_proc_ctx_index(struct amdgpu_mes *mes,
struct amdgpu_usermode_queue *queue)
{
@@ -1080,9 +1086,15 @@ void amdgpu_mes_free_proc_ctx_index(struct amdgpu_mes *mes,
amdgpu_mes_unlock(mes);
}
/**
* amdgpu_mes_alloc_gang_ctx_index - allocate a gang context slot
*/
/**
* amdgpu_mes_alloc_gang_ctx_index - allocate a gang context slot
*
* @mes: MES instance
* @queue: Usermode queue receiving the allocated gang context index
*
* Returns 0 on success, -ENOSPC if all slots are used, or
* -EOPNOTSUPP if RS64 local memory is unavailable.
*/
int amdgpu_mes_alloc_gang_ctx_index(struct amdgpu_mes *mes,
struct amdgpu_usermode_queue *queue)
{
@@ -1105,9 +1117,12 @@ int amdgpu_mes_alloc_gang_ctx_index(struct amdgpu_mes *mes,
return 0;
}
/**
* amdgpu_mes_free_gang_ctx_index - free a gang context slot
*/
/**
* amdgpu_mes_free_gang_ctx_index - free a gang context slot
*
* @mes: MES instance
* @queue: Usermode queue whose gang context index is released
*/
void amdgpu_mes_free_gang_ctx_index(struct amdgpu_mes *mes,
struct amdgpu_usermode_queue *queue)
{

View File

@@ -509,6 +509,7 @@ struct amdgpu_crtc {
struct drm_pending_vblank_event *event;
bool wb_pending;
bool wb_frame_done;
bool wb_enabled;
struct drm_writeback_connector *wb_conn;
};

View File

@@ -275,6 +275,7 @@ static int psp_early_init(struct amdgpu_ip_block *ip_block)
psp->boot_time_tmr = false;
break;
case IP_VERSION(15, 0, 0):
case IP_VERSION(15, 0, 5):
case IP_VERSION(15, 0, 9):
psp_v15_0_0_set_psp_funcs(psp);
psp->boot_time_tmr = false;
@@ -1222,6 +1223,33 @@ int psp_memory_partition(struct psp_context *psp, int mode)
return ret;
}
int psp_set_mmhub_eco_sec_level(struct amdgpu_device *adev)
{
int ret;
struct psp_context *psp = &adev->psp;
struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
cmd->cmd_id = GFX_CMD_ID_SET_MMHUB_ECO_SEC_LEVEL;
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
if (ret) {
dev_err(psp->adev->dev,
"PSP request failed to set mmuhub eco sec level with ret=%d\n", ret);
release_psp_cmd_buf(psp);
return ret;
}
if (cmd->resp.status) {
dev_err(psp->adev->dev,
"MMHUB ECO SEC LEVEL command 0x%x failed, PSP response status: 0x%X\n",
cmd->cmd_id, cmd->resp.status);
ret = -EIO;
}
release_psp_cmd_buf(psp);
return ret;
}
static int psp_ptl_fmt_verify(struct psp_context *psp, enum amdgpu_ptl_fmt fmt,
uint32_t *ptl_fmt)
{
@@ -1264,8 +1292,19 @@ static int psp_ptl_invoke(struct psp_context *psp, u32 req_code,
{
struct psp_gfx_cmd_resp *cmd;
struct amdgpu_ptl *ptl = &psp->ptl;
struct amdgpu_device *adev = psp->adev;
int ret;
if (amdgpu_sriov_vf(adev)) {
ret = amdgpu_virt_ptl_request(adev, req_code, ptl_state, fmt1, fmt2);
if (!ret) {
ptl->enabled = *ptl_state;
ptl->fmt1 = *fmt1;
ptl->fmt2 = *fmt2;
}
return ret;
}
cmd = acquire_psp_cmd_buf(psp);
cmd->cmd_id = GFX_CMD_ID_PERF_HW;
@@ -1328,15 +1367,18 @@ int amdgpu_ptl_perf_monitor_ctrl(struct amdgpu_device *adev, u32 req_code,
if (!adev || !ptl_state || !fmt1 || !fmt2)
return -EINVAL;
if (amdgpu_sriov_vf(adev))
return 0;
psp = &adev->psp;
ptl = &psp->ptl;
if (ptl->permanently_disabled && *ptl_state == 1)
return 0;
if (amdgpu_sriov_vf(adev)) {
ptl_fmt1 = *fmt1;
ptl_fmt2 = *fmt2;
return psp_ptl_invoke(psp, req_code, ptl_state, &ptl_fmt1, &ptl_fmt2);
}
if (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 4) ||
psp->sos.fw_version < 0x0036081a)
return -EOPNOTSUPP;
@@ -1475,6 +1517,18 @@ static ssize_t ptl_enable_show(struct device *dev, struct device_attribute *attr
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(ddev);
struct amdgpu_ptl *ptl = &adev->psp.ptl;
uint32_t ptl_state, fmt1, fmt2;
int ret;
if (amdgpu_sriov_vf(adev)) {
ptl_state = ptl->enabled;
fmt1 = ptl->fmt1;
fmt2 = ptl->fmt2;
ret = amdgpu_ptl_perf_monitor_ctrl(adev, PSP_PTL_PERF_MON_QUERY,
&ptl_state, &fmt1, &fmt2);
if (ret)
return ret;
}
if (ptl->permanently_disabled)
return sysfs_emit(buf, "permanently disabled\n");
@@ -1533,11 +1587,23 @@ static ssize_t ptl_format_show(struct device *dev, struct device_attribute *attr
{
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(ddev);
struct psp_context *psp = &adev->psp;
struct amdgpu_ptl *ptl = &adev->psp.ptl;
uint32_t ptl_state, fmt1, fmt2;
int ret;
if (amdgpu_sriov_vf(adev)) {
ptl_state = ptl->enabled;
fmt1 = ptl->fmt1;
fmt2 = ptl->fmt2;
ret = amdgpu_ptl_perf_monitor_ctrl(adev, PSP_PTL_PERF_MON_QUERY,
&ptl_state, &fmt1, &fmt2);
if (ret)
return ret;
}
return sysfs_emit(buf, "%s,%s\n",
amdgpu_ptl_fmt_str[psp->ptl.fmt1],
amdgpu_ptl_fmt_str[psp->ptl.fmt2]);
amdgpu_ptl_fmt_str[ptl->fmt1],
amdgpu_ptl_fmt_str[ptl->fmt2]);
}
static umode_t amdgpu_ptl_is_visible(struct kobject *kobj, struct attribute *attr, int idx)
@@ -1547,7 +1613,7 @@ static umode_t amdgpu_ptl_is_visible(struct kobject *kobj, struct attribute *att
struct amdgpu_device *adev = drm_to_adev(ddev);
/* Only show PTL sysfs files if PTL hardware is supported */
if (!adev->psp.ptl.hw_supported)
if (adev->psp.ptl.hw_supported_state != AMDGPU_PTL_HW_SUPPORTED)
return 0;
return attr->mode;
@@ -1558,7 +1624,7 @@ int amdgpu_ptl_sysfs_init(struct amdgpu_device *adev)
struct amdgpu_ptl *ptl = &adev->psp.ptl;
int ret;
if (!ptl->hw_supported)
if (ptl->hw_supported_state != AMDGPU_PTL_HW_SUPPORTED)
return 0;
if (ptl->ptl_sysfs_created)
@@ -1575,7 +1641,7 @@ void amdgpu_ptl_sysfs_fini(struct amdgpu_device *adev)
{
struct amdgpu_ptl *ptl = &adev->psp.ptl;
if (!ptl->hw_supported)
if (ptl->hw_supported_state != AMDGPU_PTL_HW_SUPPORTED)
return;
if (!ptl->ptl_sysfs_created)
@@ -1861,6 +1927,12 @@ int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool lo
/* note down the capbility flag for XGMI TA */
psp->xgmi_context.xgmi_ta_caps = xgmi_cmd->caps_flag;
if (!amdgpu_sriov_vf(psp->adev))
psp->xgmi_context.supports_ext_link_info = psp->xgmi_context.xgmi_ta_caps &
EXTEND_PEER_LINK_INFO_CMD_FLAG;
else
psp->xgmi_context.supports_ext_link_info = amdgpu_sriov_xgmi_ta_ext_peer_link_en(psp->adev);
return ret;
}
@@ -2038,15 +2110,13 @@ int psp_xgmi_get_topology_info(struct psp_context *psp,
amdgpu_ip_version(psp->adev, MP0_HWIP, 0) ==
IP_VERSION(13, 0, 14) ||
amdgpu_sriov_vf(psp->adev);
bool ta_port_num_support = psp->xgmi_context.xgmi_ta_caps & EXTEND_PEER_LINK_INFO_CMD_FLAG ||
amdgpu_sriov_xgmi_ta_ext_peer_link_en(psp->adev);
/* popluate the shared output buffer rather than the cmd input buffer
* with node_ids as the input for GET_PEER_LINKS command execution.
* This is required for GET_PEER_LINKS per xgmi ta implementation.
* The same requirement for GET_EXTEND_PEER_LINKS command.
*/
if (ta_port_num_support) {
if (psp->xgmi_context.supports_ext_link_info) {
link_extend_info_output = &xgmi_cmd->xgmi_out_message.get_extend_link_info;
for (i = 0; i < topology->num_nodes; i++)
@@ -2069,7 +2139,7 @@ int psp_xgmi_get_topology_info(struct psp_context *psp,
return ret;
for (i = 0; i < topology->num_nodes; i++) {
uint8_t node_num_links = ta_port_num_support ?
uint8_t node_num_links = psp->xgmi_context.supports_ext_link_info ?
link_extend_info_output->nodes[i].num_links : link_info_output->nodes[i].num_links;
/* accumulate num_links on extended data */
if (get_extended_data) {
@@ -2079,7 +2149,7 @@ int psp_xgmi_get_topology_info(struct psp_context *psp,
topology->nodes[i].num_links : node_num_links;
}
/* popluate the connected port num info if supported and available */
if (ta_port_num_support && topology->nodes[i].num_links) {
if (psp->xgmi_context.supports_ext_link_info && topology->nodes[i].num_links) {
memcpy(topology->nodes[i].port_num, link_extend_info_output->nodes[i].port_num,
sizeof(struct xgmi_connected_port_num) * TA_XGMI__MAX_PORT_NUM);
}
@@ -3476,8 +3546,10 @@ static int psp_load_non_psp_fw(struct psp_context *psp)
amdgpu_ip_version(adev, MP0_HWIP, 0) ==
IP_VERSION(15, 0, 0) ||
amdgpu_ip_version(adev, MP0_HWIP, 0) ==
IP_VERSION(15, 0, 8) ||
IP_VERSION(15, 0, 5) ||
amdgpu_ip_version(adev, MP0_HWIP, 0) ==
IP_VERSION(15, 0, 8) ||
amdgpu_ip_version(adev, MP0_HWIP, 0) ==
IP_VERSION(15, 0, 9)) &&
(ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1 ||
ucode->ucode_id == AMDGPU_UCODE_ID_SDMA2 ||

View File

@@ -232,6 +232,7 @@ struct psp_xgmi_context {
struct ta_context context;
struct psp_xgmi_topology_info top_info;
bool supports_extended_data;
bool supports_ext_link_info;
uint8_t xgmi_ta_caps;
};
@@ -656,5 +657,6 @@ int amdgpu_psp_reg_program_no_ring(struct psp_context *psp, uint32_t val,
void amdgpu_psp_debugfs_init(struct amdgpu_device *adev);
int amdgpu_psp_get_fw_type(struct amdgpu_firmware_info *ucode,
enum psp_gfx_fw_type *type);
int psp_set_mmhub_eco_sec_level(struct amdgpu_device *adev);
#endif

View File

@@ -1436,7 +1436,7 @@ static int amdgpu_uniras_clear_badpages_info(struct amdgpu_device *adev)
&req, sizeof(req), NULL, 0);
if (ret) {
dev_err(adev->dev, "Failed to clear bad pages info, ret: %d\n", ret);
return ret;
return -EINVAL;
}
return 0;
@@ -1536,7 +1536,7 @@ static int amdgpu_uniras_error_inject(struct amdgpu_device *adev,
inject_req.method = info->value;
return amdgpu_ras_mgr_handle_ras_cmd(adev, RAS_CMD__INJECT_ERROR,
&inject_req, sizeof(inject_req), &rsp, sizeof(rsp));
&inject_req, sizeof(inject_req), &rsp, sizeof(rsp)) ? -EINVAL : 0;
}
/* wrapper of psp_ras_trigger_error */

View File

@@ -526,7 +526,7 @@ static ssize_t amdgpu_ras_cper_debugfs_read(struct file *f, char __user *buf,
snapshot_req, sizeof(struct ras_cmd_cper_snapshot_req),
snapshot_rsp, sizeof(struct ras_cmd_cper_snapshot_rsp));
if (r)
return r;
return -EINVAL;
if (!snapshot_rsp->total_cper_num) {
if (!read_header)
@@ -568,7 +568,7 @@ static ssize_t amdgpu_ras_cper_debugfs_read(struct file *f, char __user *buf,
record_rsp,
sizeof(struct ras_cmd_cper_record_rsp));
if (r)
return r;
return -EINVAL;
if (!record_rsp->real_data_size || !record_rsp->real_cper_num)
break;

View File

@@ -68,8 +68,6 @@ enum amdgpu_ring_priority_level {
#define to_amdgpu_ring(s) container_of((s), struct amdgpu_ring, sched)
#define AMDGPU_IB_POOL_SIZE (1024 * 1024)
enum amdgpu_ring_type {
AMDGPU_RING_TYPE_GFX = AMDGPU_HW_IP_GFX,
AMDGPU_RING_TYPE_COMPUTE = AMDGPU_HW_IP_COMPUTE,
@@ -585,6 +583,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
struct dma_fence **f);
int amdgpu_ib_pool_init(struct amdgpu_device *adev);
void amdgpu_ib_pool_fini(struct amdgpu_device *adev);
gfp_t amdgpu_ib_pool_gfp_flags(struct amdgpu_device *adev,
enum amdgpu_ib_pool_type type);
int amdgpu_ib_ring_tests(struct amdgpu_device *adev);
bool amdgpu_ring_sched_ready(struct amdgpu_ring *ring);
void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring,

View File

@@ -46,11 +46,13 @@
int amdgpu_sa_bo_manager_init(struct amdgpu_device *adev,
struct amdgpu_sa_manager *sa_manager,
unsigned int size, u32 suballoc_align, u32 domain)
unsigned int size, gfp_t gfp_flags)
{
int r;
r = amdgpu_bo_create_kernel(adev, size, AMDGPU_GPU_PAGE_SIZE, domain,
sa_manager->gfp_flags = gfp_flags;
r = amdgpu_bo_create_kernel(adev, size, AMDGPU_GPU_PAGE_SIZE,
AMDGPU_GEM_DOMAIN_GTT,
&sa_manager->bo, &sa_manager->gpu_addr,
&sa_manager->cpu_ptr);
if (r) {
@@ -59,7 +61,8 @@ int amdgpu_sa_bo_manager_init(struct amdgpu_device *adev,
}
memset(sa_manager->cpu_ptr, 0, size);
drm_suballoc_manager_init(&sa_manager->base, size, suballoc_align);
drm_suballoc_manager_init(&sa_manager->base, size, 256);
return r;
}
@@ -73,7 +76,8 @@ void amdgpu_sa_bo_manager_fini(struct amdgpu_device *adev,
drm_suballoc_manager_fini(&sa_manager->base);
amdgpu_bo_free_kernel(&sa_manager->bo, &sa_manager->gpu_addr, &sa_manager->cpu_ptr);
amdgpu_bo_free_kernel(&sa_manager->bo, &sa_manager->gpu_addr,
&sa_manager->cpu_ptr);
}
int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,
@@ -81,7 +85,8 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,
unsigned int size)
{
struct drm_suballoc *sa = drm_suballoc_new(&sa_manager->base, size,
GFP_KERNEL, false, 0);
sa_manager->gfp_flags,
false, 0);
if (IS_ERR(sa)) {
*sa_bo = NULL;
@@ -110,6 +115,7 @@ void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager,
{
struct drm_printer p = drm_seq_file_printer(m);
drm_suballoc_dump_debug_info(&sa_manager->base, &p, sa_manager->gpu_addr);
drm_suballoc_dump_debug_info(&sa_manager->base, &p,
sa_manager->gpu_addr);
}
#endif

View File

@@ -35,6 +35,7 @@ struct amdgpu_sa_manager {
struct amdgpu_bo *bo;
uint64_t gpu_addr;
void *cpu_ptr;
gfp_t gfp_flags;
};
static inline struct amdgpu_sa_manager *
@@ -57,7 +58,7 @@ static inline void *amdgpu_sa_bo_cpu_addr(struct drm_suballoc *sa_bo)
int amdgpu_sa_bo_manager_init(struct amdgpu_device *adev,
struct amdgpu_sa_manager *sa_manager,
unsigned size, u32 align, u32 domain);
unsigned size, gfp_t gfp_flags);
void amdgpu_sa_bo_manager_fini(struct amdgpu_device *adev,
struct amdgpu_sa_manager *sa_manager);
int amdgpu_sa_bo_manager_start(struct amdgpu_device *adev,

View File

@@ -244,8 +244,9 @@ static int amdgpu_ttm_map_buffer(struct amdgpu_ttm_buffer_entity *entity,
r = amdgpu_job_alloc_with_ib(adev, &entity->base,
AMDGPU_FENCE_OWNER_UNDEFINED,
num_dw * 4 + num_bytes,
AMDGPU_IB_POOL_DELAYED, &job,
AMDGPU_KERNEL_JOB_ID_TTM_MAP_BUFFER);
AMDGPU_IB_POOL_DELAYED,
AMDGPU_KERNEL_JOB_ID_TTM_MAP_BUFFER,
&job);
if (r)
return r;
@@ -1487,6 +1488,7 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
const struct ttm_place *place)
{
struct dma_resv_iter resv_cursor;
struct amdgpu_bo *abo;
struct dma_fence *f;
if (!amdgpu_bo_is_amdgpu_bo(bo))
@@ -1496,6 +1498,21 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
if (bo->resource->mem_type == TTM_PL_SYSTEM)
return true;
abo = ttm_to_amdgpu_bo(bo);
if (abo->flags & AMDGPU_GEM_CREATE_DISCARDABLE) {
/*
* SVM BOs are migrated to system memory synchronously in this
* TTM eviction context. The migration needs the owning
* process's mmap lock, but the normal lock order is
* mmap_lock -> BO reservation and the BO is already reserved
* here. svm_range_evict_svm_bo() only trylocks the mmap lock;
* if the eviction fails for any reason, we return false so TTM
* skips this BO instead of risking a deadlock.
*/
if (amdgpu_amdkfd_evict_svm_bo(abo) < 0)
return false;
}
if (bo->type == ttm_bo_type_kernel &&
!amdgpu_vm_evictable(ttm_to_amdgpu_bo(bo)))
return false;
@@ -1592,8 +1609,8 @@ static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo,
r = amdgpu_job_alloc_with_ib(adev, &adev->mman.default_entity.base,
AMDGPU_FENCE_OWNER_UNDEFINED,
num_dw * 4, AMDGPU_IB_POOL_DELAYED,
&job,
AMDGPU_KERNEL_JOB_ID_TTM_ACCESS_MEMORY_SDMA);
AMDGPU_KERNEL_JOB_ID_TTM_ACCESS_MEMORY_SDMA,
&job);
if (r)
goto out;
@@ -2173,6 +2190,18 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
gtt_size = configured_size;
}
/* Cap GTT so that it does not exceed total physical RAM. */
if (adev->flags & AMD_IS_APU) {
u64 phys_ram = (u64)totalram_pages() << PAGE_SHIFT;
if (gtt_size > phys_ram) {
gtt_size = phys_ram;
dev_info(adev->dev,
"Capping GTT to %uM to not exceed available system memory\n",
(unsigned int)(gtt_size / (1024 * 1024)));
}
}
/* Initialize GTT memory pool */
r = amdgpu_gtt_mgr_init(adev, gtt_size);
if (r) {
@@ -2443,7 +2472,7 @@ static int amdgpu_ttm_prepare_job(struct amdgpu_device *adev,
int r;
r = amdgpu_job_alloc_with_ib(adev, &entity->base,
AMDGPU_FENCE_OWNER_UNDEFINED,
num_dw * 4, pool, job, k_job_id);
num_dw * 4, pool, k_job_id, job);
if (r)
return r;
@@ -2460,6 +2489,27 @@ static int amdgpu_ttm_prepare_job(struct amdgpu_device *adev,
DMA_RESV_USAGE_BOOKKEEP);
}
static int amdgpu_calc_bytes_per_packet(u32 max_bytes_per_packet,
u32 byte_count)
{
/* Byte count is dword-aligned and fits a single packet */
if (!(byte_count & 0x3) && byte_count <= max_bytes_per_packet)
return max_bytes_per_packet;
/*
* Align down maximum byte count to 256 bytes so that
* the copy optimally uses all memory channels and
* also to ensure that SDMA can use its dword mode, which
* is faster.
*
* This assumes that the starting addresses of BOs are always
* dword aligned, which should be the case for every copy
* operation in the kernel, because the kernel always copies
* pages.
*/
return ALIGN_DOWN(max_bytes_per_packet, SZ_256);
}
int amdgpu_copy_buffer(struct amdgpu_device *adev,
struct amdgpu_ttm_buffer_entity *entity,
uint64_t src_offset,
@@ -2483,7 +2533,8 @@ int amdgpu_copy_buffer(struct amdgpu_device *adev,
return -EINVAL;
}
max_bytes = adev->mman.buffer_funcs->copy_max_bytes;
max_bytes = amdgpu_calc_bytes_per_packet(adev->mman.buffer_funcs->copy_max_bytes,
byte_count);
num_loops = DIV_ROUND_UP(byte_count, max_bytes);
num_dw = ALIGN(num_loops * adev->mman.buffer_funcs->copy_num_dw, 8);
r = amdgpu_ttm_prepare_job(adev, entity, num_dw,
@@ -2527,7 +2578,8 @@ static int amdgpu_ttm_fill_mem(struct amdgpu_device *adev,
unsigned int i;
int r;
max_bytes = adev->mman.buffer_funcs->fill_max_bytes;
max_bytes = amdgpu_calc_bytes_per_packet(adev->mman.buffer_funcs->fill_max_bytes,
byte_count);
num_loops = DIV_ROUND_UP_ULL(byte_count, max_bytes);
num_dw = ALIGN(num_loops * adev->mman.buffer_funcs->fill_num_dw, 8);
r = amdgpu_ttm_prepare_job(adev, entity, num_dw, resv,

View File

@@ -123,6 +123,8 @@ static void amdgpu_userq_hang_detect_work(struct work_struct *work)
struct amdgpu_device *adev = uq_mgr->adev;
const struct amdgpu_userq_funcs *userq_funcs =
adev->userq_funcs[queue->queue_type];
struct drm_wedge_task_info *info = NULL;
struct amdgpu_task_info *ti = NULL;
bool gpu_reset = false;
if (unlikely(adev->debug_disable_gpu_ring_reset)) {
@@ -137,6 +139,14 @@ static void amdgpu_userq_hang_detect_work(struct work_struct *work)
if (!amdgpu_gpu_recovery)
return;
if (queue->vm && queue->vm->pasid) {
ti = amdgpu_vm_get_task_info_pasid(adev, queue->vm->pasid);
if (ti) {
amdgpu_vm_print_task_info(adev, ti);
info = &ti->task;
}
}
if (amdgpu_userq_is_reset_type_supported(adev, queue->queue_type,
AMDGPU_RESET_TYPE_PER_QUEUE)) {
int r;
@@ -146,11 +156,17 @@ static void amdgpu_userq_hang_detect_work(struct work_struct *work)
queue, NULL, NULL);
else
r = userq_funcs->reset(queue);
if (r)
if (r) {
gpu_reset = true;
} else {
atomic_inc(&adev->gpu_reset_counter);
amdgpu_userq_fence_driver_force_completion(queue);
drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE, info);
}
} else {
gpu_reset = true;
}
amdgpu_vm_put_task_info(ti);
/*
* Don't schedule the work here! Scheduling or queue work from one reset
@@ -985,6 +1001,7 @@ amdgpu_userq_vm_validate_and_restore_queue(struct amdgpu_userq_mgr *uq_mgr)
struct amdgpu_vm *vm = &fpriv->vm;
unsigned long key, tmp_key;
struct amdgpu_bo_va *bo_va;
struct amdgpu_usermode_queue *queue;
struct amdgpu_bo *bo;
struct drm_exec exec;
struct xarray xa;
@@ -1100,6 +1117,24 @@ amdgpu_userq_vm_validate_and_restore_queue(struct amdgpu_userq_mgr *uq_mgr)
dma_fence_wait(bo_va->last_pt_update, false);
dma_fence_wait(vm->last_update, false);
xa_for_each(&uq_mgr->userq_xa, tmp_key, queue) {
bo = queue->wptr_obj.obj;
if (!bo) {
ret = -EINVAL;
goto unlock_all;
}
ret = amdgpu_ttm_alloc_gart(&bo->tbo);
if (unlikely(ret)) {
drm_file_err(uq_mgr->file,
"failed to bind wptr bo to gart on resume, qid=%lu ret=%d\n",
tmp_key, ret);
goto unlock_all;
}
queue->wptr_obj.gpu_addr = amdgpu_bo_gpu_offset(bo);
}
ret = amdgpu_evf_mgr_rearm(&fpriv->evf_mgr, &exec);
if (ret) {
drm_file_err(uq_mgr->file, "Failed to replace eviction fence\n");

View File

@@ -1165,8 +1165,9 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
r = amdgpu_job_alloc_with_ib(ring->adev, &adev->uvd.entity,
AMDGPU_FENCE_OWNER_UNDEFINED,
64, direct ? AMDGPU_IB_POOL_DIRECT :
AMDGPU_IB_POOL_DELAYED, &job,
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST);
AMDGPU_IB_POOL_DELAYED,
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST,
&job);
if (r)
return r;

View File

@@ -473,7 +473,8 @@ static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
r = amdgpu_job_alloc_with_ib(ring->adev, &ring->adev->vce.entity,
AMDGPU_FENCE_OWNER_UNDEFINED,
ib_size_dw * 4, AMDGPU_IB_POOL_DIRECT,
&job, AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST);
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST,
&job);
if (r)
return r;
@@ -564,8 +565,9 @@ static int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
AMDGPU_FENCE_OWNER_UNDEFINED,
ib_size_dw * 4,
direct ? AMDGPU_IB_POOL_DIRECT :
AMDGPU_IB_POOL_DELAYED, &job,
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST);
AMDGPU_IB_POOL_DELAYED,
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST,
&job);
if (r)
return r;

View File

@@ -629,7 +629,8 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
64, AMDGPU_IB_POOL_DIRECT,
&job, AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST);
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST,
&job);
if (r)
goto err;
@@ -809,7 +810,8 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
ib_size_dw * 4, AMDGPU_IB_POOL_DIRECT,
&job, AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST);
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST,
&job);
if (r)
goto err;
@@ -939,7 +941,8 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
ib_size_dw * 4, AMDGPU_IB_POOL_DIRECT,
&job, AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST);
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST,
&job);
if (r)
return r;
@@ -1006,7 +1009,8 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
ib_size_dw * 4, AMDGPU_IB_POOL_DIRECT,
&job, AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST);
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST,
&job);
if (r)
return r;

View File

@@ -2090,3 +2090,39 @@ int amdgpu_virt_send_remote_ras_cmd(struct amdgpu_device *adev,
return ret;
}
int amdgpu_virt_ptl_request(struct amdgpu_device *adev, u32 req_code,
uint32_t *ptl_state, uint32_t *fmt1, uint32_t *fmt2)
{
int ret;
if (!ptl_state || !fmt1 || !fmt2)
return -EINVAL;
if (!amdgpu_sriov_ptl_support(adev) ||
!adev->virt.ops || !adev->virt.ops->req_ptl_update)
return -EOPNOTSUPP;
if (req_code == PSP_PTL_PERF_MON_SET && *ptl_state) {
if (*fmt1 == *fmt2) {
dev_warn(adev->dev,
"PTL formats must be different (fmt1=%u, fmt2=%u)\n",
*fmt1, *fmt2);
return -EINVAL;
}
}
ret = adev->virt.ops->req_ptl_update(adev, req_code, *ptl_state, *fmt1, *fmt2);
if (ret) {
dev_warn(adev->dev, "VF PTL update request failed: %d\n", ret);
return ret;
}
if (req_code == PSP_PTL_PERF_MON_QUERY) {
*ptl_state = adev->virt.ptl_state;
*fmt1 = adev->virt.ptl_pref_format1;
*fmt2 = adev->virt.ptl_pref_format2;
}
return 0;
}

View File

@@ -116,6 +116,8 @@ struct amdgpu_virt_ops {
int (*req_ras_chk_criti)(struct amdgpu_device *adev, u64 addr);
int (*req_remote_ras_cmd)(struct amdgpu_device *adev,
u32 param1, u32 param2, u32 param3);
int (*req_ptl_update)(struct amdgpu_device *adev,
u32 req_code, u32 ptl_state, u32 fmt1, u32 fmt2);
};
/*
@@ -341,6 +343,11 @@ struct amdgpu_virt {
/* Spinlock to protect access to the RLCG register interface */
spinlock_t rlcg_reg_lock;
/* PTL (Performance Throttle Limiter) response from host */
uint32_t ptl_state;
uint32_t ptl_pref_format1;
uint32_t ptl_pref_format2;
struct mutex access_req_mutex;
union amd_sriov_ras_caps ras_en_caps;
@@ -447,6 +454,8 @@ static inline bool is_virtual_machine(void)
((adev)->virt.gim_feature & AMDGIM_FEATURE_MES_INFO_ENABLE)
#define amdgpu_sriov_is_unitid_support(adev) \
((adev)->virt.gim_feature & AMDGIM_FEATURE_UNITID_SUPPORT)
#define amdgpu_sriov_ptl_support(adev) \
((adev)->virt.gim_feature & AMDGIM_FEATURE_PTL_SUPPORT)
#define amdgpu_virt_xgmi_migrate_enabled(adev) \
((adev)->virt.is_xgmi_node_migrate_enabled && (adev)->gmc.xgmi.node_segment_size != 0)
@@ -457,6 +466,8 @@ int amdgpu_virt_request_full_gpu(struct amdgpu_device *adev, bool init);
int amdgpu_virt_release_full_gpu(struct amdgpu_device *adev, bool init);
int amdgpu_virt_reset_gpu(struct amdgpu_device *adev);
void amdgpu_virt_request_init_data(struct amdgpu_device *adev);
int amdgpu_virt_ptl_request(struct amdgpu_device *adev, u32 req_code,
uint32_t *ptl_state, uint32_t *fmt1, uint32_t *fmt2);
void amdgpu_virt_ready_to_reset(struct amdgpu_device *adev);
int amdgpu_virt_wait_reset(struct amdgpu_device *adev);
int amdgpu_virt_alloc_mm_table(struct amdgpu_device *adev);

View File

@@ -1553,6 +1553,8 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
struct amdgpu_sync sync;
int r;
if (list_empty(&vm->freed))
return 0;
/*
* Implicitly sync to command submissions in the same VM before
@@ -2504,14 +2506,16 @@ amdgpu_vm_get_task_info_vm(struct amdgpu_vm *vm)
struct amdgpu_task_info *
amdgpu_vm_get_task_info_pasid(struct amdgpu_device *adev, u32 pasid)
{
struct amdgpu_fpriv *fpriv;
struct amdgpu_task_info *ti;
struct amdgpu_vm *vm;
unsigned long flags;
xa_lock_irqsave(&adev->vm_manager.pasids, flags);
vm = xa_load(&adev->vm_manager.pasids, pasid);
amdgpu_pasid_lock(&flags);
fpriv = amdgpu_pasid_get_fpriv_locked(pasid);
vm = fpriv ? &fpriv->vm : NULL;
ti = amdgpu_vm_get_task_info_vm(vm);
xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
amdgpu_pasid_unlock(flags);
return ti;
}
@@ -2552,7 +2556,6 @@ void amdgpu_vm_set_task_info(struct amdgpu_vm *vm)
* @adev: amdgpu_device pointer
* @vm: requested vm
* @xcp_id: GPU partition selection id
* @pasid: the pasid the VM is using on this GPU
*
* Init @vm fields.
*
@@ -2560,7 +2563,7 @@ void amdgpu_vm_set_task_info(struct amdgpu_vm *vm)
* 0 for success, error for failure.
*/
int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
int32_t xcp_id, uint32_t pasid)
int32_t xcp_id)
{
struct amdgpu_bo *root_bo;
struct amdgpu_bo_vm *root;
@@ -2635,26 +2638,12 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
if (r)
dev_dbg(adev->dev, "Failed to create task info for VM\n");
/* Store new PASID in XArray (if non-zero) */
if (pasid != 0) {
r = xa_err(xa_store_irq(&adev->vm_manager.pasids, pasid, vm, GFP_KERNEL));
if (r < 0)
goto error_free_root;
vm->pasid = pasid;
}
amdgpu_bo_unreserve(vm->root.bo);
amdgpu_bo_unref(&root_bo);
return 0;
error_free_root:
/* If PASID was partially set, erase it from XArray before failing */
if (vm->pasid != 0) {
xa_erase_irq(&adev->vm_manager.pasids, vm->pasid);
vm->pasid = 0;
}
amdgpu_vm_pt_free_root(adev, vm);
amdgpu_bo_unreserve(vm->root.bo);
amdgpu_bo_unref(&root_bo);
@@ -2761,11 +2750,6 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
root = amdgpu_bo_ref(vm->root.bo);
amdgpu_bo_reserve(root, true);
/* Remove PASID mapping before destroying VM */
if (vm->pasid != 0) {
xa_erase_irq(&adev->vm_manager.pasids, vm->pasid);
vm->pasid = 0;
}
dma_fence_wait(vm->last_unlocked, false);
dma_fence_put(vm->last_unlocked);
dma_fence_wait(vm->last_tlb_flush, false);
@@ -2861,8 +2845,6 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)
#else
adev->vm_manager.vm_update_mode = 0;
#endif
xa_init_flags(&adev->vm_manager.pasids, XA_FLAGS_LOCK_IRQ);
}
/**
@@ -2874,9 +2856,6 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)
*/
void amdgpu_vm_manager_fini(struct amdgpu_device *adev)
{
WARN_ON(!xa_empty(&adev->vm_manager.pasids));
xa_destroy(&adev->vm_manager.pasids);
amdgpu_vmid_mgr_fini(adev);
amdgpu_pasid_mgr_cleanup();
}
@@ -2933,14 +2912,16 @@ struct amdgpu_vm *amdgpu_vm_lock_by_pasid(struct amdgpu_device *adev,
u32 pasid, struct drm_exec *exec)
{
unsigned long irqflags;
struct amdgpu_fpriv *fpriv;
struct amdgpu_bo *root;
struct amdgpu_vm *vm;
int r;
xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
vm = xa_load(&adev->vm_manager.pasids, pasid);
root = vm ? amdgpu_bo_ref(vm->root.bo) : NULL;
xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
amdgpu_pasid_lock(&irqflags);
fpriv = amdgpu_pasid_get_fpriv_locked(pasid);
vm = fpriv ? &fpriv->vm : NULL;
root = vm && vm->root.bo ? amdgpu_bo_ref(vm->root.bo) : NULL;
amdgpu_pasid_unlock(irqflags);
if (!root)
return NULL;
@@ -2952,11 +2933,17 @@ struct amdgpu_vm *amdgpu_vm_lock_by_pasid(struct amdgpu_device *adev,
}
/* Double check that the VM still exists */
xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
vm = xa_load(&adev->vm_manager.pasids, pasid);
if (vm && vm->root.bo != root)
amdgpu_pasid_lock(&irqflags);
fpriv = amdgpu_pasid_get_fpriv_locked(pasid);
if (!fpriv) {
vm = NULL;
xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
} else {
vm = &fpriv->vm;
if (vm->root.bo != root)
vm = NULL;
}
amdgpu_pasid_unlock(irqflags);
if (!vm) {
drm_exec_unlock_obj(exec, &root->tbo.base);
amdgpu_bo_unref(&root);
@@ -3153,12 +3140,14 @@ void amdgpu_vm_update_fault_cache(struct amdgpu_device *adev,
uint32_t status,
unsigned int vmhub)
{
struct amdgpu_fpriv *fpriv;
struct amdgpu_vm *vm;
unsigned long flags;
xa_lock_irqsave(&adev->vm_manager.pasids, flags);
amdgpu_pasid_lock(&flags);
vm = xa_load(&adev->vm_manager.pasids, pasid);
fpriv = amdgpu_pasid_get_fpriv_locked(pasid);
vm = fpriv ? &fpriv->vm : NULL;
/* Don't update the fault cache if status is 0. In the multiple
* fault case, subsequent faults will return a 0 status which is
* useless for userspace and replaces the useful fault status, so
@@ -3191,7 +3180,7 @@ void amdgpu_vm_update_fault_cache(struct amdgpu_device *adev,
WARN_ONCE(1, "Invalid vmhub %u\n", vmhub);
}
}
xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
amdgpu_pasid_unlock(flags);
}
void amdgpu_vm_print_task_info(struct amdgpu_device *adev,

View File

@@ -481,10 +481,6 @@ struct amdgpu_vm_manager {
*/
int vm_update_mode;
/* PASID to VM mapping, will be used in interrupt context to
* look up VM of a page fault
*/
struct xarray pasids;
/* Global registration of recent page fault information */
struct amdgpu_vm_fault_info fault_info;
};
@@ -502,7 +498,7 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev);
void amdgpu_vm_manager_fini(struct amdgpu_device *adev);
long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout);
int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t xcp_id, uint32_t pasid);
int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t xcp_id);
int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm);
void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
int amdgpu_vm_lock_pd(struct amdgpu_vm *vm, struct drm_exec *exec,

View File

@@ -56,7 +56,7 @@ static int amdgpu_vm_sdma_alloc_job(struct amdgpu_vm_update_params *p,
ndw = min(ndw, AMDGPU_VM_SDMA_MAX_NUM_DW);
r = amdgpu_job_alloc_with_ib(p->adev, entity, AMDGPU_FENCE_OWNER_VM,
ndw * 4, pool, &p->job, k_job_id);
ndw * 4, pool, k_job_id, &p->job);
if (r)
return r;

View File

@@ -559,7 +559,7 @@ static int amdgpu_xgmi_sysfs_add_dev_info(struct amdgpu_device *adev,
pr_err("failed to create xgmi_num_links\n");
/* Create xgmi port num file if supported */
if (adev->psp.xgmi_context.xgmi_ta_caps & EXTEND_PEER_LINK_INFO_CMD_FLAG) {
if (adev->psp.xgmi_context.supports_ext_link_info) {
ret = device_create_file(adev->dev, &dev_attr_xgmi_port_num);
if (ret)
dev_err(adev->dev, "failed to create xgmi_port_num\n");
@@ -595,7 +595,7 @@ static int amdgpu_xgmi_sysfs_add_dev_info(struct amdgpu_device *adev,
device_remove_file(adev->dev, &dev_attr_xgmi_error);
device_remove_file(adev->dev, &dev_attr_xgmi_num_hops);
device_remove_file(adev->dev, &dev_attr_xgmi_num_links);
if (adev->psp.xgmi_context.xgmi_ta_caps & EXTEND_PEER_LINK_INFO_CMD_FLAG)
if (adev->psp.xgmi_context.supports_ext_link_info)
device_remove_file(adev->dev, &dev_attr_xgmi_port_num);
success:
@@ -613,7 +613,7 @@ static void amdgpu_xgmi_sysfs_rem_dev_info(struct amdgpu_device *adev,
device_remove_file(adev->dev, &dev_attr_xgmi_error);
device_remove_file(adev->dev, &dev_attr_xgmi_num_hops);
device_remove_file(adev->dev, &dev_attr_xgmi_num_links);
if (adev->psp.xgmi_context.xgmi_ta_caps & EXTEND_PEER_LINK_INFO_CMD_FLAG)
if (adev->psp.xgmi_context.supports_ext_link_info)
device_remove_file(adev->dev, &dev_attr_xgmi_port_num);
if (hive->kobj.parent != (&adev->dev->kobj))

View File

@@ -379,7 +379,7 @@ struct amd_sriov_msg_vf2pf_info {
struct {
uint8_t id;
uint32_t version;
} ucode_info[AMD_SRIOV_MSG_RESERVE_UCODE];
} __packed ucode_info[AMD_SRIOV_MSG_RESERVE_UCODE];
uint64_t dummy_page_addr;
/* FB allocated for guest MES to record UQ info */
uint64_t mes_info_addr;
@@ -404,6 +404,9 @@ enum amd_sriov_mailbox_request_message {
MB_REQ_RAS_ERROR_COUNT = 203,
MB_REQ_RAS_CPER_DUMP = 204,
MB_REQ_RAS_BAD_PAGES = 205,
MB_REQ_RAS_CHK_CRITI = 206,
MB_REQ_RAS_REMOTE_CMD = 207,
MB_REQ_MSG_PTL_UPDATE = 208,
};
/* mailbox message send from host to guest */
@@ -424,9 +427,33 @@ enum amd_sriov_mailbox_response_message {
MB_RES_MSG_RAS_BAD_PAGES_READY = 15,
MB_RES_MSG_RAS_BAD_PAGES_NOTIFICATION = 16,
MB_RES_MSG_UNRECOV_ERR_NOTIFICATION = 17,
MB_RES_RAS_CHK_CRITI_READY = 18,
MB_RES_RAS_REMOTE_CMD_READY = 19,
MB_RES_MSG_PTL_UPDATE_READY = 20,
MB_RES_MSG_TEXT_MESSAGE = 255
};
/*
* Generic response status codes for mailbox data fields.
* Used in msg_data[1..N] to indicate operation result.
*/
enum amd_sriov_response_status {
AMD_SRIOV_RESP_SUCCESS = 0,
AMD_SRIOV_RESP_FAIL = 1,
AMD_SRIOV_RESP_UNSUPPORTED = 2,
};
/*
* PTL mailbox data format:
* Request: msg_data[1]=req_code, msg_data[2]=ptl_state, msg_data[3]=(fmt1<<16)|fmt2
* Response: msg_data[1]=(status<<16)|ptl_state, msg_data[2]=(fmt1<<16)|fmt2
*/
#define AMD_SRIOV_PTL_PACK_FORMATS(fmt1, fmt2) ((((fmt1) & 0xFFFF) << 16) | ((fmt2) & 0xFFFF))
#define AMD_SRIOV_PTL_UNPACK_STATUS(dw) (((dw) >> 16) & 0xFFFF)
#define AMD_SRIOV_PTL_UNPACK_STATE(dw) ((dw) & 0xFFFF)
#define AMD_SRIOV_PTL_UNPACK_FMT1(dw) (((dw) >> 16) & 0xFFFF)
#define AMD_SRIOV_PTL_UNPACK_FMT2(dw) ((dw) & 0xFFFF)
enum amd_sriov_ras_telemetry_gpu_block {
RAS_TELEMETRY_GPU_BLOCK_UMC = 0,
RAS_TELEMETRY_GPU_BLOCK_SDMA = 1,

View File

@@ -4580,7 +4580,7 @@ static const struct amdgpu_gfx_funcs gfx_v10_0_gfx_funcs = {
static void gfx_v10_0_gpu_early_init(struct amdgpu_device *adev)
{
u32 gb_addr_config;
u32 gb_addr_config = 0;
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 1, 10):
@@ -4620,8 +4620,9 @@ static void gfx_v10_0_gpu_early_init(struct amdgpu_device *adev)
gb_addr_config = CYAN_SKILLFISH_GB_ADDR_CONFIG_GOLDEN;
break;
default:
BUG();
break;
dev_warn(adev->dev, "Unsupported GC version 0x%08x\n",
amdgpu_ip_version(adev, GC_HWIP, 0));
return;
}
adev->gfx.config.gb_addr_config = gb_addr_config;
@@ -8602,13 +8603,16 @@ static u64 gfx_v10_0_ring_get_rptr_compute(struct amdgpu_ring *ring)
static u64 gfx_v10_0_ring_get_wptr_compute(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
u64 wptr;
/* XXX check if swapping is necessary on BE */
if (ring->use_doorbell)
if (ring->use_doorbell) {
wptr = atomic64_read((atomic64_t *)ring->wptr_cpu_addr);
else
BUG();
} else {
dev_warn_once(adev->dev, "%s requires doorbell!\n", __func__);
wptr = 0;
}
return wptr;
}
@@ -8621,7 +8625,7 @@ static void gfx_v10_0_ring_set_wptr_compute(struct amdgpu_ring *ring)
ring->wptr);
WDOORBELL64(ring->doorbell_index, ring->wptr);
} else {
BUG(); /* only DOORBELL method supported on gfx10 now */
dev_warn_once(adev->dev, "%s requires doorbell!\n", __func__);
}
}
@@ -9379,7 +9383,7 @@ static void gfx_v10_0_handle_priv_fault(struct amdgpu_device *adev,
}
break;
default:
BUG();
break;
}
}
@@ -9449,7 +9453,7 @@ static int gfx_v10_0_kiq_set_interrupt_state(struct amdgpu_device *adev,
}
break;
default:
BUG(); /* kiq only support GENERIC2_INT now */
/* kiq only support GENERIC2_INT now */
break;
}
return 0;

View File

@@ -1145,8 +1145,9 @@ static int gfx_v11_0_gpu_early_init(struct amdgpu_device *adev)
adev->gfx.config.sc_earlyz_tile_fifo_size = 0x300;
break;
default:
BUG();
break;
dev_warn(adev->dev, "Unsupported GC version 0x%08x\n",
amdgpu_ip_version(adev, GC_HWIP, 0));
return -EINVAL;
}
return 0;
@@ -5954,13 +5955,16 @@ static u64 gfx_v11_0_ring_get_rptr_compute(struct amdgpu_ring *ring)
static u64 gfx_v11_0_ring_get_wptr_compute(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
u64 wptr;
/* XXX check if swapping is necessary on BE */
if (ring->use_doorbell)
if (ring->use_doorbell) {
wptr = atomic64_read((atomic64_t *)ring->wptr_cpu_addr);
else
BUG();
} else {
dev_warn_once(adev->dev, "%s requires doorbell!\n", __func__);
wptr = 0;
}
return wptr;
}
@@ -5974,7 +5978,7 @@ static void gfx_v11_0_ring_set_wptr_compute(struct amdgpu_ring *ring)
ring->wptr);
WDOORBELL64(ring->doorbell_index, ring->wptr);
} else {
BUG(); /* only DOORBELL method supported on gfx11 now */
dev_warn_once(adev->dev, "%s requires doorbell!\n", __func__);
}
}
@@ -6747,7 +6751,6 @@ static void gfx_v11_0_handle_priv_fault(struct amdgpu_device *adev,
}
break;
default:
BUG();
break;
}
}
@@ -6832,7 +6835,7 @@ static int gfx_v11_0_kiq_set_interrupt_state(struct amdgpu_device *adev,
}
break;
default:
BUG(); /* kiq only support GENERIC2_INT now */
/* kiq only support GENERIC2_INT now */
break;
}
return 0;

View File

@@ -964,8 +964,9 @@ static int gfx_v12_0_gpu_early_init(struct amdgpu_device *adev)
adev->gfx.config.sc_earlyz_tile_fifo_size = 0x4C0;
break;
default:
BUG();
break;
dev_warn(adev->dev, "Unsupported GC version 0x%08x\n",
amdgpu_ip_version(adev, GC_HWIP, 0));
return -EINVAL;
}
return 0;
@@ -4464,13 +4465,16 @@ static u64 gfx_v12_0_ring_get_rptr_compute(struct amdgpu_ring *ring)
static u64 gfx_v12_0_ring_get_wptr_compute(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
u64 wptr;
/* XXX check if swapping is necessary on BE */
if (ring->use_doorbell)
if (ring->use_doorbell) {
wptr = atomic64_read((atomic64_t *)ring->wptr_cpu_addr);
else
BUG();
} else {
dev_warn_once(adev->dev, "%s requires doorbell!\n", __func__);
wptr = 0;
}
return wptr;
}
@@ -4484,7 +4488,7 @@ static void gfx_v12_0_ring_set_wptr_compute(struct amdgpu_ring *ring)
ring->wptr);
WDOORBELL64(ring->doorbell_index, ring->wptr);
} else {
BUG(); /* only DOORBELL method supported on gfx12 now */
dev_warn_once(adev->dev, "%s requires doorbell!\n", __func__);
}
}
@@ -5079,7 +5083,6 @@ static void gfx_v12_0_handle_priv_fault(struct amdgpu_device *adev,
}
break;
default:
BUG();
break;
}
}

View File

@@ -891,8 +891,9 @@ static int gfx_v12_1_gpu_early_init(struct amdgpu_device *adev)
adev->gfx.config.sc_earlyz_tile_fifo_size = 0x4C0;
break;
default:
BUG();
break;
dev_warn(adev->dev, "Unsupported GC version 0x%08x\n",
amdgpu_ip_version(adev, GC_HWIP, 0));
return -EINVAL;
}
return 0;
@@ -3673,13 +3674,16 @@ static u64 gfx_v12_1_ring_get_rptr_compute(struct amdgpu_ring *ring)
static u64 gfx_v12_1_ring_get_wptr_compute(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
u64 wptr;
/* XXX check if swapping is necessary on BE */
if (ring->use_doorbell)
if (ring->use_doorbell) {
wptr = atomic64_read((atomic64_t *)ring->wptr_cpu_addr);
else
BUG();
} else {
dev_warn_once(adev->dev, "%s requires doorbell!\n", __func__);
wptr = 0;
}
return wptr;
}
@@ -3693,7 +3697,7 @@ static void gfx_v12_1_ring_set_wptr_compute(struct amdgpu_ring *ring)
ring->wptr);
WDOORBELL64(ring->doorbell_index, ring->wptr);
} else {
BUG(); /* only DOORBELL method supported on gfx12 now */
dev_warn_once(adev->dev, "%s requires doorbell!\n", __func__);
}
}

View File

@@ -347,7 +347,8 @@ static int gfx_v6_0_init_microcode(struct amdgpu_device *adev)
case CHIP_HAINAN:
chip_name = "hainan";
break;
default: BUG();
default:
return -EINVAL;
}
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
@@ -1736,8 +1737,8 @@ static void gfx_v6_0_constants_init(struct amdgpu_device *adev)
gb_addr_config = HAINAN_GB_ADDR_CONFIG_GOLDEN;
break;
default:
BUG();
break;
dev_warn(adev->dev, "Unsupported asic_type 0x%08x\n", adev->asic_type);
return;
}
WREG32(mmGRBM_CNTL, (0xff << GRBM_CNTL__READ_TIMEOUT__SHIFT));
@@ -2202,7 +2203,7 @@ static u64 gfx_v6_0_ring_get_wptr(struct amdgpu_ring *ring)
else if (ring == &adev->gfx.compute_ring[1])
return RREG32(mmCP_RB2_WPTR);
else
BUG();
return 0;
}
static void gfx_v6_0_ring_set_wptr_gfx(struct amdgpu_ring *ring)
@@ -2223,8 +2224,6 @@ static void gfx_v6_0_ring_set_wptr_compute(struct amdgpu_ring *ring)
} else if (ring == &adev->gfx.compute_ring[1]) {
WREG32(mmCP_RB2_WPTR, lower_32_bits(ring->wptr));
(void)RREG32(mmCP_RB2_WPTR);
} else {
BUG();
}
}
@@ -3310,7 +3309,6 @@ static void gfx_v6_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev,
}
default:
BUG();
break;
}

View File

@@ -933,7 +933,8 @@ static int gfx_v7_0_init_microcode(struct amdgpu_device *adev)
chip_name = "mullins";
break;
default:
BUG();
dev_warn(adev->dev, "Unsupported asic_type 0x%08x\n", adev->asic_type);
return -EINVAL;
}
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,

View File

@@ -977,7 +977,8 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
chip_name = "vegam";
break;
default:
BUG();
dev_warn(adev->dev, "Unsupported asic_type 0x%08x\n", adev->asic_type);
return -EINVAL;
}
if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) {

View File

@@ -2107,8 +2107,9 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
return err;
break;
default:
BUG();
break;
dev_warn(adev->dev, "Unsupported GC version 0x%08x\n",
amdgpu_ip_version(adev, GC_HWIP, 0));
return -EINVAL;
}
adev->gfx.config.gb_addr_config = gb_addr_config;
@@ -5681,13 +5682,16 @@ static u64 gfx_v9_0_ring_get_rptr_compute(struct amdgpu_ring *ring)
static u64 gfx_v9_0_ring_get_wptr_compute(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
u64 wptr;
/* XXX check if swapping is necessary on BE */
if (ring->use_doorbell)
if (ring->use_doorbell) {
wptr = atomic64_read((atomic64_t *)ring->wptr_cpu_addr);
else
BUG();
} else {
dev_warn_once(adev->dev, "%s requires doorbell!\n", __func__);
wptr = 0;
}
return wptr;
}
@@ -5699,8 +5703,8 @@ static void gfx_v9_0_ring_set_wptr_compute(struct amdgpu_ring *ring)
if (ring->use_doorbell) {
atomic64_set((atomic64_t *)ring->wptr_cpu_addr, ring->wptr);
WDOORBELL64(ring->doorbell_index, ring->wptr);
} else{
BUG(); /* only DOORBELL method supported on gfx9 now */
} else {
dev_warn_once(adev->dev, "%s requires doorbell!\n", __func__);
}
}

View File

@@ -2331,7 +2331,7 @@ static int gfx_v9_4_3_set_userq_eop_interrupts(struct amdgpu_device *adev,
}
}
for (xcc_id--; xcc_id >= 0; xcc_id--) {
for (m = adev->gfx.mec.num_mec - 1; m <= 0; m--) {
for (m = adev->gfx.mec.num_mec - 1; m >= 0; m--) {
for (p = adev->gfx.mec.num_pipe_per_mec - 1; p >= 0; p--) {
irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP
+ (m * adev->gfx.mec.num_pipe_per_mec) + p;
@@ -2400,7 +2400,10 @@ static int gfx_v9_4_3_perf_monitor_ptl_init(struct amdgpu_device *adev, bool ena
if (!adev->psp.funcs)
return -EOPNOTSUPP;
if (!ptl->hw_supported) {
if (ptl->hw_supported_state == AMDGPU_PTL_HW_NOT_SUPPORTED)
return -EOPNOTSUPP;
if (ptl->hw_supported_state == AMDGPU_PTL_HW_UNINIT) {
fmt1 = GFX_FTYPE_VECTOR;
fmt2 = GFX_FTYPE_F8;
} else {
@@ -2411,10 +2414,17 @@ static int gfx_v9_4_3_perf_monitor_ptl_init(struct amdgpu_device *adev, bool ena
/* initialize PTL with default formats: GFX_FTYPE_VECTOR & GFX_FTYPE_F8 */
r = amdgpu_ptl_perf_monitor_ctrl(adev, PSP_PTL_PERF_MON_SET, &ptl_state,
&fmt1, &fmt2);
if (r)
return r;
if (r) {
if (ptl->hw_supported_state == AMDGPU_PTL_HW_UNINIT)
ptl->hw_supported_state = AMDGPU_PTL_HW_NOT_SUPPORTED;
ptl->hw_supported = true;
if (r != -EOPNOTSUPP)
dev_err(adev->dev, "PTL initialization failed (%d)\n", r);
return r;
}
ptl->hw_supported_state = AMDGPU_PTL_HW_SUPPORTED;
atomic_set(&ptl->disable_ref, 0);
if (!enable && !amdgpu_in_reset(adev) && !adev->in_suspend) {
@@ -2459,7 +2469,8 @@ static int gfx_v9_4_3_hw_fini(struct amdgpu_ip_block *ip_block)
struct amdgpu_device *adev = ip_block->adev;
int i, num_xcc;
if (adev->psp.ptl.hw_supported && !amdgpu_in_reset(adev))
if (adev->psp.ptl.hw_supported_state == AMDGPU_PTL_HW_SUPPORTED &&
!amdgpu_in_reset(adev))
gfx_v9_4_3_perf_monitor_ptl_init(adev, false);
amdgpu_irq_put(adev, &adev->gfx.bad_op_irq, 0);
@@ -3029,13 +3040,17 @@ static u64 gfx_v9_4_3_ring_get_rptr_compute(struct amdgpu_ring *ring)
static u64 gfx_v9_4_3_ring_get_wptr_compute(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
u64 wptr;
/* XXX check if swapping is necessary on BE */
if (ring->use_doorbell)
if (ring->use_doorbell) {
wptr = atomic64_read((atomic64_t *)&ring->adev->wb.wb[ring->wptr_offs]);
else
BUG();
} else {
dev_warn_once(adev->dev,
"%s requires doorbell!\n", __func__);
wptr = 0;
}
return wptr;
}
@@ -3048,7 +3063,8 @@ static void gfx_v9_4_3_ring_set_wptr_compute(struct amdgpu_ring *ring)
atomic64_set((atomic64_t *)&adev->wb.wb[ring->wptr_offs], ring->wptr);
WDOORBELL64(ring->doorbell_index, ring->wptr);
} else {
BUG(); /* only DOORBELL method supported on gfx9 now */
dev_warn_once(adev->dev,
"%s requires doorbell!\n", __func__);
}
}

View File

@@ -377,8 +377,9 @@ static void imu_v11_0_program_rlc_ram(struct amdgpu_device *adev)
imu_v11_0_3_program_rlc_ram(adev);
break;
default:
BUG();
break;
WARN(1, "Invalid GFX/IMU IP version 0x%08x\n",
amdgpu_ip_version(adev, GC_HWIP, 0));
return;
}
//Indicate the contents of the RAM are valid

View File

@@ -382,8 +382,9 @@ static void imu_v12_0_program_rlc_ram(struct amdgpu_device *adev)
(const u32)ARRAY_SIZE(imu_rlc_ram_golden_12_0_1));
break;
default:
BUG();
break;
WARN(1, "Invalid GFX/IMU IP version 0x%08x\n",
amdgpu_ip_version(adev, GC_HWIP, 0));
return;
}
//Indicate the latest entry

View File

@@ -399,6 +399,25 @@ static void jpeg_v5_3_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data);
}
/**
* jpeg_v5_3_0_set_mmhub_eco_sec_level - set jpeg sec lvl reg
*
* @adev: amdgpu_device pointer
*
* request psp to set secure lvl
*/
static int jpeg_v5_3_0_set_mmhub_eco_sec_level(struct amdgpu_device *adev)
{
int r = 0;
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
/* Request to PSP to program JPEG secure lvl */
r = psp_set_mmhub_eco_sec_level(adev);
}
return r;
}
/**
* jpeg_v5_3_0_start - start JPEG block
*
@@ -424,6 +443,11 @@ static int jpeg_v5_3_0_start(struct amdgpu_device *adev)
if (r)
return r;
/* program JPEG secure lvl register */
r = jpeg_v5_3_0_set_mmhub_eco_sec_level(adev);
if (r)
return r;
/* JPEG disable CGC */
jpeg_v5_3_0_disable_clock_gating(adev);

View File

@@ -70,27 +70,23 @@ mes_userq_create_wptr_mapping(struct amdgpu_device *adev,
ret = -EINVAL;
goto fail_map;
}
/* TODO use eviction fence instead of pinning. */
ret = amdgpu_bo_pin(wptr_obj->obj, AMDGPU_GEM_DOMAIN_GTT);
/* Keep WPTR BO under eviction-fence control instead of pinning. */
ret = amdgpu_evf_mgr_attach_fence(&uq_mgr_to_fpriv(uq_mgr)->evf_mgr, wptr_obj->obj);
if (ret) {
DRM_ERROR("Failed to pin wptr bo. ret %d\n", ret);
DRM_ERROR("Failed to attach eviction fence to wptr bo. ret %d\n", ret);
goto fail_map;
}
ret = amdgpu_ttm_alloc_gart(&wptr_obj->obj->tbo);
if (ret) {
DRM_ERROR("Failed to bind bo to GART. ret %d\n", ret);
goto fail_alloc_gart;
DRM_ERROR("Failed to bind wptr bo to GART. ret %d\n", ret);
goto fail_map;
}
queue->wptr_obj.gpu_addr = amdgpu_bo_gpu_offset(wptr_obj->obj);
drm_exec_fini(&exec);
return 0;
fail_alloc_gart:
amdgpu_bo_unpin(wptr_obj->obj);
fail_map:
amdgpu_bo_unref(&wptr_obj->obj);
fail_lock:
@@ -239,9 +235,7 @@ int mes_userq_reset_queue(struct amdgpu_device *adev,
r = mes_userq_unmap(uq);
if (r)
return r;
atomic_inc(&adev->gpu_reset_counter);
amdgpu_userq_fence_driver_force_completion(uq);
drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE, NULL);
break;
}
}
@@ -513,9 +507,6 @@ static void mes_userq_mqd_destroy(struct amdgpu_usermode_queue *queue)
amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
&queue->mqd.cpu_ptr);
amdgpu_bo_reserve(queue->wptr_obj.obj, true);
amdgpu_bo_unpin(queue->wptr_obj.obj);
amdgpu_bo_unreserve(queue->wptr_obj.obj);
amdgpu_bo_unref(&queue->wptr_obj.obj);
}

View File

@@ -86,7 +86,7 @@ static void mes_v11_0_ring_set_wptr(struct amdgpu_ring *ring)
ring->wptr);
WDOORBELL64(ring->doorbell_index, ring->wptr);
} else {
BUG();
dev_warn_once(adev->dev, "%s requires doorbell!\n", __func__);
}
}
@@ -97,12 +97,15 @@ static u64 mes_v11_0_ring_get_rptr(struct amdgpu_ring *ring)
static u64 mes_v11_0_ring_get_wptr(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
u64 wptr;
if (ring->use_doorbell)
if (ring->use_doorbell) {
wptr = atomic64_read((atomic64_t *)ring->wptr_cpu_addr);
else
BUG();
} else {
dev_warn_once(adev->dev, "%s requires doorbell!\n", __func__);
wptr = 0;
}
return wptr;
}
@@ -294,8 +297,8 @@ static int convert_to_mes_queue_type(int queue_type)
else if (queue_type == AMDGPU_RING_TYPE_SDMA)
return MES_QUEUE_TYPE_SDMA;
else
BUG();
return -1;
WARN(1, "Invalid queue type %d\n", queue_type);
return MES_QUEUE_TYPE_GFX;
}
static int convert_to_mes_priority_level(int priority_level)
@@ -1599,12 +1602,14 @@ static int mes_v11_0_queue_init(struct amdgpu_device *adev,
struct amdgpu_ring *ring;
int r;
if (pipe == AMDGPU_MES_KIQ_PIPE)
if (pipe == AMDGPU_MES_KIQ_PIPE) {
ring = &adev->gfx.kiq[0].ring;
else if (pipe == AMDGPU_MES_SCHED_PIPE)
} else if (pipe == AMDGPU_MES_SCHED_PIPE) {
ring = &adev->mes.ring[0];
else
BUG();
} else {
WARN(1, "Invalid MES pipe %d\n", pipe);
return -EINVAL;
}
if ((pipe == AMDGPU_MES_SCHED_PIPE) &&
(amdgpu_in_reset(adev) || adev->in_suspend)) {
@@ -1687,7 +1692,7 @@ static int mes_v11_0_mqd_sw_init(struct amdgpu_device *adev,
else if (pipe == AMDGPU_MES_SCHED_PIPE)
ring = &adev->mes.ring[0];
else
BUG();
return -EINVAL;
if (ring->mqd_obj)
return 0;

View File

@@ -59,7 +59,7 @@ static void mes_v12_0_ring_set_wptr(struct amdgpu_ring *ring)
ring->wptr);
WDOORBELL64(ring->doorbell_index, ring->wptr);
} else {
BUG();
dev_warn_once(adev->dev, "%s requires doorbell!\n", __func__);
}
}
@@ -70,12 +70,15 @@ static u64 mes_v12_0_ring_get_rptr(struct amdgpu_ring *ring)
static u64 mes_v12_0_ring_get_wptr(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
u64 wptr;
if (ring->use_doorbell)
if (ring->use_doorbell) {
wptr = atomic64_read((atomic64_t *)ring->wptr_cpu_addr);
else
BUG();
} else {
dev_warn_once(adev->dev, "%s requires doorbell!\n", __func__);
wptr = 0;
}
return wptr;
}
@@ -279,8 +282,8 @@ static int convert_to_mes_queue_type(int queue_type)
else if (queue_type == AMDGPU_RING_TYPE_MES)
return MES_QUEUE_TYPE_SCHQ;
else
BUG();
return -1;
WARN(1, "Invalid queue type %d\n", queue_type);
return MES_QUEUE_TYPE_GFX;
}
static int convert_to_mes_priority_level(int priority_level)

View File

@@ -61,7 +61,7 @@ static void mes_v12_1_ring_set_wptr(struct amdgpu_ring *ring)
ring->wptr);
WDOORBELL64(ring->doorbell_index, ring->wptr);
} else {
BUG();
dev_warn_once(adev->dev, "%s requires doorbell!\n", __func__);
}
}
@@ -72,12 +72,16 @@ static u64 mes_v12_1_ring_get_rptr(struct amdgpu_ring *ring)
static u64 mes_v12_1_ring_get_wptr(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
u64 wptr;
if (ring->use_doorbell)
if (ring->use_doorbell) {
wptr = atomic64_read((atomic64_t *)ring->wptr_cpu_addr);
else
BUG();
} else {
dev_warn_once(adev->dev, "%s requires doorbell!\n", __func__);
wptr = 0;
}
return wptr;
}
@@ -278,8 +282,8 @@ static int convert_to_mes_queue_type(int queue_type)
else if (queue_type == AMDGPU_RING_TYPE_MES)
return MES_QUEUE_TYPE_SCHQ;
else
BUG();
return -1;
WARN(1, "Invalid queue type %d\n", queue_type);
return MES_QUEUE_TYPE_GFX;
}
static int mes_v12_1_add_hw_queue(struct amdgpu_mes *mes,

View File

@@ -185,8 +185,11 @@ static int xgpu_ai_send_access_requests(struct amdgpu_device *adev,
} else if (req == IDH_REQ_GPU_INIT_DATA){
/* Dummy REQ_GPU_INIT_DATA handling */
r = xgpu_ai_poll_msg(adev, IDH_REQ_GPU_INIT_DATA_READY);
/* version set to 0 since dummy */
adev->virt.req_init_data_ver = 0;
/*
* AI uses the GPU_CRIT_REGION_V1 layout in practice, so fix the
* dummy version value to match the actual init-data format.
*/
adev->virt.req_init_data_ver = GPU_CRIT_REGION_V1;
}
return 0;

View File

@@ -214,6 +214,9 @@ static int xgpu_nv_send_access_requests_with_param(struct amdgpu_device *adev,
case IDH_REQ_RAS_REMOTE_CMD:
event = IDH_REQ_RAS_REMOTE_CMD_READY;
break;
case IDH_REQ_PTL_UPDATE:
event = IDH_PTL_UPDATE_READY;
break;
default:
break;
}
@@ -253,6 +256,23 @@ static int xgpu_nv_send_access_requests_with_param(struct amdgpu_device *adev,
adev->virt.fw_reserve.checksum_key =
RREG32_NO_KIQ(mmMAILBOX_MSGBUF_RCV_DW2);
}
/* Retrieve PTL response from mailbox */
if (req == IDH_REQ_PTL_UPDATE) {
u32 dw1 = RREG32_NO_KIQ(mmMAILBOX_MSGBUF_RCV_DW1);
u32 dw2 = RREG32_NO_KIQ(mmMAILBOX_MSGBUF_RCV_DW2);
u32 status = AMD_SRIOV_PTL_UNPACK_STATUS(dw1);
if (status == AMD_SRIOV_RESP_UNSUPPORTED) {
r = -EOPNOTSUPP;
} else if (status == AMD_SRIOV_RESP_FAIL) {
r = -EIO;
} else {
adev->virt.ptl_state = AMD_SRIOV_PTL_UNPACK_STATE(dw1);
adev->virt.ptl_pref_format1 = AMD_SRIOV_PTL_UNPACK_FMT1(dw2);
adev->virt.ptl_pref_format2 = AMD_SRIOV_PTL_UNPACK_FMT2(dw2);
}
}
}
out:
@@ -597,6 +617,13 @@ static int xgpu_nv_req_remote_ras_cmd(struct amdgpu_device *adev,
adev, IDH_REQ_RAS_REMOTE_CMD, param1, param2, param3);
}
static int xgpu_nv_req_ptl_update(struct amdgpu_device *adev,
u32 req_code, u32 ptl_state, u32 fmt1, u32 fmt2)
{
return xgpu_nv_send_access_requests_with_param(adev, IDH_REQ_PTL_UPDATE,
req_code, ptl_state, AMD_SRIOV_PTL_PACK_FORMATS(fmt1, fmt2));
}
const struct amdgpu_virt_ops xgpu_nv_virt_ops = {
.req_full_gpu = xgpu_nv_request_full_gpu_access,
.rel_full_gpu = xgpu_nv_release_full_gpu_access,
@@ -612,4 +639,5 @@ const struct amdgpu_virt_ops xgpu_nv_virt_ops = {
.req_bad_pages = xgpu_nv_req_ras_bad_pages,
.req_ras_chk_criti = xgpu_nv_check_vf_critical_region,
.req_remote_ras_cmd = xgpu_nv_req_remote_ras_cmd,
.req_ptl_update = xgpu_nv_req_ptl_update,
};

View File

@@ -45,6 +45,7 @@ enum idh_request {
IDH_REQ_RAS_BAD_PAGES = 205,
IDH_REQ_RAS_CHK_CRITI = 206,
IDH_REQ_RAS_REMOTE_CMD = 207,
IDH_REQ_PTL_UPDATE = 208
};
enum idh_event {
@@ -66,6 +67,7 @@ enum idh_event {
IDH_UNRECOV_ERR_NOTIFICATION = 17,
IDH_REQ_RAS_CHK_CRITI_READY = 18,
IDH_REQ_RAS_REMOTE_CMD_READY = 19,
IDH_PTL_UPDATE_READY = 20,
IDH_TEXT_MESSAGE = 255,
};

View File

@@ -30,70 +30,76 @@
#include "ivsrcid/nbio/irqsrcs_nbif_7_4.h"
#include <uapi/linux/kfd_ioctl.h>
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_0_CTRL_nbif_4_10 0x4f0aeb
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_0_CTRL_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_0_CTRL1_nbif_4_10 0x4f0aec
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_0_CTRL1_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL_nbif_4_10 0x4f0aed
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL1_nbif_4_10 0x4f0aee
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL1_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL_nbif_4_10 0x4f0aef
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL1_nbif_4_10 0x4f0af0
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL1_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_3_CTRL_nbif_4_10 0x4f0af1
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_3_CTRL_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_3_CTRL1_nbif_4_10 0x4f0af2
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_3_CTRL1_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_4_CTRL_nbif_4_10 0x4f0af3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_4_CTRL_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_4_CTRL1_nbif_4_10 0x4f0af4
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_4_CTRL1_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL_nbif_4_10 0x4f0af5
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL1_nbif_4_10 0x4f0af6
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL1_nbif_4_10_BASE_IDX 3
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10 0x0021
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10_BASE_IDX 2
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_0_CTRL_nbif_4_10 0x4f0aeb
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_0_CTRL_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_0_CTRL1_nbif_4_10 0x4f0aec
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_0_CTRL1_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL_nbif_4_10 0x4f0aed
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL1_nbif_4_10 0x4f0aee
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL1_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL_nbif_4_10 0x4f0aef
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL1_nbif_4_10 0x4f0af0
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL1_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_3_CTRL_nbif_4_10 0x4f0af1
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_3_CTRL_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_3_CTRL1_nbif_4_10 0x4f0af2
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_3_CTRL1_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_4_CTRL_nbif_4_10 0x4f0af3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_4_CTRL_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_4_CTRL1_nbif_4_10 0x4f0af4
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_4_CTRL1_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL_nbif_4_10 0x4f0af5
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL1_nbif_4_10 0x4f0af6
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL1_nbif_4_10_BASE_IDX 3
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10 0x0021
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10_BASE_IDX 2
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_BASE_HIGH_nbio_7_11_5 0x8e13
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_BASE_HIGH_nbio_7_11_5_BASE_IDX 5
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_BASE_LOW_nbio_7_11_5 0x8e14
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_BASE_LOW_nbio_7_11_5_BASE_IDX 5
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_CNTL_nbio_7_11_5 0x8e15
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_CNTL_nbio_7_11_5_BASE_IDX 5
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_BASE_HIGH_nbio_7_11_5 0x8e13
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_BASE_HIGH_nbio_7_11_5_BASE_IDX 5
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_BASE_LOW_nbio_7_11_5 0x8e14
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_BASE_LOW_nbio_7_11_5_BASE_IDX 5
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_CNTL_nbio_7_11_5 0x8e15
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_CNTL_nbio_7_11_5_BASE_IDX 5
#define regBIF_BX0_REMAP_HDP_MEM_FLUSH_CNTL_nbio_7_11_5 0x8e4d
#define regBIF_BX0_REMAP_HDP_MEM_FLUSH_CNTL_nbio_7_11_5_BASE_IDX 5
#define regBIF_BX0_REMAP_HDP_REG_FLUSH_CNTL_nbio_7_11_5 0x8e4e
#define regBIF_BX0_REMAP_HDP_REG_FLUSH_CNTL_nbio_7_11_5_BASE_IDX 5
#define regBIF_BX1_REMAP_HDP_MEM_FLUSH_CNTL_nbio_7_11_5 0x012d
#define regBIF_BX1_REMAP_HDP_MEM_FLUSH_CNTL_nbio_7_11_5_BASE_IDX 2
#define regBIF_BX1_REMAP_HDP_REG_FLUSH_CNTL_nbio_7_11_5 0x012e
#define regBIF_BX1_REMAP_HDP_REG_FLUSH_CNTL_nbio_7_11_5_BASE_IDX 2
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbio_7_11_5 0xd000
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbio_7_11_5_BASE_IDX 5
#define regRCC_STRAP1_RCC_DEV0_EPF0_STRAP0_nbio_7_11_5 0x0021
#define regRCC_STRAP1_RCC_DEV0_EPF0_STRAP0_nbio_7_11_5_BASE_IDX 2
#define regBIF_BX0_BIF_FB_EN_nbio_7_11_5 0x8e20
#define regBIF_BX0_BIF_FB_EN_nbio_7_11_5_BASE_IDX 5
#define regBIF_BX1_BIF_FB_EN_nbio_7_11_5 0x0100
#define regBIF_BX1_BIF_FB_EN_nbio_7_11_5_BASE_IDX 2
#define regBIF_BX0_INTERRUPT_CNTL_nbio_7_11_5 0x8e11
#define regBIF_BX0_INTERRUPT_CNTL_nbio_7_11_5_BASE_IDX 5
#define regBIF_BX0_INTERRUPT_CNTL2_nbio_7_11_5 0x8e12
#define regBIF_BX0_INTERRUPT_CNTL2_nbio_7_11_5_BASE_IDX 5
#define regBIF_BX1_INTERRUPT_CNTL_nbio_7_11_5 0x00f1
#define regBIF_BX1_INTERRUPT_CNTL_nbio_7_11_5_BASE_IDX 2
#define regBIF_BX1_INTERRUPT_CNTL2_nbio_7_11_5 0x00f2
#define regBIF_BX1_INTERRUPT_CNTL2_nbio_7_11_5_BASE_IDX 2
#define regBIF_BX_PF0_GPU_HDP_FLUSH_REQ_nbio_7_11_5 0x8e26
#define regBIF_BX_PF0_GPU_HDP_FLUSH_REQ_nbio_7_11_5_BASE_IDX 5
#define regBIF_BX_PF0_GPU_HDP_FLUSH_DONE_nbio_7_11_5 0x8e27
#define regBIF_BX_PF0_GPU_HDP_FLUSH_DONE_nbio_7_11_5_BASE_IDX 5
#define regBIF_BX_PF1_GPU_HDP_FLUSH_REQ_nbio_7_11_5 0x0106
#define regBIF_BX_PF1_GPU_HDP_FLUSH_REQ_nbio_7_11_5_BASE_IDX 2
#define regBIF_BX_PF1_GPU_HDP_FLUSH_DONE_nbio_7_11_5 0x0107
#define regBIF_BX_PF1_GPU_HDP_FLUSH_DONE_nbio_7_11_5_BASE_IDX 2
#define regBIF_BX_PF0_HDP_MEM_COHERENCY_FLUSH_CNTL_nbio_7_11_5 0x8e17
#define regBIF_BX_PF0_HDP_MEM_COHERENCY_FLUSH_CNTL_nbio_7_11_5_BASE_IDX 5
#define regBIF_BX_PF1_HDP_MEM_COHERENCY_FLUSH_CNTL_nbio_7_11_5 0x00f7
#define regBIF_BX_PF1_HDP_MEM_COHERENCY_FLUSH_CNTL_nbio_7_11_5_BASE_IDX 2
//BIF_BX1_BIF_FB_EN
#define BIF_BX1_BIF_FB_EN__FB_READ_EN__SHIFT_nbio_7_11_5 0x0
#define BIF_BX1_BIF_FB_EN__FB_WRITE_EN__SHIFT_nbio_7_11_5 0x1
#define BIF_BX1_BIF_FB_EN__FB_READ_EN_MASK_nbio_7_11_5 0x00000001L
#define BIF_BX1_BIF_FB_EN__FB_WRITE_EN_MASK_nbio_7_11_5 0x00000002L
static void nbif_v6_3_1_remap_hdp_registers(struct amdgpu_device *adev)
{
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5)) {
WREG32_SOC15(NBIO, 0, regBIF_BX0_REMAP_HDP_MEM_FLUSH_CNTL_nbio_7_11_5,
WREG32_SOC15(NBIO, 0, regBIF_BX1_REMAP_HDP_MEM_FLUSH_CNTL_nbio_7_11_5,
adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL);
WREG32_SOC15(NBIO, 0, regBIF_BX0_REMAP_HDP_REG_FLUSH_CNTL_nbio_7_11_5,
WREG32_SOC15(NBIO, 0, regBIF_BX1_REMAP_HDP_REG_FLUSH_CNTL_nbio_7_11_5,
adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_REG_FLUSH_CNTL);
} else {
WREG32_SOC15(NBIO, 0, regBIF_BX0_REMAP_HDP_MEM_FLUSH_CNTL,
@@ -110,7 +116,7 @@ static u32 nbif_v6_3_1_get_rev_id(struct amdgpu_device *adev)
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 4))
tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10);
else if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5))
tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbio_7_11_5);
tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP1_RCC_DEV0_EPF0_STRAP0_nbio_7_11_5);
else
tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0);
@@ -124,11 +130,11 @@ static void nbif_v6_3_1_mc_access_enable(struct amdgpu_device *adev, bool enable
{
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5)) {
if (enable)
WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN_nbio_7_11_5,
BIF_BX0_BIF_FB_EN__FB_READ_EN_MASK |
BIF_BX0_BIF_FB_EN__FB_WRITE_EN_MASK);
WREG32_SOC15(NBIO, 0, regBIF_BX1_BIF_FB_EN_nbio_7_11_5,
BIF_BX1_BIF_FB_EN__FB_READ_EN_MASK_nbio_7_11_5 |
BIF_BX1_BIF_FB_EN__FB_WRITE_EN_MASK_nbio_7_11_5);
else
WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN_nbio_7_11_5, 0);
WREG32_SOC15(NBIO, 0, regBIF_BX1_BIF_FB_EN_nbio_7_11_5, 0);
} else {
if (enable)
WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN,
@@ -383,12 +389,12 @@ static void nbif_v6_3_1_ih_control(struct amdgpu_device *adev)
/* setup interrupt control */
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5))
WREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL2_nbio_7_11_5,
WREG32_SOC15(NBIO, 0, regBIF_BX1_INTERRUPT_CNTL2_nbio_7_11_5,
adev->dummy_page_addr >> 8);
else
WREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL2, adev->dummy_page_addr >> 8);
interrupt_cntl = RREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL_nbio_7_11_5);
interrupt_cntl = RREG32_SOC15(NBIO, 0, regBIF_BX1_INTERRUPT_CNTL_nbio_7_11_5);
/*
* BIF_BX0_INTERRUPT_CNTL__IH_DUMMY_RD_OVERRIDE_MASK=0 - dummy read disabled with msi, enabled without msi
* BIF_BX0_INTERRUPT_CNTL__IH_DUMMY_RD_OVERRIDE_MASK=1 - dummy read controlled by IH_DUMMY_RD_EN
@@ -401,7 +407,7 @@ static void nbif_v6_3_1_ih_control(struct amdgpu_device *adev)
IH_REQ_NONSNOOP_EN, 0);
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5))
WREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL_nbio_7_11_5, interrupt_cntl);
WREG32_SOC15(NBIO, 0, regBIF_BX1_INTERRUPT_CNTL_nbio_7_11_5, interrupt_cntl);
else
WREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL, interrupt_cntl);
}
@@ -427,7 +433,7 @@ nbif_v6_3_1_get_clockgating_state(struct amdgpu_device *adev,
static u32 nbif_v6_3_1_get_hdp_flush_req_offset(struct amdgpu_device *adev)
{
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5))
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF0_GPU_HDP_FLUSH_REQ_nbio_7_11_5);
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF1_GPU_HDP_FLUSH_REQ_nbio_7_11_5);
else
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF0_GPU_HDP_FLUSH_REQ);
}
@@ -435,7 +441,7 @@ static u32 nbif_v6_3_1_get_hdp_flush_req_offset(struct amdgpu_device *adev)
static u32 nbif_v6_3_1_get_hdp_flush_done_offset(struct amdgpu_device *adev)
{
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5))
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF0_GPU_HDP_FLUSH_DONE_nbio_7_11_5);
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF1_GPU_HDP_FLUSH_DONE_nbio_7_11_5);
else
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF0_GPU_HDP_FLUSH_DONE);
}
@@ -622,7 +628,7 @@ static void nbif_v6_3_1_set_reg_remap(struct amdgpu_device *adev)
} else {
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5))
adev->rmmio_remap.reg_offset = SOC15_REG_OFFSET(NBIO, 0,
regBIF_BX_PF0_HDP_MEM_COHERENCY_FLUSH_CNTL_nbio_7_11_5) << 2;
regBIF_BX_PF1_HDP_MEM_COHERENCY_FLUSH_CNTL_nbio_7_11_5) << 2;
else
adev->rmmio_remap.reg_offset = SOC15_REG_OFFSET(NBIO, 0,
regBIF_BX_PF0_HDP_MEM_COHERENCY_FLUSH_CNTL) << 2;

View File

@@ -110,6 +110,7 @@ enum psp_gfx_cmd_id
GFX_CMD_ID_PERF_HW = 0x0000004C, /* performance monitor */
GFX_CMD_ID_FB_FW_RESERV_ADDR = 0x00000050, /* Query FW reservation addr */
GFX_CMD_ID_FB_FW_RESERV_EXT_ADDR = 0x00000051, /* Query FW reservation extended addr */
GFX_CMD_ID_SET_MMHUB_ECO_SEC_LEVEL = 0x0000005D, /* Set MMHUB ECO sec lvls on VCN block */
};
/* PSP boot config sub-commands */

View File

@@ -136,7 +136,9 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
err = psp_init_toc_microcode(psp, ucode_prefix);
break;
default:
BUG();
dev_warn(adev->dev, "Unsupported MP0 version 0x%08x\n",
amdgpu_ip_version(adev, MP0_HWIP, 0));
return -EINVAL;
}
return err;

View File

@@ -133,7 +133,9 @@ static int psp_v13_0_init_microcode(struct psp_context *psp)
return err;
break;
default:
BUG();
dev_warn(adev->dev, "Unsupported MP0 version 0x%08x\n",
amdgpu_ip_version(adev, MP0_HWIP, 0));
return -EINVAL;
}
return 0;

View File

@@ -50,7 +50,9 @@ static int psp_v13_0_4_init_microcode(struct psp_context *psp)
return err;
break;
default:
BUG();
dev_warn(adev->dev, "Unsupported MP0 version 0x%08x\n",
amdgpu_ip_version(adev, MP0_HWIP, 0));
return -EINVAL;
}
return 0;

View File

@@ -85,7 +85,9 @@ static int psp_v14_0_init_microcode(struct psp_context *psp)
return err;
break;
default:
BUG();
dev_warn(adev->dev, "Unsupported MP0 version 0x%08x\n",
amdgpu_ip_version(adev, MP0_HWIP, 0));
return -EINVAL;
}
return 0;

View File

@@ -33,9 +33,22 @@
MODULE_FIRMWARE("amdgpu/psp_15_0_0_toc.bin");
MODULE_FIRMWARE("amdgpu/psp_15_0_0_ta.bin");
MODULE_FIRMWARE("amdgpu/psp_15_0_5_toc.bin");
MODULE_FIRMWARE("amdgpu/psp_15_0_5_ta.bin");
MODULE_FIRMWARE("amdgpu/psp_15_0_9_toc.bin");
MODULE_FIRMWARE("amdgpu/psp_15_0_9_ta.bin");
#define regMPASP_PCRU0_MPASP_C2PMSG_64 0x4280
#define regMPASP_PCRU0_MPASP_C2PMSG_64_BASE_IDX 2
#define regMPASP_PCRU0_MPASP_C2PMSG_67 0x4283
#define regMPASP_PCRU0_MPASP_C2PMSG_67_BASE_IDX 2
#define regMPASP_PCRU0_MPASP_C2PMSG_69 0x4285
#define regMPASP_PCRU0_MPASP_C2PMSG_69_BASE_IDX 2
#define regMPASP_PCRU0_MPASP_C2PMSG_70 0x4286
#define regMPASP_PCRU0_MPASP_C2PMSG_70_BASE_IDX 2
#define regMPASP_PCRU0_MPASP_C2PMSG_71 0x4287
#define regMPASP_PCRU0_MPASP_C2PMSG_71_BASE_IDX 2
static int psp_v15_0_0_init_microcode(struct psp_context *psp)
{
struct amdgpu_device *adev = psp->adev;
@@ -71,14 +84,25 @@ static int psp_v15_0_0_ring_stop(struct psp_context *psp,
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_101),
0x80000000, 0x80000000, false);
} else {
/* Write the ring destroy command*/
WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64,
GFX_CTRL_CMD_ID_DESTROY_RINGS);
/* there might be handshake issue with hardware which needs delay */
mdelay(20);
/* Wait for response flag (bit 31) */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64),
0x80000000, 0x80000000, false);
if (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(15, 0, 5)) {
/* Write the ring destroy command*/
WREG32_SOC15(MP0, 0, regMPASP_PCRU0_MPASP_C2PMSG_64,
GFX_CTRL_CMD_ID_DESTROY_RINGS);
/* there might be handshake issue with hardware which needs delay */
mdelay(20);
/* Wait for response flag (bit 31) */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU0_MPASP_C2PMSG_64),
0x80000000, 0x80000000, false);
} else {
/* Write the ring destroy command*/
WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64,
GFX_CTRL_CMD_ID_DESTROY_RINGS);
/* there might be handshake issue with hardware which needs delay */
mdelay(20);
/* Wait for response flag (bit 31) */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64),
0x80000000, 0x80000000, false);
}
}
return ret;
@@ -118,14 +142,44 @@ static int psp_v15_0_0_ring_create(struct psp_context *psp,
0x80000000, 0x8000FFFF, false);
} else {
/* Wait for sOS ready for ring creation */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64),
0x80000000, 0x80000000, false);
if (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(15, 0, 5)) {
/* Wait for sOS ready for ring creation */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU0_MPASP_C2PMSG_64),
0x80000000, 0x80000000, false);
if (ret) {
DRM_ERROR("Failed to wait for trust OS ready for ring creation\n");
return ret;
}
/* Write low address of the ring to C2PMSG_69 */
psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr);
WREG32_SOC15(MP0, 0, regMPASP_PCRU0_MPASP_C2PMSG_69, psp_ring_reg);
/* Write high address of the ring to C2PMSG_70 */
psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr);
WREG32_SOC15(MP0, 0, regMPASP_PCRU0_MPASP_C2PMSG_70, psp_ring_reg);
/* Write size of ring to C2PMSG_71 */
psp_ring_reg = ring->ring_size;
WREG32_SOC15(MP0, 0, regMPASP_PCRU0_MPASP_C2PMSG_71, psp_ring_reg);
/* Write the ring initialization command to C2PMSG_64 */
psp_ring_reg = ring_type;
psp_ring_reg = psp_ring_reg << 16;
WREG32_SOC15(MP0, 0, regMPASP_PCRU0_MPASP_C2PMSG_64, psp_ring_reg);
/* there might be handshake issue with hardware which needs delay */
mdelay(20);
/* Wait for response flag (bit 31) in C2PMSG_64 */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU0_MPASP_C2PMSG_64),
0x80000000, 0x8000FFFF, false);
} else {
/* Wait for sOS ready for ring creation */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64),
0x80000000, 0x80000000, false);
if (ret) {
DRM_ERROR("Failed to wait for trust OS ready for ring creation\n");
return ret;
}
/* Write low address of the ring to C2PMSG_69 */
psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr);
WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_69, psp_ring_reg);
@@ -146,6 +200,7 @@ static int psp_v15_0_0_ring_create(struct psp_context *psp,
/* Wait for response flag (bit 31) in C2PMSG_64 */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64),
0x80000000, 0x8000FFFF, false);
}
}
return ret;
@@ -176,8 +231,12 @@ static uint32_t psp_v15_0_0_ring_get_wptr(struct psp_context *psp)
if (amdgpu_sriov_vf(adev))
data = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_102);
else
data = RREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_67);
else {
if (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(15, 0, 5))
data = RREG32_SOC15(MP0, 0, regMPASP_PCRU0_MPASP_C2PMSG_67);
else
data = RREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_67);
}
return data;
}
@@ -190,8 +249,12 @@ static void psp_v15_0_0_ring_set_wptr(struct psp_context *psp, uint32_t value)
WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_102, value);
WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_101,
GFX_CTRL_CMD_ID_CONSUME_CMD);
} else
WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_67, value);
} else {
if (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(15, 0, 5))
WREG32_SOC15(MP0, 0, regMPASP_PCRU0_MPASP_C2PMSG_67, value);
else
WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_67, value);
}
}
static const struct psp_funcs psp_v15_0_0_funcs = {

View File

@@ -407,6 +407,7 @@ soc21_asic_reset_method(struct amdgpu_device *adev)
case IP_VERSION(14, 0, 4):
case IP_VERSION(14, 0, 5):
case IP_VERSION(15, 0, 0):
case IP_VERSION(15, 0, 5):
case IP_VERSION(15, 0, 9):
return AMD_RESET_METHOD_MODE2;
default:

View File

@@ -217,8 +217,9 @@ static int uvd_v6_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle
int i, r;
r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,
AMDGPU_IB_POOL_DIRECT, &job,
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST);
AMDGPU_IB_POOL_DIRECT,
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST,
&job);
if (r)
return r;
@@ -282,8 +283,9 @@ static int uvd_v6_0_enc_get_destroy_msg(struct amdgpu_ring *ring,
int i, r;
r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,
AMDGPU_IB_POOL_DIRECT, &job,
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST);
AMDGPU_IB_POOL_DIRECT,
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST,
&job);
if (r)
return r;

View File

@@ -225,8 +225,9 @@ static int uvd_v7_0_enc_get_create_msg(struct amdgpu_ring *ring, u32 handle,
int i, r;
r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,
AMDGPU_IB_POOL_DIRECT, &job,
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST);
AMDGPU_IB_POOL_DIRECT,
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST,
&job);
if (r)
return r;
@@ -289,8 +290,9 @@ static int uvd_v7_0_enc_get_destroy_msg(struct amdgpu_ring *ring, u32 handle,
int i, r;
r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,
AMDGPU_IB_POOL_DIRECT, &job,
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST);
AMDGPU_IB_POOL_DIRECT,
AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST,
&job);
if (r)
return r;

View File

@@ -795,6 +795,27 @@ static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
return 0;
}
/**
* vcn_v5_0_0_set_mmhub_eco_sec_level - set vcn sec lvl reg
*
* @adev: amdgpu_device pointer
*
* request psp to set sec lvl
*/
static int vcn_v5_0_0_set_mmhub_eco_sec_level(struct amdgpu_device *adev)
{
int r = 0;
if (amdgpu_ip_version(adev, VCN_HWIP, 0) == IP_VERSION(5, 3, 0)) {
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
/* Request to PSP to program VCN secure lvl */
r = psp_set_mmhub_eco_sec_level(adev);
}
}
return r;
}
/**
* vcn_v5_0_0_start - VCN start
*
@@ -819,6 +840,11 @@ static int vcn_v5_0_0_start(struct amdgpu_vcn_inst *vinst)
fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
/* program VCN secure lvl register */
r = vcn_v5_0_0_set_mmhub_eco_sec_level(adev);
if (r)
return r;
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
return vcn_v5_0_0_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram);

View File

@@ -1387,10 +1387,30 @@ static uint64_t vi_get_pcie_replay_count(struct amdgpu_device *adev)
return (nak_r + nak_g);
}
struct vi_reset_quirk {
u16 device;
u16 subsystem_vendor;
u16 subsystem_device;
u8 revision;
};
static const struct vi_reset_quirk vi_reset_quirks[] = {
{ 0x67ef, PCI_VENDOR_ID_APPLE, 0x0190, 0xe3 }, /* Radeon Pro 555X */
{ 0x67ef, PCI_VENDOR_ID_APPLE, 0x018f, 0xc2 }, /* Radeon Pro 560X */
};
static bool vi_need_reset_on_init(struct amdgpu_device *adev)
{
unsigned int i;
u32 clock_cntl, pc;
for (i = 0; i < ARRAY_SIZE(vi_reset_quirks); i++)
if (adev->pdev->device == vi_reset_quirks[i].device &&
adev->pdev->subsystem_vendor == vi_reset_quirks[i].subsystem_vendor &&
adev->pdev->subsystem_device == vi_reset_quirks[i].subsystem_device &&
adev->pdev->revision == vi_reset_quirks[i].revision)
return true;
if (adev->flags & AMD_IS_APU)
return false;

View File

@@ -1783,6 +1783,9 @@ static int kfd_ptl_control(struct kfd_process_device *pdd, bool enable)
uint32_t ptl_state = enable ? 1 : 0;
int ret;
if (ptl->hw_supported_state != AMDGPU_PTL_HW_SUPPORTED)
return -EOPNOTSUPP;
if (!pdd->dev->kfd2kgd || !pdd->dev->kfd2kgd->ptl_ctrl)
return -EOPNOTSUPP;
@@ -1801,7 +1804,7 @@ int kfd_ptl_disable_request(struct kfd_process_device *pdd,
struct amdgpu_ptl *ptl = &adev->psp.ptl;
int ret = 0;
if (!ptl->hw_supported)
if (ptl->hw_supported_state != AMDGPU_PTL_HW_SUPPORTED)
return -EOPNOTSUPP;
mutex_lock(&ptl->mutex);
@@ -1833,7 +1836,7 @@ int kfd_ptl_disable_release(struct kfd_process_device *pdd,
struct amdgpu_ptl *ptl = &adev->psp.ptl;
int ret = 0;
if (!ptl->hw_supported)
if (ptl->hw_supported_state != AMDGPU_PTL_HW_SUPPORTED)
return -EOPNOTSUPP;
mutex_lock(&ptl->mutex);
@@ -3112,10 +3115,14 @@ static int kfd_ioctl_set_debug_trap(struct file *filep, struct kfd_process *p, v
goto out;
}
/* Check if target is still PTRACED. */
/*
* Verify debugger has permission to debug target process.
* For cross-process debugging, require active ptrace relationship.
* This applies to ALL operations to prevent unauthorized interference.
*/
rcu_read_lock();
if (target != p && args->op != KFD_IOC_DBG_TRAP_DISABLE
&& ptrace_parent(target->lead_thread) != current) {
if (target != p && ptrace_parent(target->lead_thread) != current
&& target->debugger_process != p) {
pr_err("PID %i is not PTRACED and cannot be debugged\n", args->pid);
r = -EPERM;
}
@@ -3349,7 +3356,7 @@ static inline uint32_t profile_lock_device(struct kfd_process *p,
kfd->profiler_process = p;
status = 0;
mutex_unlock(&kfd->profiler_lock);
if (ptl->hw_supported) {
if (ptl->hw_supported_state == AMDGPU_PTL_HW_SUPPORTED) {
status = kfd_ptl_disable_request(pdd, p);
if (status != 0)
dev_err(kfd_device,
@@ -3367,7 +3374,7 @@ static inline uint32_t profile_lock_device(struct kfd_process *p,
status = 0;
mutex_unlock(&kfd->profiler_lock);
if (ptl->hw_supported) {
if (ptl->hw_supported_state == AMDGPU_PTL_HW_SUPPORTED) {
status = kfd_ptl_disable_release(pdd, p);
if (status)
dev_err(kfd_device,
@@ -3715,10 +3722,10 @@ static int kfd_mmio_mmap(struct kfd_node *dev, struct kfd_process *process,
vma->vm_page_prot);
}
static int kfd_mmap(struct file *filep, struct vm_area_struct *vma)
{
struct kfd_process *process;
struct kfd_process_device *pdd;
struct kfd_node *dev = NULL;
unsigned long mmap_offset;
unsigned int gpu_id;
@@ -3732,8 +3739,10 @@ static int kfd_mmap(struct file *filep, struct vm_area_struct *vma)
mmap_offset = vma->vm_pgoff << PAGE_SHIFT;
gpu_id = KFD_MMAP_GET_GPU_ID(mmap_offset);
if (gpu_id)
dev = kfd_device_by_id(gpu_id);
pdd = kfd_process_device_data_by_id(process, gpu_id);
if (pdd)
dev = pdd->dev;
switch (mmap_offset & KFD_MMAP_TYPE_MASK) {
case KFD_MMAP_TYPE_DOORBELL:

View File

@@ -1412,6 +1412,15 @@ int kfd_parse_crat_table(void *crat_image, struct list_head *device_list,
break;
}
/* Validate subtype fits within remaining image */
if ((char *)sub_type_hdr + sub_type_hdr->length >
(char *)crat_image + image_len) {
pr_warn("CRAT subtype length %u exceeds image bounds\n",
sub_type_hdr->length);
ret = -EINVAL;
break;
}
if (sub_type_hdr->flags & CRAT_SUBTYPE_FLAGS_ENABLED) {
ret = kfd_parse_subtype(sub_type_hdr, device_list);
if (ret)

View File

@@ -448,6 +448,9 @@ int kfd_reset_queue_mes(struct device_queue_manager *dqm, int queue_type,
static int reset_queues_mes(struct device_queue_manager *dqm, struct queue *q)
{
struct amdgpu_device *adev = (struct amdgpu_device *)dqm->dev->adev;
struct drm_wedge_task_info *info = NULL;
struct amdgpu_task_info *ti = NULL;
struct kfd_process_device *pdd;
unsigned int num_hung = 0;
int r = 0;
struct mes_remove_queue_input queue_input;
@@ -476,13 +479,27 @@ static int reset_queues_mes(struct device_queue_manager *dqm, struct queue *q)
r = amdgpu_gfx_reset_mes_compute(adev, NULL, NULL, NULL, &num_hung, &queue_input);
if (r)
goto fail;
pdd = kfd_get_process_device_data(q->device, q->process);
if (pdd) {
ti = amdgpu_vm_get_task_info_pasid(adev, pdd->pasid);
if (ti) {
amdgpu_vm_print_task_info(adev, ti);
info = &ti->task;
}
}
dqm->detect_hang_count = num_hung;
/* When MES doesn't detect any queue hang, no reset happens. Don't signal reset
* event.
*/
if (dqm->detect_hang_count)
if (dqm->detect_hang_count) {
kfd_signal_reset_event(dqm->dev);
if (pdd && pdd->has_reset_queue) {
atomic_inc(&adev->gpu_reset_counter);
drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE, info);
}
}
amdgpu_vm_put_task_info(ti);
fail:
dqm->detect_hang_count = 0;

View File

@@ -452,6 +452,9 @@ int kfd_criu_restore_event(struct file *devkfd,
ret = create_other_event(p, ev, &ev_priv->event_id);
break;
default:
ret = -EINVAL;
break;
}
mutex_unlock(&p->event_mutex);
@@ -473,15 +476,27 @@ int kfd_criu_checkpoint_events(struct kfd_process *p,
int ret = 0;
struct kfd_event *ev;
uint32_t ev_id;
uint32_t num_events;
uint32_t num_events = kfd_get_num_events(p);
/* Serialize the count and the walk below against concurrent event
* create/destroy. Those paths take only p->event_mutex, not the
* p->mutex held by the CRIU checkpoint caller, so without this the
* event_idr can grow between kfd_get_num_events() and the loop and the
* walk writes past the ev_privs allocation.
*/
mutex_lock(&p->event_mutex);
if (!num_events)
num_events = kfd_get_num_events(p);
if (!num_events) {
mutex_unlock(&p->event_mutex);
return 0;
}
ev_privs = kvzalloc(num_events * sizeof(*ev_privs), GFP_KERNEL);
if (!ev_privs)
if (!ev_privs) {
mutex_unlock(&p->event_mutex);
return -ENOMEM;
}
idr_for_each_entry(&p->event_idr, ev, ev_id) {
@@ -522,6 +537,8 @@ int kfd_criu_checkpoint_events(struct kfd_process *p,
i++;
}
mutex_unlock(&p->event_mutex);
ret = copy_to_user(user_priv_data + *priv_data_offset,
ev_privs, num_events * sizeof(*ev_privs));
if (ret) {
@@ -1147,6 +1164,8 @@ void kfd_signal_reset_event(struct kfd_node *dev)
struct kfd_event *ev;
unsigned int temp;
uint32_t id, idx;
int user_gpu_id;
struct kfd_process_device *pdd;
int reset_cause = atomic_read(&dev->sram_ecc_flag) ?
KFD_HW_EXCEPTION_ECC :
KFD_HW_EXCEPTION_GPU_HANG;
@@ -1162,17 +1181,14 @@ void kfd_signal_reset_event(struct kfd_node *dev)
idx = srcu_read_lock(&kfd_processes_srcu);
hash_for_each_rcu(kfd_processes_table, temp, p, kfd_processes) {
int user_gpu_id = kfd_process_get_user_gpu_id(p, dev->id);
struct kfd_process_device *pdd = kfd_get_process_device_data(dev, p);
pdd = kfd_get_process_device_data(dev, p);
if (!pdd)
/* no process is using this device */
continue;
user_gpu_id = kfd_process_get_user_gpu_id(p, dev->id);
if (unlikely(user_gpu_id == -EINVAL)) {
WARN_ONCE(1, "Could not get user_gpu_id from dev->id:%x\n", dev->id);
continue;
}
if (unlikely(!pdd)) {
WARN_ONCE(1, "Could not get device data from process pid:%d\n",
p->lead_thread->pid);
WARN_ONCE(1, "Could not get user_gpu_id from dev->id:%d\n", dev->id);
continue;
}

View File

@@ -68,8 +68,8 @@ svm_migrate_gart_map(struct amdgpu_ring *ring,
AMDGPU_FENCE_OWNER_UNDEFINED,
num_dw * 4 + num_bytes,
AMDGPU_IB_POOL_DELAYED,
&job,
AMDGPU_KERNEL_JOB_ID_KFD_GART_MAP);
AMDGPU_KERNEL_JOB_ID_KFD_GART_MAP,
&job);
if (r)
return r;

View File

@@ -269,9 +269,19 @@ static int pm_create_runlist_ib(struct packet_manager *pm,
}
pm->is_over_subscription = !!is_over_subscription;
for (i = 0; i < alloc_size_bytes / sizeof(uint32_t); i++)
pr_debug("0x%2X ", rl_buffer[i]);
pr_debug("\n");
pr_debug("Runlist dump:");
for (i = 0; i < alloc_size_bytes / sizeof(uint32_t); i += 8) {
char buf[128];
int j, len = 0;
/* Dump 8 entries per line with an index for each line */
len += scnprintf(buf + len, sizeof(buf) - len, "%4u:", i);
for (j = 0; j < 8 && (i + j) < alloc_size_bytes / sizeof(uint32_t); j++)
len += scnprintf(buf + len, sizeof(buf) - len, " 0x%08x", rl_buffer[i + j]);
pr_debug("%s\n", buf);
}
return retval;
}

View File

@@ -309,6 +309,67 @@ static inline void pm_build_dequeue_wait_counts_packet_info(struct packet_manage
reg_data);
}
/* pm_grace_period_0_supported - whether firmware tolerates a CWSR grace
* period of 0 on this ASIC.
*
* The debugger may request a grace period of 0 via AMDKFD_IOC_DBG_TRAP.
* Most firmware revisions locked up on an infinite (0) grace period, so
* an earlier change clamped 0 to 1 for all ASICs. Firmware has since been
* fixed on most ASICs; return true only where the running MEC firmware is
* known to handle 0. The +32768 offset on IP_VERSION(9, 0, 1) accounts for
* the SR-IOV firmware version encoding.
*
* Navi3x (gfx11) and MI350 (IP_VERSION(9, 5, 0)) support a grace period of
* 0 in every firmware revision and need no version check. MI100
* (IP_VERSION(9, 4, 1)) never received the fix and is intentionally kept
* clamped. Any unlisted or future ASIC defaults to the safe behaviour
* (clamp).
*/
static bool pm_grace_period_0_supported(struct packet_manager *pm)
{
struct kfd_node *dev = pm->dqm->dev;
uint32_t mec_fw_version = dev->kfd->mec_fw_version;
/* Navi3x (gfx11) always supports a grace period of 0. */
if (KFD_GC_VERSION(dev) >= IP_VERSION(11, 0, 0) &&
KFD_GC_VERSION(dev) < IP_VERSION(12, 0, 0))
return true;
switch (KFD_GC_VERSION(dev)) {
case IP_VERSION(9, 0, 1):
return mec_fw_version >= 461 + 32768;
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 1):
case IP_VERSION(9, 2, 2):
case IP_VERSION(9, 3, 0):
case IP_VERSION(9, 4, 0):
return mec_fw_version >= 461;
/* MI100/Arcturus never received the firmware fix; keep clamped. */
case IP_VERSION(9, 4, 1):
return false;
case IP_VERSION(9, 4, 2):
return mec_fw_version >= 63;
case IP_VERSION(9, 4, 3):
case IP_VERSION(9, 4, 4):
return mec_fw_version >= 96;
/* MI350 supports a grace period of 0 in every firmware revision. */
case IP_VERSION(9, 5, 0):
return true;
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 2):
case IP_VERSION(10, 1, 1):
return mec_fw_version >= 146;
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 1):
case IP_VERSION(10, 3, 4):
case IP_VERSION(10, 3, 5):
return mec_fw_version >= 93;
default:
return false;
}
}
/* pm_config_dequeue_wait_counts_v9: Builds WRITE_DATA packet with
* register/value for configuring dequeue wait counts
*
@@ -357,11 +418,12 @@ static int pm_config_dequeue_wait_counts_v9(struct packet_manager *pm,
break;
case KFD_DEQUEUE_WAIT_SET_SCH_WAVE:
/* The CP cannot handle value 0 and it will result in
* an infinite grace period being set so set to 1 to prevent this. Also
* avoid debugger API breakage as it sets 0 and expects a low value.
/* A grace period of 0 requests an infinite CWSR grace period.
* Older firmware locks up on this, so clamp to 1 unless the ASIC
* firmware is known to handle 0. Also avoid debugger API breakage
* as it sets 0 and expects a low value.
*/
if (!value)
if (!value && !pm_grace_period_0_supported(pm))
value = 1;
pm_build_dequeue_wait_counts_packet_info(pm, value, 0, &reg_offset, &reg_data);
break;

View File

@@ -383,7 +383,7 @@ int pqm_create_queue(struct process_queue_manager *pqm,
false);
if (retval) {
dev_err(dev->adev->dev, "failed to allocate process context bo\n");
return retval;
goto err_allocate_pqn;
}
memset(pdd->proc_ctx_cpu_ptr, 0, AMDGPU_MES_PROC_CTX_SIZE);
}

View File

@@ -288,7 +288,7 @@ int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct queue_prope
}
err = kfd_queue_buffer_get(vm, (void *)properties->eop_ring_buffer_address,
&properties->eop_buf_bo,
ALIGN(properties->eop_ring_buffer_size, PAGE_SIZE));
ALIGN((u64)properties->eop_ring_buffer_size, PAGE_SIZE));
if (err)
goto out_err_unreserve;
}

View File

@@ -69,7 +69,6 @@ struct criu_svm_metadata {
struct kfd_criu_svm_range_priv_data data;
};
static void svm_range_evict_svm_bo_worker(struct work_struct *work);
static bool
svm_range_cpu_invalidate_pagetables(struct mmu_interval_notifier *mni,
const struct mmu_notifier_range *range,
@@ -97,7 +96,7 @@ static void svm_range_unlink(struct svm_range *prange)
if (prange->svm_bo) {
spin_lock(&prange->svm_bo->list_lock);
list_del(&prange->svm_bo_list);
list_del_init(&prange->svm_bo_list);
spin_unlock(&prange->svm_bo->list_lock);
}
@@ -286,6 +285,17 @@ static void svm_range_free(struct svm_range *prange, bool do_unmap)
pr_debug("svms 0x%p prange 0x%p [0x%lx 0x%lx]\n", prange->svms, prange,
prange->start, prange->last);
/* Unlink from range_list; no-op if already unlinked. */
if (prange->svm_bo) {
spin_lock(&prange->svm_bo->list_lock);
list_del_init(&prange->svm_bo_list);
spin_unlock(&prange->svm_bo->list_lock);
}
/* Wait for any in-flight eviction of this range to finish. */
mutex_lock(&prange->migrate_mutex);
mutex_unlock(&prange->migrate_mutex);
svm_range_vram_node_free(prange);
if (do_unmap)
svm_range_dma_unmap(prange);
@@ -588,7 +598,6 @@ svm_range_vram_node_new(struct kfd_node *node, struct svm_range *prange,
mm,
svm_bo, p->context_id);
mmput(mm);
INIT_WORK(&svm_bo->eviction_work, svm_range_evict_svm_bo_worker);
svm_bo->evicting = 0;
memset(&bp, 0, sizeof(bp));
bp.size = prange->npages * PAGE_SIZE;
@@ -3631,39 +3640,36 @@ svm_range_trigger_migration(struct mm_struct *mm, struct svm_range *prange,
return 0;
}
int svm_range_schedule_evict_svm_bo(struct amdgpu_amdkfd_fence *fence)
int svm_range_evict_svm_bo(struct svm_range_bo *svm_bo)
{
/* Dereferencing fence->svm_bo is safe here because the fence hasn't
* signaled yet and we're under the protection of the fence->lock.
* After the fence is signaled in svm_range_bo_release, we cannot get
* here any more.
*
* Reference is dropped in svm_range_evict_svm_bo_worker.
*/
if (svm_bo_ref_unless_zero(fence->svm_bo)) {
WRITE_ONCE(fence->svm_bo->evicting, 1);
schedule_work(&fence->svm_bo->eviction_work);
}
return 0;
}
static void svm_range_evict_svm_bo_worker(struct work_struct *work)
{
struct svm_range_bo *svm_bo;
struct mm_struct *mm;
int r = 0;
svm_bo = container_of(work, struct svm_range_bo, eviction_work);
if (!svm_bo_ref_unless_zero(svm_bo))
return 0;
if (mmget_not_zero(svm_bo->eviction_fence->mm)) {
mm = svm_bo->eviction_fence->mm;
} else {
if (!mmget_not_zero(svm_bo->eviction_fence->mm)) {
svm_range_bo_unref(svm_bo);
return;
return 0;
}
mm = svm_bo->eviction_fence->mm;
/*
* Called with the BO reserved; lock order is mmap_lock -> BO
* reservation. Only trylock mmap to invert that order safely: a
* trylock never blocks, so it cannot deadlock against the reservation
* and lockdep records no reverse dependency. On contention return
* -EBUSY so TTM skips this BO.
*/
if (!mmap_read_trylock(mm)) {
pr_debug("skip eviction, contended to take mmap_read lock\n");
mmput_async(mm);
svm_range_bo_unref(svm_bo);
return -EBUSY;
}
mmap_read_lock(mm);
WRITE_ONCE(svm_bo->evicting, 1);
spin_lock(&svm_bo->list_lock);
while (!list_empty(&svm_bo->range_list) && !r) {
struct svm_range *prange =
@@ -3671,13 +3677,24 @@ static void svm_range_evict_svm_bo_worker(struct work_struct *work)
struct svm_range, svm_bo_list);
int retries = 3;
/*
* Trylock migrate_mutex under list_lock, before unlinking the
* range, so svm_range_free() cannot free it under us. On
* contention the owner is migrating this range; skip the BO.
*/
if (!mutex_trylock(&prange->migrate_mutex)) {
pr_debug("skip eviction, contended migrate_mutex\n");
/* Clear evicting so the BO keeps being reused. */
WRITE_ONCE(svm_bo->evicting, 0);
r = -EBUSY;
break;
}
list_del_init(&prange->svm_bo_list);
spin_unlock(&svm_bo->list_lock);
pr_debug("svms 0x%p [0x%lx 0x%lx]\n", prange->svms,
prange->start, prange->last);
mutex_lock(&prange->migrate_mutex);
do {
/* migrate all vram pages in this prange to sys ram
* after that prange->actual_loc should be zero
@@ -3701,15 +3718,24 @@ static void svm_range_evict_svm_bo_worker(struct work_struct *work)
}
spin_unlock(&svm_bo->list_lock);
mmap_read_unlock(mm);
mmput(mm);
/* Defer mmput: exit_mmap() must not run under the BO reservation. */
mmput_async(mm);
dma_fence_signal(&svm_bo->eviction_fence->base);
/*
* Only signal the eviction fence once the ranges have been processed.
* On -EBUSY we bailed out without migrating; leave the BO in VRAM and
* let TTM retry later.
*/
if (r != -EBUSY)
dma_fence_signal(&svm_bo->eviction_fence->base);
/* This is the last reference to svm_bo, after svm_range_vram_node_free
* has been called in svm_migrate_vram_to_ram
*/
WARN_ONCE(!r && kref_read(&svm_bo->kref) != 1, "This was not the last reference\n");
svm_range_bo_unref(svm_bo);
return r;
}
static int

View File

@@ -44,7 +44,6 @@ struct svm_range_bo {
struct list_head range_list; /* all svm ranges shared this bo */
spinlock_t list_lock;
struct amdgpu_amdkfd_fence *eviction_fence;
struct work_struct eviction_work;
uint32_t evicting;
struct work_struct release_work;
struct kfd_node *node;
@@ -175,7 +174,8 @@ void svm_range_vram_node_free(struct svm_range *prange);
int svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
uint32_t vmid, uint32_t node_id, uint64_t addr, uint64_t ts,
bool write_fault);
int svm_range_schedule_evict_svm_bo(struct amdgpu_amdkfd_fence *fence);
int svm_range_evict_svm_bo(struct svm_range_bo *svm_bo);
void svm_range_add_list_work(struct svm_range_list *svms,
struct svm_range *prange, struct mm_struct *mm,
enum svm_work_list_ops op);
@@ -229,11 +229,9 @@ static inline int svm_range_restore_pages(struct amdgpu_device *adev,
return -EFAULT;
}
static inline int svm_range_schedule_evict_svm_bo(
struct amdgpu_amdkfd_fence *fence)
static inline int svm_range_evict_svm_bo(struct svm_range_bo *svm_bo)
{
WARN_ONCE(1, "SVM eviction fence triggered, but SVM is disabled");
return -EINVAL;
return 0;
}
static inline void svm_range_get_info(struct kfd_process *p,

View File

@@ -45,7 +45,9 @@ AMDGPUDM = \
amdgpu_dm_backlight.o \
amdgpu_dm_audio.o \
amdgpu_dm_dmub.o \
amdgpu_dm_connector.o
amdgpu_dm_connector.o \
amdgpu_dm_freesync.o \
amdgpu_dm_cursor.o
ifdef CONFIG_DRM_AMD_DC_FP
AMDGPUDM += dc_fpu.o

File diff suppressed because it is too large Load Diff

View File

@@ -1134,30 +1134,62 @@ bool amdgpu_dm_is_headless(struct amdgpu_device *adev);
bool amdgpu_dm_crtc_complete_writeback(struct amdgpu_crtc *acrtc);
void retrieve_dmi_info(struct amdgpu_display_manager *dm);
struct pci_dev;
bool dm_should_disable_stutter(struct pci_dev *pdev);
void amdgpu_dm_emulated_link_detect(struct dc_link *link);
void amdgpu_dm_apply_delay_after_dpcd_poweroff(struct amdgpu_device *adev,
struct dc_sink *sink);
struct __drm_planes_state *amdgpu_dm_get_next_zpos(struct drm_atomic_commit *state,
struct __drm_planes_state *prev);
/*
* Use the uniqueness of the plane's (zpos, drm obj ID) combination to iterate
* by descending zpos, as read from the new plane state. This is the same
* ordering as defined by drm_atomic_normalize_zpos().
*/
#define for_each_oldnew_plane_in_descending_zpos(__state, plane, old_plane_state, new_plane_state) \
for (struct __drm_planes_state *__i = amdgpu_dm_get_next_zpos((__state), NULL); \
__i != NULL; __i = amdgpu_dm_get_next_zpos((__state), __i)) \
for_each_if(((plane) = __i->ptr, \
(void)(plane) /* Only to avoid unused-but-set-variable warning */, \
(old_plane_state) = __i->old_state, \
(new_plane_state) = __i->new_state, 1))
#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
struct amdgpu_ip_block;
bool dm_is_idle(struct amdgpu_ip_block *ip_block);
int dm_wait_for_idle(struct amdgpu_ip_block *ip_block);
int dm_soft_reset(struct amdgpu_ip_block *ip_block);
int dm_set_clockgating_state(struct amdgpu_ip_block *ip_block,
enum amd_clockgating_state state);
int dm_set_powergating_state(struct amdgpu_ip_block *ip_block,
enum amd_powergating_state state);
void dm_bandwidth_update(struct amdgpu_device *adev);
u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc);
int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
u32 *vbl, u32 *position);
struct dm_atomic_state *dm_atomic_get_new_state(struct drm_atomic_commit *state);
void dm_atomic_destroy_state(struct drm_private_obj *obj,
struct drm_private_state *state);
int dm_plane_layer_index_cmp(const void *a, const void *b);
int fill_plane_color_attributes(const struct drm_plane_state *plane_state,
const enum surface_pixel_format format,
enum dc_color_space *color_space);
bool modereset_required(struct drm_crtc_state *crtc_state);
void dm_get_oriented_plane_size(struct drm_plane_state *plane_state,
int *src_w, int *src_h);
void dm_get_plane_scale(struct drm_plane_state *plane_state,
int *out_plane_scale_w, int *out_plane_scale_h);
bool is_scaling_state_different(const struct dm_connector_state *dm_state,
const struct dm_connector_state *old_dm_state);
bool is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
struct drm_crtc_state *new_crtc_state);
void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state);
bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
struct dm_crtc_state *new_state);
void set_multisync_trigger_params(struct dc_stream_state *stream);
void set_master_stream(struct dc_stream_state *stream_set[], int stream_count);
void dm_enable_per_frame_crtc_master_sync(struct dc_state *context);
struct hdcp_workqueue;
bool is_content_protection_different(struct drm_crtc_state *new_crtc_state,
struct drm_crtc_state *old_crtc_state,
struct drm_connector_state *new_conn_state,
struct drm_connector_state *old_conn_state,
const struct drm_connector *connector,
struct hdcp_workqueue *hdcp_w);
#endif
#endif /* __AMDGPU_DM_H__ */

View File

@@ -26,7 +26,7 @@
#include "amdgpu.h"
#include "amdgpu_dm.h"
#include "amdgpu_dm_audio.h"
#include "amdgpu_dm_kunit_helpers.h"
#include "dm_helpers.h"
#include "dc.h"
#include <linux/component.h>
@@ -321,6 +321,7 @@ void amdgpu_dm_commit_audio(struct drm_device *dev,
amdgpu_dm_audio_eld_notify(adev, inst);
}
}
EXPORT_IF_KUNIT(amdgpu_dm_commit_audio);
#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
int amdgpu_dm_audio_get_param(void)

View File

@@ -47,7 +47,7 @@
#include "amdgpu_dm_trace.h"
#include "amd_shared.h"
#include "amdgpu_dm_kunit_helpers.h"
#include "dm_helpers.h"
void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm,
int bl_idx)

View File

@@ -33,7 +33,7 @@
#include "amdgpu_dm_colorop.h"
#include "dc.h"
#include "modules/color/color_gamma.h"
#include "amdgpu_dm_kunit_helpers.h"
#include "dm_helpers.h"
/**
@@ -172,6 +172,7 @@ void amdgpu_dm_init_color_mod(void)
{
setup_x_points_distribution();
}
EXPORT_IF_KUNIT(amdgpu_dm_init_color_mod);
STATIC_IFN_KUNIT INLINE_IFN_KUNIT
struct fixed31_32 amdgpu_dm_fixpt_from_s3132(__u64 x)
@@ -617,9 +618,10 @@ EXPORT_IF_KUNIT(__drm_ctm_3x4_to_dc_matrix);
* Returns:
* 0 in case of success, -ENOMEM if fails
*/
static int __set_legacy_tf(struct dc_transfer_func *func,
const struct drm_color_lut *lut, uint32_t lut_size,
bool has_rom)
STATIC_IFN_KUNIT int
__set_legacy_tf(struct dc_transfer_func *func,
const struct drm_color_lut *lut, uint32_t lut_size,
bool has_rom)
{
struct dc_gamma *gamma = NULL;
struct calculate_buffer cal_buffer = {0};
@@ -644,6 +646,7 @@ static int __set_legacy_tf(struct dc_transfer_func *func,
return res ? 0 : -ENOMEM;
}
EXPORT_IF_KUNIT(__set_legacy_tf);
/**
* __set_output_tf - calculates the output transfer function based on expected input space.
@@ -655,9 +658,10 @@ static int __set_legacy_tf(struct dc_transfer_func *func,
* Returns:
* 0 in case of success. -ENOMEM if fails.
*/
static int __set_output_tf(struct dc_transfer_func *func,
const struct drm_color_lut *lut, uint32_t lut_size,
bool has_rom)
STATIC_IFN_KUNIT int
__set_output_tf(struct dc_transfer_func *func,
const struct drm_color_lut *lut, uint32_t lut_size,
bool has_rom)
{
struct dc_gamma *gamma = NULL;
struct calculate_buffer cal_buffer = {0};
@@ -702,6 +706,7 @@ static int __set_output_tf(struct dc_transfer_func *func,
return res ? 0 : -ENOMEM;
}
EXPORT_IF_KUNIT(__set_output_tf);
/**
* __set_output_tf_32 - calculates the output transfer function based on expected input space.
@@ -713,9 +718,10 @@ static int __set_output_tf(struct dc_transfer_func *func,
* Returns:
* 0 in case of success. -ENOMEM if fails.
*/
static int __set_output_tf_32(struct dc_transfer_func *func,
const struct drm_color_lut32 *lut, uint32_t lut_size,
bool has_rom)
STATIC_IFN_KUNIT int
__set_output_tf_32(struct dc_transfer_func *func,
const struct drm_color_lut32 *lut, uint32_t lut_size,
bool has_rom)
{
struct dc_gamma *gamma = NULL;
struct calculate_buffer cal_buffer = {0};
@@ -758,6 +764,7 @@ static int __set_output_tf_32(struct dc_transfer_func *func,
return res ? 0 : -ENOMEM;
}
EXPORT_IF_KUNIT(__set_output_tf_32);
STATIC_IFN_KUNIT void __set_tf_bypass(struct dc_transfer_func *tf)
{
@@ -819,8 +826,9 @@ EXPORT_IF_KUNIT(amdgpu_dm_set_atomic_regamma);
* Returns:
* 0 in case of success. -ENOMEM if fails.
*/
static int __set_input_tf(struct dc_color_caps *caps, struct dc_transfer_func *func,
const struct drm_color_lut *lut, uint32_t lut_size)
STATIC_IFN_KUNIT int __set_input_tf(struct dc_color_caps *caps,
struct dc_transfer_func *func,
const struct drm_color_lut *lut, uint32_t lut_size)
{
struct dc_gamma *gamma = NULL;
bool res;
@@ -843,6 +851,7 @@ static int __set_input_tf(struct dc_color_caps *caps, struct dc_transfer_func *f
return res ? 0 : -ENOMEM;
}
EXPORT_IF_KUNIT(__set_input_tf);
/**
* __set_input_tf_32 - calculates the input transfer function based on expected
@@ -855,8 +864,9 @@ static int __set_input_tf(struct dc_color_caps *caps, struct dc_transfer_func *f
* Returns:
* 0 in case of success. -ENOMEM if fails.
*/
static int __set_input_tf_32(struct dc_color_caps *caps, struct dc_transfer_func *func,
const struct drm_color_lut32 *lut, uint32_t lut_size)
STATIC_IFN_KUNIT int __set_input_tf_32(struct dc_color_caps *caps,
struct dc_transfer_func *func,
const struct drm_color_lut32 *lut, uint32_t lut_size)
{
struct dc_gamma *gamma = NULL;
bool res;
@@ -879,6 +889,7 @@ static int __set_input_tf_32(struct dc_color_caps *caps, struct dc_transfer_func
return res ? 0 : -ENOMEM;
}
EXPORT_IF_KUNIT(__set_input_tf_32);
STATIC_IFN_KUNIT
enum dc_transfer_func_predefined
@@ -1177,6 +1188,7 @@ int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *adev,
return 0;
}
EXPORT_IF_KUNIT(amdgpu_dm_verify_lut3d_size);
/**
* amdgpu_dm_verify_lut_sizes - verifies if DRM luts match the hw supported sizes
@@ -1321,6 +1333,7 @@ int amdgpu_dm_check_crtc_color_mgmt(struct dm_crtc_state *crtc,
return r;
}
EXPORT_IF_KUNIT(amdgpu_dm_check_crtc_color_mgmt);
/**
* amdgpu_dm_update_crtc_color_mgmt: Maps DRM color management to DC stream.
@@ -1379,6 +1392,7 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc)
return 0;
}
EXPORT_IF_KUNIT(amdgpu_dm_update_crtc_color_mgmt);
static int
map_crtc_degamma_to_dc_plane(struct dm_crtc_state *crtc,
@@ -1545,7 +1559,7 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
}
EXPORT_IF_KUNIT(__set_colorop_in_tf_1d_curve);
static int
STATIC_IFN_KUNIT int
__set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
struct dc_plane_state *dc_plane_state,
struct drm_colorop *colorop)
@@ -1571,8 +1585,9 @@ __set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
return __set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state);
}
EXPORT_IF_KUNIT(__set_dm_plane_colorop_degamma);
static int
STATIC_IFN_KUNIT int
__set_dm_plane_colorop_3x4_matrix(struct drm_plane_state *plane_state,
struct dc_plane_state *dc_plane_state,
struct drm_colorop *colorop)
@@ -1612,8 +1627,9 @@ __set_dm_plane_colorop_3x4_matrix(struct drm_plane_state *plane_state,
return 0;
}
EXPORT_IF_KUNIT(__set_dm_plane_colorop_3x4_matrix);
static int
STATIC_IFN_KUNIT int
__set_dm_plane_colorop_multiplier(struct drm_plane_state *plane_state,
struct dc_plane_state *dc_plane_state,
struct drm_colorop *colorop)
@@ -1641,6 +1657,7 @@ __set_dm_plane_colorop_multiplier(struct drm_plane_state *plane_state,
return 0;
}
EXPORT_IF_KUNIT(__set_dm_plane_colorop_multiplier);
static int
__set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
@@ -2125,3 +2142,4 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
return amdgpu_dm_plane_set_color_properties(plane_state, dc_plane_state);
}
EXPORT_IF_KUNIT(amdgpu_dm_update_plane_color_mgmt);

View File

@@ -44,6 +44,7 @@ struct dc_plane_state;
struct fixed31_32;
struct tetrahedral_params;
struct dc_transfer_func;
struct dc_3dlut;
#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
/*
@@ -63,6 +64,20 @@ void __drm_ctm_to_dc_matrix(const struct drm_color_ctm *ctm,
struct fixed31_32 *matrix);
void __drm_ctm_3x4_to_dc_matrix(const struct drm_color_ctm_3x4 *ctm,
struct fixed31_32 *matrix);
int __set_legacy_tf(struct dc_transfer_func *func,
const struct drm_color_lut *lut, uint32_t lut_size,
bool has_rom);
int __set_output_tf(struct dc_transfer_func *func,
const struct drm_color_lut *lut, uint32_t lut_size,
bool has_rom);
int __set_output_tf_32(struct dc_transfer_func *func,
const struct drm_color_lut32 *lut, uint32_t lut_size,
bool has_rom);
struct dc_color_caps;
int __set_input_tf(struct dc_color_caps *caps, struct dc_transfer_func *func,
const struct drm_color_lut *lut, uint32_t lut_size);
int __set_input_tf_32(struct dc_color_caps *caps, struct dc_transfer_func *func,
const struct drm_color_lut32 *lut, uint32_t lut_size);
enum dc_transfer_func_predefined
amdgpu_tf_to_dc_tf(enum amdgpu_transfer_function tf);
enum dc_transfer_func_predefined
@@ -113,6 +128,17 @@ int amdgpu_dm_atomic_blend_lut(const struct drm_color_lut *blend_lut,
struct dc_plane_cm *cm);
int __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
struct drm_colorop_state *colorop_state);
struct drm_plane_state;
struct drm_colorop;
int __set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
struct dc_plane_state *dc_plane_state,
struct drm_colorop *colorop);
int __set_dm_plane_colorop_3x4_matrix(struct drm_plane_state *plane_state,
struct dc_plane_state *dc_plane_state,
struct drm_colorop *colorop);
int __set_dm_plane_colorop_multiplier(struct drm_plane_state *plane_state,
struct dc_plane_state *dc_plane_state,
struct drm_colorop *colorop);
#endif
#endif /* __AMDGPU_DM_COLOR_H__ */

View File

@@ -31,7 +31,7 @@
#include "amdgpu.h"
#include "amdgpu_dm_colorop.h"
#include "amdgpu_dm_kunit_helpers.h"
#include "dm_helpers.h"
#include "dc.h"
const u64 amdgpu_dm_supported_degam_tfs =

View File

@@ -42,7 +42,6 @@
#include "amdgpu_display.h"
#include "amdgpu_dm.h"
#include "amdgpu_dm_connector.h"
#include "amdgpu_dm_kunit_helpers.h"
#include "amdgpu_dm_plane.h"
#include "amdgpu_dm_crtc.h"
#include "amdgpu_dm_wb.h"
@@ -91,11 +90,12 @@ static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = {
.destroy = amdgpu_dm_encoder_destroy,
};
static void dm_encoder_helper_disable(struct drm_encoder *encoder)
STATIC_IFN_KUNIT void dm_encoder_helper_disable(struct drm_encoder *encoder)
{
}
EXPORT_IF_KUNIT(dm_encoder_helper_disable);
static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
STATIC_IFN_KUNIT int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
@@ -165,6 +165,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
}
return 0;
}
EXPORT_IF_KUNIT(dm_encoder_helper_atomic_check);
const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = {
.disable = dm_encoder_helper_disable,
@@ -333,7 +334,7 @@ int amdgpu_dm_detect_mst_link_for_all_connectors(struct drm_device *dev)
}
EXPORT_IF_KUNIT(amdgpu_dm_detect_mst_link_for_all_connectors);
static void hdmi_cec_unset_edid(struct amdgpu_dm_connector *aconnector)
STATIC_IFN_KUNIT void hdmi_cec_unset_edid(struct amdgpu_dm_connector *aconnector)
{
struct cec_notifier *n = aconnector->notifier;
@@ -342,6 +343,7 @@ static void hdmi_cec_unset_edid(struct amdgpu_dm_connector *aconnector)
cec_notifier_phys_addr_invalidate(n);
}
EXPORT_IF_KUNIT(hdmi_cec_unset_edid);
void amdgpu_dm_hdmi_cec_set_edid(struct amdgpu_dm_connector *aconnector)
{
@@ -354,6 +356,7 @@ void amdgpu_dm_hdmi_cec_set_edid(struct amdgpu_dm_connector *aconnector)
cec_notifier_set_phys_addr(n,
connector->display_info.source_physical_address);
}
EXPORT_IF_KUNIT(amdgpu_dm_hdmi_cec_set_edid);
void amdgpu_dm_s3_handle_hdmi_cec(struct drm_device *ddev, bool suspend)
{
@@ -374,6 +377,7 @@ void amdgpu_dm_s3_handle_hdmi_cec(struct drm_device *ddev, bool suspend)
}
drm_connector_list_iter_end(&conn_iter);
}
EXPORT_IF_KUNIT(amdgpu_dm_s3_handle_hdmi_cec);
struct drm_connector *
@@ -655,6 +659,7 @@ void amdgpu_dm_update_connector_after_detect(
if (!drm_kms_helper_is_poll_worker())
mutex_unlock(&dev->mode_config.mutex);
}
EXPORT_IF_KUNIT(amdgpu_dm_update_connector_after_detect);
enum dc_color_depth
amdgpu_dm_convert_color_depth_from_display_info(const struct drm_connector *connector,
@@ -1384,7 +1389,64 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector,
}
#endif
static struct dc_stream_state *
void amdgpu_dm_update_stream_scaling_settings(struct drm_device *dev,
const struct drm_display_mode *mode,
const struct dm_connector_state *dm_state,
struct dc_stream_state *stream)
{
enum amdgpu_rmx_type rmx_type;
struct rect src = { 0 }; /* viewport in composition space*/
struct rect dst = { 0 }; /* stream addressable area */
/* no mode. nothing to be done */
if (!mode)
return;
/* Full screen scaling by default */
src.width = mode->hdisplay;
src.height = mode->vdisplay;
dst.width = stream->timing.h_addressable;
dst.height = stream->timing.v_addressable;
if (dm_state) {
rmx_type = dm_state->scaling;
if (rmx_type == RMX_ASPECT || rmx_type == RMX_OFF) {
if (src.width * dst.height <
src.height * dst.width) {
/* height needs less upscaling/more downscaling */
dst.width = src.width *
dst.height / src.height;
} else {
/* width needs less upscaling/more downscaling */
dst.height = src.height *
dst.width / src.width;
}
} else if (rmx_type == RMX_CENTER) {
dst = src;
}
dst.x = (stream->timing.h_addressable - dst.width) / 2;
dst.y = (stream->timing.v_addressable - dst.height) / 2;
if (dm_state->underscan_enable) {
dst.x += dm_state->underscan_hborder / 2;
dst.y += dm_state->underscan_vborder / 2;
dst.width -= dm_state->underscan_hborder;
dst.height -= dm_state->underscan_vborder;
}
}
stream->src = src;
stream->dst = dst;
drm_dbg_kms(dev, "Destination Rectangle x:%d y:%d width:%d height:%d\n",
dst.x, dst.y, dst.width, dst.height);
}
EXPORT_IF_KUNIT(amdgpu_dm_update_stream_scaling_settings);
STATIC_IFN_KUNIT struct dc_stream_state *
create_stream_for_sink(struct drm_connector *connector,
const struct drm_display_mode *drm_mode,
const struct dm_connector_state *dm_state,
@@ -1568,6 +1630,7 @@ create_stream_for_sink(struct drm_connector *connector,
return stream;
}
EXPORT_IF_KUNIT(create_stream_for_sink);
/**
* amdgpu_dm_connector_poll - Poll a connector to see if it's connected to a display
@@ -1583,7 +1646,7 @@ create_stream_for_sink(struct drm_connector *connector,
*
* Return: The probed connector status (connected/disconnected/unknown).
*/
static enum drm_connector_status
STATIC_IFN_KUNIT enum drm_connector_status
amdgpu_dm_connector_poll(struct amdgpu_dm_connector *aconnector, bool force)
{
struct drm_connector *connector = &aconnector->base;
@@ -1635,6 +1698,40 @@ amdgpu_dm_connector_poll(struct amdgpu_dm_connector *aconnector, bool force)
mutex_unlock(&aconnector->hpd_lock);
return status;
}
EXPORT_IF_KUNIT(amdgpu_dm_connector_poll);
/*
* Apple Studio Display exposes two SST DP links for a 2x1 tiled panel.
* The primary tile advertises the full 5120x2880 mode (with DSC on the
* bandwidth-sufficient link) while the secondary carries a per-tile
* 2560x2880 timing on a insufficient bandwidth link. Hide the secondary
* connector from userspace so compositors configure a single 5K stream
* on the primary link only.
*/
static bool amdgpu_dm_hide_secondary_tile_from_userspace(struct drm_connector *connector)
{
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
if (!aconnector->dc_sink)
return false;
if (!aconnector->dc_sink->edid_caps.panel_patch.disable_second_tile)
return false;
drm_edid_connector_update(connector, aconnector->drm_edid);
if (!connector->has_tile)
return false;
if (!connector->tile_h_loc && !connector->tile_v_loc)
return false;
drm_dbg_kms(connector->dev,
"[CONNECTOR:%d:%s] hiding secondary Apple Studio Display tile from userspace\n",
connector->base.id, connector->name);
return true;
}
/**
* amdgpu_dm_connector_detect() - Detect whether a DRM connector is connected to a display
@@ -1658,7 +1755,7 @@ amdgpu_dm_connector_poll(struct amdgpu_dm_connector *aconnector, bool force)
* Return: The connector status (connected, disconnected, or unknown).
*
*/
static enum drm_connector_status
STATIC_IFN_KUNIT enum drm_connector_status
amdgpu_dm_connector_detect(struct drm_connector *connector, bool force)
{
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
@@ -1679,9 +1776,13 @@ amdgpu_dm_connector_detect(struct drm_connector *connector, bool force)
(!aconnector->dc_sink || aconnector->dc_sink->edid_caps.analog))
return amdgpu_dm_connector_poll(aconnector, force);
if (amdgpu_dm_hide_secondary_tile_from_userspace(connector))
return connector_status_disconnected;
return (aconnector->dc_sink ? connector_status_connected :
connector_status_disconnected);
}
EXPORT_IF_KUNIT(amdgpu_dm_connector_detect);
int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector,
struct drm_connector_state *connector_state,
@@ -1800,7 +1901,7 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector,
}
EXPORT_IF_KUNIT(amdgpu_dm_connector_atomic_get_property);
static void amdgpu_dm_connector_unregister(struct drm_connector *connector)
STATIC_IFN_KUNIT void amdgpu_dm_connector_unregister(struct drm_connector *connector)
{
struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector);
@@ -1810,8 +1911,9 @@ static void amdgpu_dm_connector_unregister(struct drm_connector *connector)
cec_notifier_conn_unregister(amdgpu_dm_connector->notifier);
drm_dp_aux_unregister(&amdgpu_dm_connector->dm_dp_aux.aux);
}
EXPORT_IF_KUNIT(amdgpu_dm_connector_unregister);
static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
STATIC_IFN_KUNIT void amdgpu_dm_connector_destroy(struct drm_connector *connector)
{
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
struct amdgpu_device *adev = drm_to_adev(connector->dev);
@@ -1852,6 +1954,7 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
kfree(connector);
}
EXPORT_IF_KUNIT(amdgpu_dm_connector_destroy);
void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector)
{
@@ -1913,7 +2016,7 @@ amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector)
}
EXPORT_IF_KUNIT(amdgpu_dm_connector_atomic_duplicate_state);
static int
STATIC_IFN_KUNIT int
amdgpu_dm_connector_late_register(struct drm_connector *connector)
{
struct amdgpu_dm_connector *amdgpu_dm_connector =
@@ -1943,8 +2046,9 @@ amdgpu_dm_connector_late_register(struct drm_connector *connector)
return 0;
}
EXPORT_IF_KUNIT(amdgpu_dm_connector_late_register);
static void amdgpu_dm_connector_funcs_force(struct drm_connector *connector)
STATIC_IFN_KUNIT void amdgpu_dm_connector_funcs_force(struct drm_connector *connector)
{
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
struct dc_link *dc_link = aconnector->dc_link;
@@ -1980,6 +2084,7 @@ static void amdgpu_dm_connector_funcs_force(struct drm_connector *connector)
&dc_em_sink->edid_caps);
}
}
EXPORT_IF_KUNIT(amdgpu_dm_connector_funcs_force);
static const struct drm_connector_funcs amdgpu_dm_connector_funcs = {
.reset = amdgpu_dm_connector_funcs_reset,
@@ -2000,7 +2105,7 @@ static int get_modes(struct drm_connector *connector)
return amdgpu_dm_connector_get_modes(connector);
}
static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
STATIC_IFN_KUNIT void create_eml_sink(struct amdgpu_dm_connector *aconnector)
{
struct drm_connector *connector = &aconnector->base;
struct dc_link *dc_link = aconnector->dc_link;
@@ -2045,8 +2150,9 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
dc_sink_retain(aconnector->dc_sink);
}
}
EXPORT_IF_KUNIT(create_eml_sink);
static void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector)
STATIC_IFN_KUNIT void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector)
{
struct dc_link *link = (struct dc_link *)aconnector->dc_link;
@@ -2061,8 +2167,9 @@ static void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector)
create_eml_sink(aconnector);
}
EXPORT_IF_KUNIT(handle_edid_mgmt);
static enum dc_status dm_validate_stream_and_context(struct dc *dc,
STATIC_IFN_KUNIT enum dc_status dm_validate_stream_and_context(struct dc *dc,
struct dc_stream_state *stream)
{
enum dc_status dc_result = DC_ERROR_UNEXPECTED;
@@ -2124,6 +2231,7 @@ static enum dc_status dm_validate_stream_and_context(struct dc *dc,
return dc_result;
}
EXPORT_IF_KUNIT(dm_validate_stream_and_context);
static enum dc_status
dm_validate_stream_color_format(const struct drm_connector_state *drm_state,
@@ -2262,6 +2370,7 @@ amdgpu_dm_create_validate_stream_for_sink(struct drm_connector *connector,
return stream;
}
EXPORT_IF_KUNIT(amdgpu_dm_create_validate_stream_for_sink);
enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connector,
const struct drm_display_mode *mode)
@@ -2315,6 +2424,7 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec
/* TODO: error handling*/
return result;
}
EXPORT_IF_KUNIT(amdgpu_dm_connector_mode_valid);
int amdgpu_dm_fill_hdr_info_packet(const struct drm_connector_state *state,
struct dc_info_packet *out)
@@ -2529,7 +2639,7 @@ STATIC_IFN_KUNIT int to_drm_connector_type(enum signal_type st, uint32_t connect
}
EXPORT_IF_KUNIT(to_drm_connector_type);
static struct drm_encoder *amdgpu_dm_connector_to_encoder(struct drm_connector *connector)
STATIC_IFN_KUNIT struct drm_encoder *amdgpu_dm_connector_to_encoder(struct drm_connector *connector)
{
struct drm_encoder *encoder;
@@ -2539,8 +2649,9 @@ static struct drm_encoder *amdgpu_dm_connector_to_encoder(struct drm_connector *
return NULL;
}
EXPORT_IF_KUNIT(amdgpu_dm_connector_to_encoder);
static void amdgpu_dm_get_native_mode(struct drm_connector *connector)
STATIC_IFN_KUNIT void amdgpu_dm_get_native_mode(struct drm_connector *connector)
{
struct drm_encoder *encoder;
struct amdgpu_encoder *amdgpu_encoder;
@@ -2568,8 +2679,9 @@ static void amdgpu_dm_get_native_mode(struct drm_connector *connector)
}
}
EXPORT_IF_KUNIT(amdgpu_dm_get_native_mode);
static struct drm_display_mode *
STATIC_IFN_KUNIT struct drm_display_mode *
amdgpu_dm_create_common_mode(struct drm_encoder *encoder,
const char *name,
int hdisplay, int vdisplay)
@@ -2592,6 +2704,7 @@ amdgpu_dm_create_common_mode(struct drm_encoder *encoder,
return mode;
}
EXPORT_IF_KUNIT(amdgpu_dm_create_common_mode);
static const struct amdgpu_dm_mode_size {
char name[DRM_DISPLAY_MODE_LEN];
@@ -2611,7 +2724,7 @@ static const struct amdgpu_dm_mode_size {
{"1920x1200", 1920, 1200}
};
static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder,
STATIC_IFN_KUNIT void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder,
struct drm_connector *connector)
{
struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
@@ -2659,6 +2772,7 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder,
amdgpu_dm_connector->num_modes++;
}
}
EXPORT_IF_KUNIT(amdgpu_dm_connector_add_common_modes);
void amdgpu_set_panel_orientation(struct drm_connector *connector)
{
@@ -2690,7 +2804,48 @@ void amdgpu_set_panel_orientation(struct drm_connector *connector)
native_mode->vdisplay);
}
static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector,
/*
* The Apple Studio Display primary tile advertises both the full 5120x2880
* mode and the per-tile 2560x2880 timing. As the secondary tile is hidden from
* userspace (see amdgpu_dm_hide_secondary_tile_from_userspace()), drop the
* per-tile timing from the primary connector so compositors only pick the full
* 5K mode.
*/
static void amdgpu_dm_prune_primary_tile_modes(struct drm_connector *connector)
{
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
struct drm_display_mode *mode, *t;
if (!aconnector->dc_sink)
return;
if (!aconnector->dc_sink->edid_caps.panel_patch.disable_second_tile)
return;
if (!connector->has_tile)
return;
/* Only prune the per-tile timing from the primary tile. */
if (connector->tile_h_loc || connector->tile_v_loc)
return;
list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
if (mode->hdisplay != connector->tile_h_size ||
mode->vdisplay != connector->tile_v_size)
continue;
drm_dbg_kms(connector->dev,
"[CONNECTOR:%d:%s] pruning per-tile %dx%d timing from primary Apple Studio Display tile\n",
connector->base.id, connector->name,
mode->hdisplay, mode->vdisplay);
list_del(&mode->head);
drm_mode_destroy(connector->dev, mode);
aconnector->num_modes--;
}
}
STATIC_IFN_KUNIT void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector,
const struct drm_edid *drm_edid)
{
struct amdgpu_dm_connector *amdgpu_dm_connector =
@@ -2702,6 +2857,8 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector,
amdgpu_dm_connector->num_modes =
drm_edid_connector_add_modes(connector);
amdgpu_dm_prune_primary_tile_modes(connector);
/* sorting the probed modes before calling function
* amdgpu_dm_get_native_mode() since EDID can have
* more than one preferred mode. The modes that are
@@ -2722,6 +2879,7 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector,
amdgpu_dm_connector->num_modes = 0;
}
}
EXPORT_IF_KUNIT(amdgpu_dm_connector_ddc_get_modes);
STATIC_IFN_KUNIT bool is_duplicate_mode(struct amdgpu_dm_connector *aconnector,
struct drm_display_mode *mode)
@@ -2737,7 +2895,7 @@ STATIC_IFN_KUNIT bool is_duplicate_mode(struct amdgpu_dm_connector *aconnector,
}
EXPORT_IF_KUNIT(is_duplicate_mode);
static uint add_fs_modes(struct amdgpu_dm_connector *aconnector)
STATIC_IFN_KUNIT uint add_fs_modes(struct amdgpu_dm_connector *aconnector)
{
const struct drm_display_mode *m;
struct drm_display_mode *new_mode;
@@ -2812,8 +2970,9 @@ static uint add_fs_modes(struct amdgpu_dm_connector *aconnector)
out:
return new_modes_count;
}
EXPORT_IF_KUNIT(add_fs_modes);
static void amdgpu_dm_connector_add_freesync_modes(struct drm_connector *connector,
STATIC_IFN_KUNIT void amdgpu_dm_connector_add_freesync_modes(struct drm_connector *connector,
const struct drm_edid *drm_edid)
{
struct amdgpu_dm_connector *amdgpu_dm_connector =
@@ -2836,6 +2995,7 @@ static void amdgpu_dm_connector_add_freesync_modes(struct drm_connector *connect
amdgpu_dm_connector->num_modes +=
add_fs_modes(amdgpu_dm_connector);
}
EXPORT_IF_KUNIT(amdgpu_dm_connector_add_freesync_modes);
static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
{
@@ -3068,7 +3228,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
}
}
static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap,
STATIC_IFN_KUNIT int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg *msgs, int num)
{
struct amdgpu_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap);
@@ -3112,11 +3272,13 @@ static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap,
kfree(cmd.payloads);
return result;
}
EXPORT_IF_KUNIT(amdgpu_dm_i2c_xfer);
static u32 amdgpu_dm_i2c_func(struct i2c_adapter *adap)
STATIC_IFN_KUNIT u32 amdgpu_dm_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
EXPORT_IF_KUNIT(amdgpu_dm_i2c_func);
static const struct i2c_algorithm amdgpu_dm_i2c_algo = {
.master_xfer = amdgpu_dm_i2c_xfer,
@@ -3477,7 +3639,7 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
return ret;
}
static void parse_edid_displayid_vrr(struct drm_connector *connector,
STATIC_IFN_KUNIT void parse_edid_displayid_vrr(struct drm_connector *connector,
const struct edid *edid)
{
u8 *edid_ext = NULL;
@@ -3519,8 +3681,9 @@ static void parse_edid_displayid_vrr(struct drm_connector *connector,
j++;
}
}
EXPORT_IF_KUNIT(parse_edid_displayid_vrr);
static int get_amd_vsdb(struct amdgpu_dm_connector *aconnector,
STATIC_IFN_KUNIT int get_amd_vsdb(struct amdgpu_dm_connector *aconnector,
struct amdgpu_hdmi_vsdb_info *vsdb_info)
{
struct drm_connector *connector = &aconnector->base;
@@ -3530,8 +3693,9 @@ static int get_amd_vsdb(struct amdgpu_dm_connector *aconnector,
return connector->display_info.amd_vsdb.version != 0;
}
EXPORT_IF_KUNIT(get_amd_vsdb);
static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
STATIC_IFN_KUNIT int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
const struct edid *edid,
struct amdgpu_hdmi_vsdb_info *vsdb_info)
{
@@ -3562,6 +3726,7 @@ static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
return valid_vsdb_found ? i : -ENODEV;
}
EXPORT_IF_KUNIT(parse_hdmi_amd_vsdb);
/**
* amdgpu_dm_update_freesync_caps - Update Freesync capabilities

View File

@@ -146,6 +146,38 @@ int amdgpu_dm_encoder_init(struct drm_device *dev,
uint32_t link_index);
#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg *msgs, int num);
u32 amdgpu_dm_i2c_func(struct i2c_adapter *adap);
void parse_edid_displayid_vrr(struct drm_connector *connector,
const struct edid *edid);
int get_amd_vsdb(struct amdgpu_dm_connector *aconnector,
struct amdgpu_hdmi_vsdb_info *vsdb_info);
int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
const struct edid *edid,
struct amdgpu_hdmi_vsdb_info *vsdb_info);
void amdgpu_dm_connector_funcs_force(struct drm_connector *connector);
enum dc_status dm_validate_stream_and_context(struct dc *dc,
struct dc_stream_state *stream);
struct drm_encoder *amdgpu_dm_connector_to_encoder(struct drm_connector *connector);
void amdgpu_dm_get_native_mode(struct drm_connector *connector);
struct drm_display_mode *amdgpu_dm_create_common_mode(struct drm_encoder *encoder,
const char *name,
int hdisplay, int vdisplay);
void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder,
struct drm_connector *connector);
void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector,
const struct drm_edid *drm_edid);
uint add_fs_modes(struct amdgpu_dm_connector *aconnector);
void amdgpu_dm_connector_add_freesync_modes(struct drm_connector *connector,
const struct drm_edid *drm_edid);
void hdmi_cec_unset_edid(struct amdgpu_dm_connector *aconnector);
void create_eml_sink(struct amdgpu_dm_connector *aconnector);
void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector);
void dm_encoder_helper_disable(struct drm_encoder *encoder);
int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state);
enum drm_mode_subconnector get_subconnector_type(struct dc_link *link);
void update_subconnector_property(struct amdgpu_dm_connector *aconnector);
void amdgpu_dm_fbc_init(struct drm_connector *connector);
@@ -158,6 +190,19 @@ void fill_stream_properties_from_drm_display_mode(
const struct drm_connector_state *connector_state,
const struct dc_stream_state *old_stream,
int requested_bpc);
struct dc_stream_state *
create_stream_for_sink(struct drm_connector *connector,
const struct drm_display_mode *drm_mode,
const struct dm_connector_state *dm_state,
const struct dc_stream_state *old_stream,
int requested_bpc);
enum drm_connector_status
amdgpu_dm_connector_poll(struct amdgpu_dm_connector *aconnector, bool force);
enum drm_connector_status
amdgpu_dm_connector_detect(struct drm_connector *connector, bool force);
void amdgpu_dm_connector_unregister(struct drm_connector *connector);
int amdgpu_dm_connector_late_register(struct drm_connector *connector);
void amdgpu_dm_connector_destroy(struct drm_connector *connector);
enum display_content_type
get_output_content_type(const struct drm_connector_state *connector_state);
bool adjust_colour_depth_from_display_info(struct dc_crtc_timing *timing_out,

View File

@@ -33,7 +33,7 @@
#include "amdgpu_securedisplay.h"
#include "amdgpu_dm_psr.h"
#include "amdgpu_dm_replay.h"
#include "amdgpu_dm_kunit_helpers.h"
#include "dm_helpers.h"
static const char *const pipe_crc_sources[] = {
"none",
@@ -152,6 +152,7 @@ const char *const *amdgpu_dm_crtc_get_crc_sources(struct drm_crtc *crtc,
*count = ARRAY_SIZE(pipe_crc_sources);
return pipe_crc_sources;
}
EXPORT_IF_KUNIT(amdgpu_dm_crtc_get_crc_sources);
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
static void update_phy_id_mapping(struct amdgpu_device *adev)
@@ -564,6 +565,7 @@ amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc, const char *src_name,
*values_cnt = 3;
return 0;
}
EXPORT_IF_KUNIT(amdgpu_dm_crtc_verify_crc_source);
int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
struct dm_crtc_state *dm_crtc_state,
@@ -636,6 +638,7 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
return ret;
}
EXPORT_IF_KUNIT(amdgpu_dm_crtc_configure_crc_source);
int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
{
@@ -813,6 +816,7 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
return ret;
}
EXPORT_IF_KUNIT(amdgpu_dm_crtc_set_crc_source);
/**
* amdgpu_dm_crtc_handle_crc_irq: Report to DRM the CRC on given CRTC.
@@ -870,6 +874,7 @@ void amdgpu_dm_crtc_handle_crc_irq(struct drm_crtc *crtc)
drm_crtc_accurate_vblank_count(crtc), crcs);
}
}
EXPORT_IF_KUNIT(amdgpu_dm_crtc_handle_crc_irq);
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)

View File

@@ -34,7 +34,7 @@
#include "amdgpu_dm_plane.h"
#include "amdgpu_dm_trace.h"
#include "amdgpu_dm_debugfs.h"
#include "amdgpu_dm_kunit_helpers.h"
#include "dm_helpers.h"
#include "modules/inc/mod_power.h"
#define HPD_DETECTION_PERIOD_uS 2000000
@@ -287,10 +287,19 @@ static inline int amdgpu_dm_crtc_set_vblank(struct drm_crtc *crtc, bool enable)
* is enabled. On DCE, vupdate is only needed in VRR mode.
*/
if (amdgpu_ip_version(adev, DCE_HWIP, 0) != 0) {
rc = amdgpu_dm_crtc_set_vupdate_irq(crtc, enable);
if (enable) {
rc = amdgpu_irq_get(adev, &adev->vupdate_irq, irq_type);
drm_dbg_vbl(crtc->dev, "Get vupdate_irq ret=%d\n", rc);
} else {
rc = amdgpu_irq_put(adev, &adev->vupdate_irq, irq_type);
drm_dbg_vbl(crtc->dev, "Put vupdate_irq ret=%d\n", rc);
}
} else if (dc_supports_vrr(dm->dc->ctx->dce_version)) {
if (enable) {
/* vblank irq on -> Only need vupdate irq in vrr mode */
/* vblank irq on -> Only need vupdate irq in vrr mode
* Not ref-counted since we need explicit enable/disable
* for DCE VRR handling
*/
if (amdgpu_dm_crtc_vrr_active(acrtc_state))
rc = amdgpu_dm_crtc_set_vupdate_irq(crtc, true);
} else {

View File

@@ -0,0 +1,443 @@
// SPDX-License-Identifier: MIT
/*
* Copyright 2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_blend.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_plane.h>
#include <drm/drm_colorop.h>
#include "dc.h"
#include "dal_asic_id.h"
#include "amdgpu.h"
#include "amdgpu_display.h"
#include "amdgpu_dm.h"
#include "amdgpu_dm_plane.h"
#include "amdgpu_dm_cursor.h"
#include "dm_helpers.h"
static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc,
struct drm_plane_state *new_plane_state,
struct drm_framebuffer *fb)
{
struct amdgpu_device *adev = drm_to_adev(new_acrtc->base.dev);
struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb);
unsigned int pitch;
bool linear;
if (fb->width > new_acrtc->max_cursor_width ||
fb->height > new_acrtc->max_cursor_height) {
drm_dbg_atomic(adev_to_drm(adev), "Bad cursor FB size %dx%d\n",
new_plane_state->fb->width,
new_plane_state->fb->height);
return -EINVAL;
}
if (new_plane_state->src_w != fb->width << 16 ||
new_plane_state->src_h != fb->height << 16) {
drm_dbg_atomic(adev_to_drm(adev), "Cropping not supported for cursor plane\n");
return -EINVAL;
}
/* Pitch in pixels */
pitch = fb->pitches[0] / fb->format->cpp[0];
if (fb->width != pitch) {
drm_dbg_atomic(adev_to_drm(adev), "Cursor FB width %d doesn't match pitch %d",
fb->width, pitch);
return -EINVAL;
}
switch (pitch) {
case 64:
case 128:
case 256:
/* FB pitch is supported by cursor plane */
break;
default:
drm_dbg_atomic(adev_to_drm(adev), "Bad cursor FB pitch %d px\n", pitch);
return -EINVAL;
}
/* Core DRM takes care of checking FB modifiers, so we only need to
* check tiling flags when the FB doesn't have a modifier.
*/
if (!(fb->flags & DRM_MODE_FB_MODIFIERS)) {
#if defined(CONFIG_DRM_AMD_DC_DCN6_0) || defined(CONFIG_DRM_AMD_DC_DCN5_0)
if (adev->family == AMDGPU_FAMILY_GC_12_0_0
|| adev->family == AMDGPU_FAMILY_GC_13_0_1) {
#else
if (adev->family == AMDGPU_FAMILY_GC_12_0_0) {
#endif
linear = AMDGPU_TILING_GET(afb->tiling_flags, GFX12_SWIZZLE_MODE) == 0;
} else if (adev->family >= AMDGPU_FAMILY_AI) {
linear = AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE) == 0;
} else {
linear = AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_2D_TILED_THIN1 &&
AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_1D_TILED_THIN1 &&
AMDGPU_TILING_GET(afb->tiling_flags, MICRO_TILE_MODE) == 0;
}
if (!linear) {
drm_dbg_atomic(adev_to_drm(adev), "Cursor FB not linear");
return -EINVAL;
}
}
return 0;
}
/*
* Helper function for checking the cursor in native mode
*/
int amdgpu_dm_check_native_cursor_state(struct drm_crtc *new_plane_crtc,
struct drm_plane *plane,
struct drm_plane_state *new_plane_state,
bool enable)
{
struct amdgpu_crtc *new_acrtc;
int ret;
if (!enable || !new_plane_crtc ||
drm_atomic_plane_disabling(plane->state, new_plane_state))
return 0;
new_acrtc = to_amdgpu_crtc(new_plane_crtc);
if (new_plane_state->src_x != 0 || new_plane_state->src_y != 0) {
drm_dbg_atomic(new_plane_crtc->dev, "Cropping not supported for cursor plane\n");
return -EINVAL;
}
if (new_plane_state->fb) {
ret = dm_check_cursor_fb(new_acrtc, new_plane_state,
new_plane_state->fb);
if (ret)
return ret;
}
return 0;
}
bool amdgpu_dm_should_update_native_cursor(struct drm_atomic_commit *state,
struct drm_crtc *old_plane_crtc,
struct drm_crtc *new_plane_crtc,
bool enable)
{
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
if (!enable) {
if (old_plane_crtc == NULL)
return true;
old_crtc_state = drm_atomic_get_old_crtc_state(
state, old_plane_crtc);
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
return dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE;
}
if (new_plane_crtc == NULL)
return true;
new_crtc_state = drm_atomic_get_new_crtc_state(
state, new_plane_crtc);
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
return dm_new_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE;
}
EXPORT_IF_KUNIT(amdgpu_dm_should_update_native_cursor);
STATIC_IFN_KUNIT void dm_get_oriented_plane_size(struct drm_plane_state *plane_state,
int *src_w, int *src_h)
{
switch (plane_state->rotation & DRM_MODE_ROTATE_MASK) {
case DRM_MODE_ROTATE_90:
case DRM_MODE_ROTATE_270:
*src_w = plane_state->src_h >> 16;
*src_h = plane_state->src_w >> 16;
break;
case DRM_MODE_ROTATE_0:
case DRM_MODE_ROTATE_180:
default:
*src_w = plane_state->src_w >> 16;
*src_h = plane_state->src_h >> 16;
break;
}
}
EXPORT_IF_KUNIT(dm_get_oriented_plane_size);
STATIC_IFN_KUNIT void
dm_get_plane_scale(struct drm_plane_state *plane_state,
int *out_plane_scale_w, int *out_plane_scale_h)
{
int plane_src_w, plane_src_h;
dm_get_oriented_plane_size(plane_state, &plane_src_w, &plane_src_h);
*out_plane_scale_w = plane_src_w ? plane_state->crtc_w * 1000 / plane_src_w : 0;
*out_plane_scale_h = plane_src_h ? plane_state->crtc_h * 1000 / plane_src_h : 0;
}
EXPORT_IF_KUNIT(dm_get_plane_scale);
/**
* DOC: Cursor Modes - Native vs Overlay
*
* In native mode, the cursor uses a integrated cursor pipe within each DCN hw
* plane. It does not require a dedicated hw plane to enable, but it is
* subjected to the same z-order and scaling as the hw plane. It also has format
* restrictions, a RGB cursor in native mode cannot be enabled within a non-RGB
* hw plane.
*
* In overlay mode, the cursor uses a separate DCN hw plane, and thus has its
* own scaling and z-pos. It also has no blending restrictions. It lends to a
* cursor behavior more akin to a DRM client's expectations. However, it does
* occupy an extra DCN plane, and therefore will only be used if a DCN plane is
* available.
*/
/**
* dm_plane_color_pipeline_active() - Check if a plane's color pipeline active.
* @state: DRM atomic state
* @plane: DRM plane to check
* @use_old: if true, inspect the old colorop states; otherwise the new ones
*
* A color pipeline may be selected (color_pipeline != NULL) but still is
* inactive if every colorop in the chain is bypassed. Only return
* true when at least one colorop has bypass == false, meaning the cursor
* would be subjected to the transformation in native mode.
*
* Return: true if the pipeline modifies pixels, false otherwise.
*/
static bool dm_plane_color_pipeline_active(struct drm_atomic_commit *state,
struct drm_plane *plane,
bool use_old)
{
struct drm_colorop *colorop;
struct drm_colorop_state *old_colorop_state, *new_colorop_state;
int i;
for_each_oldnew_colorop_in_state(state, colorop, old_colorop_state, new_colorop_state, i) {
struct drm_colorop_state *cstate = use_old ? old_colorop_state : new_colorop_state;
if (cstate->colorop->plane != plane)
continue;
if (!cstate->bypass)
return true;
}
return false;
}
/**
* amdgpu_dm_crtc_get_cursor_mode() - Determine the required cursor mode on crtc
* @adev: amdgpu device
* @state: DRM atomic state
* @dm_crtc_state: amdgpu state for the CRTC containing the cursor
* @cursor_mode: Returns the required cursor mode on dm_crtc_state
*
* Get whether the cursor should be enabled in native mode, or overlay mode, on
* the dm_crtc_state.
*
* The cursor should be enabled in overlay mode if there exists an underlying
* plane - on which the cursor may be blended - that is either YUV formatted,
* scaled differently from the cursor, or has a color pipeline active.
*
* Since zpos info is required, drm_atomic_normalize_zpos must be called before
* calling this function.
*
* Return: 0 on success, or an error code if getting the cursor plane state
* failed.
*/
int amdgpu_dm_crtc_get_cursor_mode(struct amdgpu_device *adev,
struct drm_atomic_commit *state,
struct dm_crtc_state *dm_crtc_state,
enum amdgpu_dm_cursor_mode *cursor_mode)
{
struct drm_plane_state *old_plane_state, *plane_state, *cursor_state;
struct drm_crtc_state *crtc_state = &dm_crtc_state->base;
struct drm_plane *plane;
bool consider_mode_change = false;
bool entire_crtc_covered = false;
bool cursor_changed = false;
int underlying_scale_w, underlying_scale_h;
int cursor_scale_w, cursor_scale_h;
int i;
/* Overlay cursor not supported on HW before DCN
* DCN401/420 does not have the cursor-on-scaled-plane or cursor-on-yuv-plane restrictions
* as previous DCN generations, so enable native mode on DCN401/420
*/
if (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1) ||
amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 0) ||
#if defined(CONFIG_DRM_AMD_DC_DCN6_0)
amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 1) ||
amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(6, 0, 0)) {
#else
amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 1)) {
#endif
*cursor_mode = DM_CURSOR_NATIVE_MODE;
return 0;
}
/* Init cursor_mode to be the same as current */
*cursor_mode = dm_crtc_state->cursor_mode;
/*
* Cursor mode can change if a plane's format changes, scale changes, is
* enabled/disabled, z-order changes, or color management properties change.
*/
for_each_oldnew_plane_in_state(state, plane, old_plane_state, plane_state, i) {
int new_scale_w, new_scale_h, old_scale_w, old_scale_h;
/* Only care about planes on this CRTC */
if ((drm_plane_mask(plane) & crtc_state->plane_mask) == 0)
continue;
if (plane->type == DRM_PLANE_TYPE_CURSOR)
cursor_changed = true;
if (drm_atomic_plane_enabling(old_plane_state, plane_state) ||
drm_atomic_plane_disabling(old_plane_state, plane_state) ||
old_plane_state->fb->format != plane_state->fb->format) {
consider_mode_change = true;
break;
}
dm_get_plane_scale(plane_state, &new_scale_w, &new_scale_h);
dm_get_plane_scale(old_plane_state, &old_scale_w, &old_scale_h);
if (new_scale_w != old_scale_w || new_scale_h != old_scale_h) {
consider_mode_change = true;
break;
}
/*
* A non-cursor plane moving or resizing (without a scale change)
* changes how much of the CRTC it covers. This can create or
* remove a hole under the cursor and thus flip the required
* cursor mode (native vs overlay), so its destination rect must
* be re-evaluated too.
*
* The cursor plane itself is deliberately excluded: the cursor
* mode depends on the underlying planes' coverage, not on the
* cursor's position (see the entire_crtc_covered logic below).
* Triggering on cursor movement would force every legacy cursor
* update off its fast path, and in a cursor-only commit - where
* the underlying planes are not part of the state - the coverage
* loop would see no covering plane and misevaluate the mode as
* overlay, regressing flip-vs-cursor-legacy.
*/
if (plane->type != DRM_PLANE_TYPE_CURSOR &&
(old_plane_state->crtc_x != plane_state->crtc_x ||
old_plane_state->crtc_y != plane_state->crtc_y ||
old_plane_state->crtc_w != plane_state->crtc_w ||
old_plane_state->crtc_h != plane_state->crtc_h)) {
consider_mode_change = true;
break;
}
if (dm_plane_color_pipeline_active(state, plane, true) !=
dm_plane_color_pipeline_active(state, plane, false)) {
consider_mode_change = true;
break;
}
}
if (!consider_mode_change && !crtc_state->zpos_changed)
return 0;
/*
* If no cursor change on this CRTC, and not enabled on this CRTC, then
* no need to set cursor mode. This avoids needlessly locking the cursor
* state.
*/
if (!cursor_changed &&
!(drm_plane_mask(crtc_state->crtc->cursor) & crtc_state->plane_mask)) {
return 0;
}
cursor_state = drm_atomic_get_plane_state(state,
crtc_state->crtc->cursor);
if (IS_ERR(cursor_state))
return PTR_ERR(cursor_state);
/* Cursor is disabled */
if (!cursor_state->fb)
return 0;
/* For all planes in descending z-order (all of which are below cursor
* as per zpos definitions), check their scaling and format
*/
for_each_oldnew_plane_in_descending_zpos(state, plane, old_plane_state, plane_state) {
/* Only care about non-cursor planes on this CRTC */
if ((drm_plane_mask(plane) & crtc_state->plane_mask) == 0 ||
plane->type == DRM_PLANE_TYPE_CURSOR)
continue;
/* Underlying plane is YUV format - use overlay cursor */
if (amdgpu_dm_plane_is_video_format(plane_state->fb->format->format)) {
*cursor_mode = DM_CURSOR_OVERLAY_MODE;
return 0;
}
/* Underlying plane has an active color pipeline - cursor would be transformed */
if (dm_plane_color_pipeline_active(state, plane, false)) {
*cursor_mode = DM_CURSOR_OVERLAY_MODE;
return 0;
}
dm_get_plane_scale(plane_state,
&underlying_scale_w, &underlying_scale_h);
dm_get_plane_scale(cursor_state,
&cursor_scale_w, &cursor_scale_h);
/* Underlying plane has different scale - use overlay cursor */
if (cursor_scale_w != underlying_scale_w &&
cursor_scale_h != underlying_scale_h) {
*cursor_mode = DM_CURSOR_OVERLAY_MODE;
return 0;
}
/* If this plane covers the whole CRTC, no need to check planes underneath */
if (plane_state->crtc_x <= 0 && plane_state->crtc_y <= 0 &&
plane_state->crtc_x + plane_state->crtc_w >= crtc_state->mode.hdisplay &&
plane_state->crtc_y + plane_state->crtc_h >= crtc_state->mode.vdisplay) {
entire_crtc_covered = true;
break;
}
}
/* If planes do not cover the entire CRTC, use overlay mode to enable
* cursor over holes
*/
if (entire_crtc_covered)
*cursor_mode = DM_CURSOR_NATIVE_MODE;
else
*cursor_mode = DM_CURSOR_OVERLAY_MODE;
return 0;
}

View File

@@ -0,0 +1,52 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright 2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#ifndef __AMDGPU_DM_CURSOR_H__
#define __AMDGPU_DM_CURSOR_H__
int amdgpu_dm_check_native_cursor_state(struct drm_crtc *new_plane_crtc,
struct drm_plane *plane,
struct drm_plane_state *new_plane_state,
bool enable);
bool amdgpu_dm_should_update_native_cursor(struct drm_atomic_commit *state,
struct drm_crtc *old_plane_crtc,
struct drm_crtc *new_plane_crtc,
bool enable);
int amdgpu_dm_crtc_get_cursor_mode(struct amdgpu_device *adev,
struct drm_atomic_commit *state,
struct dm_crtc_state *dm_crtc_state,
enum amdgpu_dm_cursor_mode *cursor_mode);
#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
void dm_get_oriented_plane_size(struct drm_plane_state *plane_state,
int *src_w, int *src_h);
void dm_get_plane_scale(struct drm_plane_state *plane_state,
int *out_plane_scale_w, int *out_plane_scale_h);
#endif /* CONFIG_DRM_AMD_DC_KUNIT_TEST */
#endif /* __AMDGPU_DM_CURSOR_H__ */

View File

@@ -38,7 +38,7 @@
#include "amdgpu_ucode.h"
#include "amdgpu_dm.h"
#include "amdgpu_dm_dmub.h"
#include "amdgpu_dm_kunit_helpers.h"
#include "dm_helpers.h"
#include <linux/component.h>
#include <linux/firmware.h>
@@ -385,7 +385,7 @@ dm_dmub_send_vbios_gpint_command(struct amdgpu_device *adev,
return DMUB_STATUS_TIMEOUT;
}
static void *dm_dmub_get_vbios_bounding_box(struct amdgpu_device *adev)
STATIC_IFN_KUNIT void *dm_dmub_get_vbios_bounding_box(struct amdgpu_device *adev)
{
void *bb;
long long addr;
@@ -440,6 +440,7 @@ static void *dm_dmub_get_vbios_bounding_box(struct amdgpu_device *adev)
return NULL;
}
EXPORT_IF_KUNIT(dm_dmub_get_vbios_bounding_box);
enum dmub_ips_disable_type dm_get_default_ips_mode(
struct amdgpu_device *adev)
@@ -829,8 +830,9 @@ int amdgpu_dm_process_dmub_aux_transfer_sync(
mutex_unlock(&adev->dm.dpia_aux_lock);
return ret;
}
EXPORT_IF_KUNIT(amdgpu_dm_process_dmub_aux_transfer_sync);
static void abort_fused_io(
STATIC_IFN_KUNIT void abort_fused_io(
struct dc_context *ctx,
const struct dmub_cmd_fused_request *request
)
@@ -844,6 +846,7 @@ static void abort_fused_io(
io->request = *request;
dm_execute_dmub_cmd(ctx, &command, DM_DMUB_WAIT_TYPE_NO_WAIT);
}
EXPORT_IF_KUNIT(abort_fused_io);
static bool execute_fused_io(
struct amdgpu_device *dev,
@@ -931,6 +934,7 @@ int amdgpu_dm_process_dmub_set_config_sync(
mutex_unlock(&adev->dm.dpia_aux_lock);
return ret;
}
EXPORT_IF_KUNIT(amdgpu_dm_process_dmub_set_config_sync);
bool dm_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type)
{
@@ -939,6 +943,7 @@ bool dm_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd, e
guard(spinlock_irqsave)(&adev->dm.dmub_lock);
return dc_dmub_srv_cmd_run(ctx->dmub_srv, cmd, wait_type);
}
EXPORT_IF_KUNIT(dm_execute_dmub_cmd);
bool dm_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type)
{

View File

@@ -65,4 +65,13 @@ int dm_init_microcode(struct amdgpu_device *adev);
#define FIRMWARE_RAVEN_DMCU "amdgpu/raven_dmcu.bin"
#define FIRMWARE_NAVI12_DMCU "amdgpu/navi12_dmcu.bin"
#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
struct dc_context;
struct dmub_cmd_fused_request;
void *dm_dmub_get_vbios_bounding_box(struct amdgpu_device *adev);
void abort_fused_io(struct dc_context *ctx,
const struct dmub_cmd_fused_request *request);
#endif
#endif /* AMDGPU_DM_AMDGPU_DM_DMUB_H_ */

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