amd-drm-next-6.20-2026-01-23:

amdgpu:
 - GC 12 fix
 - UserQ fixes
 - Misc error path fixes
 - IP discovery fixes
 - Misc cleanups
 - HDMI fixes
 - Documentation update
 - Panel replay fixes
 - Panel type handling fixes
 - DCN 3.1.x fixes
 - DC analog display fix
 - SMU 6 fixes
 - VCN 4.0.3 queue reset fix
 - VCN 5.0.1 queue reset fix
 - GPUVM TLB flush fix
 - RAS fixes
 - DC idle optimization fix
 
 amdkfd:
 - MQD fix for GC 9.4.3 and 9.5
 - GC 11 cooperative launch fix
 - GC 12.1 trap handler fixes
 - Misc cleanups
 
 radeon:
 - Use drm_* logging helpers for VCE
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCaXOwTQAKCRC93/aFa7yZ
 2G2JAQCQN5BrBSL1gY3hoGpzG/o5oTjxVqIYJDi3eC02ecAyAQD/RPSkPCKc38E1
 Jy7ApjcEoKA6qBCRA1gpKihi+BwS/Ao=
 =opLX
 -----END PGP SIGNATURE-----

Merge tag 'amd-drm-next-6.20-2026-01-23' of https://gitlab.freedesktop.org/agd5f/linux into drm-next

amd-drm-next-6.20-2026-01-23:

amdgpu:
- GC 12 fix
- UserQ fixes
- Misc error path fixes
- IP discovery fixes
- Misc cleanups
- HDMI fixes
- Documentation update
- Panel replay fixes
- Panel type handling fixes
- DCN 3.1.x fixes
- DC analog display fix
- SMU 6 fixes
- VCN 4.0.3 queue reset fix
- VCN 5.0.1 queue reset fix
- GPUVM TLB flush fix
- RAS fixes
- DC idle optimization fix

amdkfd:
- MQD fix for GC 9.4.3 and 9.5
- GC 11 cooperative launch fix
- GC 12.1 trap handler fixes
- Misc cleanups

radeon:
- Use drm_* logging helpers for VCE

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

From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patch.msgid.link/20260123173537.17221-1-alexander.deucher@amd.com
This commit is contained in:
Dave Airlie 2026-01-27 10:55:13 +10:00
commit 504f3cead6
65 changed files with 1440 additions and 1194 deletions

View file

@ -16,3 +16,6 @@ Ryzen AI 300 series, Strix Point, 3.5.0, 11.5.0, 4.0.5, 6.1.0, 14.0.0, 14.0.0
Ryzen AI 330 series, Krackan Point, 3.6.0, 11.5.3, 4.0.5, 6.1.3, 14.0.5, 14.0.5
Ryzen AI 350 series, Krackan Point, 3.5.0, 11.5.2, 4.0.5, 6.1.2, 14.0.4, 14.0.4
Ryzen AI Max 300 series, Strix Halo, 3.5.1, 11.5.1, 4.0.6, 6.1.1, 14.0.1, 14.0.1
Ryzen AI 9 475 / 470 / 465, Gorgon Point, 3.5.0, 11.5.0, 4.0.5, 6.1.0, 14.0.0, 14.0.0
Ryzen AI 7 450, Gorgon Point, 3.5.0, 11.5.2, 4.0.5, 6.1.2, 14.0.4, 14.0.4
Ryzen AI 5 440 / 435, Gorgon Point, 3.6.0, 11.5.3, 4.0.5, 6.1.3, 14.0.5, 14.0.5

1 Product Name Code Reference DCN/DCE version GC version VCE/UVD/VCN version SDMA version MP0 version MP1 version
16 Ryzen AI 330 series Krackan Point 3.6.0 11.5.3 4.0.5 6.1.3 14.0.5 14.0.5
17 Ryzen AI 350 series Krackan Point 3.5.0 11.5.2 4.0.5 6.1.2 14.0.4 14.0.4
18 Ryzen AI Max 300 series Strix Halo 3.5.1 11.5.1 4.0.6 6.1.1 14.0.1 14.0.1
19 Ryzen AI 9 475 / 470 / 465 Gorgon Point 3.5.0 11.5.0 4.0.5 6.1.0 14.0.0 14.0.0
20 Ryzen AI 7 450 Gorgon Point 3.5.0 11.5.2 4.0.5 6.1.2 14.0.4 14.0.4
21 Ryzen AI 5 440 / 435 Gorgon Point 3.6.0 11.5.3 4.0.5 6.1.3 14.0.5 14.0.5

View file

