mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
amd-drm-next-7.3-2026-08-19:
amdgpu: - eGPU fixes - Runtime PM fix - UserQ fixes - Backlight fix - Discovery sysfs fix - Reset handling fixes - Buffer func handling fix for xgmi - VCN boundary check fix - DC lut handling fixes amdkfd: - Fix return value radeon: - iMac display fix -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCaoX2XgAKCRC93/aFa7yZ 2McyAP45fRlBRPJeNkk5CDWFRFFJXGwmkiKcBAogxFYgzpJ7SAD7BTbXwPGugPPr scBCM6qcx8jBH4HSLZnV1gq5tGtcOAc= =ayyI -----END PGP SIGNATURE----- Merge tag 'amd-drm-next-7.3-2026-08-19' of https://gitlab.freedesktop.org/agd5f/linux into drm-next amd-drm-next-7.3-2026-08-19: amdgpu: - eGPU fixes - Runtime PM fix - UserQ fixes - Backlight fix - Discovery sysfs fix - Reset handling fixes - Buffer func handling fix for xgmi - VCN boundary check fix - DC lut handling fixes amdkfd: - Fix return value radeon: - iMac display fix Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patch.msgid.link/20260819183622.2406038-1-alexander.deucher@amd.com
This commit is contained in:
commit
22e48eeaf4
|
|
@ -609,6 +609,13 @@ void amdgpu_device_detect_runtime_pm_mode(struct amdgpu_device *adev)
|
|||
int bamaco_support;
|
||||
|
||||
adev->pm.rpm_mode = AMDGPU_RUNPM_NONE;
|
||||
if (pci_is_thunderbolt_attached(adev->pdev) ||
|
||||
dev_is_removable(&adev->pdev->dev)) {
|
||||
dev_info(adev->dev,
|
||||
"Runtime PM disabled for externally attached device\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bamaco_support = amdgpu_device_supports_baco(adev);
|
||||
|
||||
switch (amdgpu_runtime_pm) {
|
||||
|
|
@ -2523,7 +2530,11 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
|||
if (r)
|
||||
goto init_failed;
|
||||
|
||||
amdgpu_ttm_enable_buffer_funcs(adev);
|
||||
/* If SDMA is not brought up during hwini, the ttm buffer funcs enablement
|
||||
* is delayed after reset-on-init completes.
|
||||
*/
|
||||
if (amdgpu_ip_member_of_hwini(adev, AMD_IP_BLOCK_TYPE_SDMA))
|
||||
amdgpu_ttm_enable_buffer_funcs(adev);
|
||||
|
||||
/* Don't init kfd if whole hive need to be reset during init */
|
||||
if (adev->init_lvl->level != AMDGPU_INIT_LEVEL_MINIMAL_XGMI) {
|
||||
|
|
@ -3733,6 +3744,14 @@ static void amdgpu_device_sys_interface_fini(struct amdgpu_device *adev)
|
|||
amdgpu_ptl_sysfs_fini(adev);
|
||||
}
|
||||
|
||||
static bool
|
||||
amdgpu_device_should_register_switcheroo(struct amdgpu_device *adev, bool px)
|
||||
{
|
||||
return !pci_is_thunderbolt_attached(adev->pdev) &&
|
||||
(px || (!dev_is_removable(&adev->pdev->dev) &&
|
||||
apple_gmux_detect(NULL, NULL)));
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_init - initialize the driver
|
||||
*
|
||||
|
|
@ -4183,8 +4202,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||
|
||||
px = amdgpu_device_supports_px(adev);
|
||||
|
||||
if (px || (!dev_is_removable(&adev->pdev->dev) &&
|
||||
apple_gmux_detect(NULL, NULL)))
|
||||
if (amdgpu_device_should_register_switcheroo(adev, px))
|
||||
vga_switcheroo_register_client(adev->pdev,
|
||||
&amdgpu_switcheroo_ops, px);
|
||||
|
||||
|
|
@ -4349,8 +4367,7 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
|
|||
|
||||
px = amdgpu_device_supports_px(adev);
|
||||
|
||||
if (px || (!dev_is_removable(&adev->pdev->dev) &&
|
||||
apple_gmux_detect(NULL, NULL)))
|
||||
if (amdgpu_device_should_register_switcheroo(adev, px))
|
||||
vga_switcheroo_unregister_client(adev->pdev);
|
||||
|
||||
if (px)
|
||||
|
|
@ -5037,6 +5054,31 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
|
|||
amdgpu_fence_driver_force_completion(ring, fence);
|
||||
}
|
||||
|
||||
/*
|
||||
* MES scheduler rings have no drm scheduler, so they are missed by the
|
||||
* loop above. Realign their polling fence too (one per XCC), otherwise the
|
||||
* first post-reset submission polls forever on a stale seq. sched.ready is
|
||||
* only set while the driver owns the ring.
|
||||
*/
|
||||
for (i = 0; i < AMDGPU_MAX_MES_INST_PIPES; i++) {
|
||||
struct amdgpu_ring *mes_ring = &adev->mes.ring[i];
|
||||
|
||||
if (mes_ring->fence_drv.initialized && mes_ring->sched.ready)
|
||||
amdgpu_fence_driver_force_completion(mes_ring, fence);
|
||||
}
|
||||
|
||||
/*
|
||||
* KIQ rings are polling-fence/no_scheduler like MES, so realign their
|
||||
* fence too (one ring per XCC), otherwise the first post-reset KIQ
|
||||
* submission polls forever on a stale seq.
|
||||
*/
|
||||
for (i = 0; i < AMDGPU_MAX_GC_INSTANCES; i++) {
|
||||
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq[i].ring;
|
||||
|
||||
if (kiq_ring->fence_drv.initialized && kiq_ring->sched.ready)
|
||||
amdgpu_fence_driver_force_completion(kiq_ring, fence);
|
||||
}
|
||||
|
||||
amdgpu_fence_driver_isr_toggle(adev, false);
|
||||
|
||||
r = amdgpu_reset_prepare_hwcontext(adev, reset_context);
|
||||
|
|
@ -5137,8 +5179,6 @@ int amdgpu_device_reinit_after_reset(struct amdgpu_reset_context *reset_context)
|
|||
if (r)
|
||||
goto out;
|
||||
|
||||
amdgpu_ttm_enable_buffer_funcs(tmp_adev);
|
||||
|
||||
r = amdgpu_device_ip_resume_phase3(tmp_adev);
|
||||
if (r)
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -1307,8 +1307,19 @@ static int amdgpu_discovery_sysfs_ips(struct amdgpu_device *adev,
|
|||
ip_hw_instance->num_instance);
|
||||
ip_hw_instance->num_base_addresses = ip->num_base_address;
|
||||
|
||||
for (kk = 0; kk < ip_hw_instance->num_base_addresses; kk++)
|
||||
ip_hw_instance->base_addr[kk] = ip->base_address[kk];
|
||||
for (kk = 0; kk < ip_hw_instance->num_base_addresses; kk++) {
|
||||
/*
|
||||
* Standalone mode uses a raw copy of the discovery
|
||||
* binary; decode 64-bit addresses here. The shared
|
||||
* bin is already collapsed to 32-bit in place.
|
||||
*/
|
||||
if (reg_base_64 && ip_top->standalone_mode)
|
||||
ip_hw_instance->base_addr[kk] =
|
||||
lower_32_bits(le64_to_cpu(ip->base_address_64[kk])) & 0x3FFFFFFF;
|
||||
else
|
||||
ip_hw_instance->base_addr[kk] =
|
||||
le32_to_cpu(ip->base_address[kk]);
|
||||
}
|
||||
|
||||
kobject_init(&ip_hw_instance->kobj, &ip_hw_instance_ktype);
|
||||
ip_hw_instance->kobj.kset = &ip_hw_id->hw_id_kset;
|
||||
|
|
|
|||
|
|
@ -2557,6 +2557,7 @@ amdgpu_pci_remove(struct pci_dev *pdev)
|
|||
if (adev->pm.rpm_mode != AMDGPU_RUNPM_NONE) {
|
||||
pm_runtime_get_sync(dev->dev);
|
||||
pm_runtime_forbid(dev->dev);
|
||||
pm_runtime_dont_use_autosuspend(dev->dev);
|
||||
}
|
||||
|
||||
amdgpu_driver_unload_kms(dev);
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
|
|||
vm_af = job->hw_vm_fence;
|
||||
/* VM sequence */
|
||||
vm_af->ib_wptr = ring->wptr;
|
||||
amdgpu_vm_flush(ring, job, need_pipe_sync, &emit_spm_needed,
|
||||
amdgpu_vm_flush(ring, job, &need_pipe_sync, &emit_spm_needed,
|
||||
&emit_gds_needed);
|
||||
vm_af->ib_dw_size =
|
||||
amdgpu_ring_get_dw_distance(ring, vm_af->ib_wptr, ring->wptr);
|
||||
|
|
@ -235,6 +235,10 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
|
|||
if (ring->funcs->insert_start)
|
||||
ring->funcs->insert_start(ring);
|
||||
|
||||
/* this may have been handled by amdgpu_vm_flush */
|
||||
if (need_pipe_sync)
|
||||
amdgpu_ring_emit_pipeline_sync(ring);
|
||||
|
||||
if (emit_spm_needed)
|
||||
adev->gfx.rlc.funcs->update_spm_vmid(adev, ring->xcc_id, ring, job->vmid);
|
||||
|
||||
|
|
|
|||
|
|
@ -287,22 +287,24 @@ static bool amdgpu_userq_buffer_va_mapped(struct amdgpu_vm *vm, u64 addr)
|
|||
|
||||
static bool amdgpu_userq_buffer_vas_mapped(struct amdgpu_usermode_queue *queue)
|
||||
{
|
||||
int i, r = 0;
|
||||
int i;
|
||||
bool mapped;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(queue->userq_vas.va_array); i++) {
|
||||
if (!queue->userq_vas.va_array[i])
|
||||
continue;
|
||||
r += amdgpu_userq_buffer_va_mapped(queue->vm,
|
||||
|
||||
mapped = amdgpu_userq_buffer_va_mapped(queue->vm,
|
||||
queue->userq_vas.va_array[i]);
|
||||
dev_dbg(queue->userq_mgr->adev->dev,
|
||||
"validate the userq mapping:%p va:%llx r:%d\n",
|
||||
queue, queue->userq_vas.va_array[i], r);
|
||||
queue, queue->userq_vas.va_array[i], mapped);
|
||||
|
||||
if (!mapped)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (r != 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -416,19 +418,12 @@ static void amdgpu_userq_wait_for_last_fence(struct amdgpu_usermode_queue *queue
|
|||
dma_fence_wait(f, false);
|
||||
}
|
||||
|
||||
static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue)
|
||||
static void amdgpu_userq_detach_doorbell(struct amdgpu_usermode_queue *queue)
|
||||
{
|
||||
struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr;
|
||||
struct amdgpu_device *adev = uq_mgr->adev;
|
||||
struct amdgpu_device *adev = queue->userq_mgr->adev;
|
||||
|
||||
/* Wait for mode-1 reset to complete */
|
||||
down_read(&adev->reset_domain->sem);
|
||||
|
||||
/* Use interrupt-safe locking since IRQ handlers may access these XArrays */
|
||||
xa_erase_irq(&adev->userq_doorbell_xa, queue->doorbell_index);
|
||||
amdgpu_userq_fence_driver_free(queue);
|
||||
queue->fence_drv = NULL;
|
||||
|
||||
up_read(&adev->reset_domain->sem);
|
||||
}
|
||||
|
||||
|
|
@ -549,18 +544,19 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que
|
|||
|
||||
cancel_delayed_work_sync(&uq_mgr->resume_work);
|
||||
|
||||
/* Cancel any pending hang detection work and cleanup */
|
||||
cancel_delayed_work_sync(&queue->hang_detect_work);
|
||||
|
||||
mutex_lock(&uq_mgr->userq_mutex);
|
||||
amdgpu_userq_wait_for_last_fence(queue);
|
||||
|
||||
amdgpu_userq_detach_doorbell(queue);
|
||||
cancel_delayed_work_sync(&queue->hang_detect_work);
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
debugfs_remove_recursive(queue->debugfs_queue);
|
||||
#endif
|
||||
r = amdgpu_userq_unmap_helper(queue);
|
||||
atomic_dec(&uq_mgr->userq_count[queue->queue_type]);
|
||||
amdgpu_userq_cleanup(queue);
|
||||
amdgpu_userq_fence_driver_free(queue);
|
||||
queue->fence_drv = NULL;
|
||||
mutex_unlock(&uq_mgr->userq_mutex);
|
||||
|
||||
/*
|
||||
|
|
@ -572,7 +568,6 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que
|
|||
if (r)
|
||||
queue_work(adev->reset_domain->wq, &uq_mgr->reset_work);
|
||||
|
||||
cancel_delayed_work_sync(&queue->hang_detect_work);
|
||||
uq_funcs->mqd_destroy(queue);
|
||||
queue->userq_mgr = NULL;
|
||||
|
||||
|
|
@ -700,10 +695,10 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
|||
args->in.queue_size,
|
||||
&queue->userq_vas.va.queue_rb) ||
|
||||
amdgpu_userq_input_va_validate(adev, queue, args->in.rptr_va,
|
||||
AMDGPU_GPU_PAGE_SIZE,
|
||||
sizeof(u64),
|
||||
&queue->userq_vas.va.rptr) ||
|
||||
amdgpu_userq_input_va_validate(adev, queue, args->in.wptr_va,
|
||||
AMDGPU_GPU_PAGE_SIZE,
|
||||
sizeof(u64),
|
||||
&queue->userq_vas.va.wptr)) {
|
||||
r = -EINVAL;
|
||||
amdgpu_bo_unreserve(fpriv->vm.root.bo);
|
||||
|
|
@ -746,7 +741,7 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
|||
((queue->queue_type != AMDGPU_HW_IP_GFX) &&
|
||||
(queue->queue_type != AMDGPU_HW_IP_COMPUTE))) {
|
||||
/* Serialize the map against an in-progress GPU reset (MES is
|
||||
* unresponsive during recovery), matching amdgpu_userq_cleanup().
|
||||
* unresponsive during recovery), matching amdgpu_userq_detach_doorbell().
|
||||
*/
|
||||
down_read(&adev->reset_domain->sem);
|
||||
r = amdgpu_userq_map_helper(queue);
|
||||
|
|
@ -848,6 +843,12 @@ static int amdgpu_userq_input_args_validate(struct drm_device *dev,
|
|||
drm_file_err(filp, "invalidate userq queue rptr or wptr\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!IS_ALIGNED(args->in.wptr_va, sizeof(u64)) ||
|
||||
!IS_ALIGNED(args->in.rptr_va, sizeof(u64))) {
|
||||
drm_file_err(filp, "user queue rptr or wptr is not 8-byte aligned\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case AMDGPU_USERQ_OP_FREE:
|
||||
if (args->in.ip_type ||
|
||||
|
|
|
|||
|
|
@ -537,7 +537,7 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
|
|||
* amdgpu_userq_ensure_ev_fence() can't be called while holding the resv
|
||||
* locks.
|
||||
*/
|
||||
drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT,
|
||||
drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT | DRM_EXEC_IGNORE_DUPLICATES,
|
||||
(num_read_bo_handles + num_write_bo_handles));
|
||||
|
||||
drm_exec_until_all_locked(&exec) {
|
||||
|
|
@ -643,7 +643,7 @@ amdgpu_userq_wait_count_fences(struct drm_file *filp,
|
|||
/* TODO: It is actually not necessary to lock them */
|
||||
num_read_bo_handles = wait_info->num_bo_read_handles;
|
||||
num_write_bo_handles = wait_info->num_bo_write_handles;
|
||||
drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT,
|
||||
drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT | DRM_EXEC_IGNORE_DUPLICATES,
|
||||
num_read_bo_handles + num_write_bo_handles);
|
||||
|
||||
drm_exec_until_all_locked(&exec) {
|
||||
|
|
@ -778,7 +778,7 @@ amdgpu_userq_wait_return_fence_info(struct drm_device *dev, struct drm_file *fil
|
|||
/* Lock all the GEM objects */
|
||||
num_read_bo_handles = wait_info->num_bo_read_handles;
|
||||
num_write_bo_handles = wait_info->num_bo_write_handles;
|
||||
drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT,
|
||||
drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT | DRM_EXEC_IGNORE_DUPLICATES,
|
||||
num_read_bo_handles + num_write_bo_handles);
|
||||
|
||||
drm_exec_until_all_locked(&exec) {
|
||||
|
|
|
|||
|
|
@ -772,7 +772,7 @@ bool amdgpu_vm_need_pipeline_sync(struct amdgpu_ring *ring,
|
|||
* Emit a VM flush when it is necessary.
|
||||
*/
|
||||
void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
|
||||
bool need_pipe_sync, bool *emit_spm_needed,
|
||||
bool *need_pipe_sync, bool *emit_spm_needed,
|
||||
bool *emit_gds_needed)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
|
@ -827,8 +827,7 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
|
|||
if (gds_switch_needed && emit_fence)
|
||||
*emit_gds_needed = false;
|
||||
|
||||
if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync &&
|
||||
!cleaner_shader_needed && !spm_update_needed)
|
||||
if (!emit_fence)
|
||||
return;
|
||||
|
||||
amdgpu_ring_ib_begin(ring);
|
||||
|
|
@ -847,8 +846,10 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
|
|||
patch = amdgpu_ring_init_cond_exec(ring,
|
||||
ring->cond_exe_gpu_addr);
|
||||
|
||||
if (need_pipe_sync)
|
||||
if (*need_pipe_sync) {
|
||||
amdgpu_ring_emit_pipeline_sync(ring);
|
||||
*need_pipe_sync = false;
|
||||
}
|
||||
|
||||
if (cleaner_shader_needed)
|
||||
ring->funcs->emit_cleaner_shader(ring);
|
||||
|
|
@ -861,21 +862,19 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
|
|||
if (pasid_mapping_needed)
|
||||
amdgpu_gmc_emit_pasid_mapping(ring, job->vmid, job->pasid);
|
||||
|
||||
if (emit_fence) {
|
||||
if (spm_update_needed)
|
||||
adev->gfx.rlc.funcs->update_spm_vmid(adev, ring->xcc_id, ring, job->vmid);
|
||||
if (spm_update_needed)
|
||||
adev->gfx.rlc.funcs->update_spm_vmid(adev, ring->xcc_id, ring, job->vmid);
|
||||
|
||||
if (gds_switch_needed)
|
||||
amdgpu_ring_emit_gds_switch(ring, job->vmid, job->gds_base,
|
||||
if (gds_switch_needed)
|
||||
amdgpu_ring_emit_gds_switch(ring, job->vmid, job->gds_base,
|
||||
job->gds_size, job->gws_base,
|
||||
job->gws_size, job->oa_base,
|
||||
job->oa_size);
|
||||
|
||||
amdgpu_fence_emit(ring, job->hw_vm_fence, 0);
|
||||
fence = &job->hw_vm_fence->base;
|
||||
/* get a ref for the job */
|
||||
dma_fence_get(fence);
|
||||
}
|
||||
amdgpu_fence_emit(ring, job->hw_vm_fence, 0);
|
||||
fence = &job->hw_vm_fence->base;
|
||||
/* get a ref for the job */
|
||||
dma_fence_get(fence);
|
||||
|
||||
if (vm_flush_needed) {
|
||||
mutex_lock(&id_mgr->lock);
|
||||
|
|
|
|||
|
|
@ -512,7 +512,7 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
int (*callback)(void *p, struct amdgpu_bo *bo),
|
||||
void *param);
|
||||
void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
|
||||
bool need_pipe_sync, bool *emit_spm_needed,
|
||||
bool *need_pipe_sync, bool *emit_spm_needed,
|
||||
bool *emit_gds_needed);
|
||||
int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm, bool immediate);
|
||||
|
|
|
|||
|
|
@ -1380,6 +1380,9 @@ static void amdgpu_xgmi_reset_on_init_work(struct work_struct *work)
|
|||
amdgpu_device_unlock_reset_domain(tmp_adev->reset_domain);
|
||||
|
||||
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) {
|
||||
/* Enable ttm buffers funcs after the reset lock has been dropped. */
|
||||
amdgpu_ttm_enable_buffer_funcs(tmp_adev);
|
||||
|
||||
r = amdgpu_ras_init_badpage_info(tmp_adev);
|
||||
if (r && r != -EHWPOISON)
|
||||
dev_err(tmp_adev->dev,
|
||||
|
|
|
|||
|
|
@ -1964,9 +1964,13 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
|
|||
len_dw = msg[1] / 4;
|
||||
num_buffers = msg[2];
|
||||
|
||||
/* Verify that all indices fit within the claimed length. Each index is 4 DWORDs */
|
||||
if (num_buffers > len_dw || 6 + num_buffers * 4 > len_dw) {
|
||||
DRM_ERROR("VCN message has too many buffers!\n");
|
||||
/* Verify that all indices fit within the claimed length.
|
||||
* There are 6 dwords in the header before the first buffer.
|
||||
* Each buffer has 4 dwords. Any trailing dwords after the
|
||||
* last buffer are ignored.
|
||||
*/
|
||||
if (len_dw < 6 || num_buffers > (len_dw - 6) / 4) {
|
||||
DRM_ERROR("Invalid VCN message!\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1880,9 +1880,13 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
|
|||
len_dw = msg[1] / 4;
|
||||
num_buffers = msg[2];
|
||||
|
||||
/* Verify that all indices fit within the claimed length. Each index is 4 DWORDs */
|
||||
if (num_buffers > len_dw || 6 + num_buffers * 4 > len_dw) {
|
||||
DRM_ERROR("VCN message has too many buffers!\n");
|
||||
/* Verify that all indices fit within the claimed length.
|
||||
* There are 6 dwords in the header before the first buffer.
|
||||
* Each buffer has 4 dwords. Any trailing dwords after the
|
||||
* last buffer are ignored.
|
||||
*/
|
||||
if (len_dw < 6 || num_buffers > (len_dw - 6) / 4) {
|
||||
DRM_ERROR("Invalid VCN message!\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3329,7 +3329,7 @@ static int kfd_ioctl_create_process(struct file *filep, struct kfd_process *p, v
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t profile_lock_device(struct kfd_process *p,
|
||||
static inline int profile_lock_device(struct kfd_process *p,
|
||||
uint32_t gpu_id, uint32_t op)
|
||||
{
|
||||
struct kfd_process_device *pdd;
|
||||
|
|
|
|||
|
|
@ -106,10 +106,10 @@ int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
|
|||
}
|
||||
EXPORT_IF_KUNIT(get_brightness_range);
|
||||
|
||||
/* Rescale from [min..max] to [0..AMDGPU_MAX_BL_LEVEL] */
|
||||
static inline u32 scale_input_to_fw(int min, int max, u64 input)
|
||||
/* Rescale userspace [0..max] to the firmware curve's [0..255]. */
|
||||
static inline u32 scale_input_to_fw(int max, u64 input)
|
||||
{
|
||||
return DIV_ROUND_CLOSEST_ULL(input * AMDGPU_MAX_BL_LEVEL, max - min);
|
||||
return DIV_ROUND_CLOSEST_ULL(input * AMDGPU_MAX_BL_LEVEL, max);
|
||||
}
|
||||
|
||||
/* Rescale from [0..AMDGPU_MAX_BL_LEVEL] to [min..max] */
|
||||
|
|
@ -123,7 +123,7 @@ void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *caps,
|
|||
unsigned int min, unsigned int max,
|
||||
uint32_t *user_brightness)
|
||||
{
|
||||
u32 brightness = scale_input_to_fw(min, max, *user_brightness);
|
||||
u32 brightness = scale_input_to_fw(max, *user_brightness);
|
||||
u8 lower_signal, upper_signal, upper_lum, lower_lum, lum;
|
||||
int left, right;
|
||||
|
||||
|
|
|
|||
|
|
@ -471,6 +471,12 @@ bool __is_lut_linear(const struct drm_color_lut *lut, uint32_t size)
|
|||
uint32_t expected;
|
||||
int delta;
|
||||
|
||||
/* A LUT with fewer than two entries can't be interpolated and would
|
||||
* divide by zero below (size - 1); it can't be treated as linear.
|
||||
*/
|
||||
if (size < 2)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
/* All color values should equal */
|
||||
if ((lut[i].red != lut[i].green) || (lut[i].green != lut[i].blue))
|
||||
|
|
@ -1489,6 +1495,13 @@ __set_dm_plane_degamma(struct drm_plane_state *plane_state,
|
|||
degamma_lut = __extract_blob_lut(dm_plane_state->degamma_lut,
|
||||
°amma_size);
|
||||
|
||||
if (degamma_lut && degamma_size != MAX_COLOR_LUT_ENTRIES) {
|
||||
drm_dbg(plane_state->state->dev,
|
||||
"Invalid Plane Degamma LUT size. Should be %u but got %u.\n",
|
||||
MAX_COLOR_LUT_ENTRIES, degamma_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
has_degamma_lut = degamma_lut &&
|
||||
!__is_lut_linear(degamma_lut, degamma_size);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
* Alex Deucher
|
||||
*/
|
||||
|
||||
#include <linux/dmi.h>
|
||||
|
||||
#include <drm/drm_fixed.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
|
|
@ -594,7 +596,8 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
|
|||
if (((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880))
|
||||
&& !radeon_crtc->ss_enabled)
|
||||
radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
|
||||
if (ASIC_IS_DCE32(rdev) && mode->clock > 165000)
|
||||
if ((ASIC_IS_DCE32(rdev) || dmi_match(DMI_PRODUCT_NAME, "iMac11,1"))
|
||||
&& mode->clock > 165000)
|
||||
radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
|
||||
} else {
|
||||
radeon_crtc->pll_flags |= RADEON_PLL_LEGACY;
|
||||
|
|
|
|||
|
|
@ -1707,7 +1707,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
|
|||
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
|
||||
/* DP_SET_POWER_D0 is set in radeon_dp_link_train */
|
||||
radeon_dp_link_train(encoder, connector);
|
||||
if (ASIC_IS_DCE4(rdev))
|
||||
if (ASIC_IS_DCE4(rdev) || dmi_match(DMI_PRODUCT_NAME, "iMac11,1"))
|
||||
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
|
||||
}
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
|
||||
|
|
@ -2123,17 +2123,20 @@ int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx)
|
|||
}
|
||||
|
||||
/*
|
||||
* On DCE32 any encoder can drive any block so usually just use crtc id,
|
||||
* but Apple thinks different at least on iMac10,1 and iMac11,2, so there use linkb,
|
||||
* otherwise the internal eDP panel will stay dark.
|
||||
* Apple routes the internal eDP panel through Link B of the DIG encoder
|
||||
* instead of Link A on the iMac10,1, iMac11,1 and iMac11,2.
|
||||
* Use linkb to avoid a dark display.
|
||||
*/
|
||||
if (ASIC_IS_DCE32(rdev)) {
|
||||
if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1") ||
|
||||
dmi_match(DMI_PRODUCT_NAME, "iMac11,2"))
|
||||
enc_idx = (dig->linkb) ? 1 : 0;
|
||||
else
|
||||
enc_idx = radeon_crtc->crtc_id;
|
||||
if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1") ||
|
||||
dmi_match(DMI_PRODUCT_NAME, "iMac11,1") ||
|
||||
dmi_match(DMI_PRODUCT_NAME, "iMac11,2")) {
|
||||
enc_idx = (dig->linkb) ? 1 : 0;
|
||||
goto assigned;
|
||||
}
|
||||
|
||||
/* on DCE32 and encoder can driver any block so just crtc id */
|
||||
if (ASIC_IS_DCE32(rdev)) {
|
||||
enc_idx = radeon_crtc->crtc_id;
|
||||
goto assigned;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user