diff options
61 files changed, 475 insertions, 325 deletions
diff --git a/drivers/accel/ethosu/ethosu_gem.c b/drivers/accel/ethosu/ethosu_gem.c index 7994e7073903..3401883e207f 100644 --- a/drivers/accel/ethosu/ethosu_gem.c +++ b/drivers/accel/ethosu/ethosu_gem.c @@ -2,6 +2,7 @@ /* Copyright 2025 Arm, Ltd. */ #include <linux/err.h> +#include <linux/overflow.h> #include <linux/slab.h> #include <drm/ethosu_accel.h> @@ -163,17 +164,30 @@ static u64 dma_length(struct ethosu_validated_cmdstream_info *info, s8 mode = dma_st->mode; u64 len = dma->len; + if (len == U64_MAX) + return U64_MAX; + if (mode >= 1) { + if (dma->stride[0] < 0 && (u64)(-dma->stride[0]) > len) + return U64_MAX; len += dma->stride[0]; - len *= dma_st->size0; + if (check_mul_overflow(len, (u64)dma_st->size0, &len)) + return U64_MAX; } if (mode == 2) { + if (dma->stride[1] < 0 && (u64)(-dma->stride[1]) > len) + return U64_MAX; len += dma->stride[1]; - len *= dma_st->size1; + if (check_mul_overflow(len, (u64)dma_st->size1, &len)) + return U64_MAX; + } + if (dma->region >= 0) { + u64 end; + + if (check_add_overflow(len, dma->offset, &end)) + return U64_MAX; + info->region_size[dma->region] = max(info->region_size[dma->region], end); } - if (dma->region >= 0) - info->region_size[dma->region] = max(info->region_size[dma->region], - len + dma->offset); return len; } @@ -387,6 +401,8 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev, return -EFAULT; i++; + if (i >= size / 4) + return -EINVAL; bocmds[i] = cmds[1]; addr = cmd_to_addr(cmds); } @@ -395,6 +411,8 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev, case NPU_OP_DMA_START: srclen = dma_length(info, &st.dma, &st.dma.src); dstlen = dma_length(info, &st.dma, &st.dma.dst); + if (srclen == U64_MAX || dstlen == U64_MAX) + return -EINVAL; if (st.dma.dst.region >= 0) info->output_region[st.dma.dst.region] = true; @@ -431,8 +449,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev, return ret; break; case NPU_OP_RESIZE: // U85 only - WARN_ON(1); // TODO - break; + return -EINVAL; case NPU_SET_KERNEL_WIDTH_M1: st.ifm.width = param; break; @@ -464,7 +481,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev, st.ifm.broadcast = param; break; case NPU_SET_IFM_REGION: - st.ifm.region = param & 0x7f; + st.ifm.region = param & 0x7; break; case NPU_SET_IFM_WIDTH0_M1: st.ifm.width0 = param; @@ -599,7 +616,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev, if (ethosu_is_u65(edev)) st.scale[1].length = cmds[1]; else - st.weight[1].length = cmds[1]; + st.weight[2].length = cmds[1]; break; case NPU_SET_WEIGHT3_BASE: st.weight[3].base = addr; diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c index 107f8ad31050..33c50779c06b 100644 --- a/drivers/accel/ivpu/ivpu_fw.c +++ b/drivers/accel/ivpu/ivpu_fw.c @@ -259,6 +259,22 @@ static int ivpu_fw_parse(struct ivpu_device *vdev) return -EINVAL; } + if (!PAGE_ALIGNED(runtime_addr)) { + ivpu_err(vdev, "Runtime address 0x%llx not page aligned\n", runtime_addr); + return -EINVAL; + } + + if (!PAGE_ALIGNED(runtime_size)) { + ivpu_err(vdev, "Runtime size %llu not page aligned\n", runtime_size); + return -EINVAL; + } + + if (runtime_size < image_size) { + ivpu_err(vdev, "Runtime size too small: %llu, image size: %llu\n", + runtime_size, image_size); + return -EINVAL; + } + if (!ivpu_is_within_range(image_load_addr, image_size, &vdev->hw->ranges.runtime)) { ivpu_err(vdev, "Invalid firmware load address: 0x%llx and size %llu\n", image_load_addr, image_size); diff --git a/drivers/accel/ivpu/ivpu_fw_log.c b/drivers/accel/ivpu/ivpu_fw_log.c index 337c906b0210..275baf844b56 100644 --- a/drivers/accel/ivpu/ivpu_fw_log.c +++ b/drivers/accel/ivpu/ivpu_fw_log.c @@ -98,6 +98,11 @@ static void fw_log_print_buffer(struct vpu_tracing_buffer_header *log, const cha u32 log_start = only_new_msgs ? READ_ONCE(log->read_index) : 0; u32 log_end = READ_ONCE(log->write_index); + if (log_start >= data_size) + log_start = 0; + if (log_end > data_size) + log_end = data_size; + if (log->wrap_count == log->read_wrap_count) { if (log_end <= log_start) { drm_printf(p, "==== %s \"%s\" log empty ====\n", prefix, log->name); diff --git a/drivers/accel/ivpu/ivpu_ms.c b/drivers/accel/ivpu/ivpu_ms.c index be43851f5f32..cd176e77b9a0 100644 --- a/drivers/accel/ivpu/ivpu_ms.c +++ b/drivers/accel/ivpu/ivpu_ms.c @@ -291,6 +291,13 @@ int ivpu_ms_get_info_ioctl(struct drm_device *dev, void *data, struct drm_file * if (ret) goto unlock; + if (info_size > ivpu_bo_size(bo)) { + ivpu_warn_ratelimited(vdev, "MS info overflow: %#llx > %#zx\n", + info_size, ivpu_bo_size(bo)); + ret = -EOVERFLOW; + goto unlock; + } + if (args->buffer_size < info_size) { ret = -ENOSPC; goto unlock; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c index b6f849d51c2e..c4c21dbbbdbf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c @@ -394,7 +394,8 @@ void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa, uint64_t start_page, uint64_t num_pages, uint64_t flags, void *dst) { - u32 i, idx; + u32 i, j, t, idx; + u64 page_base; /* The SYSTEM flag indicates the pages aren't in VRAM. */ WARN_ON_ONCE(flags & AMDGPU_PTE_SYSTEM); @@ -402,9 +403,12 @@ void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa, if (!drm_dev_enter(adev_to_drm(adev), &idx)) return; - for (i = 0; i < num_pages; ++i) { - amdgpu_gmc_set_pte_pde(adev, dst, - start_page + i, pa + AMDGPU_GPU_PAGE_SIZE * i, flags); + page_base = pa; + for (i = 0, t = 0; i < num_pages; i++) { + for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) { + amdgpu_gmc_set_pte_pde(adev, dst, start_page + t, page_base, flags); + page_base += AMDGPU_GPU_PAGE_SIZE; + } } drm_dev_exit(idx); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 3d9497d121ca..c076c5f06e77 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -170,7 +170,7 @@ int amdgpu_gmc_set_pte_pde(struct amdgpu_device *adev, void *cpu_pt_addr, /* * The following is for PTE only. GART does not have PDEs. */ - value = addr & 0x0000FFFFFFFFF000ULL; + value = addr & adev->gmc.pte_addr_mask; value |= flags; writeq(value, ptr + (gpu_page_idx * 8)); @@ -1003,7 +1003,7 @@ void amdgpu_gmc_noretry_set(struct amdgpu_device *adev) gc_ver == IP_VERSION(9, 4, 3) || gc_ver == IP_VERSION(9, 4, 4) || gc_ver == IP_VERSION(9, 5, 0) || - gc_ver >= IP_VERSION(10, 3, 0)); + gc_ver >= IP_VERSION(10, 1, 0)); if (!amdgpu_sriov_xnack_support(adev)) gmc->noretry = 1; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index 6ab4c1e297fc..d03536b969b5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -280,6 +280,7 @@ struct amdgpu_gmc { u64 real_vram_size; int vram_mtrr; u64 mc_mask; + uint64_t pte_addr_mask; const struct firmware *fw; /* MC firmware */ uint32_t fw_version; struct amdgpu_irq_src vm_fault; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index a5d26b943f6d..d23a91d029aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -203,7 +203,7 @@ int amdgpu_gtt_mgr_alloc_entries(struct amdgpu_gtt_mgr *mgr, int r; /* Align to TLB L2 cache entry size to work around "V bit HW bug" */ - if (adev->asic_type == CHIP_TAHITI) { + if (adev->family == AMDGPU_FAMILY_SI) { alignment = 32 * 1024 / AMDGPU_GPU_PAGE_SIZE; num_pages = ALIGN(num_pages, alignment); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c index 5bfa5a84b09c..e452444b33b0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c @@ -67,6 +67,7 @@ static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni, { struct amdgpu_bo *bo = container_of(mni, struct amdgpu_bo, notifier); struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); + struct amdgpu_bo *vm_root = bo->vm_bo->vm->root.bo; long r; if (!mmu_notifier_range_blockable(range)) @@ -77,8 +78,9 @@ static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni, mmu_interval_set_seq(mni, cur_seq); amdgpu_vm_bo_invalidate(bo, false); - r = dma_resv_wait_timeout(bo->tbo.base.resv, DMA_RESV_USAGE_BOOKKEEP, - false, MAX_SCHEDULE_TIMEOUT); + r = dma_resv_wait_timeout(vm_root->tbo.base.resv, + DMA_RESV_USAGE_BOOKKEEP, false, + MAX_SCHEDULE_TIMEOUT); mutex_unlock(&adev->notifier_lock); if (r <= 0) DRM_ERROR("(%ld) failed to wait for user bo\n", r); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c index f4be19223588..21a225b0116a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c @@ -173,16 +173,17 @@ error: int amdgpu_seq64_alloc(struct amdgpu_device *adev, u64 *va, u64 *gpu_addr, u64 **cpu_addr) { - unsigned long bit_pos; + unsigned long bit_pos = 0; - for (;;) { - bit_pos = find_first_zero_bit(adev->seq64.used, adev->seq64.num_sem); + do { + bit_pos = find_next_zero_bit(adev->seq64.used, + adev->seq64.num_sem, bit_pos); if (bit_pos >= adev->seq64.num_sem) return -ENOSPC; - if (!test_and_set_bit(bit_pos, adev->seq64.used)) break; - } + bit_pos++; + } while (1); *va = bit_pos * sizeof(u64) + amdgpu_seq64_get_va_base(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c index cf192500800f..59ffaa7b61c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c @@ -532,10 +532,6 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que amdgpu_bo_unreserve(queue->db_obj.obj); amdgpu_bo_unref(&queue->db_obj.obj); - amdgpu_bo_reserve(queue->wptr_obj.obj, true); - amdgpu_bo_unpin(queue->wptr_obj.obj); - amdgpu_bo_unreserve(queue->wptr_obj.obj); - amdgpu_bo_unref(&queue->wptr_obj.obj); kfree(queue); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); @@ -887,7 +883,7 @@ amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr) continue; } - r = amdgpu_userq_restore_helper(queue); + r = amdgpu_userq_map_helper(queue); if (r) ret = r; @@ -1124,7 +1120,7 @@ amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr) /* Try to unmap all the queues in this process ctx */ xa_for_each(&uq_mgr->userq_xa, queue_id, queue) { - r = amdgpu_userq_preempt_helper(queue); + r = amdgpu_userq_unmap_helper(queue); if (r) ret = r; } @@ -1344,8 +1340,7 @@ int amdgpu_userq_start_sched_for_enforce_isolation(struct amdgpu_device *adev, } void amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev, - struct amdgpu_bo_va_mapping *mapping, - uint64_t saddr) + struct amdgpu_bo_va_mapping *mapping) { u32 ip_mask = amdgpu_userq_get_supported_ip_mask(adev); struct amdgpu_bo_va *bo_va = mapping->bo_va; @@ -1354,12 +1349,9 @@ void amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev, if (!ip_mask) return; - dev_warn_once(adev->dev, "now unmapping a vital queue va:%llx\n", saddr); /** - * The userq VA mapping reservation should include the eviction fence, - * if the eviction fence can't signal successfully during unmapping, - * then driver will warn to flag this improper unmap of the userq VA. - * Note: The eviction fence may be attached to different BOs, and this + * The userq VA mapping reservation should include the eviction fence. + * Note: The eviction fence may be attached to different BOs and this * unmap is only for one kind of userq VAs, so at this point suppose * the eviction fence is always unsignaled. */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h index 28cfc6682333..d1751febaefe 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h @@ -182,6 +182,5 @@ int amdgpu_userq_input_va_validate(struct amdgpu_device *adev, u64 addr, u64 expected_size, u64 *va_out); void amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev, - struct amdgpu_bo_va_mapping *mapping, - uint64_t saddr); + struct amdgpu_bo_va_mapping *mapping); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index c9f88ecce1a7..381901bc539f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2006,7 +2006,7 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev, * from user space. */ if (unlikely(bo_va->userq_va_mapped)) - amdgpu_userq_gem_va_unmap_validate(adev, mapping, saddr); + amdgpu_userq_gem_va_unmap_validate(adev, mapping); list_del(&mapping->list); amdgpu_vm_it_remove(mapping, &vm->va); diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v11_5_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v11_5_0.c index f9949fedfbb9..f2fe6f5bc7f7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v11_5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v11_5_0.c @@ -449,12 +449,10 @@ static void gfxhub_v11_5_0_set_fault_enable_default(struct amdgpu_device *adev, WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value); tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value); - if (!value) { - tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, - CRASH_ON_NO_RETRY_FAULT, 1); - tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, - CRASH_ON_RETRY_FAULT, 1); - } + tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_NO_RETRY_FAULT, !value); + tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_RETRY_FAULT, !value); WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp); } diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v12_0.c index 7609b9cecae8..efcaca70c27a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v12_0.c @@ -454,12 +454,10 @@ static void gfxhub_v12_0_set_fault_enable_default(struct amdgpu_device *adev, WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value); tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value); - if (!value) { - tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, - CRASH_ON_NO_RETRY_FAULT, 1); - tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, - CRASH_ON_RETRY_FAULT, 1); - } + tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_NO_RETRY_FAULT, !value); + tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_RETRY_FAULT, !value); WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp); } diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v12_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v12_1.c index 3544eb42dca6..4c2fd1e6616e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v12_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v12_1.c @@ -633,19 +633,17 @@ static void gfxhub_v12_1_xcc_set_fault_enable_default(struct amdgpu_device *adev tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL_LO32, OTHER_CLIENT_ID_NO_RETRY_FAULT_INTERRUPT, value); - if (!value) - tmp = REG_SET_FIELD(tmp, - GCVM_L2_PROTECTION_FAULT_CNTL_LO32, - CRASH_ON_NO_RETRY_FAULT, 1); + tmp = REG_SET_FIELD(tmp, + GCVM_L2_PROTECTION_FAULT_CNTL_LO32, + CRASH_ON_NO_RETRY_FAULT, !value); WREG32_SOC15(GC, GET_INST(GC, i), regGCVM_L2_PROTECTION_FAULT_CNTL_LO32, tmp); tmp = RREG32_SOC15(GC, GET_INST(GC, i), regGCVM_L2_PROTECTION_FAULT_CNTL_HI32); - if (!value) - tmp = REG_SET_FIELD(tmp, - GCVM_L2_PROTECTION_FAULT_CNTL_HI32, - CRASH_ON_RETRY_FAULT, 1); + tmp = REG_SET_FIELD(tmp, + GCVM_L2_PROTECTION_FAULT_CNTL_HI32, + CRASH_ON_RETRY_FAULT, !value); WREG32_SOC15(GC, GET_INST(GC, i), regGCVM_L2_PROTECTION_FAULT_CNTL_HI32, tmp); } diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c index a7bfc9f41d0e..bfe247b1a333 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c @@ -403,12 +403,10 @@ static void gfxhub_v1_0_set_fault_enable_default(struct amdgpu_device *adev, WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value); tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL, EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value); - if (!value) { - tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL, - CRASH_ON_NO_RETRY_FAULT, 1); - tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL, - CRASH_ON_RETRY_FAULT, 1); - } + tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_NO_RETRY_FAULT, !value); + tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_RETRY_FAULT, !value); WREG32_SOC15(GC, 0, mmVM_L2_PROTECTION_FAULT_CNTL, tmp); } diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c index 6c03bf9f1ae8..fbdf46070b38 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c @@ -516,12 +516,10 @@ static void gfxhub_v1_2_xcc_set_fault_enable_default(struct amdgpu_device *adev, WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value); tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL, EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value); - if (!value) { - tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL, - CRASH_ON_NO_RETRY_FAULT, 1); - tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL, - CRASH_ON_RETRY_FAULT, 1); - } + tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_NO_RETRY_FAULT, !value); + tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_RETRY_FAULT, !value); WREG32_SOC15(GC, GET_INST(GC, i), regVM_L2_PROTECTION_FAULT_CNTL, tmp); } } diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c index 793faf62cb07..9ea593e2c719 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c @@ -418,12 +418,10 @@ static void gfxhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value); tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value); - if (!value) { - tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, - CRASH_ON_NO_RETRY_FAULT, 1); - tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, - CRASH_ON_RETRY_FAULT, 1); - } + tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_NO_RETRY_FAULT, !value); + tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_RETRY_FAULT, !value); WREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL, tmp); } diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c index aceb8447feac..30b90d35abd0 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c @@ -449,12 +449,10 @@ static void gfxhub_v2_1_set_fault_enable_default(struct amdgpu_device *adev, WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value); tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value); - if (!value) { - tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, - CRASH_ON_NO_RETRY_FAULT, 1); - tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, - CRASH_ON_RETRY_FAULT, 1); - } + tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_NO_RETRY_FAULT, !value); + tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_RETRY_FAULT, !value); WREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL, tmp); } diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c index abe30c8bd2ba..f089f70571aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c @@ -446,12 +446,10 @@ static void gfxhub_v3_0_set_fault_enable_default(struct amdgpu_device *adev, WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value); tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value); - if (!value) { - tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, - CRASH_ON_NO_RETRY_FAULT, 1); - tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, - CRASH_ON_RETRY_FAULT, 1); - } + tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_NO_RETRY_FAULT, !value); + tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_RETRY_FAULT, !value); WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp); } diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c index b3ef6e71811f..128115a2cb45 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c @@ -434,12 +434,10 @@ static void gfxhub_v3_0_3_set_fault_enable_default(struct amdgpu_device *adev, WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value); tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value); - if (!value) { - tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, - CRASH_ON_NO_RETRY_FAULT, 1); - tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, - CRASH_ON_RETRY_FAULT, 1); - } + tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_NO_RETRY_FAULT, !value); + tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_RETRY_FAULT, !value); WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index e1ace7d44ffd..f5bdfea54afa 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -847,6 +847,7 @@ static int gmc_v10_0_sw_init(struct amdgpu_ip_block *ip_block) * internal address space. */ adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */ + adev->gmc.pte_addr_mask = 0x0000FFFFFFFFF000ULL; /* 48 bit PA */ r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44)); if (r) { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c index 94d6631ce0bc..807bd180b9d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c @@ -821,6 +821,7 @@ static int gmc_v11_0_sw_init(struct amdgpu_ip_block *ip_block) * internal address space. */ adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */ + adev->gmc.pte_addr_mask = 0x0000FFFFFFFFF000ULL; /* 48 bit PA */ r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44)); if (r) { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c index e10ac9788d13..8dc9c053897b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c @@ -812,8 +812,9 @@ static int gmc_v12_0_gart_init(struct amdgpu_device *adev) static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block) { - int r, vram_width = 0, vram_type = 0, vram_vendor = 0; + int r, vram_width = 0, vram_type = 0, vram_vendor = 0, dma_addr_bits; struct amdgpu_device *adev = ip_block->adev; + uint64_t pte_addr_mask = 0; int i; adev->mmhub.funcs->init(adev); @@ -843,6 +844,8 @@ static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block) * block size 512 (9bit) */ amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48); + pte_addr_mask = 0x0000FFFFFFFFF000ULL; /* 48 bit PA */ + dma_addr_bits = 44; break; case IP_VERSION(12, 1, 0): bitmap_set(adev->vmhubs_mask, AMDGPU_GFXHUB(0), @@ -855,9 +858,13 @@ static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block) * block size 512 (9bit) */ amdgpu_vm_adjust_size(adev, 128 * 1024 * 1024, 9, 4, 57); + pte_addr_mask = 0x000FFFFFFFFFF000ULL; /* 52 bit PA */ + dma_addr_bits = 52; break; default: - break; + dev_warn(adev->dev, "Unrecognized GC IP version: 0x%08x\n", + amdgpu_ip_version(adev, GC_HWIP, 0)); + return -EINVAL; } /* This interrupt is VMC page fault.*/ @@ -911,14 +918,15 @@ static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block) * internal address space. */ adev->gmc.mc_mask = AMDGPU_GMC_HOLE_MASK; + adev->gmc.pte_addr_mask = pte_addr_mask; - r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44)); + r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(dma_addr_bits)); if (r) { drm_warn(adev_to_drm(adev), "No suitable DMA available.\n"); return r; } - adev->need_swiotlb = drm_need_swiotlb(44); + adev->need_swiotlb = drm_need_swiotlb(dma_addr_bits); r = gmc_v12_0_mc_init(adev); if (r) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index cc272a96fcef..6aa581b1c148 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -836,6 +836,7 @@ static int gmc_v6_0_sw_init(struct amdgpu_ip_block *ip_block) amdgpu_vm_adjust_size(adev, 64, 9, 1, 40); adev->gmc.mc_mask = 0xffffffffffULL; + adev->gmc.pte_addr_mask = 0x000000FFFFFFF000ULL; r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(40)); if (r) { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index bb16ba2ef6fd..2b0362c4d9eb 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -1016,6 +1016,7 @@ static int gmc_v7_0_sw_init(struct amdgpu_ip_block *ip_block) * internal address space. */ adev->gmc.mc_mask = 0xffffffffffULL; /* 40 bit MC */ + adev->gmc.pte_addr_mask = 0x000000FFFFFFF000ULL; /* 40 bit PA */ r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(40)); if (r) { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index a59174f6bcc1..fbccfcb3d7cf 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -1131,6 +1131,7 @@ static int gmc_v8_0_sw_init(struct amdgpu_ip_block *ip_block) * internal address space. */ adev->gmc.mc_mask = 0xffffffffffULL; /* 40 bit MC */ + adev->gmc.pte_addr_mask = 0x000000FFFFFFF000ULL; /* 40 bit PA */ r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(40)); if (r) { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index e7b78027002b..c6dbe25f2bd9 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1994,6 +1994,7 @@ static int gmc_v9_0_sw_init(struct amdgpu_ip_block *ip_block) * internal address space. */ adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */ + adev->gmc.pte_addr_mask = 0x0000FFFFFFFFF000ULL; /* 48 bit PA */ dma_addr_bits = amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(9, 4, 2) ? diff --git a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c index 98aa00eeb2f4..4cbd46f53e85 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c @@ -467,6 +467,11 @@ static void mes_userq_mqd_destroy(struct amdgpu_usermode_queue *queue) kfree(queue->userq_prop); amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr, &queue->mqd.cpu_ptr); + + amdgpu_bo_reserve(queue->wptr_obj.obj, true); + amdgpu_bo_unpin(queue->wptr_obj.obj); + amdgpu_bo_unreserve(queue->wptr_obj.obj); + amdgpu_bo_unref(&queue->wptr_obj.obj); } static int mes_userq_preempt(struct amdgpu_usermode_queue *queue) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c b/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c index 061934a2e93a..9c9bbe043a47 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c @@ -1316,6 +1316,7 @@ static int sdma_v7_1_sw_init(struct amdgpu_ip_block *ip_block) ring->ring_obj = NULL; ring->use_doorbell = true; ring->me = i; + ring->no_user_submission = adev->sdma.no_user_submission; for (xcc_id = 0; xcc_id < fls(adev->gfx.xcc_mask); xcc_id++) { if (adev->sdma.instance[i].xcc_id == GET_INST(GC, xcc_id)) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 0d7296c739ed..31187ddbb79e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -2502,6 +2502,9 @@ static int wait_on_destroy_queue(struct device_queue_manager *dqm, if (pdd->qpd.is_debug) return ret; + if (q->properties.is_being_destroyed) + return -EBUSY; + q->properties.is_being_destroyed = true; if (pdd->process->debug_trap_enabled && q->properties.is_suspended) { @@ -2514,6 +2517,9 @@ static int wait_on_destroy_queue(struct device_queue_manager *dqm, dqm_lock(dqm); } + if (ret) + q->properties.is_being_destroyed = false; + return ret; } @@ -2607,7 +2613,7 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm, return retval; failed_try_destroy_debugged_queue: - + q->properties.is_being_destroyed = false; dqm_unlock(dqm); return retval; } @@ -3309,7 +3315,7 @@ static void copy_context_work_handler(struct work_struct *work) static uint32_t *get_queue_ids(uint32_t num_queues, uint32_t *usr_queue_id_array) { if (!usr_queue_id_array) - return NULL; + return num_queues ? ERR_PTR(-EINVAL) : NULL; if (num_queues > KFD_MAX_NUM_OF_QUEUES_PER_PROCESS) return ERR_PTR(-EINVAL); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c index a1e3cf2384dd..527c531676e4 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c @@ -320,8 +320,7 @@ static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, voi static void restore_mqd(struct mqd_manager *mm, void **mqd, struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, - struct queue_properties *qp, - const void *mqd_src, + struct queue_properties *qp, const void *mqd_src, const void *ctl_stack_src, const u32 ctl_stack_size) { uint64_t addr; @@ -337,14 +336,48 @@ static void restore_mqd(struct mqd_manager *mm, void **mqd, *gart_addr = addr; m->cp_hqd_pq_doorbell_control = - qp->doorbell_off << - CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT; - pr_debug("cp_hqd_pq_doorbell_control 0x%x\n", - m->cp_hqd_pq_doorbell_control); + qp->doorbell_off << CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT; + pr_debug("cp_hqd_pq_doorbell_control 0x%x\n", m->cp_hqd_pq_doorbell_control); qp->is_active = 0; } +static void checkpoint_mqd_sdma(struct mqd_manager *mm, + void *mqd, + void *mqd_dst, + void *ctl_stack_dst) +{ + struct v11_sdma_mqd *m; + + m = get_sdma_mqd(mqd); + + memcpy(mqd_dst, m, sizeof(struct v11_sdma_mqd)); +} + +static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd, + struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, + struct queue_properties *qp, + const void *mqd_src, + const void *ctl_stack_src, + const u32 ctl_stack_size) +{ + uint64_t addr; + struct v11_sdma_mqd *m; + + m = (struct v11_sdma_mqd *) mqd_mem_obj->cpu_ptr; + addr = mqd_mem_obj->gpu_addr; + + memcpy(m, mqd_src, sizeof(*m)); + + m->sdmax_rlcx_doorbell_offset = + qp->doorbell_off << SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT; + + *mqd = m; + if (gart_addr) + *gart_addr = addr; + + qp->is_active = 0; +} static void init_mqd_hiq(struct mqd_manager *mm, void **mqd, struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, @@ -529,8 +562,8 @@ struct mqd_manager *mqd_manager_init_v11(enum KFD_MQD_TYPE type, mqd->update_mqd = update_mqd_sdma; mqd->destroy_mqd = kfd_destroy_mqd_sdma; mqd->is_occupied = kfd_is_occupied_sdma; - mqd->checkpoint_mqd = checkpoint_mqd; - mqd->restore_mqd = restore_mqd; + mqd->checkpoint_mqd = checkpoint_mqd_sdma; + mqd->restore_mqd = restore_mqd_sdma; mqd->mqd_size = sizeof(struct v11_sdma_mqd); mqd->mqd_stride = kfd_mqd_stride; #if defined(CONFIG_DEBUG_FS) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 2409ac72b166..3a3d01ce0d42 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1344,8 +1344,13 @@ static ssize_t dp_sdp_message_debugfs_write(struct file *f, const char __user *b if (size == 0) return 0; + if (!connector->base.state || !connector->base.state->crtc) + return -ENODEV; + acrtc_state = to_dm_crtc_state(connector->base.state->crtc->state); + write_size = min_t(size_t, size, sizeof(data)); + r = copy_from_user(data, buf, write_size); write_size -= r; diff --git a/drivers/gpu/drm/amd/display/dc/basics/vector.c b/drivers/gpu/drm/amd/display/dc/basics/vector.c index e8736c134b8d..60bd9ead928a 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/vector.c +++ b/drivers/gpu/drm/amd/display/dc/basics/vector.c @@ -289,8 +289,8 @@ bool dal_vector_reserve(struct vector *vector, uint32_t capacity) if (capacity <= vector->capacity) return true; - new_container = krealloc(vector->container, - capacity * vector->struct_size, GFP_KERNEL); + new_container = krealloc_array(vector->container, + capacity, vector->struct_size, GFP_KERNEL); if (new_container) { vector->container = new_container; diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index c307f42fe0b9..507b628abdb5 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -222,6 +222,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb, ATOM_COMMON_RECORD_HEADER *header; ATOM_I2C_RECORD *record; struct bios_parser *bp = BP_FROM_DCB(dcb); + int i; if (!info) return BP_RESULT_BADINPUT; @@ -234,7 +235,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb, offset = le16_to_cpu(object->usRecordOffset) + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); if (!header) @@ -293,11 +294,12 @@ static enum bp_result bios_parser_get_device_tag_record( { ATOM_COMMON_RECORD_HEADER *header; uint32_t offset; + int i; offset = le16_to_cpu(object->usRecordOffset) + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); if (!header) @@ -966,6 +968,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, { ATOM_COMMON_RECORD_HEADER *header; uint32_t offset; + int i; if (!object) { BREAK_TO_DEBUGGER(); /* Invalid object */ @@ -975,7 +978,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, offset = le16_to_cpu(object->usRecordOffset) + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); if (!header) @@ -1670,6 +1673,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record( { ATOM_COMMON_RECORD_HEADER *header; uint32_t offset; + int i; if (!object) { BREAK_TO_DEBUGGER(); /* Invalid object */ @@ -1679,7 +1683,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record( offset = le16_to_cpu(object->usRecordOffset) + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); if (!header) @@ -2769,6 +2773,7 @@ static enum bp_result update_slot_layout_info(struct dc_bios *dcb, { (void)i; unsigned int j; + unsigned int n; struct bios_parser *bp; ATOM_BRACKET_LAYOUT_RECORD *record; ATOM_COMMON_RECORD_HEADER *record_header; @@ -2778,7 +2783,7 @@ static enum bp_result update_slot_layout_info(struct dc_bios *dcb, record = NULL; record_header = NULL; - for (;;) { + for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) { record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset); if (record_header == NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index c51c4b2c6fae..0e1f973326ed 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -396,6 +396,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb, struct atom_i2c_record *record; struct atom_i2c_record dummy_record = {0}; struct bios_parser *bp = BP_FROM_DCB(dcb); + int i; if (!info) return BP_RESULT_BADINPUT; @@ -429,7 +430,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb, break; } - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(struct atom_common_record_header, offset); if (!header) @@ -534,6 +535,7 @@ static struct atom_hpd_int_record *get_hpd_record_for_path_v3(struct bios_parser { struct atom_common_record_header *header; uint32_t offset; + int i; if (!object) { BREAK_TO_DEBUGGER(); /* Invalid object */ @@ -542,7 +544,7 @@ static struct atom_hpd_int_record *get_hpd_record_for_path_v3(struct bios_parser offset = object->disp_recordoffset + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(struct atom_common_record_header, offset); if (!header) @@ -611,6 +613,7 @@ static struct atom_hpd_int_record *get_hpd_record( { struct atom_common_record_header *header; uint32_t offset; + int i; if (!object) { BREAK_TO_DEBUGGER(); /* Invalid object */ @@ -620,7 +623,7 @@ static struct atom_hpd_int_record *get_hpd_record( offset = le16_to_cpu(object->disp_recordoffset) + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(struct atom_common_record_header, offset); if (!header) @@ -701,8 +704,10 @@ static enum bp_result bios_parser_get_gpio_pin_info( info->offset_en = info->offset + 1; info->offset_mask = info->offset - 1; - info->mask = (uint32_t) (1 << - header->gpio_pin[i].gpio_bitshift); + if (header->gpio_pin[i].gpio_bitshift >= 32) + return BP_RESULT_BADBIOSTABLE; + + info->mask = 1u << header->gpio_pin[i].gpio_bitshift; info->mask_y = info->mask + 2; info->mask_en = info->mask + 1; info->mask_mask = info->mask - 1; @@ -2193,6 +2198,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record( { struct atom_common_record_header *header; uint32_t offset; + int i; if (!object) { BREAK_TO_DEBUGGER(); /* Invalid object */ @@ -2201,7 +2207,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record( offset = object->encoder_recordoffset + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(struct atom_common_record_header, offset); if (!header) @@ -2230,6 +2236,7 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record( { struct atom_common_record_header *header; uint32_t offset; + int i; if (!object) { BREAK_TO_DEBUGGER(); /* Invalid object */ @@ -2238,7 +2245,7 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record( offset = object->disp_recordoffset + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(struct atom_common_record_header, offset); if (!header) @@ -2266,6 +2273,7 @@ static struct atom_connector_caps_record *get_connector_caps_record(struct bios_ { struct atom_common_record_header *header; uint32_t offset; + int i; if (!object) { BREAK_TO_DEBUGGER(); /* Invalid object */ @@ -2274,7 +2282,7 @@ static struct atom_connector_caps_record *get_connector_caps_record(struct bios_ offset = object->disp_recordoffset + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(struct atom_common_record_header, offset); if (!header) @@ -2352,6 +2360,7 @@ static struct atom_connector_speed_record *get_connector_speed_cap_record(struct { struct atom_common_record_header *header; uint32_t offset; + int i; if (!object) { BREAK_TO_DEBUGGER(); /* Invalid object */ @@ -2360,7 +2369,7 @@ static struct atom_connector_speed_record *get_connector_speed_cap_record(struct offset = object->disp_recordoffset + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(struct atom_common_record_header, offset); if (!header) @@ -2600,14 +2609,16 @@ static enum bp_result get_integrated_info_v11( info_v11->extdispconninfo.checksum; info->dp0_ext_hdmi_slv_addr = info_v11->dp0_retimer_set.HdmiSlvAddr; - info->dp0_ext_hdmi_reg_num = info_v11->dp0_retimer_set.HdmiRegNum; + info->dp0_ext_hdmi_reg_num = min_t(u8, info_v11->dp0_retimer_set.HdmiRegNum, + ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings)); for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) { info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index = info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val = info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal; } - info->dp0_ext_hdmi_6g_reg_num = info_v11->dp0_retimer_set.Hdmi6GRegNum; + info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp0_retimer_set.Hdmi6GRegNum, + ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings)); for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) { info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index = info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; @@ -2616,14 +2627,16 @@ static enum bp_result get_integrated_info_v11( } info->dp1_ext_hdmi_slv_addr = info_v11->dp1_retimer_set.HdmiSlvAddr; - info->dp1_ext_hdmi_reg_num = info_v11->dp1_retimer_set.HdmiRegNum; + info->dp1_ext_hdmi_reg_num = min_t(u8, info_v11->dp1_retimer_set.HdmiRegNum, + ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings)); for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) { info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index = info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val = info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal; } - info->dp1_ext_hdmi_6g_reg_num = info_v11->dp1_retimer_set.Hdmi6GRegNum; + info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp1_retimer_set.Hdmi6GRegNum, + ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings)); for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) { info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index = info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; @@ -2632,14 +2645,16 @@ static enum bp_result get_integrated_info_v11( } info->dp2_ext_hdmi_slv_addr = info_v11->dp2_retimer_set.HdmiSlvAddr; - info->dp2_ext_hdmi_reg_num = info_v11->dp2_retimer_set.HdmiRegNum; + info->dp2_ext_hdmi_reg_num = min_t(u8, info_v11->dp2_retimer_set.HdmiRegNum, + ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings)); for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) { info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index = info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val = info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal; } - info->dp2_ext_hdmi_6g_reg_num = info_v11->dp2_retimer_set.Hdmi6GRegNum; + info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp2_retimer_set.Hdmi6GRegNum, + ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings)); for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) { info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index = info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; @@ -2648,14 +2663,16 @@ static enum bp_result get_integrated_info_v11( } info->dp3_ext_hdmi_slv_addr = info_v11->dp3_retimer_set.HdmiSlvAddr; - info->dp3_ext_hdmi_reg_num = info_v11->dp3_retimer_set.HdmiRegNum; + info->dp3_ext_hdmi_reg_num = min_t(u8, info_v11->dp3_retimer_set.HdmiRegNum, + ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings)); for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) { info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index = info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val = info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal; } - info->dp3_ext_hdmi_6g_reg_num = info_v11->dp3_retimer_set.Hdmi6GRegNum; + info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp3_retimer_set.Hdmi6GRegNum, + ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings)); for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) { info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index = info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; @@ -2805,14 +2822,16 @@ static enum bp_result get_integrated_info_v2_1( info->ext_disp_conn_info.checksum = info_v2_1->extdispconninfo.checksum; info->dp0_ext_hdmi_slv_addr = info_v2_1->dp0_retimer_set.HdmiSlvAddr; - info->dp0_ext_hdmi_reg_num = info_v2_1->dp0_retimer_set.HdmiRegNum; + info->dp0_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.HdmiRegNum, + ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings)); for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) { info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index = info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val = info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal; } - info->dp0_ext_hdmi_6g_reg_num = info_v2_1->dp0_retimer_set.Hdmi6GRegNum; + info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.Hdmi6GRegNum, + ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings)); for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) { info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index = info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; @@ -2820,14 +2839,16 @@ static enum bp_result get_integrated_info_v2_1( info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal; } info->dp1_ext_hdmi_slv_addr = info_v2_1->dp1_retimer_set.HdmiSlvAddr; - info->dp1_ext_hdmi_reg_num = info_v2_1->dp1_retimer_set.HdmiRegNum; + info->dp1_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.HdmiRegNum, + ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings)); for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) { info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index = info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val = info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal; } - info->dp1_ext_hdmi_6g_reg_num = info_v2_1->dp1_retimer_set.Hdmi6GRegNum; + info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.Hdmi6GRegNum, + ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings)); for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) { info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index = info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; @@ -2835,14 +2856,16 @@ static enum bp_result get_integrated_info_v2_1( info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal; } info->dp2_ext_hdmi_slv_addr = info_v2_1->dp2_retimer_set.HdmiSlvAddr; - info->dp2_ext_hdmi_reg_num = info_v2_1->dp2_retimer_set.HdmiRegNum; + info->dp2_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.HdmiRegNum, + ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings)); for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) { info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index = info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val = info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal; } - info->dp2_ext_hdmi_6g_reg_num = info_v2_1->dp2_retimer_set.Hdmi6GRegNum; + info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.Hdmi6GRegNum, + ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings)); for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) { info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index = info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; @@ -2850,14 +2873,16 @@ static enum bp_result get_integrated_info_v2_1( info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal; } info->dp3_ext_hdmi_slv_addr = info_v2_1->dp3_retimer_set.HdmiSlvAddr; - info->dp3_ext_hdmi_reg_num = info_v2_1->dp3_retimer_set.HdmiRegNum; + info->dp3_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.HdmiRegNum, + ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings)); for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) { info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index = info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val = info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal; } - info->dp3_ext_hdmi_6g_reg_num = info_v2_1->dp3_retimer_set.Hdmi6GRegNum; + info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.Hdmi6GRegNum, + ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings)); for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) { info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index = info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; @@ -3245,6 +3270,7 @@ static enum bp_result update_slot_layout_info( { unsigned int record_offset; unsigned int j; + unsigned int n; struct atom_display_object_path_v2 *object; struct atom_bracket_layout_record *record; struct atom_common_record_header *record_header; @@ -3266,7 +3292,7 @@ static enum bp_result update_slot_layout_info( (object->disp_recordoffset) + (unsigned int)(bp->object_info_tbl_offset); - for (;;) { + for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) { record_header = (struct atom_common_record_header *) GET_IMAGE(struct atom_common_record_header, @@ -3360,6 +3386,7 @@ static enum bp_result update_slot_layout_info_v2( struct slot_layout_info *slot_layout_info) { unsigned int record_offset; + unsigned int n; struct atom_display_object_path_v3 *object; struct atom_bracket_layout_record_v2 *record; struct atom_common_record_header *record_header; @@ -3382,7 +3409,7 @@ static enum bp_result update_slot_layout_info_v2( (object->disp_recordoffset) + (unsigned int)(bp->object_info_tbl_offset); - for (;;) { + for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) { record_header = (struct atom_common_record_header *) GET_IMAGE(struct atom_common_record_header, diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h index ab162f2fe577..19fd7aea18f1 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h @@ -37,4 +37,9 @@ void bios_set_scratch_critical_state(struct dc_bios *bios, bool state); #define GET_IMAGE(type, offset) ((type *) bios_get_image(&bp->base, offset, sizeof(type))) +/* Upper bound on the number of records in a VBIOS record chain. Prevents + * unbounded looping if the VBIOS image is malformed and lacks a terminator. + */ +#define BIOS_MAX_NUM_RECORD 256 + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 7fa336bf1115..7dd73eaaf940 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -1217,7 +1217,7 @@ struct dc_lttpr_caps { union dp_main_link_channel_coding_lttpr_cap main_link_channel_coding; union dp_128b_132b_supported_lttpr_link_rates supported_128b_132b_rates; union dp_alpm_lttpr_cap alpm; - uint8_t aux_rd_interval[MAX_REPEATER_CNT - 1]; + uint8_t aux_rd_interval[MAX_REPEATER_CNT]; uint8_t lttpr_ieee_oui[3]; // Always read from closest LTTPR to host uint8_t lttpr_device_id[6]; // Always read from closest LTTPR to host }; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index c1448ae47366..0d312b40bcfa 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -110,7 +110,15 @@ static const struct out_csc_color_matrix global_color_matrix[] = { { COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, { COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, - 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } + 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, +{ COLOR_SPACE_2020_RGB_FULLRANGE, + { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, +{ COLOR_SPACE_2020_RGB_LIMITEDRANGE, + { 0x1B67, 0, 0, 0x201, 0, 0x1B67, 0, 0x201, 0, 0, 0x1B67, 0x201} }, +{ COLOR_SPACE_2020_YCBCR_LIMITED, { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868, + 0x15B2, 0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} }, +{ COLOR_SPACE_2020_YCBCR_FULL, { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868, 0x15B2, + 0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} } }; static bool setup_scaling_configuration( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c index cf63fac82832..1ed018aaa4bb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c @@ -88,7 +88,15 @@ static const struct out_csc_color_matrix global_color_matrix[] = { { COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, { COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, - 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } + 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, +{ COLOR_SPACE_2020_RGB_FULLRANGE, + { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, +{ COLOR_SPACE_2020_RGB_LIMITEDRANGE, + { 0x1B67, 0, 0, 0x201, 0, 0x1B67, 0, 0x201, 0, 0, 0x1B67, 0x201} }, +{ COLOR_SPACE_2020_YCBCR_LIMITED, { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868, + 0x15B2, 0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} }, +{ COLOR_SPACE_2020_YCBCR_FULL, { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868, 0x15B2, + 0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} } }; enum csc_color_mode { diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c index 0ca39873f807..324413a090bf 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c @@ -529,7 +529,8 @@ enum mod_hdcp_status mod_hdcp_read_rx_id_list(struct mod_hdcp *hdcp) } else { status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST, hdcp->auth.msg.hdcp2.rx_id_list, - hdcp->auth.msg.hdcp2.rx_id_list_size); + MIN(hdcp->auth.msg.hdcp2.rx_id_list_size, + sizeof(hdcp->auth.msg.hdcp2.rx_id_list))); } return status; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index 0a7f5fa3c1d3..7f8d4bb47d02 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -2390,28 +2390,30 @@ static int smu_v13_0_0_enable_mgpu_fan_boost(struct smu_context *smu) } static int smu_v13_0_0_get_power_limit(struct smu_context *smu, - uint32_t *current_power_limit, - uint32_t *default_power_limit, - uint32_t *max_power_limit, - uint32_t *min_power_limit) + uint32_t *current_power_limit, + uint32_t *default_power_limit, + uint32_t *max_power_limit, + uint32_t *min_power_limit) { struct smu_table_context *table_context = &smu->smu_table; struct smu_13_0_0_powerplay_table *powerplay_table = (struct smu_13_0_0_powerplay_table *)table_context->power_play_table; PPTable_t *pptable = table_context->driver_pptable; SkuTable_t *skutable = &pptable->SkuTable; - uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0; - uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC]; - - if (smu_v13_0_get_current_power_limit(smu, &power_limit)) - power_limit = smu->adev->pm.ac_power ? + uint32_t pp_limit = smu->adev->pm.ac_power ? skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] : skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0]; + uint32_t power_limit = 0, od_percent_upper = 0, od_percent_lower = 0; + int ret; + + if (current_power_limit) { + ret = smu_v13_0_get_current_power_limit(smu, &power_limit); + if (ret) + *current_power_limit = pp_limit; + } - if (current_power_limit) - *current_power_limit = power_limit; if (default_power_limit) - *default_power_limit = power_limit; + *default_power_limit = pp_limit; if (powerplay_table) { if (smu->od_enabled && @@ -2425,15 +2427,15 @@ static int smu_v13_0_0_get_power_limit(struct smu_context *smu, } dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n", - od_percent_upper, od_percent_lower, power_limit); + od_percent_upper, od_percent_lower, pp_limit); if (max_power_limit) { - *max_power_limit = msg_limit * (100 + od_percent_upper); + *max_power_limit = pp_limit * (100 + od_percent_upper); *max_power_limit /= 100; } if (min_power_limit) { - *min_power_limit = power_limit * (100 - od_percent_lower); + *min_power_limit = pp_limit * (100 - od_percent_lower); *min_power_limit /= 100; } @@ -2801,11 +2803,19 @@ static void smu_v13_0_0_i2c_control_fini(struct smu_context *smu) static int smu_v13_0_0_set_mp1_state(struct smu_context *smu, enum pp_mp1_state mp1_state) { + uint32_t param; int ret; switch (mp1_state) { case PP_MP1_STATE_UNLOAD: - ret = smu_cmn_set_mp1_state(smu, mp1_state); + /* + * NOTE: Param 0x55 comes from PMFW 80.31.0, ignored in older versions. + * No PMFW version check required. + */ + param = amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 10) ? + 0x55 : 0x00; + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PrepareMp1ForUnload, + param, NULL); break; default: /* Ignore others */ diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c index 5abf2b0703c6..0f774b0920ce 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c @@ -2372,28 +2372,32 @@ static int smu_v13_0_7_enable_mgpu_fan_boost(struct smu_context *smu) } static int smu_v13_0_7_get_power_limit(struct smu_context *smu, - uint32_t *current_power_limit, - uint32_t *default_power_limit, - uint32_t *max_power_limit, - uint32_t *min_power_limit) + uint32_t *current_power_limit, + uint32_t *default_power_limit, + uint32_t *max_power_limit, + uint32_t *min_power_limit) { struct smu_table_context *table_context = &smu->smu_table; struct smu_13_0_7_powerplay_table *powerplay_table = (struct smu_13_0_7_powerplay_table *)table_context->power_play_table; PPTable_t *pptable = table_context->driver_pptable; SkuTable_t *skutable = &pptable->SkuTable; - uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0; - uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC]; - - if (smu_v13_0_get_current_power_limit(smu, &power_limit)) - power_limit = smu->adev->pm.ac_power ? + uint32_t pp_limit = smu->adev->pm.ac_power ? skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] : skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0]; + uint32_t power_limit = 0, od_percent_upper = 0, od_percent_lower = 0; + int ret; + + if (current_power_limit) { + ret = smu_v13_0_get_current_power_limit(smu, &power_limit); + if (ret) + power_limit = pp_limit; - if (current_power_limit) *current_power_limit = power_limit; + } + if (default_power_limit) - *default_power_limit = power_limit; + *default_power_limit = pp_limit; if (powerplay_table) { if (smu->od_enabled && @@ -2407,15 +2411,15 @@ static int smu_v13_0_7_get_power_limit(struct smu_context *smu, } dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n", - od_percent_upper, od_percent_lower, power_limit); + od_percent_upper, od_percent_lower, pp_limit); if (max_power_limit) { - *max_power_limit = msg_limit * (100 + od_percent_upper); + *max_power_limit = pp_limit * (100 + od_percent_upper); *max_power_limit /= 100; } if (min_power_limit) { - *min_power_limit = power_limit * (100 - od_percent_lower); + *min_power_limit = pp_limit * (100 - od_percent_lower); *min_power_limit /= 100; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c index a28624d4847a..75719c47a41e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c @@ -1231,7 +1231,8 @@ static int smu_v14_0_0_set_soft_freq_limited_range(struct smu_context *smu, switch (clk_type) { case SMU_GFXCLK: case SMU_SCLK: - msg_set_min = SMU_MSG_SetHardMinGfxClk; + /* SoftMin lets PMFW throttle gfxclk; HardMin would override SoftMax. */ + msg_set_min = SMU_MSG_SetSoftMinGfxclk; msg_set_max = SMU_MSG_SetSoftMaxGfxClk; break; case SMU_FCLK: diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c index 5ce4e982ca33..fdc1456b885c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c @@ -2152,7 +2152,6 @@ static ssize_t smu_v14_0_2_get_gpu_metrics(struct smu_context *smu, metrics->Vcn1ActivityPercentage); gpu_metrics->average_socket_power = metrics->AverageSocketPower; - gpu_metrics->energy_accumulator = metrics->EnergyAccumulator; if (metrics->AverageGfxActivity <= SMU_14_0_2_BUSY_THRESHOLD) gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index 90c7127beabf..fe97fda8bfe9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -272,11 +272,15 @@ static void __smu_msg_v1_send(struct smu_msg_ctl *ctl, u16 index, { struct amdgpu_device *adev = ctl->smu->adev; struct smu_msg_config *cfg = &ctl->config; + u32 arg; int i; WREG32(cfg->resp_reg, 0); - for (i = 0; i < args->num_args; i++) - WREG32(cfg->arg_regs[i], args->args[i]); + for (i = 0; i < cfg->num_arg_regs; i++) { + /* NOTE: Clear unused argument registers to avoid stale values. */ + arg = i < args->num_args ? args->args[i] : 0; + WREG32(cfg->arg_regs[i], arg); + } WREG32(cfg->msg_reg, index); } diff --git a/drivers/gpu/drm/drm_dumb_buffers.c b/drivers/gpu/drm/drm_dumb_buffers.c index cc99681a9ed0..2156dbe601c9 100644 --- a/drivers/gpu/drm/drm_dumb_buffers.c +++ b/drivers/gpu/drm/drm_dumb_buffers.c @@ -202,13 +202,6 @@ int drm_mode_create_dumb(struct drm_device *dev, if (!args->width || !args->height || !args->bpp) return -EINVAL; - /* Reject unreasonable inputs early. Dumb buffers are for software - * rendering; nothing legitimate needs more than 8192x8192 at 32bpp. - * This prevents overflows in downstream alignment helpers. - */ - if (args->width >= 8192 || args->height >= 8192 || args->bpp > 32) - return -EINVAL; - /* overflow checks for 32bit size calculations */ if (args->bpp > U32_MAX - 8) return -EINVAL; diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index e12cdf91f4dc..3b2448a3a9de 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -1015,12 +1015,25 @@ err: return ret; } +/* + * This ioctl is disabled for security reasons but also it failed + * to follow process in terms of adding testing in igt and verifying + * all the corner cases which made fixing security bugs in it even + * harder than necessary. + * + * To re-enable this ioctl + * 1. land working IGT tests in igt-gpu-tools that cover + * all corner cases and race conditions. + * 2. handle idr_preload + * 3. handle == 0 + * 4. handle == new_handle semantics definition. + */ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_gem_change_handle *args = data; - struct drm_gem_object *obj, *idrobj; - int handle, ret; + struct drm_gem_object *obj; + int new_handle, ret; if (!drm_core_check_feature(dev, DRIVER_GEM)) return -EOPNOTSUPP; @@ -1028,52 +1041,36 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data, /* idr_alloc() limitation. */ if (args->new_handle > INT_MAX) return -EINVAL; - handle = args->new_handle; - - obj = drm_gem_object_lookup(file_priv, args->handle); - if (!obj) - return -ENOENT; + new_handle = args->new_handle; - if (args->handle == handle) { - ret = 0; - goto out; - } + if (args->handle == new_handle) + return 0; mutex_lock(&file_priv->prime.lock); - spin_lock(&file_priv->table_lock); - - /* When create_tail allocs an obj idr, it needs to first alloc as NULL, - * then later replace with the correct object. This is not necessary - * here, because the only operations that could race are drm_prime - * bookkeeping, and we hold the prime lock. - */ - ret = idr_alloc(&file_priv->object_idr, obj, handle, handle + 1, + ret = idr_alloc(&file_priv->object_idr, NULL, new_handle, new_handle + 1, GFP_NOWAIT); - if (ret < 0) { - spin_unlock(&file_priv->table_lock); - goto out_unlock; - } - - idrobj = idr_replace(&file_priv->object_idr, NULL, handle); - if (idrobj != obj) { - idr_replace(&file_priv->object_idr, idrobj, handle); - idr_remove(&file_priv->object_idr, args->new_handle); - spin_unlock(&file_priv->table_lock); - ret = -ENOENT; - goto out_unlock; - } - - idr_replace(&file_priv->object_idr, NULL, args->handle); + if (ret < 0) { + spin_unlock(&file_priv->table_lock); + goto out_unlock; + } + + obj = idr_replace(&file_priv->object_idr, NULL, args->handle); + if (IS_ERR_OR_NULL(obj)) { + idr_remove(&file_priv->object_idr, new_handle); + spin_unlock(&file_priv->table_lock); + ret = -ENOENT; + goto out_unlock; + } spin_unlock(&file_priv->table_lock); if (obj->dma_buf) { ret = drm_prime_add_buf_handle(&file_priv->prime, obj->dma_buf, - handle); + new_handle); if (ret < 0) { spin_lock(&file_priv->table_lock); - idr_remove(&file_priv->object_idr, handle); + idr_remove(&file_priv->object_idr, new_handle); idr_replace(&file_priv->object_idr, obj, args->handle); spin_unlock(&file_priv->table_lock); goto out_unlock; @@ -1086,14 +1083,12 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data, spin_lock(&file_priv->table_lock); idr_remove(&file_priv->object_idr, args->handle); - idrobj = idr_replace(&file_priv->object_idr, obj, handle); + obj = idr_replace(&file_priv->object_idr, obj, new_handle); spin_unlock(&file_priv->table_lock); - WARN_ON(idrobj != NULL); + WARN_ON(obj != NULL); out_unlock: mutex_unlock(&file_priv->prime.lock); -out: - drm_gem_object_put(obj); return ret; } diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index ff193155129e..e2df4becce62 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -660,7 +660,8 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_GEM_CHANGE_HANDLE, drm_gem_change_handle_ioctl, DRM_RENDER_ALLOW), + /* see drm_gem.c:drm_gem_change_handle_ioctl for why this is invalid */ + DRM_IOCTL_DEF(DRM_IOCTL_GEM_CHANGE_HANDLE, drm_invalid_op, DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, 0), diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index a8d56ebf06a2..7a6c07f6aaeb 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -691,10 +691,9 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) struct intel_dp *intel_dp = intel_attached_dp(connector); struct drm_device *dev = connector->base.dev; struct intel_panel *panel = &connector->panel; - bool try_intel_interface = false; + bool try_intel_interface = false, try_vesa_interface = false; - /* - * Check the VBT and user's module parameters to figure out which + /* Check the VBT and user's module parameters to figure out which * interfaces to probe */ switch (display->params.enable_dpcd_backlight) { @@ -703,6 +702,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) case INTEL_DP_AUX_BACKLIGHT_AUTO: switch (panel->vbt.backlight.type) { case INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE: + try_vesa_interface = true; break; case INTEL_BACKLIGHT_DISPLAY_DDI: try_intel_interface = true; @@ -715,12 +715,20 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) if (panel->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE) try_intel_interface = true; + try_vesa_interface = true; + break; + case INTEL_DP_AUX_BACKLIGHT_FORCE_VESA: + try_vesa_interface = true; break; case INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL: try_intel_interface = true; break; } + /* For eDP 1.5 and above we are supposed to use VESA interface for brightness control */ + if (intel_dp->edp_dpcd[0] >= DP_EDP_15) + try_vesa_interface = true; + /* * Since Intel has their own backlight control interface, the majority of machines out there * using DPCD backlight controls with Intel GPUs will be using this interface as opposed to @@ -733,9 +741,6 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) * panel with Intel's OUI - which is also required for us to be able to detect Intel's * backlight interface at all. This means that the only sensible way for us to detect both * interfaces is to probe for Intel's first, and VESA's second. - * - * Also there is a chance some VBTs may advertise false Intel backlight support even if the - * TCON DPCD says otherwise. This means we keep VESA interface as fallback in that case. */ if (try_intel_interface && intel_dp->edp_dpcd[0] <= DP_EDP_14b && intel_dp_aux_supports_hdr_backlight(connector)) { @@ -745,7 +750,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) return 0; } - if (intel_dp_aux_supports_vesa_backlight(connector)) { + if (try_vesa_interface && intel_dp_aux_supports_vesa_backlight(connector)) { drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Using VESA eDP backlight controls\n", connector->base.base.id, connector->base.name); panel->backlight.funcs = &intel_dp_vesa_bl_funcs; diff --git a/drivers/gpu/drm/i915/display/intel_plane.c b/drivers/gpu/drm/i915/display/intel_plane.c index 82f445c83158..07eae4176dad 100644 --- a/drivers/gpu/drm/i915/display/intel_plane.c +++ b/drivers/gpu/drm/i915/display/intel_plane.c @@ -144,6 +144,15 @@ intel_plane_duplicate_state(struct drm_plane *plane) if (intel_state->hw.fb) drm_framebuffer_get(intel_state->hw.fb); + if (intel_state->hw.degamma_lut) + drm_property_blob_get(intel_state->hw.degamma_lut); + if (intel_state->hw.gamma_lut) + drm_property_blob_get(intel_state->hw.gamma_lut); + if (intel_state->hw.ctm) + drm_property_blob_get(intel_state->hw.ctm); + if (intel_state->hw.lut_3d) + drm_property_blob_get(intel_state->hw.lut_3d); + return &intel_state->uapi; } @@ -167,6 +176,16 @@ intel_plane_destroy_state(struct drm_plane *plane, __drm_atomic_helper_plane_destroy_state(&plane_state->uapi); if (plane_state->hw.fb) drm_framebuffer_put(plane_state->hw.fb); + + if (plane_state->hw.degamma_lut) + drm_property_blob_put(plane_state->hw.degamma_lut); + if (plane_state->hw.gamma_lut) + drm_property_blob_put(plane_state->hw.gamma_lut); + if (plane_state->hw.ctm) + drm_property_blob_put(plane_state->hw.ctm); + if (plane_state->hw.lut_3d) + drm_property_blob_put(plane_state->hw.lut_3d); + kfree(plane_state); } @@ -317,6 +336,14 @@ static void intel_plane_clear_hw_state(struct intel_plane_state *plane_state) { if (plane_state->hw.fb) drm_framebuffer_put(plane_state->hw.fb); + if (plane_state->hw.degamma_lut) + drm_property_blob_put(plane_state->hw.degamma_lut); + if (plane_state->hw.gamma_lut) + drm_property_blob_put(plane_state->hw.gamma_lut); + if (plane_state->hw.ctm) + drm_property_blob_put(plane_state->hw.ctm); + if (plane_state->hw.lut_3d) + drm_property_blob_put(plane_state->hw.lut_3d); memset(&plane_state->hw, 0, sizeof(plane_state->hw)); } diff --git a/drivers/gpu/drm/imx/dcss/dcss-scaler.c b/drivers/gpu/drm/imx/dcss/dcss-scaler.c index 32c3f46b21da..5c7f8d952ec1 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-scaler.c +++ b/drivers/gpu/drm/imx/dcss/dcss-scaler.c @@ -166,6 +166,7 @@ static int exp_approx_q(int x) * dcss_scaler_gaussian_filter() - Generate gaussian prototype filter. * @fc_q: fixed-point cutoff frequency normalized to range [0, 1] * @use_5_taps: indicates whether to use 5 taps or 7 taps + * @phase0_identity: whether to override phase 0 coefficients with identity filter * @coef: output filter coefficients */ static void dcss_scaler_gaussian_filter(int fc_q, bool use_5_taps, @@ -262,7 +263,9 @@ static void dcss_scaler_nearest_neighbor_filter(bool use_5_taps, * @src_length: length of input * @dst_length: length of output * @use_5_taps: 0 for 7 taps per phase, 1 for 5 taps + * @phase0_identity: whether to override phase 0 coefficients with identity filter * @coef: output coefficients + * @nn_interpolation: whether to use nearest neighbor instead of gaussian filter */ static void dcss_scaler_filter_design(int src_length, int dst_length, bool use_5_taps, bool phase0_identity, diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index 75d9eccd7966..dd7da419702f 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -213,6 +213,14 @@ v3d_clean_caches(struct v3d_dev *v3d) trace_v3d_cache_clean_begin(dev); + /* GFXH-1897: Ensure pending flushes complete before writing L2TCACTL */ + if (v3d->ver < V3D_GEN_71) { + if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) & + V3D_L2TCACTL_L2TFLS), 100)) { + drm_err(dev, "Timeout waiting for L2T clean\n"); + } + } + V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF); if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) & V3D_L2TCACTL_TMUWCF), 100)) { diff --git a/drivers/gpu/drm/v3d/v3d_perfmon.c b/drivers/gpu/drm/v3d/v3d_perfmon.c index 8e0249580bba..ecfd446ff75f 100644 --- a/drivers/gpu/drm/v3d/v3d_perfmon.c +++ b/drivers/gpu/drm/v3d/v3d_perfmon.c @@ -309,8 +309,11 @@ static void v3d_perfmon_delete(struct v3d_file_priv *v3d_priv, if (perfmon == v3d->active_perfmon) v3d_perfmon_stop(v3d, perfmon, false); - /* If the global perfmon is being destroyed, set it to NULL */ - cmpxchg(&v3d->global_perfmon, perfmon, NULL); + /* If the global perfmon is being destroyed, clean it and release + * the reference stashed in v3d_perfmon_set_global_ioctl(). + */ + if (cmpxchg(&v3d->global_perfmon, perfmon, NULL) == perfmon) + v3d_perfmon_put(perfmon); v3d_perfmon_put(perfmon); } @@ -461,16 +464,27 @@ int v3d_perfmon_set_global_ioctl(struct drm_device *dev, void *data, /* If the request is to clear the global performance monitor */ if (req->flags & DRM_V3D_PERFMON_CLEAR_GLOBAL) { - if (!v3d->global_perfmon) + struct v3d_perfmon *old; + + /* DRM_V3D_PERFMON_CLEAR_GLOBAL doesn't check if + * v3d->global_perfmon == perfmon. Therefore, there + * is no need to keep perfmon's reference. + */ + v3d_perfmon_put(perfmon); + + old = xchg(&v3d->global_perfmon, NULL); + if (!old) return -EINVAL; - xchg(&v3d->global_perfmon, NULL); + v3d_perfmon_put(old); return 0; } - if (cmpxchg(&v3d->global_perfmon, NULL, perfmon)) + if (cmpxchg(&v3d->global_perfmon, NULL, perfmon)) { + v3d_perfmon_put(perfmon); return -EBUSY; + } return 0; } diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index 94bf628dc91c..8a635a9ec046 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -352,6 +352,16 @@ v3d_csd_job_run(struct drm_sched_job *sched_job) return NULL; } + /* The HW interprets a workgroup size of 0 as 65536; however, the + * user-space driver exposes a maximum of 65535. Therefore, a 0 in + * any dimension means that we have no workgroups and the compute + * shader should not be dispatched. + */ + if (!V3D_GET_FIELD(job->args.cfg[0], V3D_CSD_QUEUED_CFG0_NUM_WGS_X) || + !V3D_GET_FIELD(job->args.cfg[1], V3D_CSD_QUEUED_CFG1_NUM_WGS_Y) || + !V3D_GET_FIELD(job->args.cfg[2], V3D_CSD_QUEUED_CFG2_NUM_WGS_Z)) + return NULL; + v3d->queue[V3D_CSD].active_job = &job->base; v3d_invalidate_caches(v3d); @@ -402,13 +412,13 @@ v3d_rewrite_csd_job_wg_counts_from_indirect(struct v3d_cpu_job *job) wg_counts = (uint32_t *)(bo->vaddr + indirect_csd->offset); - if (wg_counts[0] == 0 || wg_counts[1] == 0 || wg_counts[2] == 0) - return; - args->cfg[0] = wg_counts[0] << V3D_CSD_CFG012_WG_COUNT_SHIFT; args->cfg[1] = wg_counts[1] << V3D_CSD_CFG012_WG_COUNT_SHIFT; args->cfg[2] = wg_counts[2] << V3D_CSD_CFG012_WG_COUNT_SHIFT; + if (wg_counts[0] == 0 || wg_counts[1] == 0 || wg_counts[2] == 0) + goto unmap_bo; + num_batches = DIV_ROUND_UP(indirect_csd->wg_size, 16) * (wg_counts[0] * wg_counts[1] * wg_counts[2]); @@ -428,6 +438,7 @@ v3d_rewrite_csd_job_wg_counts_from_indirect(struct v3d_cpu_job *job) } } +unmap_bo: v3d_put_bo_vaddr(indirect); v3d_put_bo_vaddr(bo); } diff --git a/drivers/gpu/drm/xe/xe_exec_queue.h b/drivers/gpu/drm/xe/xe_exec_queue.h index a82d99bd77bc..0225426c57b0 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.h +++ b/drivers/gpu/drm/xe/xe_exec_queue.h @@ -162,21 +162,4 @@ int xe_exec_queue_contexts_hwsp_rebase(struct xe_exec_queue *q, void *scratch); struct xe_lrc *xe_exec_queue_lrc(struct xe_exec_queue *q); struct xe_lrc *xe_exec_queue_get_lrc(struct xe_exec_queue *q, u16 idx); -/** - * xe_exec_queue_idle_skip_suspend() - Can exec queue skip suspend - * @q: The exec_queue - * - * If an exec queue is not parallel and is idle, the suspend steps can be - * skipped in the submission backend immediatley signaling the suspend fence. - * Parallel queues cannot skip this step due to limitations in the submission - * backend. - * - * Return: True if exec queue is idle and can skip suspend steps, False - * otherwise - */ -static inline bool xe_exec_queue_idle_skip_suspend(struct xe_exec_queue *q) -{ - return !xe_exec_queue_is_parallel(q) && xe_exec_queue_is_idle(q); -} - #endif diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 912182dc7704..a4a8f0d41fe8 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -71,7 +71,6 @@ exec_queue_to_guc(struct xe_exec_queue *q) #define EXEC_QUEUE_STATE_WEDGED (1 << 8) #define EXEC_QUEUE_STATE_BANNED (1 << 9) #define EXEC_QUEUE_STATE_PENDING_RESUME (1 << 10) -#define EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND (1 << 11) static bool exec_queue_registered(struct xe_exec_queue *q) { @@ -218,21 +217,6 @@ static void clear_exec_queue_pending_resume(struct xe_exec_queue *q) atomic_and(~EXEC_QUEUE_STATE_PENDING_RESUME, &q->guc->state); } -static bool exec_queue_idle_skip_suspend(struct xe_exec_queue *q) -{ - return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND; -} - -static void set_exec_queue_idle_skip_suspend(struct xe_exec_queue *q) -{ - atomic_or(EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND, &q->guc->state); -} - -static void clear_exec_queue_idle_skip_suspend(struct xe_exec_queue *q) -{ - atomic_and(~EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND, &q->guc->state); -} - static bool exec_queue_killed_or_banned_or_wedged(struct xe_exec_queue *q) { return (atomic_read(&q->guc->state) & @@ -1153,7 +1137,7 @@ static void submit_exec_queue(struct xe_exec_queue *q, struct xe_sched_job *job) if (!job->restore_replay || job->last_replay) { if (xe_exec_queue_is_parallel(q)) wq_item_append(q); - else if (!exec_queue_idle_skip_suspend(q)) + else xe_lrc_set_ring_tail(lrc, lrc->ring.tail); job->last_replay = false; } @@ -1163,9 +1147,12 @@ static void submit_exec_queue(struct xe_exec_queue *q, struct xe_sched_job *job) /* * All queues in a multi-queue group will use the primary queue - * of the group to interface with GuC. + * of the group to interface with GuC. If primay is suspended, + * just return. Jobs will get scheduled once primary is resumed. */ q = xe_exec_queue_multi_queue_primary(q); + if (exec_queue_suspended(q)) + return; if (!exec_queue_enabled(q) && !exec_queue_suspended(q)) { action[len++] = XE_GUC_ACTION_SCHED_CONTEXT_MODE_SET; @@ -1810,10 +1797,9 @@ static void __guc_exec_queue_process_msg_suspend(struct xe_sched_msg *msg) { struct xe_exec_queue *q = msg->private_data; struct xe_guc *guc = exec_queue_to_guc(q); - bool idle_skip_suspend = xe_exec_queue_idle_skip_suspend(q); - if (!idle_skip_suspend && guc_exec_queue_allowed_to_change_state(q) && - !exec_queue_suspended(q) && exec_queue_enabled(q)) { + if (guc_exec_queue_allowed_to_change_state(q) && !exec_queue_suspended(q) && + exec_queue_enabled(q)) { wait_event(guc->ct.wq, vf_recovery(guc) || ((q->guc->resume_time != RESUME_PENDING || xe_guc_read_stopped(guc)) && !exec_queue_pending_disable(q))); @@ -1832,33 +1818,11 @@ static void __guc_exec_queue_process_msg_suspend(struct xe_sched_msg *msg) disable_scheduling(q, false); } } else if (q->guc->suspend_pending) { - if (idle_skip_suspend) - set_exec_queue_idle_skip_suspend(q); set_exec_queue_suspended(q); suspend_fence_signal(q); } } -static void sched_context(struct xe_exec_queue *q) -{ - struct xe_guc *guc = exec_queue_to_guc(q); - struct xe_lrc *lrc = q->lrc[0]; - u32 action[] = { - XE_GUC_ACTION_SCHED_CONTEXT, - q->guc->id, - }; - - xe_gt_assert(guc_to_gt(guc), !xe_exec_queue_is_parallel(q)); - xe_gt_assert(guc_to_gt(guc), !exec_queue_destroyed(q)); - xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q)); - xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_disable(q)); - - trace_xe_exec_queue_submit(q); - - xe_lrc_set_ring_tail(lrc, lrc->ring.tail); - xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), 0, 0); -} - static void __guc_exec_queue_process_msg_resume(struct xe_sched_msg *msg) { struct xe_exec_queue *q = msg->private_data; @@ -1866,22 +1830,12 @@ static void __guc_exec_queue_process_msg_resume(struct xe_sched_msg *msg) if (guc_exec_queue_allowed_to_change_state(q)) { clear_exec_queue_suspended(q); if (!exec_queue_enabled(q)) { - if (exec_queue_idle_skip_suspend(q)) { - struct xe_lrc *lrc = q->lrc[0]; - - clear_exec_queue_idle_skip_suspend(q); - xe_lrc_set_ring_tail(lrc, lrc->ring.tail); - } q->guc->resume_time = RESUME_PENDING; set_exec_queue_pending_resume(q); enable_scheduling(q); - } else if (exec_queue_idle_skip_suspend(q)) { - clear_exec_queue_idle_skip_suspend(q); - sched_context(q); } } else { clear_exec_queue_suspended(q); - clear_exec_queue_idle_skip_suspend(q); } } @@ -2853,8 +2807,8 @@ static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q, xe_gt_assert(guc_to_gt(guc), exec_queue_pending_disable(q)); if (q->guc->suspend_pending) { - suspend_fence_signal(q); clear_exec_queue_pending_disable(q); + suspend_fence_signal(q); } else { if (exec_queue_banned(q)) { smp_wmb(); diff --git a/drivers/gpu/drm/xe/xe_hw_engine_group.c b/drivers/gpu/drm/xe/xe_hw_engine_group.c index 4c2b113364d3..02cf32ae5aa9 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine_group.c +++ b/drivers/gpu/drm/xe/xe_hw_engine_group.c @@ -208,21 +208,15 @@ static int xe_hw_engine_group_suspend_faulting_lr_jobs(struct xe_hw_engine_group lockdep_assert_held_write(&group->mode_sem); list_for_each_entry(q, &group->exec_queue_list, hw_engine_group_link) { - bool idle_skip_suspend; if (!xe_vm_in_fault_mode(q->vm)) continue; - idle_skip_suspend = xe_exec_queue_idle_skip_suspend(q); - if (!idle_skip_suspend && has_deps) + if (has_deps) return -EAGAIN; xe_gt_stats_incr(q->gt, XE_GT_STATS_ID_HW_ENGINE_GROUP_SUSPEND_LR_QUEUE_COUNT, 1); - if (idle_skip_suspend) - xe_gt_stats_incr(q->gt, - XE_GT_STATS_ID_HW_ENGINE_GROUP_SKIP_LR_QUEUE_COUNT, 1); - - need_resume |= !idle_skip_suspend; + need_resume = true; q->ops->suspend(q); gt = q->gt; } diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c index 9cebb2490245..18ebefd444fe 100644 --- a/drivers/gpu/drm/xe/xe_uc_fw.c +++ b/drivers/gpu/drm/xe/xe_uc_fw.c @@ -115,7 +115,6 @@ struct fw_blobs_by_type { #define XE_GT_TYPE_ANY XE_GT_TYPE_UNINITIALIZED #define XE_GUC_FIRMWARE_DEFS(fw_def, mmp_ver, major_ver) \ - fw_def(NOVALAKE_S, GT_TYPE_ANY, mmp_ver(xe, guc, nvl, 70, 55, 4)) \ fw_def(PANTHERLAKE, GT_TYPE_ANY, major_ver(xe, guc, ptl, 70, 54, 0)) \ fw_def(BATTLEMAGE, GT_TYPE_ANY, major_ver(xe, guc, bmg, 70, 54, 0)) \ fw_def(LUNARLAKE, GT_TYPE_ANY, major_ver(xe, guc, lnl, 70, 53, 0)) \ diff --git a/io_uring/net.c b/io_uring/net.c index 8df15b639358..ee848eb65ec9 100644 --- a/io_uring/net.c +++ b/io_uring/net.c @@ -842,7 +842,8 @@ int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) } /* bits to clear in old and inherit in new cflags on bundle retry */ -#define CQE_F_MASK (IORING_CQE_F_SOCK_NONEMPTY|IORING_CQE_F_MORE) +#define CQE_F_MASK (IORING_CQE_F_SOCK_NONEMPTY|IORING_CQE_F_MORE|\ + IORING_CQE_F_BUF_MORE) /* * Finishes io_recv and io_recvmsg. |
