summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c54
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c49
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c27
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_chardev.c2
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c8
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c13
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c5
-rw-r--r--drivers/gpu/drm/radeon/atombios_encoders.c23
16 files changed, 160 insertions, 74 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 53539ceeda16..019581577603 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -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 @@ fence_driver_init:
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;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
index a404d8aa13ee..164e85b66e2d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -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;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 0ab380ca7e64..5c33c19fd9bc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -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);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index da4dc489e80b..360e6f00cb7c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -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);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
index bcfbd7213dd6..24adad7be251 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -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 (r != 0)
- return true;
+ if (!mapped)
+ return false;
+ }
- 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 ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
index 7e80442ec3e5..a33dbe978798 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
@@ -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) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index d2ad5b0e8759..a3758c654dd4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -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);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index 7f2ba728e3ed..d32183cd9e0f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -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);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
index 2725230aa5e3..45e31b3daf06 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
@@ -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,
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index 81bba3ec2a93..00d8f35846f2 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -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;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index 0cce78b205a8..c2ddf3cb368f 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -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;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index 309510e23315..6fd18488d5cf 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -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;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
index b66ca60e697d..e61bbc310f33 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
@@ -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;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 7b68c6846039..d55dc06167a8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -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,
&degamma_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);
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 2fc0334e0d6c..075eba2d47f3 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -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;
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index 5cfd8fcfa5e8..8b3f8303a967 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -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;
}