@ -334,7 +334,8 @@ int amdgpu_amdkfd_alloc_kernel_mem(struct amdgpu_device *adev, size_t size,
bp.size = size;
bp.byte_align = PAGE_SIZE;
bp.domain = domain;
bp.flags = AMDGPU_GEM_CREATE_CPU_GTT_USWC;
bp.flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
AMDGPU_GEM_CREATE_CPU_GTT_USWC;
bp.type = ttm_bo_type_kernel;
bp.resv = NULL;
bp.bo_ptr_size = sizeof(struct amdgpu_bo);

View file

@ -380,10 +380,21 @@ static uint16_t amdgpu_discovery_calculate_checksum(uint8_t *data, uint32_t size
return checksum;
}
static inline bool amdgpu_discovery_verify_checksum(uint8_t *data, uint32_t size,
static inline bool amdgpu_discovery_verify_checksum(struct amdgpu_device *adev,
uint8_t *data, uint32_t size,
uint16_t expected)
{
return !!(amdgpu_discovery_calculate_checksum(data, size) == expected);
uint16_t calculated;
calculated = amdgpu_discovery_calculate_checksum(data, size);
if (calculated != expected) {
dev_err(adev->dev, "Discovery checksum failed: calc 0x%04x != exp 0x%04x, size %u.\n",
calculated, expected, size);
return false;
}
return true;
}
static inline bool amdgpu_discovery_verify_binary_signature(uint8_t *binary)
@ -439,7 +450,7 @@ static int amdgpu_discovery_verify_npsinfo(struct amdgpu_device *adev,
return -EINVAL;
}
if (!amdgpu_discovery_verify_checksum(discovery_bin + offset,
if (!amdgpu_discovery_verify_checksum(adev, discovery_bin + offset,
le32_to_cpu(nhdr->size_bytes),
checksum)) {
dev_dbg(adev->dev, "invalid nps info data table checksum\n");
@ -529,7 +540,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
size = le16_to_cpu(bhdr->binary_size) - offset;
checksum = le16_to_cpu(bhdr->binary_checksum);
if (!amdgpu_discovery_verify_checksum(discovery_bin + offset, size,
if (!amdgpu_discovery_verify_checksum(adev, discovery_bin + offset, size,
checksum)) {
dev_err(adev->dev, "invalid ip discovery binary checksum\n");
r = -EINVAL;
@ -549,7 +560,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
goto out;
}
if (!amdgpu_discovery_verify_checksum(discovery_bin + offset,
if (!amdgpu_discovery_verify_checksum(adev, discovery_bin + offset,
le16_to_cpu(ihdr->size),
checksum)) {
dev_err(adev->dev, "invalid ip discovery data table checksum\n");
@ -572,7 +583,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
goto out;
}
if (!amdgpu_discovery_verify_checksum(discovery_bin + offset,
if (!amdgpu_discovery_verify_checksum(adev, discovery_bin + offset,
le32_to_cpu(ghdr->size),
checksum)) {
dev_err(adev->dev, "invalid gc data table checksum\n");
@ -595,7 +606,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
goto out;
}
if (!amdgpu_discovery_verify_checksum(
if (!amdgpu_discovery_verify_checksum(adev,
discovery_bin + offset,
sizeof(struct harvest_table), checksum)) {
dev_err(adev->dev, "invalid harvest data table checksum\n");
@ -618,7 +629,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
goto out;
}
if (!amdgpu_discovery_verify_checksum(
if (!amdgpu_discovery_verify_checksum(adev,
discovery_bin + offset,
le32_to_cpu(vhdr->size_bytes), checksum)) {
dev_err(adev->dev, "invalid vcn data table checksum\n");
@ -641,7 +652,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
goto out;
}
if (!amdgpu_discovery_verify_checksum(
if (!amdgpu_discovery_verify_checksum(adev,
discovery_bin + offset,
le32_to_cpu(mhdr->size_bytes), checksum)) {
dev_err(adev->dev, "invalid mall data table checksum\n");
@ -1867,7 +1878,7 @@ static int amdgpu_discovery_refresh_nps_info(struct amdgpu_device *adev,
sizeof(*nps_data), false);
nhdr = (struct nps_info_header *)(nps_data);
if (!amdgpu_discovery_verify_checksum((uint8_t *)nps_data,
if (!amdgpu_discovery_verify_checksum(adev, (uint8_t *)nps_data,
le32_to_cpu(nhdr->size_bytes),
checksum)) {
dev_err(adev->dev, "nps data refresh, checksum mismatch\n");

View file

@ -708,12 +708,12 @@ void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring)
*/
/**
* amdgpu_fence_driver_guilty_force_completion - force signal of specified sequence
* amdgpu_fence_driver_update_timedout_fence_state - Update fence state and set errors
*
* @af: fence of the ring to signal
* @af: fence of the ring to update
*
*/
void amdgpu_fence_driver_guilty_force_completion(struct amdgpu_fence *af)
void amdgpu_fence_driver_update_timedout_fence_state(struct amdgpu_fence *af)
{
struct dma_fence *unprocessed;
struct dma_fence __rcu **ptr;
@ -763,7 +763,7 @@ void amdgpu_fence_save_wptr(struct amdgpu_fence *af)
}
static void amdgpu_ring_backup_unprocessed_command(struct amdgpu_ring *ring,
u64 start_wptr, u32 end_wptr)
u64 start_wptr, u64 end_wptr)
{
unsigned int first_idx = start_wptr & ring->buf_mask;
unsigned int last_idx = end_wptr & ring->buf_mask;

View file

@ -1298,7 +1298,8 @@ failed_undo:
failed_unlock:
spin_unlock_irqrestore(&kiq->ring_lock, flags);
failed_kiq_hdp_flush:
dev_err(adev->dev, "failed to flush HDP via KIQ\n");
if (!amdgpu_in_reset(adev))
dev_err(adev->dev, "failed to flush HDP via KIQ\n");
return r < 0 ? r : -EIO;
}

View file

@ -781,8 +781,10 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready) {
if (!adev->gmc.gmc_funcs->flush_gpu_tlb_pasid)
return 0;
if (!adev->gmc.gmc_funcs->flush_gpu_tlb_pasid) {
r = 0;
goto error_unlock_reset;
}
if (adev->gmc.flush_tlb_needs_extra_type_2)
adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,

View file

@ -302,7 +302,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
if (job && job->vmid)
amdgpu_vmid_reset(adev, ring->vm_hub, job->vmid);
amdgpu_ring_undo(ring);
return r;
goto free_fence;
}
*f = &af->base;
/* get a ref for the job */

View file

@ -218,8 +218,11 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
if (!entity)
return 0;
return drm_sched_job_init(&(*job)->base, entity, 1, owner,
drm_client_id);
r = drm_sched_job_init(&(*job)->base, entity, 1, owner, drm_client_id);
if (!r)
return 0;
kfree((*job)->hw_vm_fence);
err_fence:
kfree((*job)->hw_fence);

View file

@ -59,6 +59,10 @@ enum amdgpu_ib_pool_type;
#define AMDGPU_KERNEL_JOB_ID_FLUSH_GPU_TLB (18446744073709551604ULL)
#define AMDGPU_KERNEL_JOB_ID_KFD_GART_MAP (18446744073709551603ULL)
#define AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST (18446744073709551602ULL)
#define AMDGPU_KERNEL_JOB_ID_GFX_RING_TEST (18446744073709551601ULL)
#define AMDGPU_KERNEL_JOB_ID_SDMA_RING_TEST (18446744073709551600ULL)
#define AMDGPU_KERNEL_JOB_ID_VPE_RING_TEST (18446744073709551599ULL)
#define AMDGPU_KERNEL_JOB_ID_RUN_SHADER (18446744073709551598ULL)
struct amdgpu_job {
struct drm_sched_job base;

View file

@ -2784,6 +2784,10 @@ static int amdgpu_ras_badpages_read(struct amdgpu_device *adev,
if (!data->bps[i].ts)
continue;
/* U64_MAX is used to mark the record as invalid */
if (data->bps[i].retired_page == U64_MAX)
continue;
bps[r].bp = data->bps[i].retired_page;
r++;
if (r >= count)
@ -3090,6 +3094,8 @@ static int __amdgpu_ras_restore_bad_pages(struct amdgpu_device *adev,
if (amdgpu_ras_check_bad_page_unlock(con,
bps[j].retired_page << AMDGPU_GPU_PAGE_SHIFT)) {
/* set to U64_MAX to mark it as invalid */
data->bps[data->count].retired_page = U64_MAX;
data->count++;
data->space_left--;
continue;

View file

@ -885,9 +885,9 @@ int amdgpu_ring_reset_helper_end(struct amdgpu_ring *ring,
if (r)
return r;
/* signal the guilty fence and set an error on all fences from the context */
/* set an error on all fences from the context */
if (guilty_fence)
amdgpu_fence_driver_guilty_force_completion(guilty_fence);
amdgpu_fence_driver_update_timedout_fence_state(guilty_fence);
/* Re-emit the non-guilty commands */
if (ring->ring_backup_entries_to_copy) {
amdgpu_ring_alloc_reemit(ring, ring->ring_backup_entries_to_copy);

View file

@ -161,7 +161,7 @@ extern const struct drm_sched_backend_ops amdgpu_sched_ops;
void amdgpu_fence_driver_set_error(struct amdgpu_ring *ring, int error);
void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring);
void amdgpu_fence_driver_guilty_force_completion(struct amdgpu_fence *af);
void amdgpu_fence_driver_update_timedout_fence_state(struct amdgpu_fence *af);
void amdgpu_fence_save_wptr(struct amdgpu_fence *af);
int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring);

View file

@ -148,6 +148,69 @@ amdgpu_userq_detect_and_reset_queues(struct amdgpu_userq_mgr *uq_mgr)
return r;
}
static void amdgpu_userq_hang_detect_work(struct work_struct *work)
{
struct amdgpu_usermode_queue *queue = container_of(work,
struct amdgpu_usermode_queue,
hang_detect_work.work);
struct dma_fence *fence;
struct amdgpu_userq_mgr *uq_mgr;
if (!queue || !queue->userq_mgr)
return;
uq_mgr = queue->userq_mgr;
fence = READ_ONCE(queue->hang_detect_fence);
/* Fence already signaled no action needed */
if (!fence || dma_fence_is_signaled(fence))
return;
mutex_lock(&uq_mgr->userq_mutex);
amdgpu_userq_detect_and_reset_queues(uq_mgr);
mutex_unlock(&uq_mgr->userq_mutex);
}
/*
* Start hang detection for a user queue fence. A delayed work will be scheduled
* to check if the fence is still pending after the timeout period.
*/
void amdgpu_userq_start_hang_detect_work(struct amdgpu_usermode_queue *queue)
{
struct amdgpu_device *adev;
unsigned long timeout_ms;
if (!queue || !queue->userq_mgr || !queue->userq_mgr->adev)
return;
adev = queue->userq_mgr->adev;
/* Determine timeout based on queue type */
switch (queue->queue_type) {
case AMDGPU_RING_TYPE_GFX:
timeout_ms = adev->gfx_timeout;
break;
case AMDGPU_RING_TYPE_COMPUTE:
timeout_ms = adev->compute_timeout;
break;
case AMDGPU_RING_TYPE_SDMA:
timeout_ms = adev->sdma_timeout;
break;
default:
timeout_ms = adev->gfx_timeout;
break;
}
/* Store the fence to monitor and schedule hang detection */
WRITE_ONCE(queue->hang_detect_fence, queue->last_fence);
schedule_delayed_work(&queue->hang_detect_work,
msecs_to_jiffies(timeout_ms));
}
static void amdgpu_userq_init_hang_detect_work(struct amdgpu_usermode_queue *queue)
{
INIT_DELAYED_WORK(&queue->hang_detect_work, amdgpu_userq_hang_detect_work);
queue->hang_detect_fence = NULL;
}
static int amdgpu_userq_buffer_va_list_add(struct amdgpu_usermode_queue *queue,
struct amdgpu_bo_va_mapping *va_map, u64 addr)
{
@ -572,7 +635,6 @@ amdgpu_userq_destroy(struct drm_file *filp, int queue_id)
cancel_delayed_work_sync(&uq_mgr->resume_work);
mutex_lock(&uq_mgr->userq_mutex);
queue = amdgpu_userq_find(uq_mgr, queue_id);
if (!queue) {
drm_dbg_driver(adev_to_drm(uq_mgr->adev), "Invalid queue id to destroy\n");
@ -580,6 +642,11 @@ amdgpu_userq_destroy(struct drm_file *filp, int queue_id)
return -EINVAL;
}
amdgpu_userq_wait_for_last_fence(queue);
/* Cancel any pending hang detection work and cleanup */
if (queue->hang_detect_fence) {
cancel_delayed_work_sync(&queue->hang_detect_work);
queue->hang_detect_fence = NULL;
}
r = amdgpu_bo_reserve(queue->db_obj.obj, true);
if (!r) {
amdgpu_bo_unpin(queue->db_obj.obj);
@ -819,6 +886,7 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
queue->debugfs_queue = debugfs_create_dir(queue_name, filp->debugfs_client);
debugfs_create_file("mqd_info", 0444, queue->debugfs_queue, queue, &amdgpu_mqd_info_fops);
#endif
amdgpu_userq_init_hang_detect_work(queue);
kfree(queue_name);
args->out.queue_id = qid;

View file

@ -72,6 +72,8 @@ struct amdgpu_usermode_queue {
u32 xcp_id;
int priority;
struct dentry *debugfs_queue;
struct delayed_work hang_detect_work;
struct dma_fence *hang_detect_fence;
struct list_head userq_va_list;
};
@ -147,6 +149,7 @@ int amdgpu_userq_start_sched_for_enforce_isolation(struct amdgpu_device *adev,
void amdgpu_userq_reset_work(struct work_struct *work);
void amdgpu_userq_pre_reset(struct amdgpu_device *adev);
int amdgpu_userq_post_reset(struct amdgpu_device *adev, bool vram_lost);
void amdgpu_userq_start_hang_detect_work(struct amdgpu_usermode_queue *queue);
int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
struct amdgpu_usermode_queue *queue,

View file

@ -574,6 +574,7 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
dma_fence_put(queue->last_fence);
queue->last_fence = dma_fence_get(fence);
amdgpu_userq_start_hang_detect_work(queue);
mutex_unlock(&userq_mgr->userq_mutex);
drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT,

View file

@ -278,7 +278,6 @@ static void gfx_v12_0_select_se_sh(struct amdgpu_device *adev, u32 se_num,
u32 sh_num, u32 instance, int xcc_id);
static u32 gfx_v12_0_get_wgp_active_bitmap_per_sh(struct amdgpu_device *adev);
static void gfx_v12_0_ring_emit_frame_cntl(struct amdgpu_ring *ring, bool start, bool secure);
static void gfx_v12_0_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg,
uint32_t val);
static int gfx_v12_0_wait_for_rlc_autoload_complete(struct amdgpu_device *adev);
@ -4629,16 +4628,6 @@ static int gfx_v12_0_ring_preempt_ib(struct amdgpu_ring *ring)
return r;
}
static void gfx_v12_0_ring_emit_frame_cntl(struct amdgpu_ring *ring,
bool start,
bool secure)
{
uint32_t v = secure ? FRAME_TMZ : 0;
amdgpu_ring_write(ring, PACKET3(PACKET3_FRAME_CONTROL, 0));
amdgpu_ring_write(ring, v | FRAME_CMD(start ? 0 : 1));
}
static void gfx_v12_0_ring_emit_rreg(struct amdgpu_ring *ring, uint32_t reg,
uint32_t reg_val_offs)
{
@ -5515,7 +5504,6 @@ static const struct amdgpu_ring_funcs gfx_v12_0_ring_funcs_gfx = {
.emit_cntxcntl = gfx_v12_0_ring_emit_cntxcntl,
.init_cond_exec = gfx_v12_0_ring_emit_init_cond_exec,
.preempt_ib = gfx_v12_0_ring_preempt_ib,
.emit_frame_cntl = gfx_v12_0_ring_emit_frame_cntl,
.emit_wreg = gfx_v12_0_ring_emit_wreg,
.emit_reg_wait = gfx_v12_0_ring_emit_reg_wait,
.emit_reg_write_reg_wait = gfx_v12_0_ring_emit_reg_write_reg_wait,

View file

@ -1145,13 +1145,18 @@ static int jpeg_v4_0_3_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
if (amdgpu_sriov_vf(ring->adev))
return -EOPNOTSUPP;
struct amdgpu_device *adev = ring->adev;
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
int r;
/* take the vcn reset mutex here because resetting VCN will reset jpeg as well */
mutex_lock(&vinst->engine_reset_mutex);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
jpeg_v4_0_3_core_stall_reset(ring);
jpeg_v4_0_3_start_jrbc(ring);
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
r = amdgpu_ring_reset_helper_end(ring, timedout_fence);
mutex_unlock(&vinst->engine_reset_mutex);
return r;
}
static const struct amd_ip_funcs jpeg_v4_0_3_ip_funcs = {

View file

@ -844,10 +844,19 @@ static int jpeg_v5_0_1_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
int r;
/* take the vcn reset mutex here because resetting VCN will reset jpeg as well */
mutex_lock(&vinst->engine_reset_mutex);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
jpeg_v5_0_1_core_stall_reset(ring);
jpeg_v5_0_1_init_jrbc(ring);
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
r = amdgpu_ring_reset_helper_end(ring, timedout_fence);
mutex_unlock(&vinst->engine_reset_mutex);
return r;
}
static const struct amd_ip_funcs jpeg_v5_0_1_ip_funcs = {

View file

@ -847,6 +847,7 @@ static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
int inst_idx = vinst->inst;
struct amdgpu_vcn4_fw_shared *fw_shared =
adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__PAUSE};
struct amdgpu_ring *ring;
int vcn_inst, ret;
uint32_t tmp;
@ -951,6 +952,9 @@ static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
ring = &adev->vcn.inst[inst_idx].ring_enc[0];
/* Pause dpg */
vcn_v4_0_3_pause_dpg_mode(vinst, &state);
/* program the RB_BASE for ring buffer */
WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO,
lower_32_bits(ring->gpu_addr));
@ -1360,9 +1364,13 @@ static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
int inst_idx = vinst->inst;
uint32_t tmp;
int vcn_inst;
struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
vcn_inst = GET_INST(VCN, inst_idx);
/* Unpause dpg */
vcn_v4_0_3_pause_dpg_mode(vinst, &state);
/* Wait for power status to be 1 */
SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_POWER_STATUS, 1,
UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
@ -1486,6 +1494,39 @@ Done:
static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
struct dpg_pause_state *new_state)
{
struct amdgpu_device *adev = vinst->adev;
int inst_idx = vinst->inst;
uint32_t reg_data = 0;
int ret_code;
/* pause/unpause if state is changed */
if (adev->vcn.inst[inst_idx].pause_state.fw_based != new_state->fw_based) {
DRM_DEV_DEBUG(adev->dev, "dpg pause state changed %d -> %d",
adev->vcn.inst[inst_idx].pause_state.fw_based, new_state->fw_based);
reg_data = RREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE) &
(~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
if (new_state->fw_based == VCN_DPG_STATE__PAUSE) {
ret_code = SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 0x1,
UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
if (!ret_code) {
/* pause DPG */
reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data);
/* wait for ACK */
SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_DPG_PAUSE,
UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK,
UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
}
} else {
/* unpause dpg, no need to wait */
reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data);
}
adev->vcn.inst[inst_idx].pause_state.fw_based = new_state->fw_based;
}
return 0;
}
@ -1596,6 +1637,60 @@ static void vcn_v4_0_3_unified_ring_set_wptr(struct amdgpu_ring *ring)
}
}
static int vcn_v4_0_3_reset_jpeg_pre_helper(struct amdgpu_device *adev, int inst)
{
struct amdgpu_ring *ring;
uint32_t wait_seq = 0;
int i;
for (i = 0; i < adev->jpeg.num_jpeg_rings; ++i) {
ring = &adev->jpeg.inst[inst].ring_dec[i];
drm_sched_wqueue_stop(&ring->sched);
/* Get the last emitted fence sequence */
wait_seq = atomic_read(&ring->fence_drv.last_seq);
if (wait_seq)
continue;
/* if Jobs are still pending after timeout,
* We'll handle them in the bottom helper
*/
amdgpu_fence_wait_polling(ring, wait_seq, adev->video_timeout);
}
return 0;
}
static int vcn_v4_0_3_reset_jpeg_post_helper(struct amdgpu_device *adev, int inst)
{
struct amdgpu_ring *ring;
int i, r = 0;
for (i = 0; i < adev->jpeg.num_jpeg_rings; ++i) {
ring = &adev->jpeg.inst[inst].ring_dec[i];
/* Force completion of any remaining jobs */
amdgpu_fence_driver_force_completion(ring);
if (ring->use_doorbell)
WREG32_SOC15_OFFSET(
VCN, GET_INST(VCN, inst),
regVCN_JPEG_DB_CTRL,
(ring->pipe ? (ring->pipe - 0x15) : 0),
ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
VCN_JPEG_DB_CTRL__EN_MASK);
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
drm_sched_wqueue_start(&ring->sched);
DRM_DEV_DEBUG(adev->dev, "JPEG ring %d (inst %d) restored and sched restarted\n",
i, inst);
}
return 0;
}
static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
@ -1604,7 +1699,19 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
int vcn_inst;
struct amdgpu_device *adev = ring->adev;
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
bool pg_state = false;
/* take the vcn reset mutex here because resetting VCN will reset jpeg as well */
mutex_lock(&vinst->engine_reset_mutex);
mutex_lock(&adev->jpeg.jpeg_pg_lock);
/* Ensure JPEG is powered on during reset if currently gated */
if (adev->jpeg.cur_state == AMD_PG_STATE_GATE) {
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
AMD_PG_STATE_UNGATE);
pg_state = true;
}
vcn_v4_0_3_reset_jpeg_pre_helper(adev, ring->me);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
vcn_inst = GET_INST(VCN, ring->me);
@ -1612,7 +1719,12 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
if (r) {
DRM_DEV_ERROR(adev->dev, "VCN reset fail : %d\n", r);
return r;
/* Restore JPEG power gating state if it was originally gated */
if (pg_state)
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
AMD_PG_STATE_GATE);
mutex_unlock(&adev->jpeg.jpeg_pg_lock);
goto unlock;
}
/* This flag is not set for VF, assumed to be disabled always */
@ -1621,7 +1733,25 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
vcn_v4_0_3_hw_init_inst(vinst);
vcn_v4_0_3_start_dpg_mode(vinst, adev->vcn.inst[ring->me].indirect_sram);
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
r = amdgpu_ring_reset_helper_end(ring, timedout_fence);
if (r) {
if (pg_state)
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
AMD_PG_STATE_GATE);
mutex_unlock(&adev->jpeg.jpeg_pg_lock);
goto unlock;
}
r = vcn_v4_0_3_reset_jpeg_post_helper(adev, ring->me);
if (pg_state)
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
AMD_PG_STATE_GATE);
mutex_unlock(&adev->jpeg.jpeg_pg_lock);
unlock:
mutex_unlock(&vinst->engine_reset_mutex);
return r;
}
static const struct amdgpu_ring_funcs vcn_v4_0_3_unified_ring_vm_funcs = {

View file

@ -1301,6 +1301,59 @@ static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring)
}
}
static int vcn_v5_0_1_reset_jpeg_pre_helper(struct amdgpu_device *adev, int inst)
{
struct amdgpu_ring *ring;
uint32_t wait_seq = 0;
int i;
for (i = 0; i < adev->jpeg.num_jpeg_rings; ++i) {
ring = &adev->jpeg.inst[inst].ring_dec[i];
drm_sched_wqueue_stop(&ring->sched);
wait_seq = atomic_read(&ring->fence_drv.last_seq);
if (wait_seq)
continue;
/* if Jobs are still pending after timeout,
* We'll handle them in the bottom helper
*/
amdgpu_fence_wait_polling(ring, wait_seq, adev->video_timeout);
}
return 0;
}
static int vcn_v5_0_1_reset_jpeg_post_helper(struct amdgpu_device *adev, int inst)
{
struct amdgpu_ring *ring;
int i, r = 0;
for (i = 0; i < adev->jpeg.num_jpeg_rings; ++i) {
ring = &adev->jpeg.inst[inst].ring_dec[i];
/* Force completion of any remaining jobs */
amdgpu_fence_driver_force_completion(ring);
if (ring->use_doorbell)
WREG32_SOC15_OFFSET(
VCN, GET_INST(VCN, inst),
regVCN_JPEG_DB_CTRL,
(ring->pipe ? (ring->pipe - 0x15) : 0),
ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
VCN_JPEG_DB_CTRL__EN_MASK);
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
drm_sched_wqueue_start(&ring->sched);
DRM_DEV_DEBUG(adev->dev, "JPEG ring %d (inst %d) restored and sched restarted\n",
i, inst);
}
return 0;
}
static int vcn_v5_0_1_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
@ -1309,6 +1362,18 @@ static int vcn_v5_0_1_ring_reset(struct amdgpu_ring *ring,
int vcn_inst;
struct amdgpu_device *adev = ring->adev;
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
bool pg_state = false;
/* take the vcn reset mutex here because resetting VCN will reset jpeg as well */
mutex_lock(&vinst->engine_reset_mutex);
vcn_v5_0_1_reset_jpeg_pre_helper(adev, ring->me);
mutex_lock(&adev->jpeg.jpeg_pg_lock);
/* Ensure JPEG is powered on during reset if currently gated */
if (adev->jpeg.cur_state == AMD_PG_STATE_GATE) {
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
AMD_PG_STATE_UNGATE);
pg_state = true;
}
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
@ -1317,13 +1382,37 @@ static int vcn_v5_0_1_ring_reset(struct amdgpu_ring *ring,
if (r) {
DRM_DEV_ERROR(adev->dev, "VCN reset fail : %d\n", r);
return r;
/* Restore JPEG power gating state if it was originally gated */
if (pg_state)
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
AMD_PG_STATE_GATE);
mutex_unlock(&adev->jpeg.jpeg_pg_lock);
goto unlock;
}
vcn_v5_0_1_hw_init_inst(adev, ring->me);
vcn_v5_0_1_start_dpg_mode(vinst, vinst->indirect_sram);
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
r = amdgpu_ring_reset_helper_end(ring, timedout_fence);
if (r) {
if (pg_state)
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
AMD_PG_STATE_GATE);
mutex_unlock(&adev->jpeg.jpeg_pg_lock);
goto unlock;
}
if (pg_state)
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
AMD_PG_STATE_GATE);
mutex_unlock(&adev->jpeg.jpeg_pg_lock);
r = vcn_v5_0_1_reset_jpeg_post_helper(adev, ring->me);
unlock:
mutex_unlock(&vinst->engine_reset_mutex);
return r;
}
static const struct amdgpu_ring_funcs vcn_v5_0_1_unified_ring_vm_funcs = {

File diff suppressed because it is too large Load diff

View file

@ -35,6 +35,8 @@
#define HAVE_BANKED_VGPRS (ASIC_FAMILY == CHIP_GC_12_0_3)
#define NUM_NAMED_BARRIERS (ASIC_FAMILY == CHIP_GC_12_0_3 ? 0x10 : 0)
#define HAVE_CLUSTER_BARRIER (ASIC_FAMILY == CHIP_GC_12_0_3)
#define CLUSTER_BARRIER_SERIALIZE_WORKAROUND (ASIC_FAMILY == CHIP_GC_12_0_3)
#define RELAXED_SCHEDULING_IN_TRAP (ASIC_FAMILY == CHIP_GFX12)
#define SINGLE_STEP_MISSED_WORKAROUND 1 //workaround for lost TRAP_AFTER_INST exception when SAVECTX raised
#define HAVE_VALU_SGPR_HAZARD (ASIC_FAMILY == CHIP_GFX12)
@ -104,10 +106,17 @@ var SQ_WAVE_SCHED_MODE_DEP_MODE_SHIFT = 0
var SQ_WAVE_SCHED_MODE_DEP_MODE_SIZE = 2
var BARRIER_STATE_SIGNAL_OFFSET = 16
var BARRIER_STATE_SIGNAL_SIZE = 7
var BARRIER_STATE_MEMBER_OFFSET = 4
var BARRIER_STATE_MEMBER_SIZE = 7
var BARRIER_STATE_VALID_OFFSET = 0
#if RELAXED_SCHEDULING_IN_TRAP
var TTMP11_SCHED_MODE_SHIFT = 26
var TTMP11_SCHED_MODE_SIZE = 2
var TTMP11_SCHED_MODE_MASK = 0xC000000
#endif
var NAMED_BARRIERS_SR_OFFSET_FROM_HWREG = 0x80
var S_BARRIER_INIT_MEMBERCNT_MASK = 0x7F0000
var S_BARRIER_INIT_MEMBERCNT_SHIFT = 0x10
@ -220,18 +229,22 @@ L_JUMP_TO_RESTORE:
s_branch L_RESTORE
L_SKIP_RESTORE:
#if RELAXED_SCHEDULING_IN_TRAP
// Assume most relaxed scheduling mode is set. Save and revert to normal mode.
s_getreg_b32 ttmp2, hwreg(HW_REG_WAVE_SCHED_MODE)
s_wait_alu 0
s_setreg_imm32_b32 hwreg(HW_REG_WAVE_SCHED_MODE, \
SQ_WAVE_SCHED_MODE_DEP_MODE_SHIFT, SQ_WAVE_SCHED_MODE_DEP_MODE_SIZE), 0
#endif
s_getreg_b32 s_save_state_priv, hwreg(HW_REG_WAVE_STATE_PRIV) //save STATUS since we will change SCC
#if RELAXED_SCHEDULING_IN_TRAP
// Save SCHED_MODE[1:0] into ttmp11[27:26].
s_andn2_b32 ttmp11, ttmp11, TTMP11_SCHED_MODE_MASK
s_lshl_b32 ttmp2, ttmp2, TTMP11_SCHED_MODE_SHIFT
s_or_b32 ttmp11, ttmp11, ttmp2
#endif
// Clear SPI_PRIO: do not save with elevated priority.
// Clear ECC_ERR: prevents SQC store and triggers FATAL_HALT if setreg'd.
@ -313,7 +326,7 @@ L_FETCH_2ND_TRAP:
s_cbranch_scc0 L_NO_SIGN_EXTEND_TMA
s_or_b32 ttmp15, ttmp15, ~ADDRESS_HI32_MASK
L_NO_SIGN_EXTEND_TMA:
#if ASIC_FAMILY == CHIP_GFX12
#if RELAXED_SCHEDULING_IN_TRAP
// Move SCHED_MODE[1:0] from ttmp11 to unused bits in ttmp1[27:26] (return PC_HI).
// The second-level trap will restore from ttmp1 for backwards compatibility.
s_and_b32 ttmp2, ttmp11, TTMP11_SCHED_MODE_MASK
@ -379,8 +392,10 @@ L_EXIT_TRAP:
// Only restore fields which the trap handler changes.
s_lshr_b32 s_save_state_priv, s_save_state_priv, SQ_WAVE_STATE_PRIV_SCC_SHIFT
#if RELAXED_SCHEDULING_IN_TRAP
// Assume relaxed scheduling mode after this point.
restore_sched_mode(ttmp2)
#endif
s_setreg_b32 hwreg(HW_REG_WAVE_STATE_PRIV, SQ_WAVE_STATE_PRIV_SCC_SHIFT, \
SQ_WAVE_STATE_PRIV_POISON_ERR_SHIFT - SQ_WAVE_STATE_PRIV_SCC_SHIFT + 1), s_save_state_priv
@ -519,9 +534,11 @@ L_SAVE_HWREG:
v_mov_b32 v2, 0x0 //Set of SGPRs for TCP store
s_mov_b32 m0, 0x0 //Next lane of v2 to write to
write_hwreg_to_v2(s_save_m0)
// Ensure no further changes to barrier or LDS state.
// STATE_PRIV.*BARRIER_COMPLETE may change up to this point.
wait_trap_barriers(s_save_tmp)
wait_trap_barriers(s_save_tmp, s_save_m0, 1)
// Re-read final state of *BARRIER_COMPLETE fields for save.
s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_STATE_PRIV)
@ -529,9 +546,8 @@ L_SAVE_HWREG:
s_andn2_b32 s_save_state_priv, s_save_state_priv, SQ_WAVE_STATE_PRIV_ALL_BARRIER_COMPLETE_MASK
s_or_b32 s_save_state_priv, s_save_state_priv, s_save_tmp
write_hwreg_to_v2(s_save_m0)
write_hwreg_to_v2(s_save_pc_lo)
s_andn2_b32 s_save_tmp, s_save_pc_hi, S_SAVE_PC_HI_FIRST_WAVE_MASK
s_and_b32 s_save_tmp, s_save_pc_hi, ADDRESS_HI32_MASK
write_hwreg_to_v2(s_save_tmp)
write_hwreg_to_v2(s_save_exec_lo)
#if WAVE32_ONLY
@ -587,8 +603,18 @@ L_SAVE_HWREG:
write_hwreg_to_v2(s_save_tmp)
#endif
#if ASIC_FAMILY >= CHIP_GC_12_0_3
s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_SCHED_MODE)
write_hwreg_to_v2(s_save_tmp)
#endif
#if ! SAVE_TTMPS_IN_SGPR_BLOCK
// Write HWREGs with 16 VGPR lanes. TTMPs occupy space after this.
s_mov_b32 exec_lo, 0xFFFF
#else
// All 128 bytes are available for HWREGs.
s_mov_b32 exec_lo, 0xFFFFFFFF
#endif
s_mov_b32 exec_hi, 0x0
s_add_u32 s_save_addr_lo, s_save_base_addr_lo, s_save_mem_offset
s_addc_u32 s_save_addr_hi, s_save_base_addr_hi, 0x0
@ -1151,6 +1177,12 @@ L_SKIP_TRAP_CLUSTER_BARRIER_SIGNAL:
L_SKIP_CLUSTER_BARRIER_RESTORE:
#endif
#if ASIC_FAMILY >= CHIP_GC_12_0_3
s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x40
s_wait_kmcnt 0
s_setreg_b32 hwreg(HW_REG_WAVE_SCHED_MODE), s_restore_tmp
#endif
s_mov_b32 m0, s_restore_m0
s_mov_b32 exec_lo, s_restore_exec_lo
s_mov_b32 exec_hi, s_restore_exec_hi
@ -1190,14 +1222,16 @@ L_SKIP_CLUSTER_BARRIER_RESTORE:
s_and_b64 exec, exec, exec // Restore STATUS.EXECZ, not writable by s_setreg_b32
s_and_b64 vcc, vcc, vcc // Restore STATUS.VCCZ, not writable by s_setreg_b32
#if RELAXED_SCHEDULING_IN_TRAP
// Assume relaxed scheduling mode after this point.
restore_sched_mode(s_restore_tmp)
#endif
s_setreg_b32 hwreg(HW_REG_WAVE_STATE_PRIV), s_restore_state_priv // SCC is included, which is changed by previous salu
// Make barrier and LDS state visible to all waves in the group/cluster.
// STATE_PRIV.*BARRIER_COMPLETE may change after this point.
wait_trap_barriers(s_restore_tmp)
wait_trap_barriers(s_restore_tmp, 0, 0)
#if HAVE_CLUSTER_BARRIER
// SCC is changed by wait_trap_barriers, restore it separately.
@ -1210,7 +1244,7 @@ L_SKIP_CLUSTER_BARRIER_RESTORE:
L_END_PGM:
// Make sure that no wave of the group/cluster can exit the trap handler
// before the group/cluster barrier state is saved.
wait_trap_barriers(s_restore_tmp)
wait_trap_barriers(s_restore_tmp, 0, 0)
s_endpgm_saved
end
@ -1300,11 +1334,11 @@ function restore_xnack_state_priv(s_tmp)
end
#endif
function wait_trap_barriers(s_tmp)
function wait_trap_barriers(s_tmp1, s_tmp2, serialize_wa)
#if HAVE_CLUSTER_BARRIER
// If not in a WG then wave cannot use s_barrier_signal_isfirst.
s_getreg_b32 s_tmp, hwreg(HW_REG_WAVE_STATUS)
s_bitcmp0_b32 s_tmp, SQ_WAVE_STATUS_IN_WG_SHIFT
s_getreg_b32 s_tmp1, hwreg(HW_REG_WAVE_STATUS)
s_bitcmp0_b32 s_tmp1, SQ_WAVE_STATUS_IN_WG_SHIFT
s_cbranch_scc1 L_TRAP_CLUSTER_BARRIER_SIGNAL
s_barrier_signal_isfirst -2
@ -1318,15 +1352,37 @@ L_TRAP_CLUSTER_BARRIER_SIGNAL:
L_SKIP_TRAP_CLUSTER_BARRIER_SIGNAL:
s_barrier_wait -4
#if CLUSTER_BARRIER_SERIALIZE_WORKAROUND
if serialize_wa
// Trap cluster barrier may complete with a user cluster barrier in-flight.
// This is indicated if user cluster member count and signal count are equal.
L_WAIT_USER_CLUSTER_BARRIER_COMPLETE:
s_sendmsg_rtn_b32 s_tmp1, sendmsg(MSG_RTN_GET_CLUSTER_BARRIER_STATE)
s_wait_kmcnt 0
s_bitcmp0_b32 s_tmp1, BARRIER_STATE_VALID_OFFSET
s_cbranch_scc1 L_NOT_IN_CLUSTER
s_bfe_u32 s_tmp2, s_tmp1, (BARRIER_STATE_MEMBER_OFFSET | (BARRIER_STATE_MEMBER_SIZE << 0x10))
s_bfe_u32 s_tmp1, s_tmp1, (BARRIER_STATE_SIGNAL_OFFSET | (BARRIER_STATE_SIGNAL_SIZE << 0x10))
s_cmp_eq_u32 s_tmp1, s_tmp2
s_cbranch_scc1 L_WAIT_USER_CLUSTER_BARRIER_COMPLETE
end
L_NOT_IN_CLUSTER:
#endif
#else
s_barrier_signal -2
s_barrier_wait -2
#endif
end
#if RELAXED_SCHEDULING_IN_TRAP
function restore_sched_mode(s_tmp)
s_bfe_u32 s_tmp, ttmp11, (TTMP11_SCHED_MODE_SHIFT | (TTMP11_SCHED_MODE_SIZE << 0x10))
s_setreg_b32 hwreg(HW_REG_WAVE_SCHED_MODE), s_tmp
end
#endif
function restore_barrier_signal_count(barrier_id)
// extract the saved signal count from s_restore_tmp
@ -1354,8 +1410,8 @@ function fixup_vgpr_bank_selection
// ttmp[0:1]: {7b'0} PC[56:0]
// ttmp2, 3, 10, 13, 14, 15: free
s_load_b64 [ttmp14, ttmp15], [ttmp0, ttmp1], 0 scope:SCOPE_CU // Load the 2 instruction DW we are returning to
s_wait_kmcnt 0
s_load_b64 [ttmp2, ttmp3], [ttmp0, ttmp1], 8 scope:SCOPE_CU // Load the next 2 instruction DW, just in case
s_wait_kmcnt 1
s_and_b32 ttmp10, ttmp14, 0x80000000 // Check bit 31 in the first DWORD
// SCC set if ttmp10 is != 0, i.e. if bit 31 == 1
s_cbranch_scc1 L_FIXUP_NOT_VOP12C // If bit 31 is 1, we are not VOP1, VOP2, or VOP3C

View file

@ -120,8 +120,7 @@ static inline bool kfd_dbg_has_gws_support(struct kfd_node *dev)
&& dev->kfd->mec2_fw_version < 0x1b6) ||
(KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 1)
&& dev->kfd->mec2_fw_version < 0x30) ||
(KFD_GC_VERSION(dev) >= IP_VERSION(11, 0, 0) &&
KFD_GC_VERSION(dev) < IP_VERSION(12, 0, 0)))
kfd_dbg_has_cwsr_workaround(dev))
return false;
/* Assume debugging and cooperative launch supported otherwise. */

View file

@ -109,6 +109,17 @@ static void set_priority(struct v9_mqd *m, struct queue_properties *q)
m->cp_hqd_queue_priority = q->priority;
}
static bool mqd_on_vram(struct amdgpu_device *adev)
{
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 4, 3):
case IP_VERSION(9, 5, 0):
return true;
default:
return false;
}
}
static struct kfd_mem_obj *allocate_mqd(struct kfd_node *node,
struct queue_properties *q)
{
@ -139,7 +150,8 @@ static struct kfd_mem_obj *allocate_mqd(struct kfd_node *node,
(ALIGN(q->ctl_stack_size, PAGE_SIZE) +
ALIGN(sizeof(struct v9_mqd), PAGE_SIZE)) *
NUM_XCC(node->xcc_mask),
AMDGPU_GEM_DOMAIN_GTT,
mqd_on_vram(node->adev) ? AMDGPU_GEM_DOMAIN_VRAM :
AMDGPU_GEM_DOMAIN_GTT,
&(mqd_mem_obj->mem),
&(mqd_mem_obj->gpu_addr),
(void *)&(mqd_mem_obj->cpu_ptr), true);
@ -739,6 +751,9 @@ static void init_mqd_v9_4_3(struct mqd_manager *mm, void **mqd,
*gart_addr = xcc_gart_addr;
}
}
if (mqd_on_vram(mm->dev->adev))
amdgpu_device_flush_hdp(mm->dev->adev, NULL);
}
static void update_mqd_v9_4_3(struct mqd_manager *mm, void *mqd,
@ -775,6 +790,9 @@ static void update_mqd_v9_4_3(struct mqd_manager *mm, void *mqd,
m->pm4_target_xcc_in_xcp = q->pm4_target_xcc;
}
}
if (mqd_on_vram(mm->dev->adev))
amdgpu_device_flush_hdp(mm->dev->adev, NULL);
}
static void restore_mqd_v9_4_3(struct mqd_manager *mm, void **mqd,
@ -813,6 +831,9 @@ static void restore_mqd_v9_4_3(struct mqd_manager *mm, void **mqd,
(uint8_t *)ctl_stack_src + xcc * mqd_ctl_stack_size,
mqd_ctl_stack_size);
}
if (mqd_on_vram(mm->dev->adev))
amdgpu_device_flush_hdp(mm->dev->adev, NULL);
}
static int destroy_mqd_v9_4_3(struct mqd_manager *mm, void *mqd,
enum kfd_preempt_type type, unsigned int timeout,

View file

@ -1372,7 +1372,6 @@ static int
svm_range_unmap_from_gpus(struct svm_range *prange, unsigned long start,
unsigned long last, uint32_t trigger)
{
DECLARE_BITMAP(bitmap, MAX_GPU_INSTANCE);
struct kfd_process_device *pdd;
struct dma_fence *fence = NULL;
struct kfd_process *p;
@ -1390,11 +1389,9 @@ svm_range_unmap_from_gpus(struct svm_range *prange, unsigned long start,
prange->mapped_to_gpu = false;
}
bitmap_or(bitmap, prange->bitmap_access, prange->bitmap_aip,
MAX_GPU_INSTANCE);
p = container_of(prange->svms, struct kfd_process, svms);
for_each_set_bit(gpuidx, bitmap, MAX_GPU_INSTANCE) {
for_each_or_bit(gpuidx, prange->bitmap_access, prange->bitmap_aip, MAX_GPU_INSTANCE) {
pr_debug("unmap from gpu idx 0x%x\n", gpuidx);
pdd = kfd_process_device_from_gpuidx(p, gpuidx);
if (!pdd) {

View file

@ -7768,10 +7768,12 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
drm_dp_mst_topology_mgr_destroy(&aconnector->mst_mgr);
/* Cancel and flush any pending HDMI HPD debounce work */
cancel_delayed_work_sync(&aconnector->hdmi_hpd_debounce_work);
if (aconnector->hdmi_prev_sink) {
dc_sink_release(aconnector->hdmi_prev_sink);
aconnector->hdmi_prev_sink = NULL;
if (aconnector->hdmi_hpd_debounce_delay_ms) {
cancel_delayed_work_sync(&aconnector->hdmi_hpd_debounce_work);
if (aconnector->hdmi_prev_sink) {
dc_sink_release(aconnector->hdmi_prev_sink);
aconnector->hdmi_prev_sink = NULL;
}
}
if (aconnector->bl_idx != -1) {
@ -13144,9 +13146,24 @@ static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector,
if (ieeeId == HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID &&
amd_vsdb->version == HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3) {
u8 panel_type;
vsdb_info->replay_mode = (amd_vsdb->feature_caps & AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE) ? true : false;
vsdb_info->amd_vsdb_version = HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3;
drm_dbg_kms(aconnector->base.dev, "Panel supports Replay Mode: %d\n", vsdb_info->replay_mode);
panel_type = (amd_vsdb->color_space_eotf_support & AMD_VDSB_VERSION_3_PANEL_TYPE_MASK) >> AMD_VDSB_VERSION_3_PANEL_TYPE_SHIFT;
switch (panel_type) {
case AMD_VSDB_PANEL_TYPE_OLED:
aconnector->dc_link->panel_type = PANEL_TYPE_OLED;
break;
case AMD_VSDB_PANEL_TYPE_MINILED:
aconnector->dc_link->panel_type = PANEL_TYPE_MINILED;
break;
default:
aconnector->dc_link->panel_type = PANEL_TYPE_NONE;
break;
}
drm_dbg_kms(aconnector->base.dev, "Panel type: %d\n",
aconnector->dc_link->panel_type);
return true;
}

View file

@ -55,8 +55,17 @@
#define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID 0x00001A
#define AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE 0x40
#define AMD_VDSB_VERSION_3_PANEL_TYPE_MASK 0xC0
#define AMD_VDSB_VERSION_3_PANEL_TYPE_SHIFT 6
#define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3 0x3
enum amd_vsdb_panel_type {
AMD_VSDB_PANEL_TYPE_DEFAULT = 0,
AMD_VSDB_PANEL_TYPE_MINILED,
AMD_VSDB_PANEL_TYPE_OLED,
AMD_VSDB_PANEL_TYPE_RESERVED,
};
#define AMDGPU_HDR_MULT_DEFAULT (0x100000000LL)
/*
@ -92,6 +101,8 @@ struct amd_vsdb_block {
unsigned char ieee_id[3];
unsigned char version;
unsigned char feature_caps;
unsigned char reserved[3];
unsigned char color_space_eotf_support;
};
struct common_irq_params {

View file

@ -248,8 +248,6 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
struct vblank_control_work *vblank_work =
container_of(work, struct vblank_control_work, work);
struct amdgpu_display_manager *dm = vblank_work->dm;
struct amdgpu_device *adev = drm_to_adev(dm->ddev);
int r;
mutex_lock(&dm->dc_lock);
@ -279,16 +277,7 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
if (dm->active_vblank_irq_count == 0) {
dc_post_update_surfaces_to_stream(dm->dc);
r = amdgpu_dpm_pause_power_profile(adev, true);
if (r)
dev_warn(adev->dev, "failed to set default power profile mode\n");
dc_allow_idle_optimizations(dm->dc, true);
r = amdgpu_dpm_pause_power_profile(adev, false);
if (r)
dev_warn(adev->dev, "failed to restore the power profile mode\n");
}
mutex_unlock(&dm->dc_lock);

View file

@ -2709,6 +2709,65 @@ static int ips_status_show(struct seq_file *m, void *unused)
return 0;
}
/*
* IPS residency information from DMUB service. Read only.
*
* For time-window (segment) measurement:
* 1) echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_ips_residency_cntl
* 2) sleep <seconds>
* 3) echo 0 > /sys/kernel/debug/dri/0/amdgpu_dm_ips_residency_cntl
* 4) cat /sys/kernel/debug/dri/0/amdgpu_dm_ips_residency
*/
static int ips_residency_show(struct seq_file *m, void *unused)
{
struct amdgpu_device *adev = m->private;
struct dc *dc = adev->dm.dc;
uint8_t panel_inst = 0;
enum ips_residency_mode mode;
struct dmub_ips_residency_info info;
mutex_lock(&adev->dm.dc_lock);
mode = IPS_RESIDENCY__IPS1_RCG;
if (!dc_dmub_srv_ips_query_residency_info(dc->ctx, panel_inst, &info, mode)) {
seq_printf(m, "ISP query failed\n");
} else {
unsigned int pct, frac;
pct = info.residency_millipercent / 1000;
frac = info.residency_millipercent % 1000;
seq_printf(m, "IPS residency: %u.%03u%% \n", pct, frac);
seq_printf(m, " entry_counter: %u\n", info.entry_counter);
seq_printf(m, " total_time_us: %llu\n",
(unsigned long long)info.total_time_us);
seq_printf(m, " total_inactive_time_us: %llu\n",
(unsigned long long)info.total_inactive_time_us);
}
mutex_unlock(&adev->dm.dc_lock);
return 0;
}
static int ips_residency_cntl_get(void *data, u64 *val)
{
*val = 0;
return 0;
}
static int ips_residency_cntl_set(void *data, u64 val)
{
struct amdgpu_device *adev = data;
struct dc *dc = adev->dm.dc;
uint8_t panel_inst = 0;
int ret = 0;
mutex_lock(&adev->dm.dc_lock);
if (!dc_dmub_srv_ips_residency_cntl(dc->ctx, panel_inst, !!val))
ret = -EIO;
mutex_unlock(&adev->dm.dc_lock);
return ret;
}
/*
* Backlight at this moment. Read only.
* As written to display, taking ABM and backlight lut into account.
@ -3370,9 +3429,12 @@ DEFINE_DEBUGFS_ATTRIBUTE(disallow_edp_enter_psr_fops,
disallow_edp_enter_psr_get,
disallow_edp_enter_psr_set, "%llu\n");
DEFINE_DEBUGFS_ATTRIBUTE(ips_residency_cntl_fops, ips_residency_cntl_get,
ips_residency_cntl_set, "%llu\n");
DEFINE_SHOW_ATTRIBUTE(current_backlight);
DEFINE_SHOW_ATTRIBUTE(target_backlight);
DEFINE_SHOW_ATTRIBUTE(ips_status);
DEFINE_SHOW_ATTRIBUTE(ips_residency);
static const struct {
char *name;
@ -4271,7 +4333,14 @@ void dtn_debugfs_init(struct amdgpu_device *adev)
debugfs_create_file_unsafe("amdgpu_dm_disable_hpd", 0644, root, adev,
&disable_hpd_ops);
if (adev->dm.dc->caps.ips_support)
if (adev->dm.dc->caps.ips_support) {
debugfs_create_file_unsafe("amdgpu_dm_ips_status", 0644, root, adev,
&ips_status_fops);
debugfs_create_file_unsafe("amdgpu_dm_ips_residency_cntl", 0644, root, adev,
&ips_residency_cntl_fops);
debugfs_create_file_unsafe("amdgpu_dm_ips_residency", 0644, root, adev,
&ips_residency_fops);
}
}

View file

@ -1121,6 +1121,12 @@ void dm_set_dcn_clocks(struct dc_context *ctx, struct dc_clocks *clks)
/* TODO: something */
}
void dm_helpers_dmu_timeout(struct dc_context *ctx)
{
// TODO:
//amdgpu_device_gpu_recover(dc_context->driver-context, NULL);
}
void dm_helpers_smu_timeout(struct dc_context *ctx, unsigned int msg_id, unsigned int param, unsigned int timeout_us)
{
// TODO:

View file

@ -915,13 +915,19 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
struct amdgpu_dm_connector *amdgpu_dm_connector;
const struct dc_link *dc_link;
use_polling |= connector->polled != DRM_CONNECTOR_POLL_HPD;
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
continue;
amdgpu_dm_connector = to_amdgpu_dm_connector(connector);
/*
* Analog connectors may be hot-plugged unlike other connector
* types that don't support HPD. Only poll analog connectors.
*/
use_polling |=
amdgpu_dm_connector->dc_link &&
dc_connector_supports_analog(amdgpu_dm_connector->dc_link->link_id.id);
dc_link = amdgpu_dm_connector->dc_link;
/*

View file

@ -77,7 +77,6 @@ static const struct IP_BASE CLK_BASE = { { { { 0x00016C00, 0x02401800, 0, 0, 0,
#undef DC_LOGGER
#define DC_LOGGER \
clk_mgr->base.base.ctx->logger
#define regCLK1_CLK_PLL_REQ 0x0237
#define regCLK1_CLK_PLL_REQ_BASE_IDX 0
@ -88,70 +87,8 @@ static const struct IP_BASE CLK_BASE = { { { { 0x00016C00, 0x02401800, 0, 0, 0,
#define CLK1_CLK_PLL_REQ__PllSpineDiv_MASK 0x0000F000L
#define CLK1_CLK_PLL_REQ__FbMult_frac_MASK 0xFFFF0000L
#define regCLK1_CLK0_DFS_CNTL 0x0269
#define regCLK1_CLK0_DFS_CNTL_BASE_IDX 0
#define regCLK1_CLK1_DFS_CNTL 0x026c
#define regCLK1_CLK1_DFS_CNTL_BASE_IDX 0
#define regCLK1_CLK2_DFS_CNTL 0x026f
#define regCLK1_CLK2_DFS_CNTL_BASE_IDX 0
#define regCLK1_CLK3_DFS_CNTL 0x0272
#define regCLK1_CLK3_DFS_CNTL_BASE_IDX 0
#define regCLK1_CLK4_DFS_CNTL 0x0275
#define regCLK1_CLK4_DFS_CNTL_BASE_IDX 0
#define regCLK1_CLK5_DFS_CNTL 0x0278
#define regCLK1_CLK5_DFS_CNTL_BASE_IDX 0
#define regCLK1_CLK0_CURRENT_CNT 0x02fb
#define regCLK1_CLK0_CURRENT_CNT_BASE_IDX 0
#define regCLK1_CLK1_CURRENT_CNT 0x02fc
#define regCLK1_CLK1_CURRENT_CNT_BASE_IDX 0
#define regCLK1_CLK2_CURRENT_CNT 0x02fd
#define regCLK1_CLK2_CURRENT_CNT_BASE_IDX 0
#define regCLK1_CLK3_CURRENT_CNT 0x02fe
#define regCLK1_CLK3_CURRENT_CNT_BASE_IDX 0
#define regCLK1_CLK4_CURRENT_CNT 0x02ff
#define regCLK1_CLK4_CURRENT_CNT_BASE_IDX 0
#define regCLK1_CLK5_CURRENT_CNT 0x0300
#define regCLK1_CLK5_CURRENT_CNT_BASE_IDX 0
#define regCLK1_CLK0_BYPASS_CNTL 0x028a
#define regCLK1_CLK0_BYPASS_CNTL_BASE_IDX 0
#define regCLK1_CLK1_BYPASS_CNTL 0x0293
#define regCLK1_CLK1_BYPASS_CNTL_BASE_IDX 0
#define regCLK1_CLK2_BYPASS_CNTL 0x029c
#define regCLK1_CLK2_BYPASS_CNTL_BASE_IDX 0
#define regCLK1_CLK3_BYPASS_CNTL 0x02a5
#define regCLK1_CLK3_BYPASS_CNTL_BASE_IDX 0
#define regCLK1_CLK4_BYPASS_CNTL 0x02ae
#define regCLK1_CLK4_BYPASS_CNTL_BASE_IDX 0
#define regCLK1_CLK5_BYPASS_CNTL 0x02b7
#define regCLK1_CLK5_BYPASS_CNTL_BASE_IDX 0
#define regCLK1_CLK0_DS_CNTL 0x0283
#define regCLK1_CLK0_DS_CNTL_BASE_IDX 0
#define regCLK1_CLK1_DS_CNTL 0x028c
#define regCLK1_CLK1_DS_CNTL_BASE_IDX 0
#define regCLK1_CLK2_DS_CNTL 0x0295
#define regCLK1_CLK2_DS_CNTL_BASE_IDX 0
#define regCLK1_CLK3_DS_CNTL 0x029e
#define regCLK1_CLK3_DS_CNTL_BASE_IDX 0
#define regCLK1_CLK4_DS_CNTL 0x02a7
#define regCLK1_CLK4_DS_CNTL_BASE_IDX 0
#define regCLK1_CLK5_DS_CNTL 0x02b0
#define regCLK1_CLK5_DS_CNTL_BASE_IDX 0
#define regCLK1_CLK0_ALLOW_DS 0x0284
#define regCLK1_CLK0_ALLOW_DS_BASE_IDX 0
#define regCLK1_CLK1_ALLOW_DS 0x028d
#define regCLK1_CLK1_ALLOW_DS_BASE_IDX 0
#define regCLK1_CLK2_ALLOW_DS 0x0296
#define regCLK1_CLK2_ALLOW_DS_BASE_IDX 0
#define regCLK1_CLK3_ALLOW_DS 0x029f
#define regCLK1_CLK3_ALLOW_DS_BASE_IDX 0
#define regCLK1_CLK4_ALLOW_DS 0x02a8
#define regCLK1_CLK4_ALLOW_DS_BASE_IDX 0
#define regCLK1_CLK5_ALLOW_DS 0x02b1
#define regCLK1_CLK5_ALLOW_DS_BASE_IDX 0
#define CLK1_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL__SHIFT 0x0
#define CLK1_CLK2_BYPASS_CNTL__CLK2_BYPASS_DIV__SHIFT 0x10
@ -248,8 +185,6 @@ void dcn314_init_clocks(struct clk_mgr *clk_mgr)
{
struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr);
uint32_t ref_dtbclk = clk_mgr->clks.ref_dtbclk_khz;
struct clk_mgr_dcn314 *clk_mgr_dcn314 = TO_CLK_MGR_DCN314(clk_mgr_int);
struct clk_log_info log_info = {0};
memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
// Assumption is that boot state always supports pstate
@ -265,9 +200,6 @@ void dcn314_init_clocks(struct clk_mgr *clk_mgr)
dce_adjust_dp_ref_freq_for_ss(clk_mgr_int, clk_mgr->dprefclk_khz);
else
clk_mgr->dp_dto_source_clock_in_khz = clk_mgr->dprefclk_khz;
dcn314_dump_clk_registers(&clk_mgr->boot_snapshot, &clk_mgr_dcn314->base.base, &log_info);
clk_mgr->clks.dispclk_khz = clk_mgr->boot_snapshot.dispclk * 1000;
}
void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
@ -278,7 +210,7 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
struct dc *dc = clk_mgr_base->ctx->dc;
int display_count;
int display_count = 0;
bool update_dppclk = false;
bool update_dispclk = false;
bool dpp_clock_lowered = false;
@ -287,7 +219,6 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
return;
display_count = dcn314_get_active_display_cnt_wa(dc, context);
/*
* if it is safe to lower, but we are already in the lower state, we don't have to do anything
* also if safe to lower is false, we just go in the higher state
@ -363,7 +294,7 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
}
if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) &&
(new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) {
(new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) {
int requested_dispclk_khz = new_clocks->dispclk_khz;
dcn314_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true);
@ -374,7 +305,6 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
dcn314_smu_set_dispclk(clk_mgr, requested_dispclk_khz);
clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
dcn314_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false);
update_dispclk = true;
@ -462,65 +392,10 @@ bool dcn314_are_clock_states_equal(struct dc_clocks *a,
return true;
}
static void dcn314_dump_clk_registers_internal(struct dcn35_clk_internal *internal, struct clk_mgr *clk_mgr_base)
{
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
// read dtbclk
internal->CLK1_CLK4_CURRENT_CNT = REG_READ(CLK1_CLK4_CURRENT_CNT);
internal->CLK1_CLK4_BYPASS_CNTL = REG_READ(CLK1_CLK4_BYPASS_CNTL);
// read dcfclk
internal->CLK1_CLK3_CURRENT_CNT = REG_READ(CLK1_CLK3_CURRENT_CNT);
internal->CLK1_CLK3_BYPASS_CNTL = REG_READ(CLK1_CLK3_BYPASS_CNTL);
// read dcf deep sleep divider
internal->CLK1_CLK3_DS_CNTL = REG_READ(CLK1_CLK3_DS_CNTL);
internal->CLK1_CLK3_ALLOW_DS = REG_READ(CLK1_CLK3_ALLOW_DS);
// read dppclk
internal->CLK1_CLK1_CURRENT_CNT = REG_READ(CLK1_CLK1_CURRENT_CNT);
internal->CLK1_CLK1_BYPASS_CNTL = REG_READ(CLK1_CLK1_BYPASS_CNTL);
// read dprefclk
internal->CLK1_CLK2_CURRENT_CNT = REG_READ(CLK1_CLK2_CURRENT_CNT);
internal->CLK1_CLK2_BYPASS_CNTL = REG_READ(CLK1_CLK2_BYPASS_CNTL);
// read dispclk
internal->CLK1_CLK0_CURRENT_CNT = REG_READ(CLK1_CLK0_CURRENT_CNT);
internal->CLK1_CLK0_BYPASS_CNTL = REG_READ(CLK1_CLK0_BYPASS_CNTL);
}
void dcn314_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
static void dcn314_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
{
struct dcn35_clk_internal internal = {0};
dcn314_dump_clk_registers_internal(&internal, clk_mgr_base);
regs_and_bypass->dcfclk = internal.CLK1_CLK3_CURRENT_CNT / 10;
regs_and_bypass->dcf_deep_sleep_divider = internal.CLK1_CLK3_DS_CNTL / 10;
regs_and_bypass->dcf_deep_sleep_allow = internal.CLK1_CLK3_ALLOW_DS;
regs_and_bypass->dprefclk = internal.CLK1_CLK2_CURRENT_CNT / 10;
regs_and_bypass->dispclk = internal.CLK1_CLK0_CURRENT_CNT / 10;
regs_and_bypass->dppclk = internal.CLK1_CLK1_CURRENT_CNT / 10;
regs_and_bypass->dtbclk = internal.CLK1_CLK4_CURRENT_CNT / 10;
regs_and_bypass->dppclk_bypass = internal.CLK1_CLK1_BYPASS_CNTL & 0x0007;
if (regs_and_bypass->dppclk_bypass > 4)
regs_and_bypass->dppclk_bypass = 0;
regs_and_bypass->dcfclk_bypass = internal.CLK1_CLK3_BYPASS_CNTL & 0x0007;
if (regs_and_bypass->dcfclk_bypass > 4)
regs_and_bypass->dcfclk_bypass = 0;
regs_and_bypass->dispclk_bypass = internal.CLK1_CLK0_BYPASS_CNTL & 0x0007;
if (regs_and_bypass->dispclk_bypass > 4)
regs_and_bypass->dispclk_bypass = 0;
regs_and_bypass->dprefclk_bypass = internal.CLK1_CLK2_BYPASS_CNTL & 0x0007;
if (regs_and_bypass->dprefclk_bypass > 4)
regs_and_bypass->dprefclk_bypass = 0;
return;
}
static struct clk_bw_params dcn314_bw_params = {

View file

@ -65,9 +65,4 @@ void dcn314_clk_mgr_construct(struct dc_context *ctx,
void dcn314_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int);
void dcn314_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info);
#endif //__DCN314_CLK_MGR_H__

View file

@ -40,7 +40,7 @@
#include "dm_helpers.h"
#include "dc_dmub_srv.h"
#include "reg_helper.h"
#include "logger_types.h"
#undef DC_LOGGER
#define DC_LOGGER \
@ -48,43 +48,9 @@
#include "link_service.h"
#define MAX_INSTANCE 7
#define MAX_SEGMENT 8
struct IP_BASE_INSTANCE {
unsigned int segment[MAX_SEGMENT];
};
struct IP_BASE {
struct IP_BASE_INSTANCE instance[MAX_INSTANCE];
};
static const struct IP_BASE CLK_BASE = { { { { 0x00016C00, 0x02401800, 0, 0, 0, 0, 0, 0 } },
{ { 0x00016E00, 0x02401C00, 0, 0, 0, 0, 0, 0 } },
{ { 0x00017000, 0x02402000, 0, 0, 0, 0, 0, 0 } },
{ { 0x00017200, 0x02402400, 0, 0, 0, 0, 0, 0 } },
{ { 0x0001B000, 0x0242D800, 0, 0, 0, 0, 0, 0 } },
{ { 0x0001B200, 0x0242DC00, 0, 0, 0, 0, 0, 0 } } } };
#define regCLK1_CLK0_CURRENT_CNT 0x0314
#define regCLK1_CLK0_CURRENT_CNT_BASE_IDX 0
#define regCLK1_CLK1_CURRENT_CNT 0x0315
#define regCLK1_CLK1_CURRENT_CNT_BASE_IDX 0
#define regCLK1_CLK2_CURRENT_CNT 0x0316
#define regCLK1_CLK2_CURRENT_CNT_BASE_IDX 0
#define regCLK1_CLK3_CURRENT_CNT 0x0317
#define regCLK1_CLK3_CURRENT_CNT_BASE_IDX 0
#define regCLK1_CLK4_CURRENT_CNT 0x0318
#define regCLK1_CLK4_CURRENT_CNT_BASE_IDX 0
#define regCLK1_CLK5_CURRENT_CNT 0x0319
#define regCLK1_CLK5_CURRENT_CNT_BASE_IDX 0
#define TO_CLK_MGR_DCN315(clk_mgr)\
container_of(clk_mgr, struct clk_mgr_dcn315, base)
#define REG(reg_name) \
(CLK_BASE.instance[0].segment[reg ## reg_name ## _BASE_IDX] + reg ## reg_name)
#define UNSUPPORTED_DCFCLK 10000000
#define MIN_DPP_DISP_CLK 100000
@ -172,7 +138,7 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
if (dc->work_arounds.skip_clock_update)
return;
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
display_count = dcn315_get_active_display_cnt_wa(dc, context);
/*
* if it is safe to lower, but we are already in the lower state, we don't have to do anything
* also if safe to lower is false, we just go in the higher state
@ -185,7 +151,6 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
}
/* check that we're not already in lower */
if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
display_count = dcn315_get_active_display_cnt_wa(dc, context);
/* if we can go lower, go lower */
if (display_count == 0) {
union display_idle_optimization_u idle_info = { 0 };
@ -279,38 +244,9 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
static void dcn315_dump_clk_registers_internal(struct dcn35_clk_internal *internal, struct clk_mgr *clk_mgr_base)
{
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
// read dtbclk
internal->CLK1_CLK4_CURRENT_CNT = REG_READ(CLK1_CLK4_CURRENT_CNT);
// read dcfclk
internal->CLK1_CLK3_CURRENT_CNT = REG_READ(CLK1_CLK3_CURRENT_CNT);
// read dppclk
internal->CLK1_CLK1_CURRENT_CNT = REG_READ(CLK1_CLK1_CURRENT_CNT);
// read dprefclk
internal->CLK1_CLK2_CURRENT_CNT = REG_READ(CLK1_CLK2_CURRENT_CNT);
// read dispclk
internal->CLK1_CLK0_CURRENT_CNT = REG_READ(CLK1_CLK0_CURRENT_CNT);
}
static void dcn315_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
{
struct dcn35_clk_internal internal = {0};
dcn315_dump_clk_registers_internal(&internal, clk_mgr_base);
regs_and_bypass->dcfclk = internal.CLK1_CLK3_CURRENT_CNT / 10;
regs_and_bypass->dprefclk = internal.CLK1_CLK2_CURRENT_CNT / 10;
regs_and_bypass->dispclk = internal.CLK1_CLK0_CURRENT_CNT / 10;
regs_and_bypass->dppclk = internal.CLK1_CLK1_CURRENT_CNT / 10;
regs_and_bypass->dtbclk = internal.CLK1_CLK4_CURRENT_CNT / 10;
return;
}
@ -657,32 +593,13 @@ static struct clk_mgr_funcs dcn315_funcs = {
.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
.get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz,
.update_clocks = dcn315_update_clocks,
.init_clocks = dcn315_init_clocks,
.init_clocks = dcn31_init_clocks,
.enable_pme_wa = dcn315_enable_pme_wa,
.are_clock_states_equal = dcn31_are_clock_states_equal,
.notify_wm_ranges = dcn315_notify_wm_ranges
};
extern struct clk_mgr_funcs dcn3_fpga_funcs;
void dcn315_init_clocks(struct clk_mgr *clk_mgr)
{
struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr);
uint32_t ref_dtbclk = clk_mgr->clks.ref_dtbclk_khz;
struct clk_mgr_dcn315 *clk_mgr_dcn315 = TO_CLK_MGR_DCN315(clk_mgr_int);
struct clk_log_info log_info = {0};
memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
// Assumption is that boot state always supports pstate
clk_mgr->clks.ref_dtbclk_khz = ref_dtbclk; // restore ref_dtbclk
clk_mgr->clks.p_state_change_support = true;
clk_mgr->clks.prev_p_state_change_support = true;
clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN;
clk_mgr->clks.zstate_support = DCN_ZSTATE_SUPPORT_UNKNOWN;
dcn315_dump_clk_registers(&clk_mgr->boot_snapshot, &clk_mgr_dcn315->base.base, &log_info);
clk_mgr->clks.dispclk_khz = clk_mgr->boot_snapshot.dispclk * 1000;
}
void dcn315_clk_mgr_construct(
struct dc_context *ctx,
struct clk_mgr_dcn315 *clk_mgr,
@ -743,7 +660,6 @@ void dcn315_clk_mgr_construct(
/* Saved clocks configured at boot for debug purposes */
dcn315_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
&clk_mgr->base.base, &log_info);
clk_mgr->base.base.clks.dispclk_khz = clk_mgr->base.base.boot_snapshot.dispclk * 1000;
clk_mgr->base.base.dprefclk_khz = 600000;
clk_mgr->base.base.dprefclk_khz = dcn315_smu_get_dpref_clk(&clk_mgr->base);

View file

@ -44,7 +44,6 @@ void dcn315_clk_mgr_construct(struct dc_context *ctx,
struct pp_smu_funcs *pp_smu,
struct dccg *dccg);
void dcn315_init_clocks(struct clk_mgr *clk_mgr);
void dcn315_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int);
#endif //__DCN315_CLK_MGR_H__

View file

@ -7143,22 +7143,24 @@ void dc_log_preos_dmcub_info(const struct dc *dc)
bool dc_get_qos_info(struct dc *dc, struct dc_qos_info *info)
{
const struct dc_clocks *clk = &dc->current_state->bw_ctx.bw.dcn.clk;
struct memory_qos qos;
memset(info, 0, sizeof(*info));
// Check if all measurement functions are available
if (!dc->hwss.measure_peak_bw_mbps ||
!dc->hwss.measure_avg_bw_mbps ||
!dc->hwss.measure_max_latency_ns ||
!dc->hwss.measure_avg_latency_ns) {
// Check if measurement function is available
if (!dc->hwss.measure_memory_qos) {
return false;
}
// Call measurement functions to get actual values
info->actual_peak_bw_in_mbps = dc->hwss.measure_peak_bw_mbps(dc);
info->actual_avg_bw_in_mbps = dc->hwss.measure_avg_bw_mbps(dc);
info->actual_max_latency_in_ns = dc->hwss.measure_max_latency_ns(dc);
info->actual_avg_latency_in_ns = dc->hwss.measure_avg_latency_ns(dc);
// Call unified measurement function
dc->hwss.measure_memory_qos(dc, &qos);
// Populate info from measured qos
info->actual_peak_bw_in_mbps = qos.peak_bw_mbps;
info->actual_avg_bw_in_mbps = qos.avg_bw_mbps;
info->actual_min_latency_in_ns = qos.min_latency_ns;
info->actual_max_latency_in_ns = qos.max_latency_ns;
info->actual_avg_latency_in_ns = qos.avg_latency_ns;
info->dcn_bandwidth_ub_in_mbps = (uint32_t)(clk->fclk_khz / 1000 * 64);
return true;

View file

@ -63,7 +63,7 @@ struct dcn_dsc_reg_state;
struct dcn_optc_reg_state;
struct dcn_dccg_reg_state;
#define DC_VER "3.2.365"
#define DC_VER "3.2.366"
/**
* MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC
@ -962,6 +962,7 @@ struct dc_qos_info {
uint32_t actual_avg_bw_in_mbps;
uint32_t calculated_avg_bw_in_mbps;
uint32_t actual_max_latency_in_ns;
uint32_t actual_min_latency_in_ns;
uint32_t qos_max_latency_ub_in_ns;
uint32_t actual_avg_latency_in_ns;
uint32_t qos_avg_latency_ub_in_ns;
@ -1208,6 +1209,7 @@ struct dc_debug_options {
uint32_t custom_psp_footer_size;
bool disable_deferred_minimal_transitions;
unsigned int num_fast_flips_to_steady_state_override;
bool enable_dmu_recovery;
};
@ -1733,6 +1735,7 @@ struct dc_scratch_space {
bool link_powered_externally; // Used to bypass hardware sequencing delays when panel is powered down forcibly
struct dc_panel_config panel_config;
enum dc_panel_type panel_type;
struct phy_state phy_state;
uint32_t phy_transition_bitmask;
// BW ALLOCATON USB4 ONLY

View file

@ -41,6 +41,8 @@
#define DC_LOGGER CTX->logger
#define GPINT_RETRY_NUM 20
#define MAX_WAIT_US 100000
static void dc_dmub_srv_construct(struct dc_dmub_srv *dc_srv, struct dc *dc,
struct dmub_srv *dmub)
{
@ -48,6 +50,13 @@ static void dc_dmub_srv_construct(struct dc_dmub_srv *dc_srv, struct dc *dc,
dc_srv->ctx = dc->ctx;
}
static void dc_dmub_srv_handle_failure(struct dc_dmub_srv *dc_dmub_srv)
{
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
if (dc_dmub_srv->ctx->dc->debug.enable_dmu_recovery)
dm_helpers_dmu_timeout(dc_dmub_srv->ctx);
}
struct dc_dmub_srv *dc_dmub_srv_create(struct dc *dc, struct dmub_srv *dmub)
{
struct dc_dmub_srv *dc_srv =
@ -84,12 +93,12 @@ bool dc_dmub_srv_wait_for_pending(struct dc_dmub_srv *dc_dmub_srv)
dmub = dc_dmub_srv->dmub;
do {
status = dmub_srv_wait_for_pending(dmub, 100000);
status = dmub_srv_wait_for_pending(dmub, MAX_WAIT_US);
} while (dc_dmub_srv->ctx->dc->debug.disable_timeout && status != DMUB_STATUS_OK);
if (status != DMUB_STATUS_OK) {
DC_ERROR("Error waiting for DMUB idle: status=%d\n", status);
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
dc_dmub_srv_handle_failure(dc_dmub_srv);
}
return status == DMUB_STATUS_OK;
@ -104,7 +113,7 @@ void dc_dmub_srv_clear_inbox0_ack(struct dc_dmub_srv *dc_dmub_srv)
status = dmub_srv_clear_inbox0_ack(dmub);
if (status != DMUB_STATUS_OK) {
DC_ERROR("Error clearing INBOX0 ack: status=%d\n", status);
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
dc_dmub_srv_handle_failure(dc_dmub_srv);
}
}
@ -114,10 +123,10 @@ void dc_dmub_srv_wait_for_inbox0_ack(struct dc_dmub_srv *dc_dmub_srv)
struct dc_context *dc_ctx = dc_dmub_srv->ctx;
enum dmub_status status = DMUB_STATUS_OK;
status = dmub_srv_wait_for_inbox0_ack(dmub, 100000);
status = dmub_srv_wait_for_inbox0_ack(dmub, MAX_WAIT_US);
if (status != DMUB_STATUS_OK) {
DC_ERROR("Error waiting for INBOX0 HW Lock Ack\n");
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
dc_dmub_srv_handle_failure(dc_dmub_srv);
}
}
@ -131,7 +140,7 @@ void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dc_dmub_srv,
status = dmub_srv_send_inbox0_cmd(dmub, data);
if (status != DMUB_STATUS_OK) {
DC_ERROR("Error sending INBOX0 cmd\n");
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
dc_dmub_srv_handle_failure(dc_dmub_srv);
}
}
@ -153,7 +162,7 @@ static bool dc_dmub_srv_reg_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_s
for (i = 0 ; i < count; i++) {
/* confirm no messages pending */
do {
status = dmub_srv_wait_for_idle(dmub, 100000);
status = dmub_srv_wait_for_idle(dmub, MAX_WAIT_US);
} while (dc_dmub_srv->ctx->dc->debug.disable_timeout && status != DMUB_STATUS_OK);
/* queue command */
@ -169,7 +178,7 @@ static bool dc_dmub_srv_reg_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_s
if (status != DMUB_STATUS_OK) {
if (status != DMUB_STATUS_POWER_STATE_D3) {
DC_ERROR("Error starting DMUB execution: status=%d\n", status);
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
dc_dmub_srv_handle_failure(dc_dmub_srv);
}
return false;
}
@ -208,7 +217,7 @@ static bool dc_dmub_srv_fb_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_sr
return false;
do {
status = dmub_srv_wait_for_inbox_free(dmub, 100000, count - i);
status = dmub_srv_wait_for_inbox_free(dmub, MAX_WAIT_US, count - i);
} while (dc_dmub_srv->ctx->dc->debug.disable_timeout && status != DMUB_STATUS_OK);
/* Requeue the command. */
@ -218,7 +227,7 @@ static bool dc_dmub_srv_fb_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_sr
if (status != DMUB_STATUS_OK) {
if (status != DMUB_STATUS_POWER_STATE_D3) {
DC_ERROR("Error queueing DMUB command: status=%d\n", status);
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
dc_dmub_srv_handle_failure(dc_dmub_srv);
}
return false;
}
@ -228,7 +237,7 @@ static bool dc_dmub_srv_fb_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_sr
if (status != DMUB_STATUS_OK) {
if (status != DMUB_STATUS_POWER_STATE_D3) {
DC_ERROR("Error starting DMUB execution: status=%d\n", status);
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
dc_dmub_srv_handle_failure(dc_dmub_srv);
}
return false;
}
@ -271,7 +280,7 @@ bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv,
// Wait for DMUB to process command
if (wait_type != DM_DMUB_WAIT_TYPE_NO_WAIT) {
do {
status = dmub_srv_wait_for_idle(dmub, 100000);
status = dmub_srv_wait_for_idle(dmub, MAX_WAIT_US);
} while (dc_dmub_srv->ctx->dc->debug.disable_timeout && status != DMUB_STATUS_OK);
if (status != DMUB_STATUS_OK) {
@ -282,7 +291,7 @@ bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv,
dmub->debug.timeout_info.timeout_cmd = *cmd_list;
dmub->debug.timeout_info.timestamp = dm_get_timestamp(dc_dmub_srv->ctx);
}
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
dc_dmub_srv_handle_failure(dc_dmub_srv);
return false;
}

View file

@ -964,6 +964,13 @@ struct display_endpoint_id {
enum display_endpoint_type ep_type;
};
enum dc_panel_type {
PANEL_TYPE_NONE = 0, // UNKONWN, not determined yet
PANEL_TYPE_LCD = 1,
PANEL_TYPE_OLED = 2,
PANEL_TYPE_MINILED = 3,
};
enum backlight_control_type {
BACKLIGHT_CONTROL_PWM = 0,
BACKLIGHT_CONTROL_VESA_AUX = 1,

View file

@ -197,6 +197,7 @@ void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz);
bool dm_helpers_dmub_outbox_interrupt_control(struct dc_context *ctx, bool enable);
void dm_helpers_dmu_timeout(struct dc_context *ctx);
void dm_helpers_smu_timeout(struct dc_context *ctx, unsigned int msg_id, unsigned int param, unsigned int timeout_us);
// 0x1 = Result_OK, 0xFE = Result_UnkmownCmd, 0x0 = Status_Busy

View file

@ -1157,7 +1157,7 @@ static bool setup_dsc_config(
if (!is_dsc_possible)
goto done;
/* increase miniumum slice count to meet sink slice width limitations */
/* increase minimum slice count to meet sink slice width limitations */
min_slices_h = dc_fixpt_ceil(dc_fixpt_max(
dc_fixpt_div_int(dc_fixpt_from_int(pic_width), dsc_common_caps.max_slice_width), // sink min
dc_fixpt_from_int(min_slices_h))); // source min

View file

@ -59,6 +59,7 @@
#include "dc_state_priv.h"
#include "dpcd_defs.h"
#include "dsc.h"
#include "dc_dp_types.h"
/* include DCE11 register header files */
#include "dce/dce_11_0_d.h"
#include "dce/dce_11_0_sh_mask.h"
@ -1759,20 +1760,25 @@ static void power_down_encoders(struct dc *dc)
int i;
for (i = 0; i < dc->link_count; i++) {
enum signal_type signal = dc->links[i]->connector_signal;
dc->link_srv->blank_dp_stream(dc->links[i], false);
struct dc_link *link = dc->links[i];
struct link_encoder *link_enc = link->link_enc;
enum signal_type signal = link->connector_signal;
dc->link_srv->blank_dp_stream(link, false);
if (signal != SIGNAL_TYPE_EDP)
signal = SIGNAL_TYPE_NONE;
if (dc->links[i]->ep_type == DISPLAY_ENDPOINT_PHY)
dc->links[i]->link_enc->funcs->disable_output(
dc->links[i]->link_enc, signal);
if (link->ep_type == DISPLAY_ENDPOINT_PHY)
link_enc->funcs->disable_output(link_enc, signal);
dc->links[i]->link_status.link_active = false;
memset(&dc->links[i]->cur_link_settings, 0,
sizeof(dc->links[i]->cur_link_settings));
if (link->fec_state == dc_link_fec_enabled) {
link_enc->funcs->fec_set_enable(link_enc, false);
link_enc->funcs->fec_set_ready(link_enc, false);
link->fec_state = dc_link_fec_not_ready;
}
link->link_status.link_active = false;
memset(&link->cur_link_settings, 0, sizeof(link->cur_link_settings));
}
}

View file

@ -3145,8 +3145,6 @@ void dcn20_fpga_init_hw(struct dc *dc)
REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF);
REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF);
hws->funcs.dccg_init(hws);
REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
if (REG(REFCLK_CNTL))

View file

@ -143,7 +143,6 @@ static const struct hwseq_private_funcs dcn30_private_funcs = {
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
.dccg_init = dcn20_dccg_init,
.set_blend_lut = dcn30_set_blend_lut,
.set_shaper_3dlut = dcn20_set_shaper_3dlut,
};

View file

@ -140,7 +140,6 @@ static const struct hwseq_private_funcs dcn301_private_funcs = {
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
.dccg_init = dcn20_dccg_init,
.set_blend_lut = dcn30_set_blend_lut,
.set_shaper_3dlut = dcn20_set_shaper_3dlut,
};

View file

@ -546,8 +546,22 @@ static void dcn31_reset_back_end_for_pipe(
if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass)
pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
/*
* TODO - convert symclk_ref_cnts for otg to a bit map to solve
* the case where the same symclk is shared across multiple otg
* instances
*/
if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0;
link->phy_state.symclk_ref_cnts.otg = 0;
if (pipe_ctx->top_pipe == NULL) {
if (link->phy_state.symclk_state == SYMCLK_ON_TX_OFF) {
const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
link_hwss->disable_link_output(link, &pipe_ctx->link_res, pipe_ctx->stream->signal);
link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
}
}
set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL);

View file

@ -144,7 +144,6 @@ static const struct hwseq_private_funcs dcn31_private_funcs = {
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
.dccg_init = dcn20_dccg_init,
.set_blend_lut = dcn30_set_blend_lut,
.set_shaper_3dlut = dcn20_set_shaper_3dlut,
.setup_hpo_hw_control = dcn31_setup_hpo_hw_control,

View file

@ -149,7 +149,6 @@ static const struct hwseq_private_funcs dcn314_private_funcs = {
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
.dccg_init = dcn20_dccg_init,
.set_blend_lut = dcn30_set_blend_lut,
.set_shaper_3dlut = dcn20_set_shaper_3dlut,
.setup_hpo_hw_control = dcn31_setup_hpo_hw_control,

View file

@ -154,7 +154,6 @@ static const struct hwseq_private_funcs dcn32_private_funcs = {
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
.dccg_init = dcn20_dccg_init,
.set_mcm_luts = dcn32_set_mcm_luts,
.program_mall_pipe_config = dcn32_program_mall_pipe_config,
.update_force_pstate = dcn32_update_force_pstate,

View file

@ -164,7 +164,6 @@ static const struct hwseq_private_funcs dcn35_private_funcs = {
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
.dccg_init = dcn20_dccg_init,
.set_mcm_luts = dcn32_set_mcm_luts,
.setup_hpo_hw_control = dcn35_setup_hpo_hw_control,
.calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values,

View file

@ -153,7 +153,6 @@ static const struct hwseq_private_funcs dcn351_private_funcs = {
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
.dccg_init = dcn20_dccg_init,
.set_mcm_luts = dcn32_set_mcm_luts,
.setup_hpo_hw_control = dcn35_setup_hpo_hw_control,
.calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values,

View file

@ -948,7 +948,7 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx)
const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
struct dc *dc = pipe_ctx->stream->ctx->dc;
struct dccg *dccg = dc->res_pool->dccg;
enum phyd32clk_clock_source phyd32clk;
enum phyd32clk_clock_source phyd32clk = PHYD32CLKA;
int dp_hpo_inst = 0;
unsigned int tmds_div = PIXEL_RATE_DIV_NA;
unsigned int unused_div = PIXEL_RATE_DIV_NA;

View file

@ -156,7 +156,6 @@ static const struct hwseq_private_funcs dcn401_private_funcs = {
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.verify_allow_pstate_change_high_sequence = dcn401_verify_allow_pstate_change_high_sequence,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
.dccg_init = dcn20_dccg_init,
.set_mcm_luts = dcn401_set_mcm_luts,
.program_mall_pipe_config = dcn32_program_mall_pipe_config,
.program_mall_pipe_config_sequence = dcn401_program_mall_pipe_config_sequence,

View file

@ -52,7 +52,7 @@ struct drr_params;
struct dc_underflow_debug_data;
struct dsc_optc_config;
struct vm_system_aperture_param;
struct memory_qos;
struct subvp_pipe_control_lock_fast_params {
struct dc *dc;
bool lock;
@ -1289,40 +1289,14 @@ struct hw_sequencer_funcs {
struct dc_underflow_debug_data *out_data);
/**
* measure_peak_bw_mbps - Measure actual peak bandwidth in Mbps
* measure_memory_qos - Measure memory QoS metrics
* @dc: DC structure
* @qos: Pointer to memory_qos struct to populate with measured values
*
* Returns the measured peak bandwidth value in Mbps from hardware
* performance counters or registers.
* Populates the provided memory_qos struct with peak bandwidth, average bandwidth,
* max latency, min latency, and average latency from hardware performance counters.
*/
uint32_t (*measure_peak_bw_mbps)(struct dc *dc);
/**
* measure_avg_bw_mbps - Measure actual average bandwidth in Mbps
* @dc: DC structure
*
* Returns the measured average bandwidth value in Mbps from hardware
* performance counters or registers.
*/
uint32_t (*measure_avg_bw_mbps)(struct dc *dc);
/**
* measure_max_latency_ns - Measure actual maximum latency in nanoseconds
* @dc: DC structure
*
* Returns the measured maximum latency value in nanoseconds from hardware
* performance counters or registers.
*/
uint32_t (*measure_max_latency_ns)(struct dc *dc);
/**
* measure_avg_latency_ns - Measure actual average latency in nanoseconds
* @dc: DC structure
*
* Returns the measured average latency value in nanoseconds from hardware
* performance counters or registers.
*/
uint32_t (*measure_avg_latency_ns)(struct dc *dc);
void (*measure_memory_qos)(struct dc *dc, struct memory_qos *qos);
};

View file

@ -704,4 +704,12 @@ struct dc_bounding_box_max_clk {
int max_phyclk_mhz;
};
struct memory_qos {
uint32_t peak_bw_mbps;
uint32_t avg_bw_mbps;
uint32_t max_latency_ns;
uint32_t min_latency_ns;
uint32_t avg_latency_ns;
};
#endif /* _CORE_TYPES_H_ */

View file

@ -254,30 +254,38 @@ struct hubbub_funcs {
bool (*program_arbiter)(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs, bool safe_to_lower);
void (*dchvm_init)(struct hubbub *hubbub);
/* Performance monitoring related functions */
struct hubbub_perfmon_funcs {
void (*reset)(struct hubbub *hubbub);
void (*start_measuring_max_memory_latency_ns)(
void (*start_measuring_memory_latencies)(
struct hubbub *hubbub);
uint32_t (*get_max_memory_latency_ns)(struct hubbub *hubbub,
uint32_t refclk_mhz, uint32_t *sample_count);
void (*start_measuring_average_memory_latency_ns)(
uint32_t (*get_memory_latencies_ns)(struct hubbub *hubbub,
uint32_t refclk_mhz, uint32_t *min_latency_ns,
uint32_t *max_latency_ns, uint32_t *avg_latency_ns);
void (*start_measuring_urgent_assertion_count)(
struct hubbub *hubbub);
uint32_t (*get_average_memory_latency_ns)(struct hubbub *hubbub,
uint32_t refclk_mhz, uint32_t *sample_count);
void (*start_measuring_urgent_ramp_latency_ns)(
bool (*get_urgent_assertion_count)(struct hubbub *hubbub,
uint32_t refclk_mhz,
uint32_t *assertion_count,
uint32_t *deassertion_count,
uint32_t *timestamp_us);
void (*start_measuring_urgent_ramp_latency)(
struct hubbub *hubbub,
const struct hubbub_urgent_latency_params *params);
uint32_t (*get_urgent_ramp_latency_ns)(struct hubbub *hubbub,
uint32_t refclk_mhz);
void (*start_measuring_unbounded_bandwidth_mbps)(
void (*start_measuring_unbounded_bandwidth)(
struct hubbub *hubbub);
uint32_t (*get_unbounded_bandwidth_mbps)(struct hubbub *hubbub,
uint32_t refclk_mhz, uint32_t *duration_ns);
void (*start_measuring_average_bandwidth_mbps)(
void (*start_measuring_in_order_bandwidth)(
struct hubbub *hubbub);
uint32_t (*get_average_bandwidth_mbps)(struct hubbub *hubbub,
uint32_t (*get_in_order_bandwidth_mbps)(struct hubbub *hubbub,
uint32_t refclk_mhz, uint32_t min_duration_ns,
uint32_t *duration_ns);
void (*start_measuring_prefetch_data_size)(
struct hubbub *hubbub);
uint32_t (*get_prefetch_data_size)(struct hubbub *hubbub);
} perfmon;
struct hubbub_qos_funcs {

View file

@ -156,13 +156,23 @@ bool dp_pr_get_panel_inst(const struct dc *dc,
const struct dc_link *link,
unsigned int *inst_out)
{
if (dc_is_embedded_signal(link->connector_signal)) {
/* TODO: just get edp link panel inst for now, fix it */
return dc_get_edp_link_panel_inst(dc, link, inst_out);
} else if (dc_is_dp_sst_signal(link->connector_signal)) {
/* TODO: just set to 1 for now, fix it */
*inst_out = 1;
return true;
if (!dc || !link || !inst_out)
return false;
if (!dc_is_dp_sst_signal(link->connector_signal)) /* only supoprt DP sst (eDP included) for now */
return false;
for (unsigned int i = 0; i < MAX_PIPES; i++) {
if (dc->current_state->res_ctx.pipe_ctx[i].stream &&
dc->current_state->res_ctx.pipe_ctx[i].stream->link == link) {
/* *inst_out is equal to otg number */
if (dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg)
*inst_out = dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg->inst;
else
*inst_out = 0;
return true;
}
}
return false;
@ -280,13 +290,13 @@ bool dp_pr_update_state(struct dc_link *link, struct dmub_cmd_pr_update_state_da
return false;
memset(&cmd, 0, sizeof(cmd));
memcpy(&cmd.pr_update_state.data, update_state_data, sizeof(struct dmub_cmd_pr_update_state_data));
cmd.pr_update_state.header.type = DMUB_CMD__PR;
cmd.pr_update_state.header.sub_type = DMUB_CMD__PR_UPDATE_STATE;
cmd.pr_update_state.header.payload_bytes = sizeof(struct dmub_cmd_pr_update_state_data);
cmd.pr_update_state.data.panel_inst = panel_inst;
memcpy(&cmd.pr_update_state.data, update_state_data, sizeof(struct dmub_cmd_pr_update_state_data));
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
@ -301,13 +311,13 @@ bool dp_pr_set_general_cmd(struct dc_link *link, struct dmub_cmd_pr_general_cmd_
return false;
memset(&cmd, 0, sizeof(cmd));
memcpy(&cmd.pr_general_cmd.data, general_cmd_data, sizeof(struct dmub_cmd_pr_general_cmd_data));
cmd.pr_general_cmd.header.type = DMUB_CMD__PR;
cmd.pr_general_cmd.header.sub_type = DMUB_CMD__PR_GENERAL_CMD;
cmd.pr_general_cmd.header.payload_bytes = sizeof(struct dmub_cmd_pr_general_cmd_data);
cmd.pr_general_cmd.data.panel_inst = panel_inst;
memcpy(&cmd.pr_general_cmd.data, general_cmd_data, sizeof(struct dmub_cmd_pr_general_cmd_data));
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}

View file

@ -39,6 +39,7 @@
#include "dce/dmub_replay.h"
#include "abm.h"
#include "resource.h"
#include "link_dp_panel_replay.h"
#define DC_LOGGER \
link->ctx->logger
#define DC_LOGGER_INIT(logger)
@ -942,7 +943,7 @@ bool edp_set_replay_allow_active(struct dc_link *link, const bool *allow_active,
if (replay == NULL && force_static)
return false;
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
return false;
/* Set power optimization flag */
@ -973,7 +974,7 @@ bool edp_get_replay_state(const struct dc_link *link, uint64_t *state)
unsigned int panel_inst;
enum replay_state pr_state = REPLAY_STATE_0;
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
return false;
if (replay != NULL && link->replay_settings.replay_feature_enabled)
@ -1020,7 +1021,7 @@ bool edp_setup_freesync_replay(struct dc_link *link, const struct dc_stream_stat
if (!replay)
return false;
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
return false;
replay_context.aux_inst = link->ddc->ddc_pin->hw_info.ddc_channel;
@ -1099,7 +1100,7 @@ bool edp_send_replay_cmd(struct dc_link *link,
DC_LOGGER_INIT(link->ctx->logger);
if (dc_get_edp_link_panel_inst(dc, link, &panel_inst))
if (dp_pr_get_panel_inst(dc, link, &panel_inst))
cmd_data->panel_inst = panel_inst;
else {
DC_LOG_DC("%s(): get edp panel inst fail ", __func__);
@ -1120,7 +1121,7 @@ bool edp_set_coasting_vtotal(struct dc_link *link, uint32_t coasting_vtotal, uin
if (!replay)
return false;
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
return false;
if (coasting_vtotal && (link->replay_settings.coasting_vtotal != coasting_vtotal ||
@ -1140,7 +1141,7 @@ bool edp_replay_residency(const struct dc_link *link,
struct dmub_replay *replay = dc->res_pool->replay;
unsigned int panel_inst;
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
return false;
if (!residency)
@ -1161,7 +1162,7 @@ bool edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link *link,
struct dmub_replay *replay = dc->res_pool->replay;
unsigned int panel_inst;
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
return false;
/* Only both power and coasting vtotal changed, this func could return true */

View file

@ -1635,9 +1635,9 @@ union dmub_inbox0_cmd_lock_hw {
uint32_t lock_dig: 1;
uint32_t triple_buffer_lock: 1;
uint32_t lock: 1; /**< Lock */
uint32_t lock: 1; /**< Lock */
uint32_t should_release: 1; /**< Release */
uint32_t reserved: 7; /**< Reserved for extending more clients, HW, etc. */
uint32_t reserved: 7; /**< Reserved for extending more clients, HW, etc. */
} bits;
uint32_t all;
};
@ -2658,7 +2658,6 @@ struct dmub_cmd_fams2_global_config {
union dmub_cmd_fams2_config {
struct dmub_cmd_fams2_global_config global;
// coverity[cert_dcl37_c_violation:FALSE] errno.h, stddef.h, stdint.h not included in atombios.h
struct dmub_fams2_stream_static_state stream; //v0
union {
struct dmub_fams2_cmd_stream_static_base_state base;
@ -3678,7 +3677,7 @@ struct dmub_cmd_psr_copy_settings_data {
/**
* @ rate_control_caps : Indicate FreeSync PSR Sink Capabilities
*/
uint8_t rate_control_caps ;
uint8_t rate_control_caps;
/*
* Force PSRSU always doing full frame update
*/
@ -5164,8 +5163,8 @@ enum dmub_cmd_lsdma_type {
*/
DMUB_CMD__LSDMA_LINEAR_COPY = 1,
/**
* LSDMA copies data from source to destination linearly in sub window
*/
* LSDMA copies data from source to destination linearly in sub window
*/
DMUB_CMD__LSDMA_LINEAR_SUB_WINDOW_COPY = 2,
/**
* Send the tiled-to-tiled copy command

View file

@ -984,10 +984,13 @@ void set_replay_frame_skip_number(struct dc_link *link,
uint32_t *frame_skip_number_array = NULL;
uint32_t frame_skip_number = 0;
if (link == NULL)
return;
if (false == link->replay_settings.config.frame_skip_supported)
return;
if (link == NULL || flicker_free_refresh_rate_mhz == 0 || coasting_vtotal_refresh_rate_mhz == 0)
if (flicker_free_refresh_rate_mhz == 0 || coasting_vtotal_refresh_rate_mhz == 0)
return;
if (is_defer)

View file

@ -1569,7 +1569,7 @@ int amdgpu_dpm_get_power_limit(struct amdgpu_device *adev,
int ret = 0;
if (!pp_funcs->get_power_limit)
return -ENODATA;
return -EOPNOTSUPP;
mutex_lock(&adev->pm.mutex);
ret = pp_funcs->get_power_limit(adev->powerplay.pp_handle,

View file

@ -3878,7 +3878,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
attr == &sensor_dev_attr_temp3_emergency.dev_attr.attr))
return 0;
/* only Vangogh has fast PPT limit and power labels */
/* only a few GPUs have fast PPT limit and power labels */
if ((attr == &sensor_dev_attr_power2_cap_max.dev_attr.attr ||
attr == &sensor_dev_attr_power2_cap_min.dev_attr.attr ||
attr == &sensor_dev_attr_power2_cap.dev_attr.attr ||

View file

@ -2273,8 +2273,6 @@ static int si_populate_smc_tdp_limits(struct amdgpu_device *adev,
if (scaling_factor == 0)
return -EINVAL;
memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE));
ret = si_calculate_adjusted_tdp_limits(adev,
false, /* ??? */
adev->pm.dpm.tdp_adjustment,
@ -2283,6 +2281,12 @@ static int si_populate_smc_tdp_limits(struct amdgpu_device *adev,
if (ret)
return ret;
if (adev->pdev->device == 0x6611 && adev->pdev->revision == 0x87) {
/* Workaround buggy powertune on Radeon 430 and 520. */
tdp_limit = 32;
near_tdp_limit = 28;
}
smc_table->dpm2Params.TDPLimit =
cpu_to_be32(si_scale_power_for_smc(tdp_limit, scaling_factor) * 1000);
smc_table->dpm2Params.NearTDPLimit =
@ -2328,16 +2332,8 @@ static int si_populate_smc_tdp_limits_2(struct amdgpu_device *adev,
if (ni_pi->enable_power_containment) {
SISLANDS_SMC_STATETABLE *smc_table = &si_pi->smc_statetable;
u32 scaling_factor = si_get_smc_power_scaling_factor(adev);
int ret;
memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE));
smc_table->dpm2Params.NearTDPLimit =
cpu_to_be32(si_scale_power_for_smc(adev->pm.dpm.near_tdp_limit_adjusted, scaling_factor) * 1000);
smc_table->dpm2Params.SafePowerLimit =
cpu_to_be32(si_scale_power_for_smc((adev->pm.dpm.near_tdp_limit_adjusted * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000);
ret = amdgpu_si_copy_bytes_to_smc(adev,
(si_pi->state_table_start +
offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) +
@ -3473,10 +3469,15 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,
(adev->pdev->revision == 0x80) ||
(adev->pdev->revision == 0x81) ||
(adev->pdev->revision == 0x83) ||
(adev->pdev->revision == 0x87) ||
(adev->pdev->revision == 0x87 &&
adev->pdev->device != 0x6611) ||
(adev->pdev->device == 0x6604) ||
(adev->pdev->device == 0x6605)) {
max_sclk = 75000;
} else if (adev->pdev->revision == 0x87 &&
adev->pdev->device == 0x6611) {
/* Radeon 430 and 520 */
max_sclk = 78000;
}
}
@ -7600,12 +7601,12 @@ static int si_dpm_set_interrupt_state(struct amdgpu_device *adev,
case AMDGPU_IRQ_STATE_DISABLE:
cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);
cg_thermal_int |= CG_THERMAL_INT__THERM_INT_MASK_HIGH_MASK;
WREG32_SMC(mmCG_THERMAL_INT, cg_thermal_int);
WREG32(mmCG_THERMAL_INT, cg_thermal_int);
break;
case AMDGPU_IRQ_STATE_ENABLE:
cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);
cg_thermal_int &= ~CG_THERMAL_INT__THERM_INT_MASK_HIGH_MASK;
WREG32_SMC(mmCG_THERMAL_INT, cg_thermal_int);
WREG32(mmCG_THERMAL_INT, cg_thermal_int);
break;
default:
break;
@ -7617,12 +7618,12 @@ static int si_dpm_set_interrupt_state(struct amdgpu_device *adev,
case AMDGPU_IRQ_STATE_DISABLE:
cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);
cg_thermal_int |= CG_THERMAL_INT__THERM_INT_MASK_LOW_MASK;
WREG32_SMC(mmCG_THERMAL_INT, cg_thermal_int);
WREG32(mmCG_THERMAL_INT, cg_thermal_int);
break;
case AMDGPU_IRQ_STATE_ENABLE:
cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);
cg_thermal_int &= ~CG_THERMAL_INT__THERM_INT_MASK_LOW_MASK;
WREG32_SMC(mmCG_THERMAL_INT, cg_thermal_int);
WREG32(mmCG_THERMAL_INT, cg_thermal_int);
break;
default:
break;

View file

@ -956,7 +956,7 @@ void smu_v13_0_12_get_gpu_metrics(struct smu_context *smu, void **table,
gpu_metrics->gfx_below_host_limit_total_acc
[i] = SMUQ10_ROUND(
metrics->GfxclkBelowHostLimitTotalAcc[inst]);
};
}
}
gpu_metrics->xgmi_link_width = metrics->XgmiWidth;

View file

@ -121,8 +121,9 @@ int radeon_vce_init(struct radeon_device *rdev)
if (sscanf(c, "%2u]", &rdev->vce.fb_version) != 1)
return -EINVAL;
DRM_INFO("Found VCE firmware/feedback version %d.%d.%d / %d!\n",
start, mid, end, rdev->vce.fb_version);
drm_info(&rdev->ddev,
"Found VCE firmware/feedback version %d.%d.%d / %d!\n",
start, mid, end, rdev->vce.fb_version);
rdev->vce.fw_version = (start << 24) | (mid << 16) | (end << 8);