mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
amd-drm-next-7.3-2026-07-31:
amdgpu: - PM sysfs fix for APUs - DC pageflip timeout fixes - New GFX7 soft reset implementation - Misc code cleanup amdkfd: - Remove svm_bo eviction fence -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCamy9NAAKCRC93/aFa7yZ 2NmJAP9dfXEzqxC4xoozErqmDsAHd5zCYtD80aJSyNfQuZkzhQEAnCogTQDJPK5u 67LKXehWeCYJBx38gk412ZesZUYoKQE= =+H72 -----END PGP SIGNATURE----- Merge tag 'amd-drm-next-7.3-2026-07-31' of https://gitlab.freedesktop.org/agd5f/linux into drm-next amd-drm-next-7.3-2026-07-31: amdgpu: - PM sysfs fix for APUs - DC pageflip timeout fixes - New GFX7 soft reset implementation - Misc code cleanup amdkfd: - Remove svm_bo eviction fence Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patch.msgid.link/20260731153253.1393962-1-alexander.deucher@amd.com
This commit is contained in:
commit
24893f3f08
|
|
@ -973,24 +973,3 @@ 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,6 @@ struct amdgpu_amdkfd_fence {
|
|||
struct mm_struct *mm;
|
||||
spinlock_t lock;
|
||||
char timeline_name[TASK_COMM_LEN];
|
||||
struct svm_range_bo *svm_bo;
|
||||
uint16_t context_id;
|
||||
};
|
||||
|
||||
|
|
@ -194,7 +193,6 @@ int amdgpu_queue_mask_bit_to_set_resource_bit(struct amdgpu_device *adev,
|
|||
|
||||
struct amdgpu_amdkfd_fence *amdgpu_amdkfd_fence_create(u64 context,
|
||||
struct mm_struct *mm,
|
||||
struct svm_range_bo *svm_bo,
|
||||
u16 context_id);
|
||||
|
||||
int amdgpu_amdkfd_drm_client_create(struct amdgpu_device *adev);
|
||||
|
|
@ -286,7 +284,6 @@ 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
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ static atomic_t fence_seq = ATOMIC_INIT(0);
|
|||
|
||||
struct amdgpu_amdkfd_fence *amdgpu_amdkfd_fence_create(u64 context,
|
||||
struct mm_struct *mm,
|
||||
struct svm_range_bo *svm_bo,
|
||||
u16 context_id)
|
||||
{
|
||||
struct amdgpu_amdkfd_fence *fence;
|
||||
|
|
@ -76,7 +75,6 @@ struct amdgpu_amdkfd_fence *amdgpu_amdkfd_fence_create(u64 context,
|
|||
fence->mm = mm;
|
||||
get_task_comm(fence->timeline_name, current);
|
||||
spin_lock_init(&fence->lock);
|
||||
fence->svm_bo = svm_bo;
|
||||
fence->context_id = context_id;
|
||||
dma_fence_init(&fence->base, &amdkfd_fence_ops, &fence->lock,
|
||||
context, atomic_inc_return(&fence_seq));
|
||||
|
|
@ -128,14 +126,8 @@ static bool amdkfd_fence_enable_signaling(struct dma_fence *f)
|
|||
if (dma_fence_is_signaled(f))
|
||||
return true;
|
||||
|
||||
/* if fence->svm_bo is NULL, means this fence is created through
|
||||
* init_kfd_vm() or amdgpu_amdkfd_gpuvm_restore_process_bos().
|
||||
* Therefore, this fence is amdgpu_amdkfd_fence->eviction_fence.
|
||||
*/
|
||||
if (!fence->svm_bo) {
|
||||
if (!kgd2kfd_schedule_evict_and_restore_process(fence->mm, fence->context_id, f))
|
||||
return true;
|
||||
}
|
||||
if (!kgd2kfd_schedule_evict_and_restore_process(fence->mm, fence->context_id, f))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -169,7 +161,6 @@ static void amdkfd_fence_release(struct dma_fence *f)
|
|||
*
|
||||
* Check if @mm is same as that of the fence @f, if same return TRUE else
|
||||
* return FALSE.
|
||||
* For svm bo, which support vram overcommitment, always return FALSE.
|
||||
*/
|
||||
bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm)
|
||||
{
|
||||
|
|
@ -177,7 +168,7 @@ bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm)
|
|||
|
||||
if (!fence)
|
||||
return false;
|
||||
else if (fence->mm == mm && !fence->svm_bo)
|
||||
else if (fence->mm == mm)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1423,7 +1423,7 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info,
|
|||
info->eviction_fence =
|
||||
amdgpu_amdkfd_fence_create(dma_fence_context_alloc(1),
|
||||
current->mm,
|
||||
NULL, process->context_id);
|
||||
process->context_id);
|
||||
if (!info->eviction_fence) {
|
||||
pr_err("Failed to create eviction fence\n");
|
||||
ret = -ENOMEM;
|
||||
|
|
@ -3093,7 +3093,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu *
|
|||
amdgpu_amdkfd_fence_create(
|
||||
process_info->eviction_fence->base.context,
|
||||
process_info->eviction_fence->mm,
|
||||
NULL, process_info->context_id);
|
||||
process_info->context_id);
|
||||
|
||||
if (!new_fence) {
|
||||
pr_err("Failed to create eviction fence\n");
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "amdgpu_xcp.h"
|
||||
#include "amdgpu_xgmi.h"
|
||||
#include "amdgpu_mes.h"
|
||||
#include "amdgpu_userq.h"
|
||||
#include "mes_userqueue.h"
|
||||
#include "nvd.h"
|
||||
|
||||
|
|
@ -419,8 +420,8 @@ int amdgpu_gfx_mqd_sw_init(struct amdgpu_device *adev,
|
|||
domain |= AMDGPU_GEM_DOMAIN_VRAM;
|
||||
#endif
|
||||
|
||||
/* create MQD for KIQ */
|
||||
if (!adev->enable_mes_kiq && !ring->mqd_obj) {
|
||||
/* create MQD for KIQ (on GFX8+ where we use KIQ) */
|
||||
if (adev->asic_type >= CHIP_TOPAZ && !adev->enable_mes_kiq && !ring->mqd_obj) {
|
||||
/* originaly the KIQ MQD is put in GTT domain, but for SRIOV VRAM domain is a must
|
||||
* otherwise hypervisor trigger SAVE_VF fail after driver unloaded which mean MQD
|
||||
* deallocated and gart_unbind, to strict diverage we decide to use VRAM domain for
|
||||
|
|
@ -855,6 +856,59 @@ int amdgpu_gfx_enable_kgq(struct amdgpu_device *adev, int xcc_id)
|
|||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_gfx_handle_priv_fault - Handle privileged instruction fault
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @entry: interrupt vector entry containing fault information
|
||||
* @me_id: micro-engine ID of the faulty ring
|
||||
* @pipe_id: pipe ID of the faulty ring
|
||||
* @queue_id: queue ID of the faulty ring
|
||||
*
|
||||
* This function handles privileged instruction faults by identifying
|
||||
* the faulty ring (gfx or compute) and triggering a scheduler fault
|
||||
*/
|
||||
void amdgpu_gfx_handle_priv_fault(struct amdgpu_device *adev,
|
||||
struct amdgpu_iv_entry *entry,
|
||||
u8 me_id, u8 pipe_id, u8 queue_id)
|
||||
{
|
||||
struct amdgpu_ring *ring;
|
||||
u32 doorbell_offset;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Try KQ first by ring_id (HW slot is authoritative). The
|
||||
* KMD compute_hqd_mask contract guarantees KCQ and user queues
|
||||
* never share a HW slot.
|
||||
*/
|
||||
if (!adev->gfx.disable_kq) {
|
||||
for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
|
||||
ring = &adev->gfx.gfx_ring[i];
|
||||
if (ring->me == me_id && ring->pipe == pipe_id &&
|
||||
ring->queue == queue_id) {
|
||||
drm_sched_fault(&ring->sched);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
|
||||
ring = &adev->gfx.compute_ring[i];
|
||||
if (ring->me == me_id && ring->pipe == pipe_id &&
|
||||
ring->queue == queue_id) {
|
||||
drm_sched_fault(&ring->sched);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doorbell_offset = entry->src_data[0] & AMDGPU_CTXID0_DOORBELL_ID_MASK;
|
||||
|
||||
/* No KQ matched: HW slot is a MES-scheduled user queue. */
|
||||
if (adev->enable_mes && doorbell_offset)
|
||||
amdgpu_userq_process_reset_irq(adev, entry->pasid,
|
||||
doorbell_offset);
|
||||
}
|
||||
|
||||
static void amdgpu_gfx_do_off_ctrl(struct amdgpu_device *adev, bool enable,
|
||||
bool no_delay)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -620,6 +620,9 @@ bool amdgpu_gfx_is_high_priority_graphics_queue(struct amdgpu_device *adev,
|
|||
struct amdgpu_ring *ring);
|
||||
bool amdgpu_gfx_is_me_queue_enabled(struct amdgpu_device *adev, int me,
|
||||
int pipe, int queue);
|
||||
void amdgpu_gfx_handle_priv_fault(struct amdgpu_device *adev,
|
||||
struct amdgpu_iv_entry *entry,
|
||||
u8 me_id, u8 pipe_id, u8 queue_id);
|
||||
void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable);
|
||||
void amdgpu_gfx_off_ctrl_immediate(struct amdgpu_device *adev, bool enable);
|
||||
int amdgpu_get_gfx_off_status(struct amdgpu_device *adev, uint32_t *value);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#include "amdgpu_vram_mgr.h"
|
||||
#include "amdgpu_vm.h"
|
||||
#include "amdgpu_dma_buf.h"
|
||||
#include "kfd_svm.h"
|
||||
|
||||
/**
|
||||
* DOC: amdgpu_object
|
||||
|
|
@ -93,7 +94,8 @@ static void amdgpu_bo_user_destroy(struct ttm_buffer_object *tbo)
|
|||
bool amdgpu_bo_is_amdgpu_bo(struct ttm_buffer_object *bo)
|
||||
{
|
||||
if (bo->destroy == &amdgpu_bo_destroy ||
|
||||
bo->destroy == &amdgpu_bo_user_destroy)
|
||||
bo->destroy == &amdgpu_bo_user_destroy ||
|
||||
bo->destroy == &svm_range_bo_destroy)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@
|
|||
#include "amdgpu_atomfirmware.h"
|
||||
#include "amdgpu_res_cursor.h"
|
||||
#include "bif/bif_4_1_d.h"
|
||||
#include "kfd_svm.h"
|
||||
|
||||
MODULE_IMPORT_NS("DMA_BUF");
|
||||
|
||||
|
|
@ -1499,7 +1500,8 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
|
|||
return true;
|
||||
|
||||
abo = ttm_to_amdgpu_bo(bo);
|
||||
if (abo->flags & AMDGPU_GEM_CREATE_DISCARDABLE) {
|
||||
if ((abo->flags & AMDGPU_GEM_CREATE_DISCARDABLE) &&
|
||||
bo->destroy == &svm_range_bo_destroy) {
|
||||
/*
|
||||
* SVM BOs are migrated to system memory synchronously in this
|
||||
* TTM eviction context. The migration needs the owning
|
||||
|
|
@ -1509,7 +1511,7 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
|
|||
* 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)
|
||||
if (svm_range_evict_svm_bo(abo) < 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -892,7 +892,12 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
|
|||
|
||||
amdgpu_ring_patch_cond_exec(ring, patch);
|
||||
|
||||
/* the double SWITCH_BUFFER here *cannot* be skipped by COND_EXEC */
|
||||
/*
|
||||
* Sync CE with ME to prevent CE from fetching the next CE IB
|
||||
* before the context switch is done. This is emitted before
|
||||
* the first IB of a job submission after a context switch.
|
||||
* The double SWITCH_BUFFER here *cannot* be skipped by COND_EXEC.
|
||||
*/
|
||||
if (ring->funcs->emit_switch_buffer) {
|
||||
amdgpu_ring_emit_switch_buffer(ring);
|
||||
amdgpu_ring_emit_switch_buffer(ring);
|
||||
|
|
|
|||
|
|
@ -6714,51 +6714,13 @@ static int gfx_v11_0_set_priv_inst_fault_state(struct amdgpu_device *adev,
|
|||
static void gfx_v11_0_handle_priv_fault(struct amdgpu_device *adev,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
u32 doorbell_offset = entry->src_data[0] & AMDGPU_CTXID0_DOORBELL_ID_MASK;
|
||||
u8 me_id, pipe_id, queue_id;
|
||||
|
||||
/*
|
||||
* Try KQ first by ring_id (HW slot is authoritative). The
|
||||
* KMD compute_hqd_mask contract guarantees KCQ and user queues
|
||||
* never share a HW slot.
|
||||
*/
|
||||
if (!adev->gfx.disable_kq) {
|
||||
u8 me_id = (entry->ring_id & 0x0c) >> 2;
|
||||
u8 pipe_id = (entry->ring_id & 0x03) >> 0;
|
||||
u8 queue_id = (entry->ring_id & 0x70) >> 4;
|
||||
struct amdgpu_ring *ring;
|
||||
int i;
|
||||
me_id = (entry->ring_id & 0x0c) >> 2;
|
||||
pipe_id = (entry->ring_id & 0x03) >> 0;
|
||||
queue_id = (entry->ring_id & 0x70) >> 4;
|
||||
|
||||
switch (me_id) {
|
||||
case 0:
|
||||
for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
|
||||
ring = &adev->gfx.gfx_ring[i];
|
||||
if (ring->me == me_id && ring->pipe == pipe_id &&
|
||||
ring->queue == queue_id) {
|
||||
drm_sched_fault(&ring->sched);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
|
||||
ring = &adev->gfx.compute_ring[i];
|
||||
if (ring->me == me_id && ring->pipe == pipe_id &&
|
||||
ring->queue == queue_id) {
|
||||
drm_sched_fault(&ring->sched);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* No KQ matched: HW slot is a MES-scheduled user queue. */
|
||||
if (adev->enable_mes && doorbell_offset)
|
||||
amdgpu_userq_process_reset_irq(adev, entry->pasid,
|
||||
doorbell_offset);
|
||||
amdgpu_gfx_handle_priv_fault(adev, entry, me_id, pipe_id, queue_id);
|
||||
}
|
||||
|
||||
static int gfx_v11_0_priv_reg_irq(struct amdgpu_device *adev,
|
||||
|
|
|
|||
|
|
@ -5045,52 +5045,13 @@ static int gfx_v12_0_set_priv_inst_fault_state(struct amdgpu_device *adev,
|
|||
static void gfx_v12_0_handle_priv_fault(struct amdgpu_device *adev,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
u32 doorbell_offset = entry->src_data[0] & AMDGPU_CTXID0_DOORBELL_ID_MASK;
|
||||
u8 me_id, pipe_id, queue_id;
|
||||
|
||||
/*
|
||||
* Try KQ first by ring_id; UQ as fallback. KCQ and UQ never share
|
||||
* a HW slot (compute_hqd_mask contract).
|
||||
*/
|
||||
if (!adev->gfx.disable_kq) {
|
||||
u8 me_id, pipe_id, queue_id;
|
||||
struct amdgpu_ring *ring;
|
||||
int i;
|
||||
me_id = (entry->ring_id & 0x0c) >> 2;
|
||||
pipe_id = (entry->ring_id & 0x03) >> 0;
|
||||
queue_id = (entry->ring_id & 0x70) >> 4;
|
||||
|
||||
me_id = (entry->ring_id & 0x0c) >> 2;
|
||||
pipe_id = (entry->ring_id & 0x03) >> 0;
|
||||
queue_id = (entry->ring_id & 0x70) >> 4;
|
||||
|
||||
switch (me_id) {
|
||||
case 0:
|
||||
for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
|
||||
ring = &adev->gfx.gfx_ring[i];
|
||||
if (ring->me == me_id && ring->pipe == pipe_id &&
|
||||
ring->queue == queue_id) {
|
||||
drm_sched_fault(&ring->sched);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
|
||||
ring = &adev->gfx.compute_ring[i];
|
||||
if (ring->me == me_id && ring->pipe == pipe_id &&
|
||||
ring->queue == queue_id) {
|
||||
drm_sched_fault(&ring->sched);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* No KQ matched: HW slot is a MES-scheduled user queue. */
|
||||
if (adev->enable_mes && doorbell_offset)
|
||||
amdgpu_userq_process_reset_irq(adev, entry->pasid,
|
||||
doorbell_offset);
|
||||
amdgpu_gfx_handle_priv_fault(adev, entry, me_id, pipe_id, queue_id);
|
||||
}
|
||||
|
||||
static int gfx_v12_0_priv_reg_irq(struct amdgpu_device *adev,
|
||||
|
|
|
|||
|
|
@ -2202,12 +2202,6 @@ static void gfx_v7_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
|
|||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
u32 header, control = 0;
|
||||
|
||||
/* insert SWITCH_BUFFER packet before first IB in the ring frame */
|
||||
if (flags & AMDGPU_HAVE_CTX_SWITCH) {
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
}
|
||||
|
||||
if (ib->flags & AMDGPU_IB_FLAG_CE)
|
||||
header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2);
|
||||
else
|
||||
|
|
@ -2259,6 +2253,12 @@ static void gfx_v7_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
|
|||
amdgpu_ring_write(ring, control);
|
||||
}
|
||||
|
||||
static void gfx_v7_0_ring_emit_sb(struct amdgpu_ring *ring)
|
||||
{
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
}
|
||||
|
||||
static void gfx_v7_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags)
|
||||
{
|
||||
uint32_t dw2 = 0;
|
||||
|
|
@ -2547,8 +2547,12 @@ static int gfx_v7_0_cp_gfx_resume(struct amdgpu_device *adev)
|
|||
WREG32(mmSCRATCH_ADDR, 0);
|
||||
|
||||
/* ring 0 - compute and gfx */
|
||||
/* Set ring buffer size */
|
||||
ring = &adev->gfx.gfx_ring[0];
|
||||
*ring->wptr_cpu_addr = 0;
|
||||
*ring->rptr_cpu_addr = 0;
|
||||
amdgpu_ring_clear_ring(ring);
|
||||
|
||||
/* Set ring buffer size */
|
||||
rb_bufsz = order_base_2(ring->ring_size / 8);
|
||||
tmp = (order_base_2(AMDGPU_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
|
||||
#ifdef __BIG_ENDIAN
|
||||
|
|
@ -2560,6 +2564,7 @@ static int gfx_v7_0_cp_gfx_resume(struct amdgpu_device *adev)
|
|||
WREG32(mmCP_RB0_CNTL, tmp | CP_RB0_CNTL__RB_RPTR_WR_ENA_MASK);
|
||||
ring->wptr = 0;
|
||||
WREG32(mmCP_RB0_WPTR, lower_32_bits(ring->wptr));
|
||||
WREG32(mmCP_RB0_RPTR, lower_32_bits(ring->wptr));
|
||||
|
||||
/* set the wb address whether it's enabled or not */
|
||||
rptr_addr = ring->rptr_gpu_addr;
|
||||
|
|
@ -2577,7 +2582,10 @@ static int gfx_v7_0_cp_gfx_resume(struct amdgpu_device *adev)
|
|||
WREG32(mmCP_RB0_BASE_HI, upper_32_bits(rb_addr));
|
||||
|
||||
/* start the ring */
|
||||
gfx_v7_0_cp_gfx_start(adev);
|
||||
r = gfx_v7_0_cp_gfx_start(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
return r;
|
||||
|
|
@ -2699,25 +2707,6 @@ static int gfx_v7_0_cp_compute_load_microcode(struct amdgpu_device *adev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gfx_v7_0_cp_compute_fini - stop the compute queues
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Stop the compute queues and tear down the driver queue
|
||||
* info.
|
||||
*/
|
||||
static void gfx_v7_0_cp_compute_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
|
||||
struct amdgpu_ring *ring = &adev->gfx.compute_ring[i];
|
||||
|
||||
amdgpu_bo_free_kernel(&ring->mqd_obj, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_v7_0_mec_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_bo_free_kernel(&adev->gfx.mec.hpd_eop_obj, NULL, NULL);
|
||||
|
|
@ -2789,28 +2778,29 @@ static void gfx_v7_0_compute_pipe_init(struct amdgpu_device *adev,
|
|||
mutex_unlock(&adev->srbm_mutex);
|
||||
}
|
||||
|
||||
static int gfx_v7_0_mqd_deactivate(struct amdgpu_device *adev)
|
||||
static int gfx_v7_0_deactivate_hqd(struct amdgpu_device *adev, u32 req)
|
||||
{
|
||||
int i;
|
||||
int i, r = 0;
|
||||
|
||||
/* disable the queue if it's active */
|
||||
if (RREG32(mmCP_HQD_ACTIVE) & 1) {
|
||||
WREG32(mmCP_HQD_DEQUEUE_REQUEST, 1);
|
||||
if (RREG32(mmCP_HQD_ACTIVE) & CP_HQD_ACTIVE__ACTIVE_MASK) {
|
||||
WREG32_FIELD(CP_HQD_DEQUEUE_REQUEST, DEQUEUE_REQ, req);
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
if (!(RREG32(mmCP_HQD_ACTIVE) & 1))
|
||||
if (!(RREG32(mmCP_HQD_ACTIVE) & CP_HQD_ACTIVE__ACTIVE_MASK))
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
if (i == adev->usec_timeout)
|
||||
return -ETIMEDOUT;
|
||||
r = -ETIMEDOUT;
|
||||
|
||||
WREG32(mmCP_HQD_DEQUEUE_REQUEST, 0);
|
||||
WREG32(mmCP_HQD_PQ_RPTR, 0);
|
||||
WREG32(mmCP_HQD_PQ_WPTR, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
WREG32(mmCP_HQD_DEQUEUE_REQUEST, 0);
|
||||
WREG32(mmCP_HQD_PQ_RPTR, 0);
|
||||
WREG32(mmCP_HQD_PQ_WPTR, 0);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void gfx_v7_0_mqd_init(struct amdgpu_device *adev,
|
||||
|
|
@ -2965,31 +2955,42 @@ static int gfx_v7_0_mqd_commit(struct amdgpu_device *adev, struct cik_mqd *mqd)
|
|||
|
||||
static int gfx_v7_0_compute_queue_init(struct amdgpu_device *adev, int ring_id)
|
||||
{
|
||||
int r;
|
||||
u64 mqd_gpu_addr;
|
||||
struct cik_mqd *mqd;
|
||||
struct amdgpu_ring *ring = &adev->gfx.compute_ring[ring_id];
|
||||
struct cik_mqd *mqd = ring->mqd_ptr;
|
||||
int mqd_idx = ring - &adev->gfx.compute_ring[0];
|
||||
|
||||
r = amdgpu_bo_create_reserved(adev, sizeof(struct cik_mqd), PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_GTT, &ring->mqd_obj,
|
||||
&mqd_gpu_addr, (void **)&mqd);
|
||||
if (r) {
|
||||
dev_warn(adev->dev, "(%d) create MQD bo failed\n", r);
|
||||
return r;
|
||||
if (!amdgpu_in_reset(adev) && !adev->in_suspend) {
|
||||
memset((void *)mqd, 0, ring->mqd_size);
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
cik_srbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
|
||||
gfx_v7_0_mqd_init(adev, mqd, ring->mqd_gpu_addr, ring);
|
||||
gfx_v7_0_deactivate_hqd(adev, 1);
|
||||
gfx_v7_0_mqd_commit(adev, mqd);
|
||||
cik_srbm_select(adev, 0, 0, 0, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
|
||||
if (adev->gfx.mec.mqd_backup[mqd_idx])
|
||||
memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, ring->mqd_size);
|
||||
} else {
|
||||
/* restore MQD to a clean status */
|
||||
if (adev->gfx.mec.mqd_backup[mqd_idx])
|
||||
memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], ring->mqd_size);
|
||||
|
||||
/* Re-commit the restored backup */
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
cik_srbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
|
||||
gfx_v7_0_deactivate_hqd(adev, 2);
|
||||
gfx_v7_0_mqd_commit(adev, mqd);
|
||||
cik_srbm_select(adev, 0, 0, 0, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
|
||||
/* reset ring buffer */
|
||||
ring->wptr = 0;
|
||||
atomic64_set((atomic64_t *)ring->wptr_cpu_addr, 0);
|
||||
atomic64_set((atomic64_t *)ring->rptr_cpu_addr, 0);
|
||||
amdgpu_ring_clear_ring(ring);
|
||||
}
|
||||
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
cik_srbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
|
||||
|
||||
gfx_v7_0_mqd_init(adev, mqd, mqd_gpu_addr, ring);
|
||||
gfx_v7_0_mqd_deactivate(adev);
|
||||
gfx_v7_0_mqd_commit(adev, mqd);
|
||||
|
||||
cik_srbm_select(adev, 0, 0, 0, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
|
||||
amdgpu_bo_kunmap(ring->mqd_obj);
|
||||
amdgpu_bo_unreserve(ring->mqd_obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3021,20 +3022,20 @@ static int gfx_v7_0_cp_compute_resume(struct amdgpu_device *adev)
|
|||
/* init the queues */
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
|
||||
r = gfx_v7_0_compute_queue_init(adev, i);
|
||||
if (r) {
|
||||
gfx_v7_0_cp_compute_fini(adev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
gfx_v7_0_cp_compute_enable(adev, true);
|
||||
|
||||
r = 0;
|
||||
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
|
||||
ring = &adev->gfx.compute_ring[i];
|
||||
amdgpu_ring_test_helper(ring);
|
||||
r |= amdgpu_ring_test_helper(ring);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
static void gfx_v7_0_cp_enable(struct amdgpu_device *adev, bool enable)
|
||||
|
|
@ -3116,14 +3117,6 @@ static void gfx_v7_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
|
|||
amdgpu_ring_write(ring, seq);
|
||||
amdgpu_ring_write(ring, 0xffffffff);
|
||||
amdgpu_ring_write(ring, 4); /* poll interval */
|
||||
|
||||
if (usepfp) {
|
||||
/* sync CE with ME to prevent CE fetch CEIB before context switch done */
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -3165,15 +3158,25 @@ static void gfx_v7_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
|
|||
/* sync PFP to ME, otherwise we might get invalid PFP reads */
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
|
||||
amdgpu_ring_write(ring, 0x0);
|
||||
|
||||
/* synce CE with ME to prevent CE fetch CEIB before context switch done */
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int gfx_v7_0_ring_emit_init_cond_exec(struct amdgpu_ring *ring,
|
||||
uint64_t gpu_addr)
|
||||
{
|
||||
unsigned int ret;
|
||||
|
||||
/* Discard following DWs after this packet when gpu_addr==0 */
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_COND_EXEC, 3));
|
||||
amdgpu_ring_write(ring, lower_32_bits(gpu_addr));
|
||||
amdgpu_ring_write(ring, upper_32_bits(gpu_addr));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
ret = ring->wptr & ring->buf_mask;
|
||||
/* patch dummy value later */
|
||||
amdgpu_ring_write(ring, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void gfx_v7_0_ring_emit_wreg(struct amdgpu_ring *ring,
|
||||
uint32_t reg, uint32_t val)
|
||||
{
|
||||
|
|
@ -3614,21 +3617,6 @@ static void gfx_v7_0_enable_mgcg(struct amdgpu_device *adev, bool enable)
|
|||
}
|
||||
}
|
||||
|
||||
static void gfx_v7_0_update_cg(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
gfx_v7_0_enable_gui_idle_interrupt(adev, false);
|
||||
/* order matters! */
|
||||
if (enable) {
|
||||
gfx_v7_0_enable_mgcg(adev, true);
|
||||
gfx_v7_0_enable_cgcg(adev, true);
|
||||
} else {
|
||||
gfx_v7_0_enable_cgcg(adev, false);
|
||||
gfx_v7_0_enable_mgcg(adev, false);
|
||||
}
|
||||
gfx_v7_0_enable_gui_idle_interrupt(adev, true);
|
||||
}
|
||||
|
||||
static void gfx_v7_0_enable_sclk_slowdown_on_pu(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
|
|
@ -4431,6 +4419,11 @@ static int gfx_v7_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
}
|
||||
}
|
||||
|
||||
/* create MQD for all compute queues */
|
||||
r = amdgpu_gfx_mqd_sw_init(adev, sizeof(struct cik_mqd), 0);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
adev->gfx.ce_ram_size = 0x8000;
|
||||
|
||||
gfx_v7_0_gpu_early_init(adev);
|
||||
|
|
@ -4440,6 +4433,11 @@ static int gfx_v7_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
adev->gfx.compute_supported_reset =
|
||||
amdgpu_get_soft_full_reset_mask(&adev->gfx.compute_ring[0]);
|
||||
|
||||
if (!amdgpu_sriov_vf(adev) && !adev->debug_disable_ip_block_soft_reset) {
|
||||
adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_IP_BLOCK_SOFT_RESET;
|
||||
adev->gfx.gfx_supported_reset |= AMDGPU_RESET_TYPE_IP_BLOCK_SOFT_RESET;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -4453,7 +4451,7 @@ static int gfx_v7_0_sw_fini(struct amdgpu_ip_block *ip_block)
|
|||
for (i = 0; i < adev->gfx.num_compute_rings; i++)
|
||||
amdgpu_ring_fini(&adev->gfx.compute_ring[i]);
|
||||
|
||||
gfx_v7_0_cp_compute_fini(adev);
|
||||
amdgpu_gfx_mqd_sw_fini(adev, 0);
|
||||
amdgpu_gfx_rlc_fini(adev);
|
||||
gfx_v7_0_mec_fini(adev);
|
||||
amdgpu_bo_free_kernel(&adev->gfx.rlc.clear_state_obj,
|
||||
|
|
@ -4542,80 +4540,99 @@ static int gfx_v7_0_wait_for_idle(struct amdgpu_ip_block *ip_block)
|
|||
|
||||
static int gfx_v7_0_soft_reset(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
|
||||
u32 tmp;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
int i;
|
||||
int r;
|
||||
|
||||
/* GRBM_STATUS */
|
||||
tmp = RREG32(mmGRBM_STATUS);
|
||||
if (tmp & (GRBM_STATUS__PA_BUSY_MASK | GRBM_STATUS__SC_BUSY_MASK |
|
||||
GRBM_STATUS__BCI_BUSY_MASK | GRBM_STATUS__SX_BUSY_MASK |
|
||||
GRBM_STATUS__TA_BUSY_MASK | GRBM_STATUS__VGT_BUSY_MASK |
|
||||
GRBM_STATUS__DB_BUSY_MASK | GRBM_STATUS__CB_BUSY_MASK |
|
||||
GRBM_STATUS__GDS_BUSY_MASK | GRBM_STATUS__SPI_BUSY_MASK |
|
||||
GRBM_STATUS__IA_BUSY_MASK | GRBM_STATUS__IA_BUSY_NO_DMA_MASK))
|
||||
grbm_soft_reset |= GRBM_SOFT_RESET__SOFT_RESET_CP_MASK |
|
||||
GRBM_SOFT_RESET__SOFT_RESET_GFX_MASK;
|
||||
grbm_soft_reset =
|
||||
REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_RLC, 1) |
|
||||
REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_GFX, 1) |
|
||||
REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_CP, 1) |
|
||||
REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_CPF, 1) |
|
||||
REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_CPC, 1) |
|
||||
REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_CPG, 1);
|
||||
|
||||
if (tmp & (GRBM_STATUS__CP_BUSY_MASK | GRBM_STATUS__CP_COHERENCY_BUSY_MASK)) {
|
||||
grbm_soft_reset |= GRBM_SOFT_RESET__SOFT_RESET_CP_MASK;
|
||||
srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_GRBM_MASK;
|
||||
}
|
||||
srbm_soft_reset =
|
||||
REG_SET_FIELD(0, SRBM_SOFT_RESET, SOFT_RESET_GRBM, 1) |
|
||||
REG_SET_FIELD(0, SRBM_SOFT_RESET, SOFT_RESET_SEM, 1);
|
||||
|
||||
/* GRBM_STATUS2 */
|
||||
tmp = RREG32(mmGRBM_STATUS2);
|
||||
if (tmp & GRBM_STATUS2__RLC_BUSY_MASK)
|
||||
grbm_soft_reset |= GRBM_SOFT_RESET__SOFT_RESET_RLC_MASK;
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
|
||||
struct amdgpu_ring *ring = &adev->gfx.compute_ring[i];
|
||||
|
||||
/* SRBM_STATUS */
|
||||
tmp = RREG32(mmSRBM_STATUS);
|
||||
if (tmp & SRBM_STATUS__GRBM_RQ_PENDING_MASK)
|
||||
srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_GRBM_MASK;
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
cik_srbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
|
||||
gfx_v7_0_deactivate_hqd(adev, 2);
|
||||
cik_srbm_select(adev, 0, 0, 0, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
|
||||
if (grbm_soft_reset || srbm_soft_reset) {
|
||||
/* disable CG/PG */
|
||||
gfx_v7_0_fini_pg(adev);
|
||||
gfx_v7_0_update_cg(adev, false);
|
||||
|
||||
/* stop the rlc */
|
||||
adev->gfx.rlc.funcs->stop(adev);
|
||||
|
||||
/* Disable GFX parsing/prefetching */
|
||||
WREG32(mmCP_ME_CNTL, CP_ME_CNTL__ME_HALT_MASK | CP_ME_CNTL__PFP_HALT_MASK | CP_ME_CNTL__CE_HALT_MASK);
|
||||
|
||||
/* Disable MEC parsing/prefetching */
|
||||
WREG32(mmCP_MEC_CNTL, CP_MEC_CNTL__MEC_ME1_HALT_MASK | CP_MEC_CNTL__MEC_ME2_HALT_MASK);
|
||||
|
||||
if (grbm_soft_reset) {
|
||||
tmp = RREG32(mmGRBM_SOFT_RESET);
|
||||
tmp |= grbm_soft_reset;
|
||||
dev_info(adev->dev, "GRBM_SOFT_RESET=0x%08X\n", tmp);
|
||||
WREG32(mmGRBM_SOFT_RESET, tmp);
|
||||
tmp = RREG32(mmGRBM_SOFT_RESET);
|
||||
|
||||
udelay(50);
|
||||
|
||||
tmp &= ~grbm_soft_reset;
|
||||
WREG32(mmGRBM_SOFT_RESET, tmp);
|
||||
tmp = RREG32(mmGRBM_SOFT_RESET);
|
||||
}
|
||||
|
||||
if (srbm_soft_reset) {
|
||||
tmp = RREG32(mmSRBM_SOFT_RESET);
|
||||
tmp |= srbm_soft_reset;
|
||||
dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
|
||||
WREG32(mmSRBM_SOFT_RESET, tmp);
|
||||
tmp = RREG32(mmSRBM_SOFT_RESET);
|
||||
|
||||
udelay(50);
|
||||
|
||||
tmp &= ~srbm_soft_reset;
|
||||
WREG32(mmSRBM_SOFT_RESET, tmp);
|
||||
tmp = RREG32(mmSRBM_SOFT_RESET);
|
||||
}
|
||||
/* Wait a little for things to settle down */
|
||||
udelay(50);
|
||||
}
|
||||
|
||||
ip_block->version->funcs->set_clockgating_state(ip_block, AMD_CG_STATE_UNGATE);
|
||||
ip_block->version->funcs->set_powergating_state(ip_block, AMD_PG_STATE_UNGATE);
|
||||
ip_block->version->funcs->suspend(ip_block);
|
||||
|
||||
if (grbm_soft_reset || srbm_soft_reset) {
|
||||
tmp = RREG32(mmGMCON_DEBUG);
|
||||
tmp = REG_SET_FIELD(tmp, GMCON_DEBUG, GFX_STALL, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GMCON_DEBUG, GFX_CLEAR, 1);
|
||||
WREG32(mmGMCON_DEBUG, tmp);
|
||||
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
if (grbm_soft_reset) {
|
||||
tmp = RREG32(mmGRBM_SOFT_RESET);
|
||||
tmp |= grbm_soft_reset;
|
||||
dev_info(adev->dev, "GRBM_SOFT_RESET=0x%08X\n", tmp);
|
||||
WREG32(mmGRBM_SOFT_RESET, tmp);
|
||||
tmp = RREG32(mmGRBM_SOFT_RESET);
|
||||
|
||||
udelay(100);
|
||||
|
||||
tmp &= ~grbm_soft_reset;
|
||||
WREG32(mmGRBM_SOFT_RESET, tmp);
|
||||
tmp = RREG32(mmGRBM_SOFT_RESET);
|
||||
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
if (srbm_soft_reset) {
|
||||
tmp = RREG32(mmSRBM_SOFT_RESET);
|
||||
tmp |= srbm_soft_reset;
|
||||
dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
|
||||
WREG32(mmSRBM_SOFT_RESET, tmp);
|
||||
tmp = RREG32(mmSRBM_SOFT_RESET);
|
||||
|
||||
udelay(100);
|
||||
|
||||
tmp &= ~srbm_soft_reset;
|
||||
WREG32(mmSRBM_SOFT_RESET, tmp);
|
||||
tmp = RREG32(mmSRBM_SOFT_RESET);
|
||||
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
if (grbm_soft_reset || srbm_soft_reset) {
|
||||
tmp = RREG32(mmGMCON_DEBUG);
|
||||
tmp = REG_SET_FIELD(tmp, GMCON_DEBUG, GFX_STALL, 0);
|
||||
tmp = REG_SET_FIELD(tmp, GMCON_DEBUG, GFX_CLEAR, 0);
|
||||
WREG32(mmGMCON_DEBUG, tmp);
|
||||
}
|
||||
|
||||
/* Wait a little for things to settle down */
|
||||
udelay(100);
|
||||
|
||||
r = ip_block->version->funcs->resume(ip_block);
|
||||
r |= ip_block->version->funcs->late_init(ip_block);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ip_block->version->funcs->set_clockgating_state(ip_block, AMD_CG_STATE_GATE);
|
||||
ip_block->version->funcs->set_powergating_state(ip_block, AMD_PG_STATE_GATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -4950,12 +4967,15 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = {
|
|||
.get_wptr = gfx_v7_0_ring_get_wptr_gfx,
|
||||
.set_wptr = gfx_v7_0_ring_set_wptr_gfx,
|
||||
.emit_frame_size =
|
||||
5 + /* gfx_v7_0_ring_emit_init_cond_exec (from amdgpu_ib_schedule) */
|
||||
5 + /* gfx_v7_0_ring_emit_init_cond_exec (from amdgpu_vm_flush) */
|
||||
20 + /* gfx_v7_0_ring_emit_gds_switch */
|
||||
7 + /* gfx_v7_0_ring_emit_hdp_flush */
|
||||
5 + /* hdp invalidate */
|
||||
12 + 12 + 12 + /* gfx_v7_0_ring_emit_fence_gfx x3 for user fence, vm fence */
|
||||
7 + 4 + /* gfx_v7_0_ring_emit_pipeline_sync */
|
||||
CIK_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + 6 + /* gfx_v7_0_ring_emit_vm_flush */
|
||||
7 + /* gfx_v7_0_ring_emit_pipeline_sync */
|
||||
CIK_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + 2 + /* gfx_v7_0_ring_emit_vm_flush */
|
||||
3 * 2 + /* gfx_v7_0_ring_emit_sb x3 (from amdgpu_vm_flush, amdgpu_ib_schedule) */
|
||||
3 + 4 + /* gfx_v7_ring_emit_cntxcntl including vgt flush*/
|
||||
5, /* SURFACE_SYNC */
|
||||
.emit_ib_size = 4, /* gfx_v7_0_ring_emit_ib_gfx */
|
||||
|
|
@ -4969,7 +4989,9 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = {
|
|||
.test_ib = gfx_v7_0_ring_test_ib,
|
||||
.insert_nop = amdgpu_ring_insert_nop,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.emit_switch_buffer = gfx_v7_0_ring_emit_sb,
|
||||
.emit_cntxcntl = gfx_v7_ring_emit_cntxcntl,
|
||||
.init_cond_exec = gfx_v7_0_ring_emit_init_cond_exec,
|
||||
.emit_wreg = gfx_v7_0_ring_emit_wreg,
|
||||
.soft_recovery = gfx_v7_0_ring_soft_recovery,
|
||||
.emit_mem_sync = gfx_v7_0_emit_mem_sync,
|
||||
|
|
@ -4984,6 +5006,8 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = {
|
|||
.get_wptr = gfx_v7_0_ring_get_wptr_compute,
|
||||
.set_wptr = gfx_v7_0_ring_set_wptr_compute,
|
||||
.emit_frame_size =
|
||||
5 + /* gfx_v7_0_ring_emit_init_cond_exec (from amdgpu_ib_schedule) */
|
||||
5 + /* gfx_v7_0_ring_emit_init_cond_exec (from amdgpu_vm_flush) */
|
||||
20 + /* gfx_v7_0_ring_emit_gds_switch */
|
||||
7 + /* gfx_v7_0_ring_emit_hdp_flush */
|
||||
5 + /* hdp invalidate */
|
||||
|
|
@ -5002,6 +5026,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = {
|
|||
.test_ib = gfx_v7_0_ring_test_ib,
|
||||
.insert_nop = amdgpu_ring_insert_nop,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.init_cond_exec = gfx_v7_0_ring_emit_init_cond_exec,
|
||||
.emit_wreg = gfx_v7_0_ring_emit_wreg,
|
||||
.soft_recovery = gfx_v7_0_ring_soft_recovery,
|
||||
.emit_mem_sync = gfx_v7_0_emit_mem_sync_compute,
|
||||
|
|
|
|||
|
|
@ -954,12 +954,12 @@ static vm_fault_t svm_migrate_to_ram(struct vm_fault *vmf)
|
|||
pr_debug("failed get device page at addr 0x%lx\n", addr);
|
||||
return VM_FAULT_SIGBUS;
|
||||
}
|
||||
if (!mmget_not_zero(svm_bo->eviction_fence->mm)) {
|
||||
if (!mmget_not_zero(svm_bo->mm)) {
|
||||
pr_debug("addr 0x%lx of process mm is destroyed\n", addr);
|
||||
return VM_FAULT_SIGBUS;
|
||||
}
|
||||
|
||||
mm = svm_bo->eviction_fence->mm;
|
||||
mm = svm_bo->mm;
|
||||
if (mm != vmf->vma->vm_mm)
|
||||
pr_debug("addr 0x%lx is COW mapping in child process\n", addr);
|
||||
|
||||
|
|
|
|||
|
|
@ -390,8 +390,10 @@ static bool svm_bo_ref_unless_zero(struct svm_range_bo *svm_bo)
|
|||
static void svm_range_bo_release(struct kref *kref)
|
||||
{
|
||||
struct svm_range_bo *svm_bo;
|
||||
struct amdgpu_bo *bo;
|
||||
|
||||
svm_bo = container_of(kref, struct svm_range_bo, kref);
|
||||
bo = &svm_bo->bo;
|
||||
pr_debug("svm_bo 0x%p\n", svm_bo);
|
||||
|
||||
spin_lock(&svm_bo->list_lock);
|
||||
|
|
@ -417,12 +419,12 @@ static void svm_range_bo_release(struct kref *kref)
|
|||
}
|
||||
spin_unlock(&svm_bo->list_lock);
|
||||
|
||||
if (mmget_not_zero(svm_bo->eviction_fence->mm)) {
|
||||
if (mmget_not_zero(svm_bo->mm)) {
|
||||
struct kfd_process_device *pdd;
|
||||
struct kfd_process *p;
|
||||
struct mm_struct *mm;
|
||||
|
||||
mm = svm_bo->eviction_fence->mm;
|
||||
mm = svm_bo->mm;
|
||||
/*
|
||||
* The forked child process takes svm_bo device pages ref, svm_bo could be
|
||||
* released after parent process is gone.
|
||||
|
|
@ -431,18 +433,13 @@ static void svm_range_bo_release(struct kref *kref)
|
|||
if (p) {
|
||||
pdd = kfd_get_process_device_data(svm_bo->node, p);
|
||||
if (pdd)
|
||||
atomic64_sub(amdgpu_bo_size(svm_bo->bo), &pdd->vram_usage);
|
||||
atomic64_sub(amdgpu_bo_size(bo), &pdd->vram_usage);
|
||||
kfd_unref_process(p);
|
||||
}
|
||||
mmput(mm);
|
||||
}
|
||||
|
||||
if (!dma_fence_is_signaled(&svm_bo->eviction_fence->base))
|
||||
/* We're not in the eviction worker. Signal the fence. */
|
||||
dma_fence_signal(&svm_bo->eviction_fence->base);
|
||||
dma_fence_put(&svm_bo->eviction_fence->base);
|
||||
amdgpu_bo_unref(&svm_bo->bo);
|
||||
kfree(svm_bo);
|
||||
amdgpu_bo_unref(&bo);
|
||||
}
|
||||
|
||||
static void svm_range_bo_wq_release(struct work_struct *work)
|
||||
|
|
@ -504,20 +501,11 @@ svm_range_validate_svm_bo(struct kfd_node *node, struct svm_range *prange)
|
|||
return false;
|
||||
}
|
||||
if (READ_ONCE(prange->svm_bo->evicting)) {
|
||||
struct dma_fence *f;
|
||||
struct svm_range_bo *svm_bo;
|
||||
/* The BO is getting evicted,
|
||||
* we need to get a new one
|
||||
*/
|
||||
mutex_unlock(&prange->lock);
|
||||
svm_bo = prange->svm_bo;
|
||||
f = dma_fence_get(&svm_bo->eviction_fence->base);
|
||||
svm_range_bo_unref(prange->svm_bo);
|
||||
/* wait for the fence to avoid long spin-loop
|
||||
* at list_empty_careful
|
||||
*/
|
||||
dma_fence_wait(f, false);
|
||||
dma_fence_put(f);
|
||||
} else {
|
||||
/* The BO was still around and we got
|
||||
* a new reference to it
|
||||
|
|
@ -526,7 +514,7 @@ svm_range_validate_svm_bo(struct kfd_node *node, struct svm_range *prange)
|
|||
pr_debug("reuse old bo svms 0x%p [0x%lx 0x%lx]\n",
|
||||
prange->svms, prange->start, prange->last);
|
||||
|
||||
prange->ttm_res = prange->svm_bo->bo->tbo.resource;
|
||||
prange->ttm_res = prange->svm_bo->bo.tbo.resource;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -545,19 +533,22 @@ svm_range_validate_svm_bo(struct kfd_node *node, struct svm_range *prange)
|
|||
return false;
|
||||
}
|
||||
|
||||
static struct svm_range_bo *svm_range_bo_new(void)
|
||||
#define to_svm_range_bo(bo) container_of((bo), struct svm_range_bo, bo)
|
||||
|
||||
void svm_range_bo_destroy(struct ttm_buffer_object *tbo)
|
||||
{
|
||||
struct svm_range_bo *svm_bo;
|
||||
struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo);
|
||||
struct svm_range_bo *svm_bo = to_svm_range_bo(bo);
|
||||
|
||||
svm_bo = kzalloc_obj(*svm_bo);
|
||||
if (!svm_bo)
|
||||
return NULL;
|
||||
|
||||
kref_init(&svm_bo->kref);
|
||||
INIT_LIST_HEAD(&svm_bo->range_list);
|
||||
spin_lock_init(&svm_bo->list_lock);
|
||||
|
||||
return svm_bo;
|
||||
drm_gem_object_release(&bo->tbo.base);
|
||||
/*
|
||||
* svm_bo->mm is only set once the BO is fully created. If
|
||||
* ttm_bo_init_reserved() fails (e.g. no VRAM could be evicted), it
|
||||
* calls this destroy callback with mm still NULL, so guard the drop.
|
||||
*/
|
||||
if (svm_bo->mm)
|
||||
mmdrop(svm_bo->mm);
|
||||
kvfree(svm_bo);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -567,7 +558,6 @@ svm_range_vram_node_new(struct kfd_node *node, struct svm_range *prange,
|
|||
struct kfd_process_device *pdd;
|
||||
struct amdgpu_bo_param bp;
|
||||
struct svm_range_bo *svm_bo;
|
||||
struct amdgpu_bo_user *ubo;
|
||||
struct amdgpu_bo *bo;
|
||||
struct kfd_process *p;
|
||||
struct mm_struct *mm;
|
||||
|
|
@ -581,26 +571,16 @@ svm_range_vram_node_new(struct kfd_node *node, struct svm_range *prange,
|
|||
if (svm_range_validate_svm_bo(node, prange))
|
||||
return 0;
|
||||
|
||||
svm_bo = svm_range_bo_new();
|
||||
if (!svm_bo) {
|
||||
pr_debug("failed to alloc svm bo\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
mm = get_task_mm(p->lead_thread);
|
||||
if (!mm) {
|
||||
pr_debug("failed to get mm\n");
|
||||
kfree(svm_bo);
|
||||
return -ESRCH;
|
||||
}
|
||||
svm_bo->node = node;
|
||||
svm_bo->eviction_fence =
|
||||
amdgpu_amdkfd_fence_create(dma_fence_context_alloc(1),
|
||||
mm,
|
||||
svm_bo, p->context_id);
|
||||
mmput(mm);
|
||||
svm_bo->evicting = 0;
|
||||
|
||||
memset(&bp, 0, sizeof(bp));
|
||||
bp.size = prange->npages * PAGE_SIZE;
|
||||
bp.bo_ptr_size = sizeof(struct svm_range_bo);
|
||||
bp.destroy = svm_range_bo_destroy;
|
||||
bp.byte_align = PAGE_SIZE;
|
||||
bp.domain = AMDGPU_GEM_DOMAIN_VRAM;
|
||||
bp.flags = AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
|
||||
|
|
@ -611,12 +591,23 @@ svm_range_vram_node_new(struct kfd_node *node, struct svm_range *prange,
|
|||
if (node->xcp)
|
||||
bp.xcp_id_plus1 = node->xcp->id + 1;
|
||||
|
||||
r = amdgpu_bo_create_user(node->adev, &bp, &ubo);
|
||||
r = amdgpu_bo_create(node->adev, &bp, &bo);
|
||||
if (r) {
|
||||
pr_debug("failed %d to create bo\n", r);
|
||||
mmput(mm);
|
||||
goto create_bo_failed;
|
||||
}
|
||||
bo = &ubo->bo;
|
||||
|
||||
svm_bo = to_svm_range_bo(bo);
|
||||
svm_bo->evicting = 0;
|
||||
kref_init(&svm_bo->kref);
|
||||
INIT_LIST_HEAD(&svm_bo->range_list);
|
||||
spin_lock_init(&svm_bo->list_lock);
|
||||
|
||||
svm_bo->node = node;
|
||||
svm_bo->mm = mm;
|
||||
mmgrab(svm_bo->mm);
|
||||
mmput(mm);
|
||||
|
||||
pr_debug("alloc bo at offset 0x%lx size 0x%lx on partition %d\n",
|
||||
bo->tbo.resource->start << PAGE_SHIFT, bp.size,
|
||||
|
|
@ -637,16 +628,8 @@ svm_range_vram_node_new(struct kfd_node *node, struct svm_range *prange,
|
|||
}
|
||||
}
|
||||
|
||||
r = dma_resv_reserve_fences(bo->tbo.base.resv, TTM_NUM_MOVE_FENCES);
|
||||
if (r) {
|
||||
amdgpu_bo_unreserve(bo);
|
||||
goto reserve_bo_failed;
|
||||
}
|
||||
amdgpu_bo_fence(bo, &svm_bo->eviction_fence->base, true);
|
||||
|
||||
amdgpu_bo_unreserve(bo);
|
||||
|
||||
svm_bo->bo = bo;
|
||||
prange->svm_bo = svm_bo;
|
||||
prange->ttm_res = bo->tbo.resource;
|
||||
prange->offset = 0;
|
||||
|
|
@ -664,9 +647,6 @@ svm_range_vram_node_new(struct kfd_node *node, struct svm_range *prange,
|
|||
reserve_bo_failed:
|
||||
amdgpu_bo_unref(&bo);
|
||||
create_bo_failed:
|
||||
dma_fence_put(&svm_bo->eviction_fence->base);
|
||||
kfree(svm_bo);
|
||||
prange->ttm_res = NULL;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
@ -3640,19 +3620,20 @@ svm_range_trigger_migration(struct mm_struct *mm, struct svm_range *prange,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int svm_range_evict_svm_bo(struct svm_range_bo *svm_bo)
|
||||
int svm_range_evict_svm_bo(struct amdgpu_bo *bo)
|
||||
{
|
||||
struct svm_range_bo *svm_bo = to_svm_range_bo(bo);
|
||||
struct mm_struct *mm;
|
||||
int r = 0;
|
||||
|
||||
if (!svm_bo_ref_unless_zero(svm_bo))
|
||||
return 0;
|
||||
|
||||
if (!mmget_not_zero(svm_bo->eviction_fence->mm)) {
|
||||
if (!mmget_not_zero(svm_bo->mm)) {
|
||||
svm_range_bo_unref(svm_bo);
|
||||
return 0;
|
||||
}
|
||||
mm = svm_bo->eviction_fence->mm;
|
||||
mm = svm_bo->mm;
|
||||
|
||||
/*
|
||||
* Called with the BO reserved; lock order is mmap_lock -> BO
|
||||
|
|
@ -3721,14 +3702,6 @@ int svm_range_evict_svm_bo(struct svm_range_bo *svm_bo)
|
|||
/* Defer mmput: exit_mmap() must not run under the BO reservation. */
|
||||
mmput_async(mm);
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -39,11 +39,11 @@
|
|||
((adev)->hive ? (void *)(adev)->hive : (void *)(adev))
|
||||
|
||||
struct svm_range_bo {
|
||||
struct amdgpu_bo *bo;
|
||||
struct amdgpu_bo bo;
|
||||
struct kref kref;
|
||||
struct list_head range_list; /* all svm ranges shared this bo */
|
||||
spinlock_t list_lock;
|
||||
struct amdgpu_amdkfd_fence *eviction_fence;
|
||||
struct mm_struct *mm;
|
||||
uint32_t evicting;
|
||||
struct work_struct release_work;
|
||||
struct kfd_node *node;
|
||||
|
|
@ -168,13 +168,14 @@ struct svm_range *svm_range_from_addr(struct svm_range_list *svms,
|
|||
struct svm_range **parent);
|
||||
struct kfd_node *svm_range_get_node_by_id(struct svm_range *prange,
|
||||
uint32_t gpu_id);
|
||||
void svm_range_bo_destroy(struct ttm_buffer_object *tbo);
|
||||
int svm_range_vram_node_new(struct kfd_node *node, struct svm_range *prange,
|
||||
bool clear);
|
||||
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_evict_svm_bo(struct svm_range_bo *svm_bo);
|
||||
int svm_range_evict_svm_bo(struct amdgpu_bo *bo);
|
||||
|
||||
void svm_range_add_list_work(struct svm_range_list *svms,
|
||||
struct svm_range *prange, struct mm_struct *mm,
|
||||
|
|
@ -229,7 +230,11 @@ static inline int svm_range_restore_pages(struct amdgpu_device *adev,
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
static inline int svm_range_evict_svm_bo(struct svm_range_bo *svm_bo)
|
||||
static inline void svm_range_bo_destroy(struct ttm_buffer_object *tbo)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int svm_range_evict_svm_bo(struct amdgpu_bo *bo)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3576,25 +3576,6 @@ static void remove_stream(struct amdgpu_device *adev,
|
|||
acrtc->enabled = false;
|
||||
}
|
||||
|
||||
static void prepare_flip_isr(struct amdgpu_crtc *acrtc)
|
||||
{
|
||||
|
||||
assert_spin_locked(&acrtc->base.dev->event_lock);
|
||||
WARN_ON(acrtc->event);
|
||||
|
||||
acrtc->event = acrtc->base.state->event;
|
||||
|
||||
/* Set the flip status */
|
||||
acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED;
|
||||
|
||||
/* Mark this event as consumed */
|
||||
acrtc->base.state->event = NULL;
|
||||
|
||||
drm_dbg_state(acrtc->base.dev,
|
||||
"crtc:%d, pflip_stat:AMDGPU_FLIP_SUBMITTED\n",
|
||||
acrtc->crtc_id);
|
||||
}
|
||||
|
||||
static void amdgpu_dm_commit_cursors(struct drm_atomic_commit *state)
|
||||
{
|
||||
struct drm_plane *plane;
|
||||
|
|
@ -3740,17 +3721,47 @@ static void dm_arm_vblank_event(struct amdgpu_crtc *acrtc,
|
|||
return;
|
||||
|
||||
if (pflip_update) {
|
||||
drm_crtc_vblank_get(&acrtc->base);
|
||||
WARN_ON(acrtc->pflip_status != AMDGPU_FLIP_NONE);
|
||||
/* Arm flip completion handling and event delivery after programming. */
|
||||
prepare_flip_isr(acrtc);
|
||||
WARN_ON(acrtc->event);
|
||||
|
||||
acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED;
|
||||
acrtc->event = acrtc->base.state->event;
|
||||
acrtc->base.state->event = NULL;
|
||||
|
||||
drm_dbg_state(acrtc->base.dev,
|
||||
"crtc:%d, pflip_stat:AMDGPU_FLIP_SUBMITTED\n",
|
||||
acrtc->crtc_id);
|
||||
} else if (cursor_update) {
|
||||
drm_crtc_vblank_get(&acrtc->base);
|
||||
acrtc->event = acrtc->base.state->event;
|
||||
acrtc->base.state->event = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_arm_vblank_event_pre_programming - Prepare for programming
|
||||
* @acrtc: The amdgpu CRTC to prepare
|
||||
* @acrtc_state: The new CRTC state
|
||||
* @pflip_update: Whether a page flip is being programmed
|
||||
* @cursor_update: Whether a cursor update is being programmed
|
||||
*
|
||||
* Grab a reference on the vblank counter if a page flip or cursor update is to
|
||||
* be programmed. Do this before programming so the HW is not in any
|
||||
* idle-optimized state (such as PSR).
|
||||
*/
|
||||
static void dm_arm_vblank_event_pre_programming(struct amdgpu_crtc *acrtc,
|
||||
struct dm_crtc_state *acrtc_state,
|
||||
bool pflip_update,
|
||||
bool cursor_update)
|
||||
{
|
||||
assert_spin_locked(&acrtc->base.dev->event_lock);
|
||||
|
||||
if (!acrtc->base.state->event || acrtc_state->active_planes == 0)
|
||||
return;
|
||||
|
||||
if (pflip_update || cursor_update)
|
||||
drm_crtc_vblank_get(&acrtc->base);
|
||||
}
|
||||
|
||||
static void amdgpu_dm_commit_planes(struct drm_atomic_commit *state,
|
||||
struct drm_device *dev,
|
||||
struct amdgpu_display_manager *dm,
|
||||
|
|
@ -4013,16 +4024,19 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_commit *state,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* DCE depends on a combination of GRPH_FLIP, VLINE0, and VUPDATE for
|
||||
* event delivery. Only GRPH_FLIP handler can send pflip events, and it
|
||||
* only fires if HW latched to the flip. Maintain legacy behavior by
|
||||
* arming event before programming.
|
||||
*/
|
||||
if (amdgpu_ip_version(dm->adev, DCE_HWIP, 0) == 0) {
|
||||
scoped_guard(spinlock_irqsave, &pcrtc->dev->event_lock) {
|
||||
scoped_guard(spinlock_irqsave, &pcrtc->dev->event_lock) {
|
||||
dm_arm_vblank_event_pre_programming(acrtc_attach, acrtc_state,
|
||||
pflip_present,
|
||||
cursor_update);
|
||||
/*
|
||||
* DCE depends on a combination of GRPH_FLIP, VLINE0, and
|
||||
* VUPDATE for event delivery. Only GRPH_FLIP handler can send
|
||||
* pflip events, and it only fires if HW latched to the flip.
|
||||
* Maintain legacy behavior by arming event before programming.
|
||||
*/
|
||||
if (amdgpu_ip_version(dm->adev, DCE_HWIP, 0) == 0) {
|
||||
dm_arm_vblank_event(acrtc_attach, acrtc_state,
|
||||
pflip_present, cursor_update);
|
||||
pflip_present, cursor_update);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1183,6 +1183,13 @@ int amdgpu_dpm_dispatch_task(struct amdgpu_device *adev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool amdgpu_dpm_is_pp_table_allowed(struct amdgpu_device *adev)
|
||||
{
|
||||
return !amdgpu_sriov_vf(adev) &&
|
||||
!(adev->flags & AMD_IS_APU) &&
|
||||
!adev->scpm_enabled;
|
||||
}
|
||||
|
||||
int amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char *table,
|
||||
size_t size)
|
||||
{
|
||||
|
|
@ -1193,7 +1200,8 @@ int amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char *table,
|
|||
if ((!table && size) || (table && !size))
|
||||
return -EINVAL;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) || !pp_funcs->get_pp_table || adev->scpm_enabled)
|
||||
if (!amdgpu_dpm_is_pp_table_allowed(adev) ||
|
||||
!pp_funcs->get_pp_table)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
|
|
@ -1717,7 +1725,8 @@ int amdgpu_dpm_set_pp_table(struct amdgpu_device *adev,
|
|||
if (!buf || !size)
|
||||
return -EINVAL;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) || !pp_funcs->set_pp_table || adev->scpm_enabled)
|
||||
if (!amdgpu_dpm_is_pp_table_allowed(adev) ||
|
||||
!pp_funcs->set_pp_table)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user