summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-04-22 03:39:21 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2026-04-22 03:39:21 +0300
commit6596a02b207886e9e00bb0161c7fd59fea53c081 (patch)
treee62870e85acc21655af12dda4d458ddc4c0148ca
parentd46dd0d88341e45f8e0226fdef5462f5270898fc (diff)
parenta7756371e57f69a137f295a418fb56f15ff2c10f (diff)
downloadlinux-master.tar.xz
Merge tag 'drm-next-2026-04-22' of https://gitlab.freedesktop.org/drm/kernelHEADmaster
Pull more drm updates from Dave Airlie: "This is a followup which is mostly next material with some fixes. Alex pointed out I missed one of his AMD MRs from last week, so I added that, then Jani sent the pipe reordering stuff, otherwise it's just some minor i915 fixes and a dma-buf fix. drm: - Add support for AMD VSDB parsing to drm_edid dma-buf: - fix documentation formatting i915: - add support for reordered pipes to support joined pipes better - Fix VESA backlight possible check condition - Verify the correct plane DDB entry amdgpu: - Audio regression fix - Use drm edid parser for AMD VSDB - Misc cleanups - VCE cs parse fixes - VCN cs parse fixes - RAS fixes - Clean up and unify vram reservation handling - GPU Partition updates - system_wq cleanups - Add CONFIG_GCOV_PROFILE_AMDGPU kconfig option - SMU vram copy updates - SMU 13/14/15 fixes - UserQ fixes - Replace pasid idr with an xarray - Dither handling fix - Enable amdgpu by default for CIK APUs - Add IBs to devcoredump amdkfd: - system_wq cleanups radeon: - system_wq cleanups" * tag 'drm-next-2026-04-22' of https://gitlab.freedesktop.org/drm/kernel: (62 commits) drm/i915/display: change pipe allocation order for discrete platforms drm/i915/wm: Verify the correct plane DDB entry drm/i915/backlight: Fix VESA backlight possible check condition drm/i915: Walk crtcs in pipe order drm/i915/joiner: Make joiner "nomodeset" state copy independent of pipe order dma-buf: fix htmldocs error for dma_buf_attach_revocable drm/amdgpu: dump job ibs in the devcoredump drm/amdgpu: store ib info for devcoredump drm/amdgpu: extract amdgpu_vm_lock_by_pasid from amdgpu_vm_handle_fault drm/amdgpu: Use amdgpu by default for CIK APUs too drm/amd/display: Remove unused NUM_ELEMENTS macros drm/amd/display: Replace inline NUM_ELEMENTS macro with ARRAY_SIZE drm/amdgpu: save ring content before resetting the device drm/amdgpu: make userq fence_drv drop explicit in queue destroy drm/amdgpu: rework userq fence driver alloc/destroy drm/amdgpu/userq: use dma_fence_wait_timeout without test for signalled drm/amdgpu/userq: call dma_resv_wait_timeout without test for signalled drm/amdgpu/userq: add the return code too in error condition drm/amdgpu/userq: fence wait for max time in amdgpu_userq_wait_for_signal drm/amd/display: Change dither policy for 10 bpc output back to dithering ...
-rw-r--r--drivers/dma-buf/dma-buf.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/Kconfig17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/Makefile4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/aldebaran.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c191
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c23
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c362
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h53
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c81
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c32
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c50
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c89
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c23
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c44
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process.c3
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c128
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h14
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c21
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c9
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_cm.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/dcn20/dcn20_mpc.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c4
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h17
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c10
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c9
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c19
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c10
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c10
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c76
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c12
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h3
-rw-r--r--drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c9
-rw-r--r--drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_virt_ras_cmd.c16
-rw-r--r--drivers/gpu/drm/drm_edid.c72
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc.c49
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c20
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.h90
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_core.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_driver.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_types.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c9
-rw-r--r--drivers/gpu/drm/i915/display/skl_watermark.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c3
-rw-r--r--drivers/gpu/drm/xe/display/xe_display.c1
-rw-r--r--include/drm/drm_connector.h38
85 files changed, 1162 insertions, 777 deletions
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index b0bc204bae14..57d4c296804d 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -1353,6 +1353,7 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_attach_revocable, "DMA_BUF");
* Upon return importers may continue to access the DMA-buf memory. The caller
* must do two additional waits to ensure that the memory is no longer being
* accessed:
+ *
* 1) Until dma_resv_wait_timeout() retires fences the importer is allowed to
* fully access the memory.
* 2) Until the importer calls unmap it is allowed to speculatively
diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig
index 7f515be5185d..7fb0b93bc1ca 100644
--- a/drivers/gpu/drm/amd/amdgpu/Kconfig
+++ b/drivers/gpu/drm/amd/amdgpu/Kconfig
@@ -103,6 +103,23 @@ config DRM_AMDGPU_WERROR
Add -Werror to the build flags for amdgpu.ko.
Only enable this if you are warning code for amdgpu.ko.
+
+config GCOV_PROFILE_AMDGPU
+ bool "Enable GCOV profiling on amdgpu"
+ depends on DRM_AMDGPU
+ depends on GCOV_KERNEL
+ default n
+ help
+ Enable GCOV profiling on the amdgpu driver for checking which
+ functions/lines are executed during testing. This adds compiler
+ instrumentation flags to all amdgpu source files, producing
+ .gcda/.gcno coverage data accessible via debugfs.
+
+ This increases the amdgpu module size by ~50% and adds ~2-5%
+ runtime overhead on GPU submission paths.
+
+ If unsure, say N.
+
source "drivers/gpu/drm/amd/acp/Kconfig"
source "drivers/gpu/drm/amd/display/Kconfig"
source "drivers/gpu/drm/amd/amdkfd/Kconfig"
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index 6a7e9bfec59e..db66c6372199 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -27,6 +27,10 @@ FULL_AMD_PATH=$(src)/..
DISPLAY_FOLDER_NAME=display
FULL_AMD_DISPLAY_PATH = $(FULL_AMD_PATH)/$(DISPLAY_FOLDER_NAME)
+ifdef CONFIG_GCOV_PROFILE_AMDGPU
+GCOV_PROFILE := y
+endif
+
ccflags-y := -I$(FULL_AMD_PATH)/include/asic_reg \
-I$(FULL_AMD_PATH)/include \
-I$(FULL_AMD_PATH)/amdgpu \
diff --git a/drivers/gpu/drm/amd/amdgpu/aldebaran.c b/drivers/gpu/drm/amd/amdgpu/aldebaran.c
index 938fb0b2368d..8686c6dc2c08 100644
--- a/drivers/gpu/drm/amd/amdgpu/aldebaran.c
+++ b/drivers/gpu/drm/amd/amdgpu/aldebaran.c
@@ -179,7 +179,7 @@ aldebaran_mode2_perform_reset(struct amdgpu_reset_control *reset_ctl,
list_for_each_entry(tmp_adev, reset_device_list, reset_list) {
/* For XGMI run all resets in parallel to speed up the process */
if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) {
- if (!queue_work(system_unbound_wq,
+ if (!queue_work(system_dfl_wq,
&tmp_adev->reset_cntl->reset_work))
r = -EALREADY;
} else
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 49e7881750fa..8bc591deb546 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1045,11 +1045,6 @@ struct amdgpu_device {
struct amdgpu_mqd mqds[AMDGPU_HW_IP_NUM];
const struct amdgpu_userq_funcs *userq_funcs[AMDGPU_HW_IP_NUM];
- /* xarray used to retrieve the user queue fence driver reference
- * in the EOP interrupt handler to signal the particular user
- * queue fence.
- */
- struct xarray userq_xa;
/**
* @userq_doorbell_xa: Global user queue map (doorbell index → queue)
* Key: doorbell_index (unique global identifier for the queue)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index 4f27c75abedb..d9e283f3b57d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -805,7 +805,10 @@ u64 amdgpu_amdkfd_xcp_memory_size(struct amdgpu_device *adev, int xcp_id)
} else {
tmp = adev->gmc.mem_partitions[mem_id].size;
}
- do_div(tmp, adev->xcp_mgr->num_xcp_per_mem_partition);
+
+ if (adev->xcp_mgr->mem_alloc_mode == AMDGPU_PARTITION_MEM_CAPPING_EVEN)
+ do_div(tmp, adev->xcp_mgr->num_xcp_per_mem_partition);
+
return ALIGN_DOWN(tmp, PAGE_SIZE);
} else if (adev->apu_prefer_gtt) {
return (ttm_tt_pages_limit() << PAGE_SHIFT);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
index 9f38b7dd1011..3698dd0330ff 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
@@ -1685,9 +1685,9 @@ static int amdgpu_atombios_allocate_fb_scratch(struct amdgpu_device *adev)
(uint32_t)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION <<
ATOM_VRAM_OPERATION_FLAGS_SHIFT)) {
/* Firmware request VRAM reservation for SR-IOV */
- adev->mman.fw_vram_usage_start_offset = (start_addr &
- (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;
- adev->mman.fw_vram_usage_size = size << 10;
+ amdgpu_ttm_init_vram_resv(adev, AMDGPU_RESV_FW_VRAM_USAGE,
+ (start_addr & (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10,
+ size << 10, true);
/* Use the default scratch size */
usage_bytes = 0;
} else {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
index cd9aa5b45e94..6860a3a4d466 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
@@ -120,9 +120,9 @@ static int amdgpu_atomfirmware_allocate_fb_v2_1(struct amdgpu_device *adev,
(u32)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION <<
ATOM_VRAM_OPERATION_FLAGS_SHIFT)) {
/* Firmware request VRAM reservation for SR-IOV */
- adev->mman.fw_vram_usage_start_offset = (start_addr &
- (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;
- adev->mman.fw_vram_usage_size = fw_size << 10;
+ amdgpu_ttm_init_vram_resv(adev, AMDGPU_RESV_FW_VRAM_USAGE,
+ (start_addr & (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10,
+ fw_size << 10, true);
/* Use the default scratch size */
*usage_bytes = 0;
} else {
@@ -152,18 +152,18 @@ static int amdgpu_atomfirmware_allocate_fb_v2_2(struct amdgpu_device *adev,
((fw_start_addr & (ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION <<
ATOM_VRAM_OPERATION_FLAGS_SHIFT)) == 0)) {
/* Firmware request VRAM reservation for SR-IOV */
- adev->mman.fw_vram_usage_start_offset = (fw_start_addr &
- (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;
- adev->mman.fw_vram_usage_size = fw_size << 10;
+ amdgpu_ttm_init_vram_resv(adev, AMDGPU_RESV_FW_VRAM_USAGE,
+ (fw_start_addr & (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10,
+ fw_size << 10, true);
}
if (amdgpu_sriov_vf(adev) &&
((drv_start_addr & (ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION <<
ATOM_VRAM_OPERATION_FLAGS_SHIFT)) == 0)) {
/* driver request VRAM reservation for SR-IOV */
- adev->mman.drv_vram_usage_start_offset = (drv_start_addr &
- (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;
- adev->mman.drv_vram_usage_size = drv_size << 10;
+ amdgpu_ttm_init_vram_resv(adev, AMDGPU_RESV_DRV_VRAM_USAGE,
+ (drv_start_addr & (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10,
+ drv_size << 10, true);
}
*usage_bytes = 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
index fddf4e1252bd..3f1cc2265645 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
@@ -210,12 +210,24 @@ static void amdgpu_devcoredump_fw_info(struct amdgpu_device *adev,
static ssize_t
amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_info *coredump)
{
+ struct amdgpu_device *adev = coredump->adev;
struct drm_printer p;
struct drm_print_iterator iter;
struct amdgpu_vm_fault_info *fault_info;
+ struct amdgpu_bo_va_mapping *mapping;
struct amdgpu_ip_block *ip_block;
- int ver;
-
+ struct amdgpu_res_cursor cursor;
+ struct amdgpu_bo *abo, *root;
+ uint64_t va_start, offset;
+ struct amdgpu_ring *ring;
+ struct amdgpu_vm *vm;
+ u32 *ib_content;
+ uint8_t *kptr;
+ int ver, i, j, r;
+ u32 ring_idx, off;
+ bool sizing_pass;
+
+ sizing_pass = buffer == NULL;
iter.data = buffer;
iter.offset = 0;
iter.remain = count;
@@ -303,23 +315,25 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
/* Add ring buffer information */
drm_printf(&p, "Ring buffer information\n");
- for (int i = 0; i < coredump->adev->num_rings; i++) {
- int j = 0;
- struct amdgpu_ring *ring = coredump->adev->rings[i];
-
- drm_printf(&p, "ring name: %s\n", ring->name);
- drm_printf(&p, "Rptr: 0x%llx Wptr: 0x%llx RB mask: %x\n",
- amdgpu_ring_get_rptr(ring),
- amdgpu_ring_get_wptr(ring),
- ring->buf_mask);
- drm_printf(&p, "Ring size in dwords: %d\n",
- ring->ring_size / 4);
- drm_printf(&p, "Ring contents\n");
- drm_printf(&p, "Offset \t Value\n");
-
- while (j < ring->ring_size) {
- drm_printf(&p, "0x%x \t 0x%x\n", j, ring->ring[j / 4]);
- j += 4;
+ if (coredump->num_rings) {
+ for (i = 0; i < coredump->num_rings; i++) {
+ ring_idx = coredump->rings[i].ring_index;
+ ring = coredump->adev->rings[ring_idx];
+ off = coredump->rings[i].offset;
+
+ drm_printf(&p, "ring name: %s\n", ring->name);
+ drm_printf(&p, "Rptr: 0x%llx Wptr: 0x%llx RB mask: %x\n",
+ coredump->rings[i].rptr,
+ coredump->rings[i].wptr,
+ ring->buf_mask);
+ drm_printf(&p, "Ring size in dwords: %d\n",
+ ring->ring_size / 4);
+ drm_printf(&p, "Ring contents\n");
+ drm_printf(&p, "Offset \t Value\n");
+
+ for (j = 0; j < ring->ring_size; j += 4)
+ drm_printf(&p, "0x%x \t 0x%x\n", j,
+ coredump->rings_dw[off + j / 4]);
}
}
@@ -328,6 +342,87 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
else if (coredump->reset_vram_lost)
drm_printf(&p, "VRAM is lost due to GPU reset!\n");
+ if (coredump->num_ibs) {
+ /* Don't try to lookup the VM or map the BOs when calculating the
+ * size required to store the devcoredump.
+ */
+ if (sizing_pass)
+ vm = NULL;
+ else
+ vm = amdgpu_vm_lock_by_pasid(adev, &root, coredump->pasid);
+
+ for (int i = 0; i < coredump->num_ibs && (sizing_pass || vm); i++) {
+ ib_content = kvmalloc_array(coredump->ibs[i].ib_size_dw, 4,
+ GFP_KERNEL);
+ if (!ib_content)
+ continue;
+
+ /* vm=NULL can only happen when 'sizing_pass' is true. Skip to the
+ * drm_printf() calls (ib_content doesn't need to be initialized
+ * as its content won't be written anywhere).
+ */
+ if (!vm)
+ goto output_ib_content;
+
+ va_start = coredump->ibs[i].gpu_addr & AMDGPU_GMC_HOLE_MASK;
+ mapping = amdgpu_vm_bo_lookup_mapping(vm, va_start / AMDGPU_GPU_PAGE_SIZE);
+ if (!mapping)
+ goto free_ib_content;
+
+ offset = va_start - (mapping->start * AMDGPU_GPU_PAGE_SIZE);
+ abo = amdgpu_bo_ref(mapping->bo_va->base.bo);
+ r = amdgpu_bo_reserve(abo, false);
+ if (r)
+ goto free_ib_content;
+
+ if (abo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) {
+ off = 0;
+
+ if (abo->tbo.resource->mem_type != TTM_PL_VRAM)
+ goto unreserve_abo;
+
+ amdgpu_res_first(abo->tbo.resource, offset,
+ coredump->ibs[i].ib_size_dw * 4,
+ &cursor);
+ while (cursor.remaining) {
+ amdgpu_device_mm_access(adev, cursor.start / 4,
+ &ib_content[off], cursor.size / 4,
+ false);
+ off += cursor.size;
+ amdgpu_res_next(&cursor, cursor.size);
+ }
+ } else {
+ r = ttm_bo_kmap(&abo->tbo, 0,
+ PFN_UP(abo->tbo.base.size),
+ &abo->kmap);
+ if (r)
+ goto unreserve_abo;
+
+ kptr = amdgpu_bo_kptr(abo);
+ kptr += offset;
+ memcpy(ib_content, kptr,
+ coredump->ibs[i].ib_size_dw * 4);
+
+ amdgpu_bo_kunmap(abo);
+ }
+
+output_ib_content:
+ drm_printf(&p, "\nIB #%d 0x%llx %d dw\n",
+ i, coredump->ibs[i].gpu_addr, coredump->ibs[i].ib_size_dw);
+ for (int j = 0; j < coredump->ibs[i].ib_size_dw; j++)
+ drm_printf(&p, "0x%08x\n", ib_content[j]);
+unreserve_abo:
+ if (vm)
+ amdgpu_bo_unreserve(abo);
+free_ib_content:
+ kvfree(ib_content);
+ }
+ if (vm) {
+ amdgpu_bo_unreserve(root);
+ amdgpu_bo_unref(&root);
+ }
+ }
+
return count - iter.remain;
}
@@ -359,6 +454,8 @@ static void amdgpu_devcoredump_free(void *data)
struct amdgpu_coredump_info *coredump = data;
kvfree(coredump->formatted);
+ kvfree(coredump->rings);
+ kvfree(coredump->rings_dw);
kvfree(data);
}
@@ -395,18 +492,26 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
{
struct drm_device *dev = adev_to_drm(adev);
struct amdgpu_coredump_info *coredump;
+ size_t size = sizeof(*coredump);
struct drm_sched_job *s_job;
+ u64 total_ring_size, ring_count;
+ struct amdgpu_ring *ring;
+ int i, off, idx;
/* No need to generate a new coredump if there's one in progress already. */
if (work_pending(&adev->coredump_work))
return;
- coredump = kzalloc_obj(*coredump, GFP_NOWAIT);
+ if (job && job->pasid)
+ size += sizeof(struct amdgpu_coredump_ib_info) * job->num_ibs;
+
+ coredump = kzalloc(size, GFP_NOWAIT);
if (!coredump)
return;
coredump->skip_vram_check = skip_vram_check;
coredump->reset_vram_lost = vram_lost;
+ coredump->pasid = job->pasid;
if (job && job->pasid) {
struct amdgpu_task_info *ti;
@@ -416,6 +521,11 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
coredump->reset_task_info = *ti;
amdgpu_vm_put_task_info(ti);
}
+ coredump->num_ibs = job->num_ibs;
+ for (i = 0; i < job->num_ibs; ++i) {
+ coredump->ibs[i].gpu_addr = job->ibs[i].gpu_addr;
+ coredump->ibs[i].ib_size_dw = job->ibs[i].length_dw;
+ }
}
if (job) {
@@ -423,6 +533,47 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
coredump->ring = to_amdgpu_ring(s_job->sched);
}
+ /* Dump ring content if memory allocation succeeds. */
+ ring_count = 0;
+ total_ring_size = 0;
+ for (i = 0; i < adev->num_rings; i++) {
+ ring = adev->rings[i];
+
+ /* Only dump rings with unsignalled fences. */
+ if (atomic_read(&ring->fence_drv.last_seq) == ring->fence_drv.sync_seq &&
+ coredump->ring != ring)
+ continue;
+
+ total_ring_size += ring->ring_size;
+ ring_count++;
+ }
+ coredump->rings_dw = kzalloc(total_ring_size, GFP_NOWAIT);
+ coredump->rings = kcalloc(ring_count, sizeof(struct amdgpu_coredump_ring), GFP_NOWAIT);
+ if (coredump->rings && coredump->rings_dw) {
+ for (i = 0, off = 0, idx = 0; i < adev->num_rings; i++) {
+ ring = adev->rings[i];
+
+ if (atomic_read(&ring->fence_drv.last_seq) == ring->fence_drv.sync_seq &&
+ coredump->ring != ring)
+ continue;
+
+ coredump->rings[idx].ring_index = ring->idx;
+ coredump->rings[idx].rptr = amdgpu_ring_get_rptr(ring);
+ coredump->rings[idx].wptr = amdgpu_ring_get_wptr(ring);
+ coredump->rings[idx].offset = off;
+
+ memcpy(&coredump->rings_dw[off], ring->ring, ring->ring_size);
+ off += ring->ring_size;
+ idx++;
+ }
+ coredump->num_rings = idx;
+ } else {
+ kvfree(coredump->rings_dw);
+ kvfree(coredump->rings);
+ coredump->rings_dw = NULL;
+ coredump->rings = NULL;
+ }
+
coredump->adev = adev;
ktime_get_ts64(&coredump->reset_time);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
index f8f2f4df129b..2371e20fc68b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
@@ -31,6 +31,18 @@
#define AMDGPU_COREDUMP_VERSION "1"
+struct amdgpu_coredump_ring {
+ u64 rptr;
+ u64 wptr;
+ u32 ring_index;
+ u32 offset;
+};
+
+struct amdgpu_coredump_ib_info {
+ uint64_t gpu_addr;
+ u32 ib_size_dw;
+};
+
struct amdgpu_coredump_info {
struct amdgpu_device *adev;
struct amdgpu_task_info reset_task_info;
@@ -39,11 +51,20 @@ struct amdgpu_coredump_info {
bool skip_vram_check;
bool reset_vram_lost;
struct amdgpu_ring *ring;
+
+ struct amdgpu_coredump_ring *rings;
+ u32 *rings_dw;
+ u32 num_rings;
+
/* Readable form of coredevdump, generate once to speed up
* reading it (see drm_coredump_printer's documentation).
*/
ssize_t formatted_size;
char *formatted;
+
+ unsigned int pasid;
+ int num_ibs;
+ struct amdgpu_coredump_ib_info ibs[] __counted_by(num_ibs);
};
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 9c936519bb2b..584c9ec28bf1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -3757,15 +3757,13 @@ int amdgpu_device_init(struct amdgpu_device *adev,
spin_lock_init(&adev->virt.rlcg_reg_lock);
spin_lock_init(&adev->wb.lock);
- xa_init_flags(&adev->userq_xa, XA_FLAGS_LOCK_IRQ);
-
INIT_LIST_HEAD(&adev->reset_list);
INIT_LIST_HEAD(&adev->ras_list);
INIT_LIST_HEAD(&adev->pm.od_kobj_list);
- xa_init(&adev->userq_doorbell_xa);
+ xa_init_flags(&adev->userq_doorbell_xa, XA_FLAGS_LOCK_IRQ);
INIT_DELAYED_WORK(&adev->delayed_init_work,
amdgpu_device_delayed_init_work_handler);
@@ -4065,7 +4063,7 @@ fence_driver_init:
}
/* must succeed. */
amdgpu_ras_resume(adev);
- queue_delayed_work(system_wq, &adev->delayed_init_work,
+ queue_delayed_work(system_dfl_wq, &adev->delayed_init_work,
msecs_to_jiffies(AMDGPU_RESUME_MS));
}
@@ -4630,7 +4628,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool notify_clients)
if (r)
goto exit;
- queue_delayed_work(system_wq, &adev->delayed_init_work,
+ queue_delayed_work(system_dfl_wq, &adev->delayed_init_work,
msecs_to_jiffies(AMDGPU_RESUME_MS));
exit:
if (amdgpu_sriov_vf(adev)) {
@@ -5339,7 +5337,7 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle,
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
/* For XGMI run all resets in parallel to speed up the process */
if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) {
- if (!queue_work(system_unbound_wq,
+ if (!queue_work(system_dfl_wq,
&tmp_adev->xgmi_reset_work))
r = -EALREADY;
} else
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 8ed637f92322..e47921e2a9af 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -641,9 +641,7 @@ module_param_named(si_support, amdgpu_si_support, int, 0444);
* CIK (Sea Islands) are second generation GCN GPUs, supported by both
* drivers: radeon (old) and amdgpu (new). This parameter controls whether
* amdgpu should support CIK.
- * By default:
- * - CIK dedicated GPUs are supported by amdgpu.
- * - CIK APUs are supported by radeon (except when radeon is not built).
+ * By default, CIK dedicated GPUs and APUs are supported by amdgpu.
* Only relevant when CONFIG_DRM_AMDGPU_CIK is enabled to build CIK support in amdgpu.
* See also radeon.cik_support which should be disabled when amdgpu.cik_support is
* enabled, and vice versa.
@@ -2323,8 +2321,6 @@ static bool amdgpu_support_enabled(struct device *dev,
case CHIP_BONAIRE:
case CHIP_HAWAII:
- support_by_default = true;
- fallthrough;
case CHIP_KAVERI:
case CHIP_KABINI:
case CHIP_MULLINS:
@@ -2332,6 +2328,7 @@ static bool amdgpu_support_enabled(struct device *dev,
param = "cik_support";
module_param = amdgpu_cik_support;
amdgpu_support_built = IS_ENABLED(CONFIG_DRM_AMDGPU_CIK);
+ support_by_default = true;
break;
default:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index cab3196a87fb..2956e45c9254 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -1580,6 +1580,36 @@ static ssize_t amdgpu_gfx_set_compute_partition(struct device *dev,
return count;
}
+static ssize_t compute_partition_mem_alloc_mode_show(struct device *dev,
+ struct device_attribute *addr,
+ char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+ int mode = adev->xcp_mgr->mem_alloc_mode;
+
+ return sysfs_emit(buf, "%s\n",
+ amdgpu_gfx_compute_mem_alloc_mode_desc(mode));
+}
+
+
+static ssize_t compute_partition_mem_alloc_mode_store(struct device *dev,
+ struct device_attribute *addr,
+ const char *buf, size_t count)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+
+ if (!strncasecmp("CAPPING", buf, strlen("CAPPING")))
+ adev->xcp_mgr->mem_alloc_mode = AMDGPU_PARTITION_MEM_CAPPING_EVEN;
+ else if (!strncasecmp("ALL", buf, strlen("ALL")))
+ adev->xcp_mgr->mem_alloc_mode = AMDGPU_PARTITION_MEM_ALLOC_ALL;
+ else
+ return -EINVAL;
+
+ return count;
+}
+
static const char *xcp_desc[] = {
[AMDGPU_SPX_PARTITION_MODE] = "SPX",
[AMDGPU_DPX_PARTITION_MODE] = "DPX",
@@ -1935,6 +1965,10 @@ static DEVICE_ATTR(gfx_reset_mask, 0444,
static DEVICE_ATTR(compute_reset_mask, 0444,
amdgpu_gfx_get_compute_reset_mask, NULL);
+static DEVICE_ATTR(compute_partition_mem_alloc_mode, 0644,
+ compute_partition_mem_alloc_mode_show,
+ compute_partition_mem_alloc_mode_store);
+
static int amdgpu_gfx_sysfs_xcp_init(struct amdgpu_device *adev)
{
struct amdgpu_xcp_mgr *xcp_mgr = adev->xcp_mgr;
@@ -1955,6 +1989,11 @@ static int amdgpu_gfx_sysfs_xcp_init(struct amdgpu_device *adev)
if (r)
return r;
+ r = device_create_file(adev->dev,
+ &dev_attr_compute_partition_mem_alloc_mode);
+ if (r)
+ return r;
+
if (xcp_switch_supported)
r = device_create_file(adev->dev,
&dev_attr_available_compute_partition);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
index 2785eda6fea5..a0cf0a3b41da 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
@@ -71,6 +71,11 @@ enum amdgpu_gfx_partition {
AMDGPU_AUTO_COMPUTE_PARTITION_MODE = -2,
};
+enum amdgpu_gfx_partition_mem_alloc_mode {
+ AMDGPU_PARTITION_MEM_CAPPING_EVEN = 0,
+ AMDGPU_PARTITION_MEM_ALLOC_ALL = 1,
+};
+
#define NUM_XCC(x) hweight16(x)
enum amdgpu_gfx_ras_mem_id_type {
@@ -677,4 +682,16 @@ static inline const char *amdgpu_gfx_compute_mode_desc(int mode)
}
}
+static inline const char *amdgpu_gfx_compute_mem_alloc_mode_desc(int mode)
+{
+ switch (mode) {
+ case AMDGPU_PARTITION_MEM_CAPPING_EVEN:
+ return "CAPPING";
+ case AMDGPU_PARTITION_MEM_ALLOC_ALL:
+ return "ALL";
+ default:
+ return "UNKNOWN";
+ }
+}
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index ec74f3971732..285e217fba04 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -1033,17 +1033,17 @@ void amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type,
}
}
-void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev)
+void amdgpu_gmc_init_vga_resv_regions(struct amdgpu_device *adev)
{
unsigned size;
+ if (adev->gmc.is_app_apu)
+ return;
+
/*
* Some ASICs need to reserve a region of video memory to avoid access
* from driver
*/
- adev->mman.stolen_reserved_offset = 0;
- adev->mman.stolen_reserved_size = 0;
-
/*
* TODO:
* Currently there is a bug where some memory client outside
@@ -1060,8 +1060,8 @@ void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev)
*/
#ifdef CONFIG_X86
if (amdgpu_sriov_vf(adev) && hypervisor_is_type(X86_HYPER_MS_HYPERV)) {
- adev->mman.stolen_reserved_offset = 0x500000;
- adev->mman.stolen_reserved_size = 0x200000;
+ amdgpu_ttm_init_vram_resv(adev, AMDGPU_RESV_STOLEN_RESERVED,
+ 0x500000, 0x200000, false);
}
#endif
break;
@@ -1099,11 +1099,14 @@ void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev)
size = 0;
if (size > AMDGPU_VBIOS_VGA_ALLOCATION) {
- adev->mman.stolen_vga_size = AMDGPU_VBIOS_VGA_ALLOCATION;
- adev->mman.stolen_extended_size = size - adev->mman.stolen_vga_size;
+ amdgpu_ttm_init_vram_resv(adev, AMDGPU_RESV_STOLEN_VGA,
+ 0, AMDGPU_VBIOS_VGA_ALLOCATION, false);
+ amdgpu_ttm_init_vram_resv(adev, AMDGPU_RESV_STOLEN_EXTENDED,
+ AMDGPU_VBIOS_VGA_ALLOCATION,
+ size - AMDGPU_VBIOS_VGA_ALLOCATION, false);
} else {
- adev->mman.stolen_vga_size = size;
- adev->mman.stolen_extended_size = 0;
+ amdgpu_ttm_init_vram_resv(adev, AMDGPU_RESV_STOLEN_VGA,
+ 0, size, false);
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
index 32e73e8ba778..6ab4c1e297fc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
@@ -456,7 +456,7 @@ extern void
amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type,
bool enable);
-void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev);
+void amdgpu_gmc_init_vga_resv_regions(struct amdgpu_device *adev);
void amdgpu_gmc_init_pdb0(struct amdgpu_device *adev);
uint64_t amdgpu_gmc_vram_mc2pa(struct amdgpu_device *adev, uint64_t mc_addr);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
index 569c5a89ff10..124fb38eb465 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
@@ -22,7 +22,7 @@
*/
#include "amdgpu_ids.h"
-#include <linux/idr.h>
+#include <linux/xarray.h>
#include <linux/dma-fence-array.h>
@@ -40,8 +40,8 @@
* VMs are looked up from the PASID per amdgpu_device.
*/
-static DEFINE_IDR(amdgpu_pasid_idr);
-static DEFINE_SPINLOCK(amdgpu_pasid_idr_lock);
+static DEFINE_XARRAY_FLAGS(amdgpu_pasid_xa, XA_FLAGS_LOCK_IRQ | XA_FLAGS_ALLOC1);
+static u32 amdgpu_pasid_xa_next;
/* Helper to free pasid from a fence callback */
struct amdgpu_pasid_cb {
@@ -62,36 +62,37 @@ struct amdgpu_pasid_cb {
*/
int amdgpu_pasid_alloc(unsigned int bits)
{
- int pasid;
+ u32 pasid;
+ int r;
if (bits == 0)
return -EINVAL;
- spin_lock(&amdgpu_pasid_idr_lock);
- /* TODO: Need to replace the idr with an xarry, and then
- * handle the internal locking with ATOMIC safe paths.
- */
- pasid = idr_alloc_cyclic(&amdgpu_pasid_idr, NULL, 1,
- 1U << bits, GFP_ATOMIC);
- spin_unlock(&amdgpu_pasid_idr_lock);
-
- if (pasid >= 0)
- trace_amdgpu_pasid_allocated(pasid);
+ r = xa_alloc_cyclic_irq(&amdgpu_pasid_xa, &pasid, xa_mk_value(0),
+ XA_LIMIT(1, (1U << bits) - 1),
+ &amdgpu_pasid_xa_next, GFP_KERNEL);
+ if (r < 0)
+ return r;
+ trace_amdgpu_pasid_allocated(pasid);
return pasid;
}
/**
* amdgpu_pasid_free - Free a PASID
* @pasid: PASID to free
+ *
+ * Called in IRQ context.
*/
void amdgpu_pasid_free(u32 pasid)
{
+ unsigned long flags;
+
trace_amdgpu_pasid_freed(pasid);
- spin_lock(&amdgpu_pasid_idr_lock);
- idr_remove(&amdgpu_pasid_idr, pasid);
- spin_unlock(&amdgpu_pasid_idr_lock);
+ xa_lock_irqsave(&amdgpu_pasid_xa, flags);
+ __xa_erase(&amdgpu_pasid_xa, pasid);
+ xa_unlock_irqrestore(&amdgpu_pasid_xa, flags);
}
static void amdgpu_pasid_free_cb(struct dma_fence *fence,
@@ -634,7 +635,5 @@ void amdgpu_vmid_mgr_fini(struct amdgpu_device *adev)
*/
void amdgpu_pasid_mgr_cleanup(void)
{
- spin_lock(&amdgpu_pasid_idr_lock);
- idr_destroy(&amdgpu_pasid_idr);
- spin_unlock(&amdgpu_pasid_idr_lock);
+ xa_destroy(&amdgpu_pasid_xa);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index d39b695cd925..f0e4d020f4c7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -1076,24 +1076,25 @@ int psp_update_fw_reservation(struct psp_context *psp)
return 0;
}
- amdgpu_bo_free_kernel(&adev->mman.fw_reserved_memory, NULL, NULL);
+ amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_FW);
reserv_size = roundup(reserv_size, SZ_1M);
- ret = amdgpu_bo_create_kernel_at(adev, reserv_addr, reserv_size, &adev->mman.fw_reserved_memory, NULL);
+ amdgpu_ttm_init_vram_resv(adev, AMDGPU_RESV_FW,
+ reserv_addr, reserv_size, false);
+ ret = amdgpu_ttm_mark_vram_reserved(adev, AMDGPU_RESV_FW);
if (ret) {
dev_err(adev->dev, "reserve fw region failed(%d)!\n", ret);
- amdgpu_bo_free_kernel(&adev->mman.fw_reserved_memory, NULL, NULL);
return ret;
}
reserv_size_ext = roundup(reserv_size_ext, SZ_1M);
- ret = amdgpu_bo_create_kernel_at(adev, reserv_addr_ext, reserv_size_ext,
- &adev->mman.fw_reserved_memory_extend, NULL);
+ amdgpu_ttm_init_vram_resv(adev, AMDGPU_RESV_FW_EXTEND,
+ reserv_addr_ext, reserv_size_ext, false);
+ ret = amdgpu_ttm_mark_vram_reserved(adev, AMDGPU_RESV_FW_EXTEND);
if (ret) {
dev_err(adev->dev, "reserve extend fw region failed(%d)!\n", ret);
- amdgpu_bo_free_kernel(&adev->mman.fw_reserved_memory_extend, NULL, NULL);
return ret;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
index 79a49cba8d40..7e94ec11c57e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
@@ -277,7 +277,6 @@ struct psp_memory_training_context {
/*vram offset of the c2p training data*/
u64 c2p_train_data_offset;
- struct amdgpu_bo *c2p_bo;
enum psp_memory_training_init_flag init;
u32 training_cnt;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index 6edcb7713299..6c644cfe6695 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -5726,7 +5726,7 @@ out:
static void amdgpu_ras_critical_region_init(struct amdgpu_device *adev)
{
- amdgpu_ras_add_critical_region(adev, adev->mman.fw_reserved_memory);
+ amdgpu_ras_add_critical_region(adev, adev->mman.resv_region[AMDGPU_RESV_FW].bo);
}
static void amdgpu_ras_critical_region_fini(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
index 7a2fcb7ded1d..1b982b803e6f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
@@ -116,7 +116,7 @@ static int amdgpu_reset_xgmi_reset_on_init_perform_reset(
/* Mode1 reset needs to be triggered on all devices together */
list_for_each_entry(tmp_adev, reset_device_list, reset_list) {
/* For XGMI run all resets in parallel to speed up the process */
- if (!queue_work(system_unbound_wq, &tmp_adev->xgmi_reset_work))
+ if (!queue_work(system_dfl_wq, &tmp_adev->xgmi_reset_work))
r = -EALREADY;
if (r) {
dev_err(tmp_adev->dev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
index ce5af137ee40..715c9e43e13a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -559,15 +559,18 @@ void amdgpu_debugfs_ring_init(struct amdgpu_device *adev,
int amdgpu_ring_init_mqd(struct amdgpu_ring *ring);
-static inline u32 amdgpu_ib_get_value(struct amdgpu_ib *ib, int idx)
+static inline u32 amdgpu_ib_get_value(struct amdgpu_ib *ib, uint32_t idx)
{
- return ib->ptr[idx];
+ if (idx < ib->length_dw)
+ return ib->ptr[idx];
+ return 0;
}
-static inline void amdgpu_ib_set_value(struct amdgpu_ib *ib, int idx,
+static inline void amdgpu_ib_set_value(struct amdgpu_ib *ib, uint32_t idx,
uint32_t value)
{
- ib->ptr[idx] = value;
+ if (idx < ib->length_dw)
+ ib->ptr[idx] = value;
}
int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index afaaab6496de..0dc68fb9d88e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -1671,87 +1671,160 @@ static struct ttm_device_funcs amdgpu_bo_driver = {
.access_memory = &amdgpu_ttm_access_memory,
};
-/*
- * Firmware Reservation functions
- */
-/**
- * amdgpu_ttm_fw_reserve_vram_fini - free fw reserved vram
- *
- * @adev: amdgpu_device pointer
- *
- * free fw reserved vram if it has been reserved.
- */
-static void amdgpu_ttm_fw_reserve_vram_fini(struct amdgpu_device *adev)
+void amdgpu_ttm_init_vram_resv(struct amdgpu_device *adev,
+ enum amdgpu_resv_region_id id,
+ uint64_t offset, uint64_t size,
+ bool needs_cpu_map)
{
- amdgpu_bo_free_kernel(&adev->mman.fw_vram_usage_reserved_bo,
- NULL, &adev->mman.fw_vram_usage_va);
+ struct amdgpu_vram_resv *resv;
+
+ if (id >= AMDGPU_RESV_MAX)
+ return;
+
+ resv = &adev->mman.resv_region[id];
+ resv->offset = offset;
+ resv->size = size;
+ resv->needs_cpu_map = needs_cpu_map;
}
-/*
- * Driver Reservation functions
- */
-/**
- * amdgpu_ttm_drv_reserve_vram_fini - free drv reserved vram
- *
- * @adev: amdgpu_device pointer
- *
- * free drv reserved vram if it has been reserved.
- */
-static void amdgpu_ttm_drv_reserve_vram_fini(struct amdgpu_device *adev)
+static void amdgpu_ttm_init_fw_resv_region(struct amdgpu_device *adev)
+{
+ uint32_t reserve_size = 0;
+
+ if (!adev->discovery.reserve_tmr)
+ return;
+
+ /*
+ * Query reserved tmr size through atom firmwareinfo for Sienna_Cichlid and onwards for all
+ * the use cases (IP discovery/G6 memory training/profiling/diagnostic data.etc)
+ *
+ * Otherwise, fallback to legacy approach to check and reserve tmr block for ip
+ * discovery data and G6 memory training data respectively
+ */
+ if (adev->bios)
+ reserve_size =
+ amdgpu_atomfirmware_get_fw_reserved_fb_size(adev);
+
+ if (!adev->bios &&
+ (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4) ||
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 5, 0)))
+ reserve_size = max(reserve_size, (uint32_t)280 << 20);
+ else if (!adev->bios &&
+ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 1, 0)) {
+ if (hweight32(adev->aid_mask) == 1)
+ reserve_size = max(reserve_size, (uint32_t)128 << 20);
+ else
+ reserve_size = max(reserve_size, (uint32_t)144 << 20);
+ } else if (!reserve_size)
+ reserve_size = DISCOVERY_TMR_OFFSET;
+
+ amdgpu_ttm_init_vram_resv(adev, AMDGPU_RESV_FW,
+ adev->gmc.real_vram_size - reserve_size,
+ reserve_size, false);
+}
+
+static void amdgpu_ttm_init_mem_train_resv_region(struct amdgpu_device *adev)
{
- amdgpu_bo_free_kernel(&adev->mman.drv_vram_usage_reserved_bo,
- NULL,
- &adev->mman.drv_vram_usage_va);
+ uint64_t reserve_size;
+ uint64_t offset;
+
+ if (!adev->discovery.reserve_tmr)
+ return;
+
+ if (!adev->bios || amdgpu_sriov_vf(adev))
+ return;
+
+ if (!amdgpu_atomfirmware_mem_training_supported(adev))
+ return;
+
+ reserve_size = adev->mman.resv_region[AMDGPU_RESV_FW].size;
+ offset = ALIGN((adev->gmc.mc_vram_size - reserve_size - SZ_1M), SZ_1M);
+ amdgpu_ttm_init_vram_resv(adev, AMDGPU_RESV_MEM_TRAIN,
+ offset,
+ GDDR6_MEM_TRAINING_DATA_SIZE_IN_BYTES,
+ false);
}
-/**
- * amdgpu_ttm_fw_reserve_vram_init - create bo vram reservation from fw
- *
- * @adev: amdgpu_device pointer
- *
- * create bo vram reservation from fw.
- */
-static int amdgpu_ttm_fw_reserve_vram_init(struct amdgpu_device *adev)
+static void amdgpu_ttm_init_vram_resv_regions(struct amdgpu_device *adev)
{
uint64_t vram_size = adev->gmc.visible_vram_size;
- adev->mman.fw_vram_usage_va = NULL;
- adev->mman.fw_vram_usage_reserved_bo = NULL;
+ /* Initialize memory reservations as required for VGA.
+ * This is used for VGA emulation and pre-OS scanout buffers to
+ * avoid display artifacts while transitioning between pre-OS
+ * and driver.
+ */
+ amdgpu_gmc_init_vga_resv_regions(adev);
+ amdgpu_ttm_init_fw_resv_region(adev);
+ amdgpu_ttm_init_mem_train_resv_region(adev);
+
+ if (adev->mman.resv_region[AMDGPU_RESV_FW_VRAM_USAGE].size > vram_size)
+ adev->mman.resv_region[AMDGPU_RESV_FW_VRAM_USAGE].size = 0;
+
+ if (adev->mman.resv_region[AMDGPU_RESV_DRV_VRAM_USAGE].size > vram_size)
+ adev->mman.resv_region[AMDGPU_RESV_DRV_VRAM_USAGE].size = 0;
+}
- if (adev->mman.fw_vram_usage_size == 0 ||
- adev->mman.fw_vram_usage_size > vram_size)
+int amdgpu_ttm_mark_vram_reserved(struct amdgpu_device *adev,
+ enum amdgpu_resv_region_id id)
+{
+ struct amdgpu_vram_resv *resv;
+ int ret;
+
+ if (id >= AMDGPU_RESV_MAX)
+ return -EINVAL;
+
+ resv = &adev->mman.resv_region[id];
+ if (!resv->size)
return 0;
- return amdgpu_bo_create_kernel_at(adev,
- adev->mman.fw_vram_usage_start_offset,
- adev->mman.fw_vram_usage_size,
- &adev->mman.fw_vram_usage_reserved_bo,
- &adev->mman.fw_vram_usage_va);
+ ret = amdgpu_bo_create_kernel_at(adev, resv->offset, resv->size,
+ &resv->bo,
+ resv->needs_cpu_map ? &resv->cpu_ptr : NULL);
+ if (ret) {
+ dev_err(adev->dev,
+ "reserve vram failed: id=%d offset=0x%llx size=0x%llx ret=%d\n",
+ id, resv->offset, resv->size, ret);
+ memset(resv, 0, sizeof(*resv));
+ }
+
+ return ret;
}
-/**
- * amdgpu_ttm_drv_reserve_vram_init - create bo vram reservation from driver
- *
- * @adev: amdgpu_device pointer
- *
- * create bo vram reservation from drv.
- */
-static int amdgpu_ttm_drv_reserve_vram_init(struct amdgpu_device *adev)
+void amdgpu_ttm_unmark_vram_reserved(struct amdgpu_device *adev,
+ enum amdgpu_resv_region_id id)
{
- u64 vram_size = adev->gmc.visible_vram_size;
+ struct amdgpu_vram_resv *resv;
- adev->mman.drv_vram_usage_va = NULL;
- adev->mman.drv_vram_usage_reserved_bo = NULL;
+ if (id >= AMDGPU_RESV_MAX)
+ return;
- if (adev->mman.drv_vram_usage_size == 0 ||
- adev->mman.drv_vram_usage_size > vram_size)
- return 0;
+ resv = &adev->mman.resv_region[id];
+ if (!resv->bo)
+ return;
- return amdgpu_bo_create_kernel_at(adev,
- adev->mman.drv_vram_usage_start_offset,
- adev->mman.drv_vram_usage_size,
- &adev->mman.drv_vram_usage_reserved_bo,
- &adev->mman.drv_vram_usage_va);
+ amdgpu_bo_free_kernel(&resv->bo, NULL,
+ resv->needs_cpu_map ? &resv->cpu_ptr : NULL);
+ memset(resv, 0, sizeof(*resv));
+}
+
+/*
+ * Reserve all regions with non-zero size. Regions whose info is not
+ * yet available (e.g., fw extended region) may still be reserved
+ * during runtime.
+ */
+static int amdgpu_ttm_alloc_vram_resv_regions(struct amdgpu_device *adev)
+{
+ int i, r;
+
+ for (i = 0; i < AMDGPU_RESV_MAX; i++) {
+ r = amdgpu_ttm_mark_vram_reserved(adev, i);
+ if (r)
+ return r;
+ }
+
+ return 0;
}
/*
@@ -1770,25 +1843,23 @@ static int amdgpu_ttm_training_reserve_vram_fini(struct amdgpu_device *adev)
struct psp_memory_training_context *ctx = &adev->psp.mem_train_ctx;
ctx->init = PSP_MEM_TRAIN_NOT_SUPPORT;
- amdgpu_bo_free_kernel(&ctx->c2p_bo, NULL, NULL);
- ctx->c2p_bo = NULL;
+ amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_MEM_TRAIN);
return 0;
}
-static void amdgpu_ttm_training_data_block_init(struct amdgpu_device *adev,
- uint32_t reserve_size)
+static void amdgpu_ttm_training_data_block_init(struct amdgpu_device *adev)
{
struct psp_memory_training_context *ctx = &adev->psp.mem_train_ctx;
+ struct amdgpu_vram_resv *resv =
+ &adev->mman.resv_region[AMDGPU_RESV_MEM_TRAIN];
memset(ctx, 0, sizeof(*ctx));
- ctx->c2p_train_data_offset =
- ALIGN((adev->gmc.mc_vram_size - reserve_size - SZ_1M), SZ_1M);
+ ctx->c2p_train_data_offset = resv->offset;
ctx->p2c_train_data_offset =
(adev->gmc.mc_vram_size - GDDR6_MEM_TRAINING_OFFSET);
- ctx->train_data_size =
- GDDR6_MEM_TRAINING_DATA_SIZE_IN_BYTES;
+ ctx->train_data_size = resv->size;
DRM_DEBUG("train_data_size:%llx,p2c_train_data_offset:%llx,c2p_train_data_offset:%llx.\n",
ctx->train_data_size,
@@ -1796,78 +1867,6 @@ static void amdgpu_ttm_training_data_block_init(struct amdgpu_device *adev,
ctx->c2p_train_data_offset);
}
-/*
- * reserve TMR memory at the top of VRAM which holds
- * IP Discovery data and is protected by PSP.
- */
-static int amdgpu_ttm_reserve_tmr(struct amdgpu_device *adev)
-{
- struct psp_memory_training_context *ctx = &adev->psp.mem_train_ctx;
- bool mem_train_support = false;
- uint32_t reserve_size = 0;
- int ret;
-
- if (adev->bios && !amdgpu_sriov_vf(adev)) {
- if (amdgpu_atomfirmware_mem_training_supported(adev))
- mem_train_support = true;
- else
- DRM_DEBUG("memory training does not support!\n");
- }
-
- /*
- * Query reserved tmr size through atom firmwareinfo for Sienna_Cichlid and onwards for all
- * the use cases (IP discovery/G6 memory training/profiling/diagnostic data.etc)
- *
- * Otherwise, fallback to legacy approach to check and reserve tmr block for ip
- * discovery data and G6 memory training data respectively
- */
- if (adev->bios)
- reserve_size =
- amdgpu_atomfirmware_get_fw_reserved_fb_size(adev);
-
- if (!adev->bios &&
- (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) ||
- amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4) ||
- amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 5, 0)))
- reserve_size = max(reserve_size, (uint32_t)280 << 20);
- else if (!adev->bios &&
- amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 1, 0)) {
- if (hweight32(adev->aid_mask) == 1)
- reserve_size = max(reserve_size, (uint32_t)128 << 20);
- else
- reserve_size = max(reserve_size, (uint32_t)144 << 20);
- } else if (!reserve_size)
- reserve_size = DISCOVERY_TMR_OFFSET;
-
- if (mem_train_support) {
- /* reserve vram for mem train according to TMR location */
- amdgpu_ttm_training_data_block_init(adev, reserve_size);
- ret = amdgpu_bo_create_kernel_at(adev,
- ctx->c2p_train_data_offset,
- ctx->train_data_size,
- &ctx->c2p_bo,
- NULL);
- if (ret) {
- dev_err(adev->dev, "alloc c2p_bo failed(%d)!\n", ret);
- amdgpu_ttm_training_reserve_vram_fini(adev);
- return ret;
- }
- ctx->init = PSP_MEM_TRAIN_RESERVE_SUCCESS;
- }
-
- ret = amdgpu_bo_create_kernel_at(
- adev, adev->gmc.real_vram_size - reserve_size, reserve_size,
- &adev->mman.fw_reserved_memory, NULL);
- if (ret) {
- dev_err(adev->dev, "alloc tmr failed(%d)!\n", ret);
- amdgpu_bo_free_kernel(&adev->mman.fw_reserved_memory, NULL,
- NULL);
- return ret;
- }
-
- return 0;
-}
-
static int amdgpu_ttm_pools_init(struct amdgpu_device *adev)
{
int i;
@@ -2115,63 +2114,18 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
adev->gmc.visible_vram_size);
#endif
- /*
- *The reserved vram for firmware must be pinned to the specified
- *place on the VRAM, so reserve it early.
- */
- r = amdgpu_ttm_fw_reserve_vram_init(adev);
- if (r)
- return r;
+ amdgpu_ttm_init_vram_resv_regions(adev);
- /*
- * The reserved VRAM for the driver must be pinned to a specific
- * location in VRAM, so reserve it early.
- */
- r = amdgpu_ttm_drv_reserve_vram_init(adev);
+ r = amdgpu_ttm_alloc_vram_resv_regions(adev);
if (r)
return r;
- /*
- * only NAVI10 and later ASICs support IP discovery.
- * If IP discovery is enabled, a block of memory should be
- * reserved for it.
- */
- if (adev->discovery.reserve_tmr) {
- r = amdgpu_ttm_reserve_tmr(adev);
- if (r)
- return r;
- }
+ if (adev->mman.resv_region[AMDGPU_RESV_MEM_TRAIN].size) {
+ struct psp_memory_training_context *ctx =
+ &adev->psp.mem_train_ctx;
- /* allocate memory as required for VGA
- * This is used for VGA emulation and pre-OS scanout buffers to
- * avoid display artifacts while transitioning between pre-OS
- * and driver.
- */
- if (!adev->gmc.is_app_apu) {
- r = amdgpu_bo_create_kernel_at(adev, 0,
- adev->mman.stolen_vga_size,
- &adev->mman.stolen_vga_memory,
- NULL);
- if (r)
- return r;
-
- r = amdgpu_bo_create_kernel_at(adev, adev->mman.stolen_vga_size,
- adev->mman.stolen_extended_size,
- &adev->mman.stolen_extended_memory,
- NULL);
-
- if (r)
- return r;
-
- r = amdgpu_bo_create_kernel_at(adev,
- adev->mman.stolen_reserved_offset,
- adev->mman.stolen_reserved_size,
- &adev->mman.stolen_reserved_memory,
- NULL);
- if (r)
- return r;
- } else {
- DRM_DEBUG_DRIVER("Skipped stolen memory reservation\n");
+ amdgpu_ttm_training_data_block_init(adev);
+ ctx->init = PSP_MEM_TRAIN_RESERVE_SUCCESS;
}
dev_info(adev->dev, " %uM of VRAM memory ready\n",
@@ -2284,23 +2238,19 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
amdgpu_ttm_training_reserve_vram_fini(adev);
/* return the stolen vga memory back to VRAM */
if (!adev->gmc.is_app_apu) {
- amdgpu_bo_free_kernel(&adev->mman.stolen_vga_memory, NULL, NULL);
- amdgpu_bo_free_kernel(&adev->mman.stolen_extended_memory, NULL, NULL);
+ amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_STOLEN_VGA);
+ amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_STOLEN_EXTENDED);
/* return the FW reserved memory back to VRAM */
- amdgpu_bo_free_kernel(&adev->mman.fw_reserved_memory, NULL,
- NULL);
- amdgpu_bo_free_kernel(&adev->mman.fw_reserved_memory_extend, NULL,
- NULL);
- if (adev->mman.stolen_reserved_size)
- amdgpu_bo_free_kernel(&adev->mman.stolen_reserved_memory,
- NULL, NULL);
+ amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_FW);
+ amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_FW_EXTEND);
+ amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_STOLEN_RESERVED);
}
amdgpu_bo_free_kernel(&adev->mman.sdma_access_bo, NULL,
&adev->mman.sdma_access_ptr);
amdgpu_ttm_free_mmio_remap_bo(adev);
- amdgpu_ttm_fw_reserve_vram_fini(adev);
- amdgpu_ttm_drv_reserve_vram_fini(adev);
+ amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_FW_VRAM_USAGE);
+ amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_DRV_VRAM_USAGE);
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
index 3b1973611446..f2f23a42b3cc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
@@ -59,6 +59,26 @@ struct amdgpu_ttm_buffer_entity {
u64 gart_window_offs[2];
};
+enum amdgpu_resv_region_id {
+ AMDGPU_RESV_STOLEN_VGA,
+ AMDGPU_RESV_STOLEN_EXTENDED,
+ AMDGPU_RESV_STOLEN_RESERVED,
+ AMDGPU_RESV_FW,
+ AMDGPU_RESV_FW_EXTEND,
+ AMDGPU_RESV_FW_VRAM_USAGE,
+ AMDGPU_RESV_DRV_VRAM_USAGE,
+ AMDGPU_RESV_MEM_TRAIN,
+ AMDGPU_RESV_MAX
+};
+
+struct amdgpu_vram_resv {
+ uint64_t offset;
+ uint64_t size;
+ struct amdgpu_bo *bo;
+ void *cpu_ptr;
+ bool needs_cpu_map;
+};
+
struct amdgpu_mman {
struct ttm_device bdev;
struct ttm_pool *ttm_pools;
@@ -83,31 +103,9 @@ struct amdgpu_mman {
struct amdgpu_gtt_mgr gtt_mgr;
struct ttm_resource_manager preempt_mgr;
- uint64_t stolen_vga_size;
- struct amdgpu_bo *stolen_vga_memory;
- uint64_t stolen_extended_size;
- struct amdgpu_bo *stolen_extended_memory;
bool keep_stolen_vga_memory;
- struct amdgpu_bo *stolen_reserved_memory;
- uint64_t stolen_reserved_offset;
- uint64_t stolen_reserved_size;
-
- /* fw reserved memory */
- struct amdgpu_bo *fw_reserved_memory;
- struct amdgpu_bo *fw_reserved_memory_extend;
-
- /* firmware VRAM reservation */
- u64 fw_vram_usage_start_offset;
- u64 fw_vram_usage_size;
- struct amdgpu_bo *fw_vram_usage_reserved_bo;
- void *fw_vram_usage_va;
-
- /* driver VRAM reservation */
- u64 drv_vram_usage_start_offset;
- u64 drv_vram_usage_size;
- struct amdgpu_bo *drv_vram_usage_reserved_bo;
- void *drv_vram_usage_va;
+ struct amdgpu_vram_resv resv_region[AMDGPU_RESV_MAX];
/* PAGE_SIZE'd BO for process memory r/w over SDMA. */
struct amdgpu_bo *sdma_access_bo;
@@ -175,6 +173,15 @@ void amdgpu_vram_mgr_clear_reset_blocks(struct amdgpu_device *adev);
bool amdgpu_res_cpu_visible(struct amdgpu_device *adev,
struct ttm_resource *res);
+void amdgpu_ttm_init_vram_resv(struct amdgpu_device *adev,
+ enum amdgpu_resv_region_id id,
+ uint64_t offset, uint64_t size,
+ bool needs_cpu_map);
+int amdgpu_ttm_mark_vram_reserved(struct amdgpu_device *adev,
+ enum amdgpu_resv_region_id id);
+void amdgpu_ttm_unmark_vram_reserved(struct amdgpu_device *adev,
+ enum amdgpu_resv_region_id id);
+
int amdgpu_ttm_init(struct amdgpu_device *adev);
void amdgpu_ttm_fini(struct amdgpu_device *adev);
void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
index 366728ed03e3..bfca5b040a32 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -427,23 +427,14 @@ static int amdgpu_userq_map_helper(struct amdgpu_usermode_queue *queue)
return r;
}
-static int amdgpu_userq_wait_for_last_fence(struct amdgpu_usermode_queue *queue)
+static void amdgpu_userq_wait_for_last_fence(struct amdgpu_usermode_queue *queue)
{
- struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr;
struct dma_fence *f = queue->last_fence;
- int ret = 0;
- if (f && !dma_fence_is_signaled(f)) {
- ret = dma_fence_wait_timeout(f, true, MAX_SCHEDULE_TIMEOUT);
- if (ret <= 0) {
- drm_file_err(uq_mgr->file, "Timed out waiting for fence=%llu:%llu\n",
- f->context, f->seqno);
- queue->state = AMDGPU_USERQ_STATE_HUNG;
- return -ETIME;
- }
- }
+ if (!f)
+ return;
- return ret;
+ dma_fence_wait(f, false);
}
static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue)
@@ -458,9 +449,10 @@ static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue)
/* Drop the userq reference. */
amdgpu_userq_buffer_vas_list_cleanup(adev, queue);
uq_funcs->mqd_destroy(queue);
- amdgpu_userq_fence_driver_free(queue);
/* 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;
queue->userq_mgr = NULL;
list_del(&queue->userq_va_list);
kfree(queue);
@@ -799,7 +791,7 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
queue->doorbell_index = index;
xa_init_flags(&queue->fence_drv_xa, XA_FLAGS_ALLOC);
- r = amdgpu_userq_fence_driver_alloc(adev, queue);
+ r = amdgpu_userq_fence_driver_alloc(adev, &queue->fence_drv);
if (r) {
drm_file_err(uq_mgr->file, "Failed to alloc fence driver\n");
goto free_queue;
@@ -1023,7 +1015,8 @@ amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr)
mutex_unlock(&uq_mgr->userq_mutex);
if (ret)
- drm_file_err(uq_mgr->file, "Failed to map all the queues\n");
+ drm_file_err(uq_mgr->file,
+ "Failed to map all the queues, restore failed ret=%d\n", ret);
return ret;
}
@@ -1230,13 +1223,11 @@ static void amdgpu_userq_restore_worker(struct work_struct *work)
ret = amdgpu_userq_vm_validate(uq_mgr);
if (ret) {
- drm_file_err(uq_mgr->file, "Failed to validate BOs to restore\n");
+ drm_file_err(uq_mgr->file, "Failed to validate BOs to restore ret=%d\n", ret);
goto put_fence;
}
- ret = amdgpu_userq_restore_all(uq_mgr);
- if (ret)
- drm_file_err(uq_mgr->file, "Failed to restore all queues\n");
+ amdgpu_userq_restore_all(uq_mgr);
put_fence:
dma_fence_put(ev_fence);
@@ -1258,7 +1249,8 @@ amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr)
}
if (ret)
- drm_file_err(uq_mgr->file, "Couldn't unmap all the queues\n");
+ drm_file_err(uq_mgr->file,
+ "Couldn't unmap all the queues, eviction failed ret=%d\n", ret);
return ret;
}
@@ -1279,46 +1271,28 @@ void amdgpu_userq_reset_work(struct work_struct *work)
amdgpu_device_gpu_recover(adev, NULL, &reset_context);
}
-static int
+static void
amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr *uq_mgr)
{
struct amdgpu_usermode_queue *queue;
unsigned long queue_id;
- int ret;
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
struct dma_fence *f = queue->last_fence;
- if (!f || dma_fence_is_signaled(f))
+ if (!f)
continue;
- ret = dma_fence_wait_timeout(f, true, msecs_to_jiffies(100));
- if (ret <= 0) {
- drm_file_err(uq_mgr->file, "Timed out waiting for fence=%llu:%llu\n",
- f->context, f->seqno);
-
- return -ETIMEDOUT;
- }
+ dma_fence_wait(f, false);
}
-
- return 0;
}
void
amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr)
{
- struct amdgpu_device *adev = uq_mgr->adev;
- int ret;
-
/* Wait for any pending userqueue fence work to finish */
- ret = amdgpu_userq_wait_for_signal(uq_mgr);
- if (ret)
- dev_err(adev->dev, "Not evicting userqueue, timeout waiting for work\n");
-
- ret = amdgpu_userq_evict_all(uq_mgr);
- if (ret)
- dev_err(adev->dev, "Failed to evict userqueue\n");
-
+ amdgpu_userq_wait_for_signal(uq_mgr);
+ amdgpu_userq_evict_all(uq_mgr);
}
int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct drm_file *file_priv,
@@ -1480,17 +1454,16 @@ int amdgpu_userq_start_sched_for_enforce_isolation(struct amdgpu_device *adev,
return ret;
}
-int amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev,
- struct amdgpu_bo_va_mapping *mapping,
- uint64_t saddr)
+void amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev,
+ struct amdgpu_bo_va_mapping *mapping,
+ uint64_t saddr)
{
u32 ip_mask = amdgpu_userq_get_supported_ip_mask(adev);
struct amdgpu_bo_va *bo_va = mapping->bo_va;
struct dma_resv *resv = bo_va->base.bo->tbo.base.resv;
- int ret = 0;
if (!ip_mask)
- return 0;
+ return;
dev_warn_once(adev->dev, "now unmapping a vital queue va:%llx\n", saddr);
/**
@@ -1501,14 +1474,8 @@ int amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev,
* unmap is only for one kind of userq VAs, so at this point suppose
* the eviction fence is always unsignaled.
*/
- if (!dma_resv_test_signaled(resv, DMA_RESV_USAGE_BOOKKEEP)) {
- ret = dma_resv_wait_timeout(resv, DMA_RESV_USAGE_BOOKKEEP, true,
- MAX_SCHEDULE_TIMEOUT);
- if (ret <= 0)
- return -EBUSY;
- }
-
- return 0;
+ dma_resv_wait_timeout(resv, DMA_RESV_USAGE_BOOKKEEP,
+ false, MAX_SCHEDULE_TIMEOUT);
}
void amdgpu_userq_pre_reset(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
index a4d44abf24fa..675fe6395ac8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
@@ -160,7 +160,7 @@ void amdgpu_userq_start_hang_detect_work(struct amdgpu_usermode_queue *queue);
int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
struct amdgpu_usermode_queue *queue,
u64 addr, u64 expected_size);
-int amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev,
- struct amdgpu_bo_va_mapping *mapping,
- uint64_t saddr);
+void amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev,
+ struct amdgpu_bo_va_mapping *mapping,
+ uint64_t saddr);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
index fe6d83e859a0..5784f2b3ecae 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
@@ -78,12 +78,15 @@ amdgpu_userq_fence_write(struct amdgpu_userq_fence_driver *fence_drv,
}
int amdgpu_userq_fence_driver_alloc(struct amdgpu_device *adev,
- struct amdgpu_usermode_queue *userq)
+ struct amdgpu_userq_fence_driver **fence_drv_req)
{
struct amdgpu_userq_fence_driver *fence_drv;
- unsigned long flags;
int r;
+ if (!fence_drv_req)
+ return -EINVAL;
+ *fence_drv_req = NULL;
+
fence_drv = kzalloc_obj(*fence_drv);
if (!fence_drv)
return -ENOMEM;
@@ -104,19 +107,10 @@ int amdgpu_userq_fence_driver_alloc(struct amdgpu_device *adev,
fence_drv->context = dma_fence_context_alloc(1);
get_task_comm(fence_drv->timeline_name, current);
- xa_lock_irqsave(&adev->userq_xa, flags);
- r = xa_err(__xa_store(&adev->userq_xa, userq->doorbell_index,
- fence_drv, GFP_KERNEL));
- xa_unlock_irqrestore(&adev->userq_xa, flags);
- if (r)
- goto free_seq64;
-
- userq->fence_drv = fence_drv;
+ *fence_drv_req = fence_drv;
return 0;
-free_seq64:
- amdgpu_seq64_free(adev, fence_drv->va);
free_fence_drv:
kfree(fence_drv);
@@ -144,10 +138,10 @@ void
amdgpu_userq_fence_driver_free(struct amdgpu_usermode_queue *userq)
{
dma_fence_put(userq->last_fence);
-
+ userq->last_fence = NULL;
amdgpu_userq_walk_and_drop_fence_drv(&userq->fence_drv_xa);
xa_destroy(&userq->fence_drv_xa);
- /* Drop the fence_drv reference held by user queue */
+ /* Drop the queue's ownership reference to fence_drv explicitly */
amdgpu_userq_fence_driver_put(userq->fence_drv);
}
@@ -187,11 +181,9 @@ void amdgpu_userq_fence_driver_destroy(struct kref *ref)
struct amdgpu_userq_fence_driver *fence_drv = container_of(ref,
struct amdgpu_userq_fence_driver,
refcount);
- struct amdgpu_userq_fence_driver *xa_fence_drv;
struct amdgpu_device *adev = fence_drv->adev;
struct amdgpu_userq_fence *fence, *tmp;
- struct xarray *xa = &adev->userq_xa;
- unsigned long index, flags;
+ unsigned long flags;
struct dma_fence *f;
spin_lock_irqsave(&fence_drv->fence_list_lock, flags);
@@ -208,12 +200,6 @@ void amdgpu_userq_fence_driver_destroy(struct kref *ref)
}
spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags);
- xa_lock_irqsave(xa, flags);
- xa_for_each(xa, index, xa_fence_drv)
- if (xa_fence_drv == fence_drv)
- __xa_erase(xa, index);
- xa_unlock_irqrestore(xa, flags);
-
/* Free seq64 memory */
amdgpu_seq64_free(adev, fence_drv->va);
kfree(fence_drv);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.h
index d76add2afc77..d56246ad8c26 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.h
@@ -64,7 +64,7 @@ void amdgpu_userq_fence_slab_fini(void);
void amdgpu_userq_fence_driver_get(struct amdgpu_userq_fence_driver *fence_drv);
void amdgpu_userq_fence_driver_put(struct amdgpu_userq_fence_driver *fence_drv);
int amdgpu_userq_fence_driver_alloc(struct amdgpu_device *adev,
- struct amdgpu_usermode_queue *userq);
+ struct amdgpu_userq_fence_driver **fence_drv_req);
void amdgpu_userq_fence_driver_free(struct amdgpu_usermode_queue *userq);
void amdgpu_userq_fence_driver_process(struct amdgpu_userq_fence_driver *fence_drv);
void amdgpu_userq_fence_driver_force_completion(struct amdgpu_usermode_queue *userq);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index eb4a15db2ef2..efdebd9c0a1f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -680,6 +680,9 @@ static int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, struct amdgpu_ib *ib,
uint64_t addr;
int r;
+ if (lo >= ib->length_dw || hi >= ib->length_dw)
+ return -EINVAL;
+
if (index == 0xffffffff)
index = 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
index dba7ea16a10d..e8d180a412d1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
@@ -437,12 +437,9 @@ static void amdgpu_virt_add_bad_page(struct amdgpu_device *adev,
struct eeprom_table_record bp;
uint64_t retired_page;
uint32_t bp_idx, bp_cnt;
- void *vram_usage_va = NULL;
-
- if (adev->mman.fw_vram_usage_va)
- vram_usage_va = adev->mman.fw_vram_usage_va;
- else
- vram_usage_va = adev->mman.drv_vram_usage_va;
+ void *fw_va = adev->mman.resv_region[AMDGPU_RESV_FW_VRAM_USAGE].cpu_ptr;
+ void *drv_va = adev->mman.resv_region[AMDGPU_RESV_DRV_VRAM_USAGE].cpu_ptr;
+ void *vram_usage_va = fw_va ? fw_va : drv_va;
memset(&bp, 0, sizeof(bp));
@@ -710,15 +707,17 @@ void amdgpu_virt_fini_data_exchange(struct amdgpu_device *adev)
void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev)
{
uint32_t *pfvf_data = NULL;
+ void *fw_va = adev->mman.resv_region[AMDGPU_RESV_FW_VRAM_USAGE].cpu_ptr;
+ void *drv_va = adev->mman.resv_region[AMDGPU_RESV_DRV_VRAM_USAGE].cpu_ptr;
adev->virt.fw_reserve.p_pf2vf = NULL;
adev->virt.fw_reserve.p_vf2pf = NULL;
adev->virt.vf2pf_update_interval_ms = 0;
adev->virt.vf2pf_update_retry_cnt = 0;
- if (adev->mman.fw_vram_usage_va && adev->mman.drv_vram_usage_va) {
+ if (fw_va && drv_va) {
dev_warn(adev->dev, "Currently fw_vram and drv_vram should not have values at the same time!");
- } else if (adev->mman.fw_vram_usage_va || adev->mman.drv_vram_usage_va) {
+ } else if (fw_va || drv_va) {
/* go through this logic in ip_init and reset to init workqueue*/
amdgpu_virt_exchange_data(adev);
@@ -763,41 +762,43 @@ void amdgpu_virt_exchange_data(struct amdgpu_device *adev)
uint64_t bp_block_offset = 0;
uint32_t bp_block_size = 0;
struct amd_sriov_msg_pf2vf_info *pf2vf_v2 = NULL;
+ void *fw_va = adev->mman.resv_region[AMDGPU_RESV_FW_VRAM_USAGE].cpu_ptr;
+ void *drv_va = adev->mman.resv_region[AMDGPU_RESV_DRV_VRAM_USAGE].cpu_ptr;
- if (adev->mman.fw_vram_usage_va || adev->mman.drv_vram_usage_va) {
- if (adev->mman.fw_vram_usage_va) {
+ if (fw_va || drv_va) {
+ if (fw_va) {
if (adev->virt.req_init_data_ver == GPU_CRIT_REGION_V2) {
adev->virt.fw_reserve.p_pf2vf =
(struct amd_sriov_msg_pf2vf_info_header *)
- (adev->mman.fw_vram_usage_va +
+ (fw_va +
adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_DATAEXCHANGE_TABLE_ID].offset);
adev->virt.fw_reserve.p_vf2pf =
(struct amd_sriov_msg_vf2pf_info_header *)
- (adev->mman.fw_vram_usage_va +
+ (fw_va +
adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_DATAEXCHANGE_TABLE_ID].offset +
(AMD_SRIOV_MSG_SIZE_KB << 10));
adev->virt.fw_reserve.ras_telemetry =
- (adev->mman.fw_vram_usage_va +
+ (fw_va +
adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_RAS_TELEMETRY_TABLE_ID].offset);
} else {
adev->virt.fw_reserve.p_pf2vf =
(struct amd_sriov_msg_pf2vf_info_header *)
- (adev->mman.fw_vram_usage_va + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB_V1 << 10));
+ (fw_va + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB_V1 << 10));
adev->virt.fw_reserve.p_vf2pf =
(struct amd_sriov_msg_vf2pf_info_header *)
- (adev->mman.fw_vram_usage_va + (AMD_SRIOV_MSG_VF2PF_OFFSET_KB_V1 << 10));
+ (fw_va + (AMD_SRIOV_MSG_VF2PF_OFFSET_KB_V1 << 10));
adev->virt.fw_reserve.ras_telemetry =
- (adev->mman.fw_vram_usage_va + (AMD_SRIOV_MSG_RAS_TELEMETRY_OFFSET_KB_V1 << 10));
+ (fw_va + (AMD_SRIOV_MSG_RAS_TELEMETRY_OFFSET_KB_V1 << 10));
}
- } else if (adev->mman.drv_vram_usage_va) {
+ } else if (drv_va) {
adev->virt.fw_reserve.p_pf2vf =
(struct amd_sriov_msg_pf2vf_info_header *)
- (adev->mman.drv_vram_usage_va + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB_V1 << 10));
+ (drv_va + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB_V1 << 10));
adev->virt.fw_reserve.p_vf2pf =
(struct amd_sriov_msg_vf2pf_info_header *)
- (adev->mman.drv_vram_usage_va + (AMD_SRIOV_MSG_VF2PF_OFFSET_KB_V1 << 10));
+ (drv_va + (AMD_SRIOV_MSG_VF2PF_OFFSET_KB_V1 << 10));
adev->virt.fw_reserve.ras_telemetry =
- (adev->mman.drv_vram_usage_va + (AMD_SRIOV_MSG_RAS_TELEMETRY_OFFSET_KB_V1 << 10));
+ (drv_va + (AMD_SRIOV_MSG_RAS_TELEMETRY_OFFSET_KB_V1 << 10));
}
amdgpu_virt_read_pf2vf_data(adev);
@@ -1081,13 +1082,14 @@ int amdgpu_virt_init_critical_region(struct amdgpu_device *adev)
}
/* reserved memory starts from crit region base offset with the size of 5MB */
- adev->mman.fw_vram_usage_start_offset = adev->virt.crit_regn.offset;
- adev->mman.fw_vram_usage_size = adev->virt.crit_regn.size_kb << 10;
+ amdgpu_ttm_init_vram_resv(adev, AMDGPU_RESV_FW_VRAM_USAGE,
+ adev->virt.crit_regn.offset,
+ adev->virt.crit_regn.size_kb << 10, true);
dev_info(adev->dev,
"critical region v%d requested to reserve memory start at %08llx with %llu KB.\n",
init_data_hdr->version,
- adev->mman.fw_vram_usage_start_offset,
- adev->mman.fw_vram_usage_size >> 10);
+ adev->mman.resv_region[AMDGPU_RESV_FW_VRAM_USAGE].offset,
+ adev->mman.resv_region[AMDGPU_RESV_FW_VRAM_USAGE].size >> 10);
adev->virt.is_dynamic_crit_regn_enabled = true;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 73abac6be5b3..115a7b269af3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -1978,7 +1978,6 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
struct amdgpu_bo_va_mapping *mapping;
struct amdgpu_vm *vm = bo_va->base.vm;
bool valid = true;
- int r;
saddr /= AMDGPU_GPU_PAGE_SIZE;
@@ -2003,12 +2002,8 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
* during user requests GEM unmap IOCTL except for forcing the unmap
* from user space.
*/
- if (unlikely(atomic_read(&bo_va->userq_va_mapped) > 0)) {
- r = amdgpu_userq_gem_va_unmap_validate(adev, mapping, saddr);
- if (unlikely(r == -EBUSY))
- dev_warn_once(adev->dev,
- "Attempt to unmap an active userq buffer\n");
- }
+ if (unlikely(atomic_read(&bo_va->userq_va_mapped) > 0))
+ amdgpu_userq_gem_va_unmap_validate(adev, mapping, saddr);
list_del(&mapping->list);
amdgpu_vm_it_remove(mapping, &vm->va);
@@ -2955,6 +2950,50 @@ int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
}
/**
+ * amdgpu_vm_lock_by_pasid - return an amdgpu_vm and its root bo from a pasid, if possible.
+ * @adev: amdgpu device pointer
+ * @root: root BO of the VM
+ * @pasid: PASID of the VM
+ * The caller needs to unreserve and unref the root bo on success.
+ */
+struct amdgpu_vm *amdgpu_vm_lock_by_pasid(struct amdgpu_device *adev,
+ struct amdgpu_bo **root, u32 pasid)
+{
+ unsigned long irqflags;
+ struct amdgpu_vm *vm;
+ int r;
+
+ xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
+ vm = xa_load(&adev->vm_manager.pasids, pasid);
+ *root = vm ? amdgpu_bo_ref(vm->root.bo) : NULL;
+ xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
+
+ if (!*root)
+ return NULL;
+
+ r = amdgpu_bo_reserve(*root, true);
+ if (r)
+ goto error_unref;
+
+ /* Double check that the VM still exists */
+ xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
+ vm = xa_load(&adev->vm_manager.pasids, pasid);
+ if (vm && vm->root.bo != *root)
+ vm = NULL;
+ xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
+ if (!vm)
+ goto error_unlock;
+
+ return vm;
+error_unlock:
+ amdgpu_bo_unreserve(*root);
+
+error_unref:
+ amdgpu_bo_unref(root);
+ return NULL;
+}
+
+/**
* amdgpu_vm_handle_fault - graceful handling of VM faults.
* @adev: amdgpu device pointer
* @pasid: PASID of the VM
@@ -2969,50 +3008,29 @@ int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
* shouldn't be reported any more.
*/
bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
- u32 vmid, u32 node_id, uint64_t addr, uint64_t ts,
- bool write_fault)
+ u32 vmid, u32 node_id, uint64_t addr,
+ uint64_t ts, bool write_fault)
{
bool is_compute_context = false;
struct amdgpu_bo *root;
- unsigned long irqflags;
uint64_t value, flags;
struct amdgpu_vm *vm;
int r;
- xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
- vm = xa_load(&adev->vm_manager.pasids, pasid);
- if (vm) {
- root = amdgpu_bo_ref(vm->root.bo);
- is_compute_context = vm->is_compute_context;
- } else {
- root = NULL;
- }
- xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
-
- if (!root)
+ vm = amdgpu_vm_lock_by_pasid(adev, &root, pasid);
+ if (!vm)
return false;
+ is_compute_context = vm->is_compute_context;
+
if (is_compute_context && !svm_range_restore_pages(adev, pasid, vmid,
node_id, addr >> PAGE_SHIFT, ts, write_fault)) {
+ amdgpu_bo_unreserve(root);
amdgpu_bo_unref(&root);
return true;
}
addr /= AMDGPU_GPU_PAGE_SIZE;
-
- r = amdgpu_bo_reserve(root, true);
- if (r)
- goto error_unref;
-
- /* Double check that the VM still exists */
- xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
- vm = xa_load(&adev->vm_manager.pasids, pasid);
- if (vm && vm->root.bo != root)
- vm = NULL;
- xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
- if (!vm)
- goto error_unlock;
-
flags = AMDGPU_PTE_VALID | AMDGPU_PTE_SNOOPED |
AMDGPU_PTE_SYSTEM;
@@ -3051,7 +3069,6 @@ error_unlock:
if (r < 0)
dev_err(adev->dev, "Can't handle page fault (%d)\n", r);
-error_unref:
amdgpu_bo_unref(&root);
return false;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index 3b32f41c3655..d083d7aab75c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -592,6 +592,9 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
u32 vmid, u32 node_id, uint64_t addr, uint64_t ts,
bool write_fault);
+struct amdgpu_vm *amdgpu_vm_lock_by_pasid(struct amdgpu_device *adev,
+ struct amdgpu_bo **root, u32 pasid);
+
void amdgpu_vm_set_task_info(struct amdgpu_vm *vm);
void amdgpu_vm_move_to_lru_tail(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
index cc5f4e01e38f..42be8ee155dd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
@@ -181,6 +181,7 @@ int amdgpu_xcp_init(struct amdgpu_xcp_mgr *xcp_mgr, int num_xcps, int mode)
}
xcp_mgr->num_xcps = num_xcps;
+ xcp_mgr->mem_alloc_mode = AMDGPU_PARTITION_MEM_CAPPING_EVEN;
amdgpu_xcp_update_partition_sched_list(adev);
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
index 8058e8f35d41..878c1c422893 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
@@ -132,6 +132,8 @@ struct amdgpu_xcp_mgr {
struct amdgpu_xcp_cfg *xcp_cfg;
uint32_t supp_xcp_modes;
uint32_t avail_xcp_modes;
+ /* used to determin KFD memory alloc mode for each partition */
+ uint32_t mem_alloc_mode;
};
struct amdgpu_xcp_mgr_funcs {
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index ae39b9e1f7d6..5097de940a19 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -6502,14 +6502,14 @@ static int gfx_v11_0_eop_irq(struct amdgpu_device *adev,
DRM_DEBUG("IH: CP EOP\n");
if (adev->enable_mes && doorbell_offset) {
- struct amdgpu_userq_fence_driver *fence_drv = NULL;
- struct xarray *xa = &adev->userq_xa;
+ struct amdgpu_usermode_queue *queue;
+ struct xarray *xa = &adev->userq_doorbell_xa;
unsigned long flags;
xa_lock_irqsave(xa, flags);
- fence_drv = xa_load(xa, doorbell_offset);
- if (fence_drv)
- amdgpu_userq_fence_driver_process(fence_drv);
+ queue = xa_load(xa, doorbell_offset);
+ if (queue)
+ amdgpu_userq_fence_driver_process(queue->fence_drv);
xa_unlock_irqrestore(xa, flags);
} else {
me_id = (entry->ring_id & 0x0c) >> 2;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
index a418ae609c36..65c33823a688 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
@@ -4854,14 +4854,14 @@ static int gfx_v12_0_eop_irq(struct amdgpu_device *adev,
DRM_DEBUG("IH: CP EOP\n");
if (adev->enable_mes && doorbell_offset) {
- struct amdgpu_userq_fence_driver *fence_drv = NULL;
- struct xarray *xa = &adev->userq_xa;
+ struct xarray *xa = &adev->userq_doorbell_xa;
+ struct amdgpu_usermode_queue *queue;
unsigned long flags;
xa_lock_irqsave(xa, flags);
- fence_drv = xa_load(xa, doorbell_offset);
- if (fence_drv)
- amdgpu_userq_fence_driver_process(fence_drv);
+ queue = xa_load(xa, doorbell_offset);
+ if (queue)
+ amdgpu_userq_fence_driver_process(queue->fence_drv);
xa_unlock_irqrestore(xa, flags);
} else {
me_id = (entry->ring_id & 0x0c) >> 2;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c
index db49582a211f..68fd3c04134d 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c
@@ -3643,14 +3643,15 @@ static int gfx_v12_1_eop_irq(struct amdgpu_device *adev,
DRM_DEBUG("IH: CP EOP\n");
if (adev->enable_mes && doorbell_offset) {
- struct amdgpu_userq_fence_driver *fence_drv = NULL;
- struct xarray *xa = &adev->userq_xa;
+ struct xarray *xa = &adev->userq_doorbell_xa;
+ struct amdgpu_usermode_queue *queue;
unsigned long flags;
xa_lock_irqsave(xa, flags);
- fence_drv = xa_load(xa, doorbell_offset);
- if (fence_drv)
- amdgpu_userq_fence_driver_process(fence_drv);
+ queue = xa_load(xa, doorbell_offset);
+ if (queue)
+ amdgpu_userq_fence_driver_process(queue->fence_drv);
+
xa_unlock_irqrestore(xa, flags);
} else {
me_id = (entry->ring_id & 0x0c) >> 2;
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
index fd691b2a6e21..e1ace7d44ffd 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
@@ -860,8 +860,6 @@ static int gmc_v10_0_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
- amdgpu_gmc_get_vbios_allocations(adev);
-
/* Memory manager */
r = amdgpu_bo_init(adev);
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 e6db87b94eb1..94d6631ce0bc 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
@@ -834,8 +834,6 @@ static int gmc_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
- amdgpu_gmc_get_vbios_allocations(adev);
-
/* Memory manager */
r = amdgpu_bo_init(adev);
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 6e184ea069ef..e10ac9788d13 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c
@@ -924,8 +924,6 @@ static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
- amdgpu_gmc_get_vbios_allocations(adev);
-
#ifdef HAVE_ACPI_DEV_GET_FIRST_MATCH_DEV
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 1, 0)) {
r = amdgpu_gmc_init_mem_ranges(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
index 886bf77309a5..cc272a96fcef 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
@@ -854,8 +854,6 @@ static int gmc_v6_0_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
- amdgpu_gmc_get_vbios_allocations(adev);
-
r = amdgpu_bo_init(adev);
if (r)
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
index d25fdedb0d9f..bb16ba2ef6fd 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
@@ -1034,8 +1034,6 @@ static int gmc_v7_0_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
- amdgpu_gmc_get_vbios_allocations(adev);
-
/* Memory manager */
r = amdgpu_bo_init(adev);
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 4910e5557a67..a59174f6bcc1 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
@@ -1149,8 +1149,6 @@ static int gmc_v8_0_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
- amdgpu_gmc_get_vbios_allocations(adev);
-
/* Memory manager */
r = amdgpu_bo_init(adev);
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 d865059e884a..e7b78027002b 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -2010,8 +2010,6 @@ static int gmc_v9_0_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
- amdgpu_gmc_get_vbios_allocations(adev);
-
if (amdgpu_is_multi_aid(adev)) {
r = amdgpu_gmc_init_mem_ranges(adev);
if (r)
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
index b005672f2f96..0f530bb8a9a3 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
@@ -1662,16 +1662,16 @@ static int sdma_v6_0_process_fence_irq(struct amdgpu_device *adev,
u32 doorbell_offset = entry->src_data[0];
if (adev->enable_mes && doorbell_offset) {
- struct amdgpu_userq_fence_driver *fence_drv = NULL;
- struct xarray *xa = &adev->userq_xa;
+ struct amdgpu_usermode_queue *queue;
+ struct xarray *xa = &adev->userq_doorbell_xa;
unsigned long flags;
doorbell_offset >>= SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT;
xa_lock_irqsave(xa, flags);
- fence_drv = xa_load(xa, doorbell_offset);
- if (fence_drv)
- amdgpu_userq_fence_driver_process(fence_drv);
+ queue = xa_load(xa, doorbell_offset);
+ if (queue)
+ amdgpu_userq_fence_driver_process(queue->fence_drv);
xa_unlock_irqrestore(xa, flags);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
index 5679a94d0815..9ed817b69a3b 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
@@ -1594,16 +1594,16 @@ static int sdma_v7_0_process_fence_irq(struct amdgpu_device *adev,
u32 doorbell_offset = entry->src_data[0];
if (adev->enable_mes && doorbell_offset) {
- struct amdgpu_userq_fence_driver *fence_drv = NULL;
- struct xarray *xa = &adev->userq_xa;
+ struct xarray *xa = &adev->userq_doorbell_xa;
+ struct amdgpu_usermode_queue *queue;
unsigned long flags;
doorbell_offset >>= SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT;
xa_lock_irqsave(xa, flags);
- fence_drv = xa_load(xa, doorbell_offset);
- if (fence_drv)
- amdgpu_userq_fence_driver_process(fence_drv);
+ queue = xa_load(xa, doorbell_offset);
+ if (queue)
+ amdgpu_userq_fence_driver_process(queue->fence_drv);
xa_unlock_irqrestore(xa, flags);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index 02d5c5af65f2..6fb4fcdbba4f 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -1909,7 +1909,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
struct ttm_operation_ctx ctx = { false, false };
struct amdgpu_device *adev = p->adev;
struct amdgpu_bo_va_mapping *map;
- uint32_t *msg, num_buffers;
+ uint32_t *msg, num_buffers, len_dw;
struct amdgpu_bo *bo;
uint64_t start, end;
unsigned int i;
@@ -1930,6 +1930,11 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
return -EINVAL;
}
+ if (end - addr < 16) {
+ DRM_ERROR("VCN messages must be at least 4 DWORDs!\n");
+ return -EINVAL;
+ }
+
bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
amdgpu_bo_placement_from_domain(bo, bo->allowed_domains);
r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
@@ -1946,8 +1951,8 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
msg = ptr + addr - start;
- /* Check length */
if (msg[1] > end - addr) {
+ DRM_ERROR("VCN message header does not fit in BO!\n");
r = -EINVAL;
goto out;
}
@@ -1955,7 +1960,16 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
if (msg[3] != RDECODE_MSG_CREATE)
goto out;
+ 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");
+ r = -EINVAL;
+ goto out;
+ }
+
for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) {
uint32_t offset, size, *create;
@@ -1965,14 +1979,15 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
offset = msg[1];
size = msg[2];
- if (offset + size > end) {
+ if (size < 4 || offset + size > end - addr) {
+ DRM_ERROR("VCN message buffer exceeds BO bounds!\n");
r = -EINVAL;
goto out;
}
create = ptr + addr + offset - start;
- /* H246, HEVC and VP9 can run on any instance */
+ /* H264, HEVC and VP9 can run on any instance */
if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
continue;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index d17219be50f3..5dec92691f73 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -1826,7 +1826,7 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
struct ttm_operation_ctx ctx = { false, false };
struct amdgpu_device *adev = p->adev;
struct amdgpu_bo_va_mapping *map;
- uint32_t *msg, num_buffers;
+ uint32_t *msg, num_buffers, len_dw;
struct amdgpu_bo *bo;
uint64_t start, end;
unsigned int i;
@@ -1847,6 +1847,11 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
return -EINVAL;
}
+ if (end - addr < 16) {
+ DRM_ERROR("VCN messages must be at least 4 DWORDs!\n");
+ return -EINVAL;
+ }
+
bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
amdgpu_bo_placement_from_domain(bo, bo->allowed_domains);
r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
@@ -1863,8 +1868,8 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
msg = ptr + addr - start;
- /* Check length */
if (msg[1] > end - addr) {
+ DRM_ERROR("VCN message header does not fit in BO!\n");
r = -EINVAL;
goto out;
}
@@ -1872,7 +1877,16 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
if (msg[3] != RDECODE_MSG_CREATE)
goto out;
+ 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");
+ r = -EINVAL;
+ goto out;
+ }
+
for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) {
uint32_t offset, size, *create;
@@ -1882,7 +1896,8 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
offset = msg[1];
size = msg[2];
- if (offset + size > end) {
+ if (size < 4 || offset + size > end - addr) {
+ DRM_ERROR("VCN message buffer exceeds BO bounds!\n");
r = -EINVAL;
goto out;
}
@@ -1913,9 +1928,10 @@ out:
static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
{
int i;
+ uint32_t len;
- for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) {
- if (ib->ptr[i + 1] == id)
+ for (i = start; (len = amdgpu_ib_get_value(ib, i)) >= 8; i += len / 4) {
+ if (amdgpu_ib_get_value(ib, i + 1) == id)
return i;
}
return -1;
@@ -1926,8 +1942,6 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
struct amdgpu_ib *ib)
{
struct amdgpu_ring *ring = amdgpu_job_ring(job);
- struct amdgpu_vcn_decode_buffer *decode_buffer;
- uint64_t addr;
uint32_t val;
int idx = 0, sidx;
@@ -1938,20 +1952,22 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
- decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
+ uint32_t valid_buf_flag = amdgpu_ib_get_value(ib, idx + 6);
+ uint64_t msg_buffer_addr;
- if (!(decode_buffer->valid_buf_flag & 0x1))
+ if (!(valid_buf_flag & 0x1))
return 0;
- addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
- decode_buffer->msg_buffer_address_lo;
- return vcn_v4_0_dec_msg(p, job, addr);
+ msg_buffer_addr = ((u64)amdgpu_ib_get_value(ib, idx + 7)) << 32 |
+ amdgpu_ib_get_value(ib, idx + 8);
+ return vcn_v4_0_dec_msg(p, job, msg_buffer_addr);
} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
- if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1)
+ if (sidx >= 0 &&
+ amdgpu_ib_get_value(ib, sidx + 2) == RENCODE_ENCODE_STANDARD_AV1)
return vcn_v4_0_limit_sched(p, job);
}
- idx += ib->ptr[idx] / 4;
+ idx += amdgpu_ib_get_value(ib, idx) / 4;
}
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index bcd21204aa50..d28ca581cad0 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -689,7 +689,8 @@ void kfd_procfs_del_queue(struct queue *q)
int kfd_process_create_wq(void)
{
if (!kfd_process_wq)
- kfd_process_wq = alloc_workqueue("kfd_process_wq", 0, 0);
+ kfd_process_wq = alloc_workqueue("kfd_process_wq", WQ_UNBOUND,
+ 0);
if (!kfd_restore_wq)
kfd_restore_wq = alloc_ordered_workqueue("kfd_restore_wq",
WQ_FREEZABLE);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 21635e80349a..1d9ceb432ec3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -572,7 +572,7 @@ static void schedule_dc_vmin_vmax(struct amdgpu_device *adev,
offload_work->stream = stream;
offload_work->adjust = adjust_copy;
- queue_work(system_wq, &offload_work->work);
+ queue_work(system_percpu_wq, &offload_work->work);
}
static void dm_vupdate_high_irq(void *interrupt_params)
@@ -3833,6 +3833,66 @@ static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = {
.atomic_commit_setup = amdgpu_dm_atomic_setup_commit,
};
+#define DDC_MANUFACTURERNAME_SAMSUNG 0x2D4C
+
+static void dm_set_panel_type(struct amdgpu_dm_connector *aconnector)
+{
+ struct drm_connector *connector = &aconnector->base;
+ struct drm_display_info *display_info = &connector->display_info;
+ struct dc_link *link = aconnector->dc_link;
+ struct amdgpu_device *adev;
+
+ adev = drm_to_adev(connector->dev);
+
+ link->panel_type = PANEL_TYPE_NONE;
+
+ switch (display_info->amd_vsdb.panel_type) {
+ case AMD_VSDB_PANEL_TYPE_OLED:
+ link->panel_type = PANEL_TYPE_OLED;
+ break;
+ case AMD_VSDB_PANEL_TYPE_MINILED:
+ link->panel_type = PANEL_TYPE_MINILED;
+ break;
+ }
+
+ /* If VSDB didn't determine panel type, check DPCD ext caps */
+ if (link->panel_type == PANEL_TYPE_NONE) {
+ if (link->dpcd_sink_ext_caps.bits.miniled == 1)
+ link->panel_type = PANEL_TYPE_MINILED;
+ if (link->dpcd_sink_ext_caps.bits.oled == 1)
+ link->panel_type = PANEL_TYPE_OLED;
+ }
+
+ /*
+ * TODO: get panel type from DID2 that has device technology field
+ * to specify if it's OLED or not. But we need to wait for DID2
+ * support in DC and EDID parser to be able to use it here.
+ */
+
+ if (link->panel_type == PANEL_TYPE_NONE) {
+ struct drm_amd_vsdb_info *vsdb = &display_info->amd_vsdb;
+ u32 lum1_max = vsdb->luminance_range1.max_luminance;
+ u32 lum2_max = vsdb->luminance_range2.max_luminance;
+
+ if (vsdb->version && link->local_sink &&
+ link->local_sink->edid_caps.manufacturer_id ==
+ DDC_MANUFACTURERNAME_SAMSUNG &&
+ lum1_max >= ((lum2_max * 3) / 2))
+ link->panel_type = PANEL_TYPE_MINILED;
+ }
+
+ if (link->panel_type == PANEL_TYPE_OLED)
+ drm_object_property_set_value(&connector->base,
+ adev_to_drm(adev)->mode_config.panel_type_property,
+ DRM_MODE_PANEL_TYPE_OLED);
+ else
+ drm_object_property_set_value(&connector->base,
+ adev_to_drm(adev)->mode_config.panel_type_property,
+ DRM_MODE_PANEL_TYPE_UNKNOWN);
+
+ drm_dbg_kms(aconnector->base.dev, "Panel type: %d\n", link->panel_type);
+}
+
static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
{
const struct drm_panel_backlight_quirk *panel_backlight_quirk;
@@ -3854,10 +3914,6 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
caps->aux_support = false;
- drm_object_property_set_value(&conn_base->base,
- adev_to_drm(adev)->mode_config.panel_type_property,
- caps->ext_caps->bits.oled ? DRM_MODE_PANEL_TYPE_OLED : DRM_MODE_PANEL_TYPE_UNKNOWN);
-
if (caps->ext_caps->bits.oled == 1
/*
* ||
@@ -4031,6 +4087,7 @@ void amdgpu_dm_update_connector_after_detect(
amdgpu_dm_update_freesync_caps(connector, aconnector->drm_edid);
update_connector_ext_caps(aconnector);
+ dm_set_panel_type(aconnector);
} else {
hdmi_cec_unset_edid(aconnector);
drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux);
@@ -4211,7 +4268,7 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
dc_sink_retain(aconnector->hdmi_prev_sink);
/* Schedule delayed detection. */
- if (mod_delayed_work(system_wq,
+ if (mod_delayed_work(system_percpu_wq,
&aconnector->hdmi_hpd_debounce_work,
msecs_to_jiffies(aconnector->hdmi_hpd_debounce_delay_ms)))
drm_dbg_kms(dev, "HDMI HPD: Re-scheduled debounce work\n");
@@ -11142,8 +11199,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
if (!adev->in_suspend) {
/* return the stolen vga memory back to VRAM */
if (!adev->mman.keep_stolen_vga_memory)
- amdgpu_bo_free_kernel(&adev->mman.stolen_vga_memory, NULL, NULL);
- amdgpu_bo_free_kernel(&adev->mman.stolen_extended_memory, NULL, NULL);
+ amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_STOLEN_VGA);
+ amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_STOLEN_EXTENDED);
}
/*
@@ -13155,56 +13212,15 @@ static void parse_edid_displayid_vrr(struct drm_connector *connector,
}
}
-static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector,
- const struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info)
+static int get_amd_vsdb(struct amdgpu_dm_connector *aconnector,
+ struct amdgpu_hdmi_vsdb_info *vsdb_info)
{
- u8 *edid_ext = NULL;
- int i;
- int j = 0;
- int total_ext_block_len;
-
- if (edid == NULL || edid->extensions == 0)
- return -ENODEV;
-
- /* Find DisplayID extension */
- for (i = 0; i < edid->extensions; i++) {
- edid_ext = (void *)(edid + (i + 1));
- if (edid_ext[0] == DISPLAYID_EXT)
- break;
- }
-
- total_ext_block_len = EDID_LENGTH * edid->extensions;
- while (j < total_ext_block_len - sizeof(struct amd_vsdb_block)) {
- struct amd_vsdb_block *amd_vsdb = (struct amd_vsdb_block *)&edid_ext[j];
- unsigned int ieeeId = (amd_vsdb->ieee_id[2] << 16) | (amd_vsdb->ieee_id[1] << 8) | (amd_vsdb->ieee_id[0]);
-
- if (ieeeId == HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID &&
- amd_vsdb->version == HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3) {
- u8 panel_type;
- vsdb_info->replay_mode = (amd_vsdb->feature_caps & AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE) ? true : false;
- vsdb_info->amd_vsdb_version = HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3;
- drm_dbg_kms(aconnector->base.dev, "Panel supports Replay Mode: %d\n", vsdb_info->replay_mode);
- panel_type = (amd_vsdb->color_space_eotf_support & AMD_VDSB_VERSION_3_PANEL_TYPE_MASK) >> AMD_VDSB_VERSION_3_PANEL_TYPE_SHIFT;
- switch (panel_type) {
- case AMD_VSDB_PANEL_TYPE_OLED:
- aconnector->dc_link->panel_type = PANEL_TYPE_OLED;
- break;
- case AMD_VSDB_PANEL_TYPE_MINILED:
- aconnector->dc_link->panel_type = PANEL_TYPE_MINILED;
- break;
- default:
- aconnector->dc_link->panel_type = PANEL_TYPE_NONE;
- break;
- }
- drm_dbg_kms(aconnector->base.dev, "Panel type: %d\n",
- aconnector->dc_link->panel_type);
+ struct drm_connector *connector = &aconnector->base;
- return true;
- }
- j++;
- }
+ vsdb_info->replay_mode = connector->display_info.amd_vsdb.replay_mode;
+ vsdb_info->amd_vsdb_version = connector->display_info.amd_vsdb.version;
- return false;
+ return connector->display_info.amd_vsdb.version != 0;
}
static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
@@ -13307,7 +13323,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
freesync_capable = true;
}
- parse_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info);
+ get_amd_vsdb(amdgpu_dm_connector, &vsdb_info);
if (vsdb_info.replay_mode) {
amdgpu_dm_connector->vsdb_info.replay_mode = vsdb_info.replay_mode;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index d1a14e0c12bd..63ce1f52b697 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -53,12 +53,6 @@
#define AMDGPU_DMUB_NOTIFICATION_MAX 8
-#define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID 0x00001A
-#define AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE 0x40
-#define AMD_VDSB_VERSION_3_PANEL_TYPE_MASK 0xC0
-#define AMD_VDSB_VERSION_3_PANEL_TYPE_SHIFT 6
-#define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3 0x3
-
enum amd_vsdb_panel_type {
AMD_VSDB_PANEL_TYPE_DEFAULT = 0,
AMD_VSDB_PANEL_TYPE_MINILED,
@@ -97,14 +91,6 @@ struct dc_plane_state;
struct dmub_notification;
struct dmub_cmd_fused_request;
-struct amd_vsdb_block {
- unsigned char ieee_id[3];
- unsigned char version;
- unsigned char feature_caps;
- unsigned char reserved[3];
- unsigned char color_space_eotf_support;
-};
-
struct common_irq_params {
struct amdgpu_device *adev;
enum dc_irq_source irq_src;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
index c3c588294665..5d2715f78314 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
@@ -101,23 +101,22 @@ bool amdgpu_dm_crtc_vrr_active(const struct dm_crtc_state *dm_state)
/**
* amdgpu_dm_crtc_set_panel_sr_feature() - Manage panel self-refresh features.
- *
- * @vblank_work: is a pointer to a struct vblank_control_work object.
- * @vblank_enabled: indicates whether the DRM vblank counter is currently
- * enabled (true) or disabled (false).
- * @allow_sr_entry: represents whether entry into the self-refresh mode is
- * allowed (true) or not allowed (false).
+ * @dm: amdgpu display manager instance.
+ * @acrtc: CRTC whose panel self-refresh state is being updated.
+ * @stream: DC stream associated with @acrtc.
+ * @vblank_enabled: Whether the DRM vblank counter is currently enabled.
+ * @allow_sr_entry: Whether entry into self-refresh mode is allowed.
*
* The DRM vblank counter enable/disable action is used as the trigger to enable
* or disable various panel self-refresh features:
*
* Panel Replay and PSR SU
* - Enable when:
- * - VRR is disabled
- * - vblank counter is disabled
- * - entry is allowed: usermode demonstrates an adequate number of fast
- * commits)
- * - CRC capture window isn't active
+ * - VRR is disabled
+ * - vblank counter is disabled
+ * - entry is allowed: usermode demonstrates an adequate number of fast
+ * commits
+ * - CRC capture window isn't active
* - Keep enabled even when vblank counter gets enabled
*
* PSR1
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c
index 65a5cfe1e106..a3ccb6fdc372 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c
@@ -35,6 +35,9 @@
/**
* dm_ism_next_state - Get next state based on current state and event
+ * @current_state: current ISM state
+ * @event: event being processed
+ * @next_state: place to store the next state
*
* This function defines the idle state management FSM. Invalid transitions
* are ignored and will not progress the FSM.
@@ -148,6 +151,11 @@ static uint64_t dm_ism_get_sso_delay(const struct amdgpu_dm_ism *ism,
/**
* dm_ism_get_idle_allow_delay - Calculate hysteresis-based idle allow delay
+ * @ism: ISM instance containing configuration, history, and current state
+ * @stream: display stream used to derive frame timing values for delay
+ *
+ * Calculates the delay before allowing idle optimizations based on recent
+ * idle history and the current stream timing.
*/
static uint64_t dm_ism_get_idle_allow_delay(const struct amdgpu_dm_ism *ism,
const struct dc_stream_state *stream)
@@ -212,6 +220,7 @@ static uint64_t dm_ism_get_idle_allow_delay(const struct amdgpu_dm_ism *ism,
/**
* dm_ism_insert_record - Insert a record into the circular history buffer
+ * @ism: ISM instance
*/
static void dm_ism_insert_record(struct amdgpu_dm_ism *ism)
{
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
index 8ba9b4f56f87..172999cc84e5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
@@ -59,7 +59,7 @@ inline void dc_assert_fp_enabled(void)
}
/**
- * dc_assert_fp_enabled - Check if FPU protection is enabled
+ * dc_is_fp_enabled - Check if FPU protection is enabled
*
* This function tells if the code is already under FPU protection or not. A
* function that works as an API for a set of FPU operations can use this
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index db86e346307c..952968ecd46e 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -23,6 +23,8 @@
*
*/
+#include <linux/array_size.h>
+
#include "dm_services.h"
#include "core_types.h"
#include "timing_generator.h"
@@ -40,7 +42,6 @@
#include "dcn10/dcn10_hubbub.h"
#include "dce/dmub_hw_lock_mgr.h"
-#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
#define MAX_NUM_MCACHE 8
/* used as index in array of black_color_format */
@@ -230,7 +231,7 @@ const uint16_t *find_color_matrix(enum dc_color_space color_space,
int i;
enum dc_color_space_type type;
const uint16_t *val = NULL;
- int arr_size = NUM_ELEMENTS(output_csc_matrix);
+ int arr_size = ARRAY_SIZE(output_csc_matrix);
type = get_color_space_type(color_space);
for (i = 0; i < arr_size; i++)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 66597a1f5b78..00b894602423 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -5062,7 +5062,7 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream,
option = DITHER_OPTION_SPATIAL8;
break;
case COLOR_DEPTH_101010:
- option = DITHER_OPTION_TRUN10;
+ option = DITHER_OPTION_SPATIAL10;
break;
default:
option = DITHER_OPTION_DISABLE;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
index 34e54fdb9d13..71a876e3dfd4 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -23,6 +23,8 @@
*
*/
+#include <linux/array_size.h>
+
#include "dm_services.h"
@@ -57,8 +59,6 @@
#define CALC_PLL_CLK_SRC_ERR_TOLERANCE 1
#define MAX_PLL_CALC_ERROR 0xFFFFFFFF
-#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
-
static const struct spread_spectrum_data *get_ss_data_entry(
struct dce110_clk_src *clk_src,
enum signal_type signal,
@@ -1271,7 +1271,7 @@ const struct pixel_rate_range_table_entry *look_up_in_video_optimized_rate_tlb(
{
int i;
- for (i = 0; i < NUM_ELEMENTS(video_optimized_pixel_rates); i++) {
+ for (i = 0; i < ARRAY_SIZE(video_optimized_pixel_rates); i++) {
const struct pixel_rate_range_table_entry *e = &video_optimized_pixel_rates[i];
if (e->range_min_khz <= pixel_rate_khz && pixel_rate_khz <= e->range_max_khz) {
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_cm.c
index f8f6019d8304..2bdd063cc1e1 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_cm.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_cm.c
@@ -49,9 +49,6 @@
#define FN(reg_name, field_name) \
dpp->tf_shift->field_name, dpp->tf_mask->field_name
-#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
-
-
enum dcn10_coef_filter_type_sel {
SCL_COEF_LUMA_VERT_FILTER = 0,
SCL_COEF_LUMA_HORZ_FILTER = 1,
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c
index 821d5173b59f..4f3b48ed8679 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c
@@ -49,9 +49,6 @@
#define FN(reg_name, field_name) \
dpp->tf_shift->field_name, dpp->tf_mask->field_name
-#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
-
-
enum dcn401_coef_filter_type_sel {
SCL_COEF_LUMA_VERT_FILTER = 0,
SCL_COEF_LUMA_HORZ_FILTER = 1,
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn20/dcn20_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn20/dcn20_mpc.c
index ea73473b970a..fa600593f4c1 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn20/dcn20_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn20/dcn20_mpc.c
@@ -43,8 +43,6 @@
#define FN(reg_name, field_name) \
mpc20->mpc_shift->field_name, mpc20->mpc_mask->field_name
-#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
-
void mpc2_update_blending(
struct mpc *mpc,
struct mpcc_blnd_cfg *blnd_cfg,
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c
index 4c7bb0522a8c..4e91e9f6f11a 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c
@@ -40,10 +40,6 @@
#define FN(reg_name, field_name) \
mpc30->mpc_shift->field_name, mpc30->mpc_mask->field_name
-
-#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
-
-
void mpc3_mpc_init(struct mpc *mpc)
{
struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
index 609f5ab07d8a..126fc54cb511 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -2164,4 +2164,21 @@ static inline void smu_feature_init(struct smu_context *smu, int feature_num)
smu_feature_list_clear_all(smu, SMU_FEATURE_LIST_ALLOWED);
}
+/*
+ * smu_safe_u16_nn - Make u16 safe by filtering negative overflow errors
+ * @val: Input u16 value, may contain invalid negative overflows
+ *
+ * Convert u16 to non-negative value. Cast to s16 to detect negative values
+ * caused by calculation errors. Return 0 for negative errors, return
+ * original value if valid.
+ *
+ * Return: Valid u16 value or 0
+ */
+static inline u16 smu_safe_u16_nn(u16 val)
+{
+ s16 tmp = (s16)val;
+
+ return tmp < 0 ? 0 : val;
+}
+
#endif
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 b414a74d29fd..0a7f5fa3c1d3 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
@@ -773,13 +773,13 @@ static int smu_v13_0_0_get_smu_metrics_data(struct smu_context *smu,
*value = metrics->AverageGfxclkFrequencyPreDs;
break;
case METRICS_AVERAGE_FCLK:
- if (metrics->AverageUclkActivity <= SMU_13_0_0_BUSY_THRESHOLD)
+ if (smu_safe_u16_nn(metrics->AverageUclkActivity) <= SMU_13_0_0_BUSY_THRESHOLD)
*value = metrics->AverageFclkFrequencyPostDs;
else
*value = metrics->AverageFclkFrequencyPreDs;
break;
case METRICS_AVERAGE_UCLK:
- if (metrics->AverageUclkActivity <= SMU_13_0_0_BUSY_THRESHOLD)
+ if (smu_safe_u16_nn(metrics->AverageUclkActivity) <= SMU_13_0_0_BUSY_THRESHOLD)
*value = metrics->AverageMemclkFrequencyPostDs;
else
*value = metrics->AverageMemclkFrequencyPreDs;
@@ -800,7 +800,7 @@ static int smu_v13_0_0_get_smu_metrics_data(struct smu_context *smu,
*value = metrics->AverageGfxActivity;
break;
case METRICS_AVERAGE_MEMACTIVITY:
- *value = metrics->AverageUclkActivity;
+ *value = smu_safe_u16_nn(metrics->AverageUclkActivity);
break;
case METRICS_AVERAGE_VCNACTIVITY:
*value = max(metrics->Vcn0ActivityPercentage,
@@ -2085,7 +2085,7 @@ static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu,
metrics->AvgTemperature[TEMP_VR_MEM1]);
gpu_metrics->average_gfx_activity = metrics->AverageGfxActivity;
- gpu_metrics->average_umc_activity = metrics->AverageUclkActivity;
+ gpu_metrics->average_umc_activity = smu_safe_u16_nn(metrics->AverageUclkActivity);
gpu_metrics->average_mm_activity = max(metrics->Vcn0ActivityPercentage,
metrics->Vcn1ActivityPercentage);
@@ -2102,7 +2102,7 @@ static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu,
else
gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPreDs;
- if (metrics->AverageUclkActivity <= SMU_13_0_0_BUSY_THRESHOLD)
+ if (smu_safe_u16_nn(metrics->AverageUclkActivity) <= SMU_13_0_0_BUSY_THRESHOLD)
gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPostDs;
else
gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPreDs;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c
index 54a86eb77cd5..fe929bd89058 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c
@@ -479,9 +479,14 @@ static int smu_v13_0_12_get_system_metrics_table(struct smu_context *smu)
}
amdgpu_hdp_invalidate(smu->adev, NULL);
+
+ ret = smu_cmn_vram_cpy(smu, sys_table->cache.buffer,
+ table->cpu_addr,
+ smu_v13_0_12_get_system_metrics_size());
+ if (ret)
+ return ret;
+
smu_table_cache_update_time(sys_table, jiffies);
- memcpy(sys_table->cache.buffer, table->cpu_addr,
- smu_v13_0_12_get_system_metrics_size());
return 0;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
index 475541189782..cd0a23f432ff 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
@@ -778,7 +778,10 @@ int smu_v13_0_6_get_metrics_table(struct smu_context *smu, void *metrics_table,
}
amdgpu_hdp_invalidate(smu->adev, NULL);
- memcpy(smu_table->metrics_table, table->cpu_addr, table_size);
+ ret = smu_cmn_vram_cpy(smu, smu_table->metrics_table,
+ table->cpu_addr, table_size);
+ if (ret)
+ return ret;
smu_table->metrics_time = jiffies;
}
@@ -857,9 +860,9 @@ int smu_v13_0_6_get_static_metrics_table(struct smu_context *smu)
}
amdgpu_hdp_invalidate(smu->adev, NULL);
- memcpy(smu_table->metrics_table, table->cpu_addr, table_size);
- return 0;
+ return smu_cmn_vram_cpy(smu, smu_table->metrics_table,
+ table->cpu_addr, table_size);
}
static void smu_v13_0_6_update_caps(struct smu_context *smu)
@@ -2404,13 +2407,15 @@ static int smu_v13_0_6_request_i2c_xfer(struct smu_context *smu,
table_size = smu_table->tables[SMU_TABLE_I2C_COMMANDS].size;
- memcpy(table->cpu_addr, table_data, table_size);
+ ret = smu_cmn_vram_cpy(smu, table->cpu_addr, table_data, table_size);
+ if (ret)
+ return ret;
+
/* Flush hdp cache */
amdgpu_hdp_flush(adev, NULL);
- ret = smu_cmn_send_smc_msg(smu, SMU_MSG_RequestI2cTransaction,
- NULL);
- return ret;
+ return smu_cmn_send_smc_msg(smu, SMU_MSG_RequestI2cTransaction,
+ NULL);
}
static int smu_v13_0_6_i2c_xfer(struct i2c_adapter *i2c_adap,
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 fd0b6215364f..5abf2b0703c6 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
@@ -783,13 +783,13 @@ static int smu_v13_0_7_get_smu_metrics_data(struct smu_context *smu,
*value = metrics->AverageGfxclkFrequencyPreDs;
break;
case METRICS_AVERAGE_FCLK:
- if (metrics->AverageUclkActivity <= SMU_13_0_7_BUSY_THRESHOLD)
+ if (smu_safe_u16_nn(metrics->AverageUclkActivity) <= SMU_13_0_7_BUSY_THRESHOLD)
*value = metrics->AverageFclkFrequencyPostDs;
else
*value = metrics->AverageFclkFrequencyPreDs;
break;
case METRICS_AVERAGE_UCLK:
- if (metrics->AverageUclkActivity <= SMU_13_0_7_BUSY_THRESHOLD)
+ if (smu_safe_u16_nn(metrics->AverageUclkActivity) <= SMU_13_0_7_BUSY_THRESHOLD)
*value = metrics->AverageMemclkFrequencyPostDs;
else
*value = metrics->AverageMemclkFrequencyPreDs;
@@ -814,7 +814,7 @@ static int smu_v13_0_7_get_smu_metrics_data(struct smu_context *smu,
*value = metrics->AverageGfxActivity;
break;
case METRICS_AVERAGE_MEMACTIVITY:
- *value = metrics->AverageUclkActivity;
+ *value = smu_safe_u16_nn(metrics->AverageUclkActivity);
break;
case METRICS_AVERAGE_SOCKETPOWER:
*value = metrics->AverageSocketPower << 8;
@@ -2091,7 +2091,7 @@ static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu,
metrics->AvgTemperature[TEMP_VR_MEM1]);
gpu_metrics->average_gfx_activity = metrics->AverageGfxActivity;
- gpu_metrics->average_umc_activity = metrics->AverageUclkActivity;
+ gpu_metrics->average_umc_activity = smu_safe_u16_nn(metrics->AverageUclkActivity);
gpu_metrics->average_mm_activity = max(metrics->Vcn0ActivityPercentage,
metrics->Vcn1ActivityPercentage);
@@ -2104,7 +2104,7 @@ static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu,
else
gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPreDs;
- if (metrics->AverageUclkActivity <= SMU_13_0_7_BUSY_THRESHOLD)
+ if (smu_safe_u16_nn(metrics->AverageUclkActivity) <= SMU_13_0_7_BUSY_THRESHOLD)
gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPostDs;
else
gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPreDs;
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 31f9566f7979..62514e3ac600 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
@@ -661,13 +661,13 @@ static int smu_v14_0_2_get_smu_metrics_data(struct smu_context *smu,
*value = metrics->AverageGfxclkFrequencyPreDs;
break;
case METRICS_AVERAGE_FCLK:
- if (metrics->AverageUclkActivity <= SMU_14_0_2_BUSY_THRESHOLD)
+ if (smu_safe_u16_nn(metrics->AverageUclkActivity) <= SMU_14_0_2_BUSY_THRESHOLD)
*value = metrics->AverageFclkFrequencyPostDs;
else
*value = metrics->AverageFclkFrequencyPreDs;
break;
case METRICS_AVERAGE_UCLK:
- if (metrics->AverageUclkActivity <= SMU_14_0_2_BUSY_THRESHOLD)
+ if (smu_safe_u16_nn(metrics->AverageUclkActivity) <= SMU_14_0_2_BUSY_THRESHOLD)
*value = metrics->AverageMemclkFrequencyPostDs;
else
*value = metrics->AverageMemclkFrequencyPreDs;
@@ -688,7 +688,7 @@ static int smu_v14_0_2_get_smu_metrics_data(struct smu_context *smu,
*value = metrics->AverageGfxActivity;
break;
case METRICS_AVERAGE_MEMACTIVITY:
- *value = metrics->AverageUclkActivity;
+ *value = smu_safe_u16_nn(metrics->AverageUclkActivity);
break;
case METRICS_AVERAGE_VCNACTIVITY:
*value = max(metrics->AverageVcn0ActivityPercentage,
@@ -2147,7 +2147,7 @@ static ssize_t smu_v14_0_2_get_gpu_metrics(struct smu_context *smu,
metrics->AvgTemperature[TEMP_VR_MEM1]);
gpu_metrics->average_gfx_activity = metrics->AverageGfxActivity;
- gpu_metrics->average_umc_activity = metrics->AverageUclkActivity;
+ gpu_metrics->average_umc_activity = smu_safe_u16_nn(metrics->AverageUclkActivity);
gpu_metrics->average_mm_activity = max(metrics->AverageVcn0ActivityPercentage,
metrics->Vcn1ActivityPercentage);
@@ -2159,7 +2159,7 @@ static ssize_t smu_v14_0_2_get_gpu_metrics(struct smu_context *smu,
else
gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPreDs;
- if (metrics->AverageUclkActivity <= SMU_14_0_2_BUSY_THRESHOLD)
+ if (smu_safe_u16_nn(metrics->AverageUclkActivity) <= SMU_14_0_2_BUSY_THRESHOLD)
gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPostDs;
else
gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPreDs;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index cc2babc6a341..db85186f2d66 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -344,7 +344,12 @@ static int smu_v15_0_8_get_metrics_table_internal(struct smu_context *smu, uint3
}
amdgpu_device_invalidate_hdp(smu->adev, NULL);
- memcpy(smu_table->metrics_table, table->cpu_addr, table_size);
+ ret = smu_cmn_vram_cpy(smu, smu_table->metrics_table,
+ table->cpu_addr, table_size);
+ if (ret) {
+ mutex_unlock(&smu_table->metrics_lock);
+ return ret;
+ }
smu_table->metrics_time = jiffies;
}
@@ -551,9 +556,14 @@ static int smu_v15_0_8_get_system_metrics_table(struct smu_context *smu)
}
amdgpu_hdp_invalidate(smu->adev, NULL);
+
+ ret = smu_cmn_vram_cpy(smu, sys_table->cache.buffer,
+ table->cpu_addr,
+ sizeof(SystemMetricsTable_t));
+ if (ret)
+ return ret;
+
smu_table_cache_update_time(sys_table, jiffies);
- memcpy(sys_table->cache.buffer, table->cpu_addr,
- sizeof(SystemMetricsTable_t));
return 0;
}
@@ -988,9 +998,9 @@ static int smu_v15_0_8_get_static_metrics_table(struct smu_context *smu)
}
amdgpu_hdp_invalidate(smu->adev, NULL);
- memcpy(smu_table->metrics_table, table->cpu_addr, table_size);
- return 0;
+ return smu_cmn_vram_cpy(smu, smu_table->metrics_table,
+ table->cpu_addr, table_size);
}
static int smu_v15_0_8_fru_get_product_info(struct smu_context *smu,
@@ -1601,8 +1611,6 @@ static ssize_t smu_v15_0_8_get_gpu_metrics(struct smu_context *smu, void **table
uint32_t mid_mask = adev->aid_mask;
MetricsTable_t *metrics;
- metrics = kzalloc(sizeof(MetricsTable_t), GFP_KERNEL);
-
ret = smu_v15_0_8_get_metrics_table_internal(smu, 1, NULL);
if (ret)
return ret;
@@ -1775,7 +1783,7 @@ static int smu_v15_0_8_get_power_limit(struct smu_context *smu,
*current_power_limit = power_limit;
if (default_power_limit)
- *max_power_limit = pptable->MaxSocketPowerLimit;
+ *default_power_limit = pptable->MaxSocketPowerLimit;
if (max_power_limit)
*max_power_limit = pptable->MaxSocketPowerLimit;
@@ -1901,42 +1909,36 @@ static int smu_v15_0_8_set_soft_freq_limited_range(struct smu_context *smu,
if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
return -EINVAL;
- if (smu_dpm->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
- if (min >= max) {
- dev_err(smu->adev->dev,
- "Minimum clk should be less than the maximum allowed clock\n");
- return -EINVAL;
- }
+ if (min >= max) {
+ dev_err(smu->adev->dev,
+ "Minimum clk should be less than the maximum allowed clock\n");
+ return -EINVAL;
+ }
- if (clk_type == SMU_GFXCLK || clk_type == SMU_SCLK) {
- if ((min == pstate_table->gfxclk_pstate.curr.min) &&
- (max == pstate_table->gfxclk_pstate.curr.max))
- return 0;
+ if (clk_type == SMU_GFXCLK || clk_type == SMU_SCLK) {
+ if ((min == pstate_table->gfxclk_pstate.curr.min) &&
+ (max == pstate_table->gfxclk_pstate.curr.max))
+ return 0;
- ret = smu_v15_0_8_set_gfx_soft_freq_limited_range(smu,
- min, max);
- if (!ret) {
- pstate_table->gfxclk_pstate.curr.min = min;
- pstate_table->gfxclk_pstate.curr.max = max;
- }
+ ret = smu_v15_0_8_set_gfx_soft_freq_limited_range(smu, min,
+ max);
+ if (!ret) {
+ pstate_table->gfxclk_pstate.curr.min = min;
+ pstate_table->gfxclk_pstate.curr.max = max;
}
+ }
- if (clk_type == SMU_UCLK) {
- if (max == pstate_table->uclk_pstate.curr.max)
- return 0;
-
- ret = smu_v15_0_set_soft_freq_limited_range(smu,
- SMU_UCLK,
- 0, max,
- false);
- if (!ret)
- pstate_table->uclk_pstate.curr.max = max;
- }
+ if (clk_type == SMU_UCLK) {
+ if (max == pstate_table->uclk_pstate.curr.max)
+ return 0;
- return ret;
+ ret = smu_v15_0_set_soft_freq_limited_range(smu, SMU_UCLK, 0,
+ max, false);
+ if (!ret)
+ pstate_table->uclk_pstate.curr.max = max;
}
- return 0;
+ return ret;
}
static int smu_v15_0_8_od_edit_dpm_table(struct smu_context *smu,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index 7bd8c435466a..006ef585a377 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -1104,6 +1104,18 @@ int smu_cmn_update_table(struct smu_context *smu,
return 0;
}
+int smu_cmn_vram_cpy(struct smu_context *smu, void *dst, const void *src,
+ size_t len)
+{
+ memcpy(dst, src, len);
+
+ /* Don't trust the copy operation if RAS fatal error happened. */
+ if (amdgpu_ras_get_fed_status(smu->adev))
+ return -EHWPOISON;
+
+ return 0;
+}
+
int smu_cmn_write_watermarks_table(struct smu_context *smu)
{
void *watermarks_table = smu->smu_table.watermarks_table;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
index b76e86df5da7..d129907535bd 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
@@ -174,6 +174,9 @@ int smu_cmn_update_table(struct smu_context *smu,
void *table_data,
bool drv2smu);
+int smu_cmn_vram_cpy(struct smu_context *smu, void *dst,
+ const void *src, size_t len);
+
int smu_cmn_write_watermarks_table(struct smu_context *smu);
int smu_cmn_write_pptable(struct smu_context *smu);
diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c
index d213eea71cff..ad8862d43263 100644
--- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c
+++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c
@@ -290,13 +290,10 @@ static int amdgpu_ras_mgr_sw_init(struct amdgpu_ip_block *ip_block)
/* Disabled by default */
con->uniras_enabled = false;
- /* Enabled only in debug mode */
- if (adev->debug_enable_ras_aca) {
+ if (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 14) ||
+ adev->debug_enable_ras_aca)
con->uniras_enabled = true;
- RAS_DEV_INFO(adev, "Debug amdgpu uniras!");
- }
-
- if (!con->uniras_enabled)
+ else
return 0;
ras_mgr = kzalloc_obj(*ras_mgr);
diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_virt_ras_cmd.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_virt_ras_cmd.c
index c83357307c55..eb552d0cce4a 100644
--- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_virt_ras_cmd.c
+++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_virt_ras_cmd.c
@@ -36,22 +36,22 @@ static int amdgpu_virt_ras_get_cmd_shared_mem(struct ras_core_context *ras_core,
struct amdgpu_device *adev = ras_core->dev;
struct amdsriov_ras_telemetry *ras_telemetry_cpu;
struct amdsriov_ras_telemetry *ras_telemetry_gpu;
+ void *fw_va = adev->mman.resv_region[AMDGPU_RESV_FW_VRAM_USAGE].cpu_ptr;
+ void *drv_va = adev->mman.resv_region[AMDGPU_RESV_DRV_VRAM_USAGE].cpu_ptr;
uint64_t fw_vram_usage_start_offset = 0;
uint64_t ras_telemetry_offset = 0;
if (!adev->virt.fw_reserve.ras_telemetry)
return -EINVAL;
- if (adev->mman.fw_vram_usage_va &&
- adev->mman.fw_vram_usage_va <= adev->virt.fw_reserve.ras_telemetry) {
- fw_vram_usage_start_offset = adev->mman.fw_vram_usage_start_offset;
+ if (fw_va && fw_va <= adev->virt.fw_reserve.ras_telemetry) {
+ fw_vram_usage_start_offset = adev->mman.resv_region[AMDGPU_RESV_FW_VRAM_USAGE].offset;
ras_telemetry_offset = (uintptr_t)adev->virt.fw_reserve.ras_telemetry -
- (uintptr_t)adev->mman.fw_vram_usage_va;
- } else if (adev->mman.drv_vram_usage_va &&
- adev->mman.drv_vram_usage_va <= adev->virt.fw_reserve.ras_telemetry) {
- fw_vram_usage_start_offset = adev->mman.drv_vram_usage_start_offset;
+ (uintptr_t)fw_va;
+ } else if (drv_va && drv_va <= adev->virt.fw_reserve.ras_telemetry) {
+ fw_vram_usage_start_offset = adev->mman.resv_region[AMDGPU_RESV_DRV_VRAM_USAGE].offset;
ras_telemetry_offset = (uintptr_t)adev->virt.fw_reserve.ras_telemetry -
- (uintptr_t)adev->mman.drv_vram_usage_va;
+ (uintptr_t)drv_va;
} else {
return -EINVAL;
}
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 5f9fcd7d9ce4..404208bf23a6 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -99,6 +99,29 @@ enum drm_edid_internal_quirk {
};
#define MICROSOFT_IEEE_OUI 0xca125c
+#define AMD_IEEE_OUI 0x00001A
+
+#define AMD_VSDB_V3_PAYLOAD_MIN_LEN 15
+#define AMD_VSDB_V3_PAYLOAD_MAX_LEN 20
+
+struct amd_vsdb_v3_payload {
+ u8 oui[3];
+ u8 version;
+ u8 feature_caps;
+ u8 rsvd0[3];
+ u8 cs_eotf_support;
+ u8 lum1_max;
+ u8 lum1_min;
+ u8 lum2_max;
+ u8 lum2_min;
+ u8 rsvd1[2];
+ /*
+ * Bytes beyond AMD_VSDB_V3_PAYLOAD_MIN_LEN are optional; a
+ * monitor may provide a payload as short as 15 bytes. Always
+ * check cea_db_payload_len() before accessing extra[].
+ */
+ u8 extra[AMD_VSDB_V3_PAYLOAD_MAX_LEN - AMD_VSDB_V3_PAYLOAD_MIN_LEN];
+} __packed;
struct detailed_mode_closure {
struct drm_connector *connector;
@@ -5205,6 +5228,13 @@ static bool cea_db_is_microsoft_vsdb(const struct cea_db *db)
cea_db_payload_len(db) == 21;
}
+static bool cea_db_is_amd_vsdb(const struct cea_db *db)
+{
+ return cea_db_is_vendor(db, AMD_IEEE_OUI) &&
+ cea_db_payload_len(db) >= AMD_VSDB_V3_PAYLOAD_MIN_LEN &&
+ cea_db_payload_len(db) <= AMD_VSDB_V3_PAYLOAD_MAX_LEN;
+}
+
static bool cea_db_is_vcdb(const struct cea_db *db)
{
return cea_db_is_extended_tag(db, CTA_EXT_DB_VIDEO_CAP) &&
@@ -6401,6 +6431,45 @@ static void drm_parse_microsoft_vsdb(struct drm_connector *connector,
connector->base.id, connector->name, version, db[5]);
}
+static void drm_parse_amd_vsdb(struct drm_connector *connector,
+ const struct cea_db *db)
+{
+ struct drm_display_info *info = &connector->display_info;
+ const u8 *data = cea_db_data(db);
+ const struct amd_vsdb_v3_payload *p;
+
+ p = (const struct amd_vsdb_v3_payload *)data;
+
+ if (p->version != 0x03) {
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] Unsupported AMD VSDB version %u\n",
+ connector->base.id, connector->name, p->version);
+ return;
+ }
+
+ info->amd_vsdb.version = p->version;
+ info->amd_vsdb.replay_mode = p->feature_caps & 0x40;
+ info->amd_vsdb.panel_type = (p->cs_eotf_support & 0xC0) >> 6;
+ info->amd_vsdb.luminance_range1.max_luminance = p->lum1_max;
+ info->amd_vsdb.luminance_range1.min_luminance = p->lum1_min;
+ info->amd_vsdb.luminance_range2.max_luminance = p->lum2_max;
+ info->amd_vsdb.luminance_range2.min_luminance = p->lum2_min;
+
+ /*
+ * The AMD VSDB v3 payload length is variable (15..20 bytes).
+ * All fields through p->rsvd1 (byte 14) are always present,
+ * but p->extra[] (bytes 15+) may not be. Any future access to
+ * extra[] must be guarded with a runtime length check to avoid
+ * out-of-bounds reads on shorter (but spec-valid) payloads.
+ * For example:
+ *
+ * int len = cea_db_payload_len(db);
+ *
+ * if (len > AMD_VSDB_V3_PAYLOAD_MIN_LEN)
+ * info->amd_vsdb.foo = p->extra[0];
+ */
+}
+
static void drm_parse_cea_ext(struct drm_connector *connector,
const struct drm_edid *drm_edid)
{
@@ -6449,6 +6518,8 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
drm_parse_hdmi_forum_scds(connector, data);
else if (cea_db_is_microsoft_vsdb(db))
drm_parse_microsoft_vsdb(connector, data);
+ else if (cea_db_is_amd_vsdb(db))
+ drm_parse_amd_vsdb(connector, db);
else if (cea_db_is_y420cmdb(db))
parse_cta_y420cmdb(connector, db, &y420cmdb_map);
else if (cea_db_is_y420vdb(db))
@@ -6641,6 +6712,7 @@ static void drm_reset_display_info(struct drm_connector *connector)
info->quirks = 0;
info->source_physical_address = CEC_PHYS_ADDR_INVALID;
+ memset(&info->amd_vsdb, 0, sizeof(info->amd_vsdb));
}
static void update_displayid_info(struct drm_connector *connector,
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
index b8189cd5d864..03de219f7a64 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -209,6 +209,8 @@ static struct intel_crtc *intel_crtc_alloc(void)
crtc->base.state = &crtc_state->uapi;
crtc->config = crtc_state;
+ INIT_LIST_HEAD(&crtc->pipe_head);
+
return crtc;
}
@@ -222,6 +224,8 @@ static void intel_crtc_destroy(struct drm_crtc *_crtc)
{
struct intel_crtc *crtc = to_intel_crtc(_crtc);
+ list_del(&crtc->pipe_head);
+
cpu_latency_qos_remove_request(&crtc->vblank_pm_qos);
drm_crtc_cleanup(&crtc->base);
@@ -308,6 +312,20 @@ static const struct drm_crtc_funcs i8xx_crtc_funcs = {
.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
};
+static void add_crtc_to_pipe_list(struct intel_display *display, struct intel_crtc *crtc)
+{
+ struct intel_crtc *iter;
+
+ list_for_each_entry(iter, &display->pipe_list, pipe_head) {
+ if (crtc->pipe < iter->pipe) {
+ list_add_tail(&crtc->pipe_head, &iter->pipe_head);
+ return;
+ }
+ }
+
+ list_add_tail(&crtc->pipe_head, &display->pipe_list);
+}
+
static int __intel_crtc_init(struct intel_display *display, enum pipe pipe)
{
struct intel_plane *primary, *cursor;
@@ -393,11 +411,11 @@ static int __intel_crtc_init(struct intel_display *display, enum pipe pipe)
cpu_latency_qos_add_request(&crtc->vblank_pm_qos, PM_QOS_DEFAULT_VALUE);
- drm_WARN_ON(display->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
-
if (HAS_CASF(display) && crtc->num_scalers >= 2)
drm_crtc_create_sharpness_strength_property(&crtc->base);
+ add_crtc_to_pipe_list(display, crtc);
+
return 0;
fail:
@@ -406,6 +424,31 @@ fail:
return ret;
}
+#define HAS_PIPE(display, pipe) (DISPLAY_RUNTIME_INFO(display)->pipe_mask & BIT(pipe))
+
+/*
+ * Expose the pipes in order A, C, B, D on discrete platforms to trick user
+ * space into using pipes that are more likely to be available for both a) user
+ * space if pipe B has been reserved for the joiner, and b) the joiner if pipe A
+ * doesn't need the joiner.
+ *
+ * Swap pipes B and C only if both are available i.e. not fused off.
+ */
+static enum pipe reorder_pipe(struct intel_display *display, enum pipe pipe)
+{
+ if (!display->platform.dgfx || !HAS_PIPE(display, PIPE_B) || !HAS_PIPE(display, PIPE_C))
+ return pipe;
+
+ switch (pipe) {
+ case PIPE_B:
+ return PIPE_C;
+ case PIPE_C:
+ return PIPE_B;
+ default:
+ return pipe;
+ }
+}
+
int intel_crtc_init(struct intel_display *display)
{
enum pipe pipe;
@@ -415,7 +458,7 @@ int intel_crtc_init(struct intel_display *display)
INTEL_NUM_PIPES(display), str_plural(INTEL_NUM_PIPES(display)));
for_each_pipe(display, pipe) {
- ret = __intel_crtc_init(display, pipe);
+ ret = __intel_crtc_init(display, reorder_pipe(display, pipe));
if (ret)
return ret;
}
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 10b6c6fcb03f..ad2fe10b6b1f 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -5939,17 +5939,6 @@ static int intel_atomic_check_joiner(struct intel_atomic_state *state,
return -EINVAL;
}
- /*
- * The state copy logic assumes the primary crtc gets processed
- * before the secondary crtc during the main compute_config loop.
- * This works because the crtcs are created in pipe order,
- * and the hardware requires primary pipe < secondary pipe as well.
- * Should that change we need to rethink the logic.
- */
- if (WARN_ON(drm_crtc_index(&primary_crtc->base) >
- drm_crtc_index(&secondary_crtc->base)))
- return -EINVAL;
-
drm_dbg_kms(display->drm,
"[CRTC:%d:%s] Used as secondary for joiner primary [CRTC:%d:%s]\n",
secondary_crtc->base.base.id, secondary_crtc->base.name,
@@ -6327,9 +6316,7 @@ static int intel_atomic_check_config(struct intel_atomic_state *state,
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
if (!intel_crtc_needs_modeset(new_crtc_state)) {
- if (intel_crtc_is_joiner_secondary(new_crtc_state))
- copy_joiner_crtc_state_nomodeset(state, crtc);
- else
+ if (!intel_crtc_is_joiner_secondary(new_crtc_state))
intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc);
continue;
}
@@ -6460,8 +6447,11 @@ int intel_atomic_check(struct drm_device *dev,
goto fail;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
- if (!intel_crtc_needs_modeset(new_crtc_state))
+ if (!intel_crtc_needs_modeset(new_crtc_state)) {
+ if (intel_crtc_is_joiner_secondary(new_crtc_state))
+ copy_joiner_crtc_state_nomodeset(state, crtc);
continue;
+ }
if (intel_crtc_is_joiner_secondary(new_crtc_state)) {
drm_WARN_ON(display->drm, new_crtc_state->uapi.enable);
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 552a59d19e0f..1e76a455d7c4 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -212,22 +212,23 @@ enum phy_fia {
base.head) \
for_each_if((intel_plane)->pipe == (intel_crtc)->pipe)
-#define for_each_intel_crtc(dev, intel_crtc) \
- list_for_each_entry(intel_crtc, \
- &(dev)->mode_config.crtc_list, \
- base.head)
+#define for_each_intel_crtc(dev, crtc) \
+ list_for_each_entry((crtc), \
+ &to_intel_display(dev)->pipe_list, \
+ pipe_head)
-#define for_each_intel_crtc_in_pipe_mask(dev, intel_crtc, pipe_mask) \
- list_for_each_entry(intel_crtc, \
- &(dev)->mode_config.crtc_list, \
- base.head) \
- for_each_if((pipe_mask) & BIT(intel_crtc->pipe))
+#define for_each_intel_crtc_reverse(dev, crtc) \
+ list_for_each_entry_reverse((crtc), \
+ &to_intel_display(dev)->pipe_list, \
+ pipe_head)
+
+#define for_each_intel_crtc_in_pipe_mask(dev, crtc, pipe_mask) \
+ for_each_intel_crtc((dev), (crtc)) \
+ for_each_if((pipe_mask) & BIT((crtc)->pipe))
-#define for_each_intel_crtc_in_pipe_mask_reverse(dev, intel_crtc, pipe_mask) \
- list_for_each_entry_reverse((intel_crtc), \
- &(dev)->mode_config.crtc_list, \
- base.head) \
- for_each_if((pipe_mask) & BIT((intel_crtc)->pipe))
+#define for_each_intel_crtc_in_pipe_mask_reverse(dev, crtc, pipe_mask) \
+ for_each_intel_crtc_reverse((dev), (crtc)) \
+ for_each_if((pipe_mask) & BIT((crtc)->pipe))
#define for_each_intel_encoder(dev, intel_encoder) \
list_for_each_entry(intel_encoder, \
@@ -269,14 +270,6 @@ enum phy_fia {
(__i)++) \
for_each_if(plane)
-#define for_each_old_intel_crtc_in_state(__state, crtc, old_crtc_state, __i) \
- for ((__i) = 0; \
- (__i) < (__state)->base.dev->mode_config.num_crtc && \
- ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
- (old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), 1); \
- (__i)++) \
- for_each_if(crtc)
-
#define for_each_new_intel_plane_in_state(__state, plane, new_plane_state, __i) \
for ((__i) = 0; \
(__i) < (__state)->base.dev->mode_config.num_total_plane && \
@@ -285,22 +278,6 @@ enum phy_fia {
(__i)++) \
for_each_if(plane)
-#define for_each_new_intel_crtc_in_state(__state, crtc, new_crtc_state, __i) \
- for ((__i) = 0; \
- (__i) < (__state)->base.dev->mode_config.num_crtc && \
- ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
- (new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
- (__i)++) \
- for_each_if(crtc)
-
-#define for_each_new_intel_crtc_in_state_reverse(__state, crtc, new_crtc_state, __i) \
- for ((__i) = (__state)->base.dev->mode_config.num_crtc - 1; \
- (__i) >= 0 && \
- ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
- (new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
- (__i)--) \
- for_each_if(crtc)
-
#define for_each_oldnew_intel_plane_in_state(__state, plane, old_plane_state, new_plane_state, __i) \
for ((__i) = 0; \
(__i) < (__state)->base.dev->mode_config.num_total_plane && \
@@ -310,23 +287,32 @@ enum phy_fia {
(__i)++) \
for_each_if(plane)
+#define for_each_old_intel_crtc_in_state(__state, crtc, old_crtc_state, __i) \
+ for_each_intel_crtc((__state)->base.dev, (crtc)) \
+ for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
+ (old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc))))
+
+#define for_each_new_intel_crtc_in_state(__state, crtc, new_crtc_state, __i) \
+ for_each_intel_crtc((__state)->base.dev, (crtc)) \
+ for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
+ (new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))))
+
+#define for_each_new_intel_crtc_in_state_reverse(__state, crtc, new_crtc_state, __i) \
+ for_each_intel_crtc_reverse((__state)->base.dev, (crtc)) \
+ for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
+ (new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))))
+
#define for_each_oldnew_intel_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \
- for ((__i) = 0; \
- (__i) < (__state)->base.dev->mode_config.num_crtc && \
- ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
- (old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), \
- (new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
- (__i)++) \
- for_each_if(crtc)
+ for_each_intel_crtc((__state)->base.dev, (crtc)) \
+ for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
+ (old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc)), \
+ (new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))))
#define for_each_oldnew_intel_crtc_in_state_reverse(__state, crtc, old_crtc_state, new_crtc_state, __i) \
- for ((__i) = (__state)->base.dev->mode_config.num_crtc - 1; \
- (__i) >= 0 && \
- ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
- (old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), \
- (new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
- (__i)--) \
- for_each_if(crtc)
+ for_each_intel_crtc_reverse((__state)->base.dev, (crtc)) \
+ for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
+ (old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc)), \
+ (new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))))
#define intel_atomic_crtc_state_for_each_plane_state( \
plane, plane_state, \
diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
index d708d322aa85..d9baca2d5aaf 100644
--- a/drivers/gpu/drm/i915/display/intel_display_core.h
+++ b/drivers/gpu/drm/i915/display/intel_display_core.h
@@ -294,6 +294,9 @@ struct intel_display {
/* Parent, or core, driver functions exposed to display */
const struct intel_display_parent_interface *parent;
+ /* list of all intel_crtcs sorted by pipe */
+ struct list_head pipe_list;
+
/* Display functions */
struct {
/* Top level crtc-ish functions */
diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c
index 23bfecc983e8..9c2f7ad6c7b7 100644
--- a/drivers/gpu/drm/i915/display/intel_display_driver.c
+++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
@@ -117,6 +117,7 @@ static void intel_mode_config_init(struct intel_display *display)
drm_mode_config_init(display->drm);
INIT_LIST_HEAD(&display->global.obj_list);
+ INIT_LIST_HEAD(&display->pipe_list);
mode_config->min_width = 0;
mode_config->min_height = 0;
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index e2496db1642a..f6cd0a062090 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1484,6 +1484,7 @@ struct intel_flipq {
struct intel_crtc {
struct drm_crtc base;
+ struct list_head pipe_head;
enum pipe pipe;
/*
* Whether the crtc and the connected output pipeline is active. Implies
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 d0c76632a946..a8d56ebf06a2 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
@@ -615,8 +615,13 @@ check_if_vesa_backlight_possible(struct intel_dp *intel_dp)
int ret;
u8 bit_min, bit_max;
- if (!(intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP))
- return true;
+ /*
+ * Since we only support Fully AUX Based VESA Backlight interface make sure
+ * backlight enable is possible via AUX along with backlight adjustment
+ */
+ if (!(intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP &&
+ intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP))
+ return false;
ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &bit_min);
if (ret < 0)
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index d45b3bcc6ef0..e0ac4e2ce4dc 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -4028,8 +4028,8 @@ void intel_wm_state_verify(struct intel_atomic_state *state,
}
/* DDB */
- hw_ddb_entry = &hw->ddb[PLANE_CURSOR];
- sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb[PLANE_CURSOR];
+ hw_ddb_entry = &hw->ddb[plane->id];
+ sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb[plane->id];
if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) {
drm_err(display->drm,
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 5c72aad3dae7..aac6733ddd82 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -686,7 +686,8 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
if (radeon_crtc == NULL)
return;
- radeon_crtc->flip_queue = alloc_workqueue("radeon-crtc", WQ_HIGHPRI, 0);
+ radeon_crtc->flip_queue = alloc_workqueue("radeon-crtc",
+ WQ_HIGHPRI | WQ_PERCPU, 0);
if (!radeon_crtc->flip_queue) {
kfree(radeon_crtc);
return;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 87fd6255c114..53d06053dec8 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -278,14 +278,13 @@ static bool radeon_support_enabled(struct device *dev,
case CHIP_BONAIRE:
case CHIP_HAWAII:
- support_by_default = false;
- fallthrough;
case CHIP_KAVERI:
case CHIP_KABINI:
case CHIP_MULLINS:
gen = "CIK";
module_param = radeon_cik_support;
amdgpu_support_built &= IS_ENABLED(CONFIG_DRM_AMDGPU_CIK);
+ support_by_default = false;
break;
default:
diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c
index a0a4ddf3bb46..00dfa68af29a 100644
--- a/drivers/gpu/drm/xe/display/xe_display.c
+++ b/drivers/gpu/drm/xe/display/xe_display.c
@@ -21,6 +21,7 @@
#include "intel_audio.h"
#include "intel_bw.h"
#include "intel_display.h"
+#include "intel_display_core.h"
#include "intel_display_device.h"
#include "intel_display_driver.h"
#include "intel_display_irq.h"
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index af8b92d2d5b7..f83f28cae207 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -694,6 +694,39 @@ enum drm_bus_flags {
};
/**
+ * struct drm_amd_vsdb_info - AMD-specific VSDB information
+ *
+ * This structure holds information parsed from the AMD Vendor-Specific Data
+ * Block (VSDB) version 3.
+ */
+struct drm_amd_vsdb_info {
+ /**
+ * @version: Version of the Vendor-Specific Data Block (VSDB)
+ */
+ u8 version;
+
+ /**
+ * @replay_mode: Panel Replay supported
+ */
+ bool replay_mode;
+
+ /**
+ * @panel_type: Panel technology type
+ */
+ u8 panel_type;
+
+ /**
+ * @luminance_range1: Luminance for max back light
+ */
+ struct drm_luminance_range_info luminance_range1;
+
+ /**
+ * @luminance_range2: Luminance for min back light
+ */
+ struct drm_luminance_range_info luminance_range2;
+};
+
+/**
* struct drm_display_info - runtime data about the connected sink
*
* Describes a given display (e.g. CRT or flat panel) and its limitations. For
@@ -883,6 +916,11 @@ struct drm_display_info {
* Defaults to CEC_PHYS_ADDR_INVALID (0xffff).
*/
u16 source_physical_address;
+
+ /**
+ * @amd_vsdb: AMD-specific VSDB information.
+ */
+ struct drm_amd_vsdb_info amd_vsdb;
};
int drm_display_info_set_bus_formats(struct drm_display_info *info,