summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDanilo Krummrich <dakr@kernel.org>2026-01-26 13:23:52 +0100
committerDanilo Krummrich <dakr@kernel.org>2026-01-26 13:23:52 +0100
commiteb3dad518e4da48ab6c6df16aa8895b8b0bd6ecf (patch)
treef960c8ab666af10bccacc947aa42f0bf3b8b54dd /drivers/gpu
parent1cab0874875a1c37f71edf1e1e3029b1cf31d81e (diff)
parent63804fed149a6750ffd28610c5c1c98cce6bd377 (diff)
downloadlwn-eb3dad518e4da48ab6c6df16aa8895b8b0bd6ecf.tar.gz
lwn-eb3dad518e4da48ab6c6df16aa8895b8b0bd6ecf.zip
Merge tag 'v6.19-rc7' into driver-core-next
We need the driver-core fixes in here as well to build on top of. Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/Kconfig2
-rw-r--r--drivers/gpu/drm/Makefile4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_job.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c8
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_debug.h3
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c31
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c36
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h5
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c4
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c11
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c10
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_detection.c4
-rw-r--r--drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c31
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c3
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-dp.c20
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c9
-rw-r--r--drivers/gpu/drm/drm_gpuvm.c69
-rw-r--r--drivers/gpu/drm/gud/gud_pipe.c20
-rw-r--r--drivers/gpu/drm/i915/display/intel_color_pipeline.c36
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c2
-rw-r--r--drivers/gpu/drm/imagination/pvr_fw_trace.c8
-rw-r--r--drivers/gpu/drm/mediatek/Kconfig2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dpi.c23
-rw-r--r--drivers/gpu/drm/mediatek/mtk_gem.c264
-rw-r--r--drivers/gpu/drm/mediatek/mtk_gem.h33
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi_common.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi_common.h2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c58
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi_v2.c7
-rw-r--r--drivers/gpu/drm/mediatek/mtk_plane.c8
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/curs507a.c1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/head.c5
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h95
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c73
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c90
-rw-r--r--drivers/gpu/drm/panthor/panthor_mmu.c10
-rw-r--r--drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c14
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_vop2_reg.c17
-rw-r--r--drivers/gpu/drm/sysfb/drm_sysfb_helper.h9
-rw-r--r--drivers/gpu/drm/vkms/vkms_colorop.c15
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_bo.c22
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fence.c10
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c14
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_shader.c4
-rw-r--r--drivers/gpu/drm/xe/Kconfig5
-rw-r--r--drivers/gpu/drm/xe/xe_bo.c9
-rw-r--r--drivers/gpu/drm/xe/xe_debugfs.c72
-rw-r--r--drivers/gpu/drm/xe/xe_device_types.h18
-rw-r--r--drivers/gpu/drm/xe/xe_exec_queue.c32
-rw-r--r--drivers/gpu/drm/xe/xe_exec_queue.h1
-rw-r--r--drivers/gpu/drm/xe/xe_exec_queue_types.h6
-rw-r--r--drivers/gpu/drm/xe/xe_ggtt.c2
-rw-r--r--drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h4
-rw-r--r--drivers/gpu/drm/xe/xe_guc_ads.c14
-rw-r--r--drivers/gpu/drm/xe/xe_guc_ads.h5
-rw-r--r--drivers/gpu/drm/xe/xe_late_bind_fw_types.h4
-rw-r--r--drivers/gpu/drm/xe/xe_lrc.c3
-rw-r--r--drivers/gpu/drm/xe/xe_migrate.c4
-rw-r--r--drivers/gpu/drm/xe/xe_sriov_vf_ccs.c2
-rw-r--r--drivers/gpu/drm/xe/xe_vm.c7
-rw-r--r--drivers/gpu/drm/xe/xe_vm.h2
78 files changed, 823 insertions, 580 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 7e6bc0b3a589..ed85d0ceee3b 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -210,7 +210,7 @@ config DRM_GPUVM
config DRM_GPUSVM
tristate
- depends on DRM && DEVICE_PRIVATE
+ depends on DRM
select HMM_MIRROR
select MMU_NOTIFIER
help
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 0e1c668b46d2..d26191717428 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -108,8 +108,10 @@ obj-$(CONFIG_DRM_EXEC) += drm_exec.o
obj-$(CONFIG_DRM_GPUVM) += drm_gpuvm.o
drm_gpusvm_helper-y := \
- drm_gpusvm.o\
+ drm_gpusvm.o
+drm_gpusvm_helper-$(CONFIG_ZONE_DEVICE) += \
drm_pagemap.o
+
obj-$(CONFIG_DRM_GPUSVM) += drm_gpusvm_helper.o
obj-$(CONFIG_DRM_BUDDY) += drm_buddy.o
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 9f9774f58ce1..b20a06abb65d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -274,6 +274,8 @@ extern int amdgpu_rebar;
extern int amdgpu_wbrf;
extern int amdgpu_user_queue;
+extern uint amdgpu_hdmi_hpd_debounce_delay_ms;
+
#define AMDGPU_VM_MAX_NUM_CTX 4096
#define AMDGPU_SG_THRESHOLD (256*1024*1024)
#define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index d5c44bd34d45..d2c3885de711 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -5063,6 +5063,14 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
amdgpu_ttm_set_buffer_funcs_status(adev, false);
+ /*
+ * device went through surprise hotplug; we need to destroy topology
+ * before ip_fini_early to prevent kfd locking refcount issues by calling
+ * amdgpu_amdkfd_suspend()
+ */
+ if (drm_dev_is_unplugged(adev_to_drm(adev)))
+ amdgpu_amdkfd_device_fini_sw(adev);
+
amdgpu_device_ip_fini_early(adev);
amdgpu_irq_fini_hw(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index b5d34797d606..52bc04452812 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -1880,7 +1880,12 @@ int amdgpu_display_get_scanout_buffer(struct drm_plane *plane,
struct drm_scanout_buffer *sb)
{
struct amdgpu_bo *abo;
- struct drm_framebuffer *fb = plane->state->fb;
+ struct drm_framebuffer *fb;
+
+ if (drm_drv_uses_atomic_modeset(plane->dev))
+ fb = plane->state->fb;
+ else
+ fb = plane->fb;
if (!fb)
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index e22cfa7c6d32..c1461317eb29 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -95,18 +95,6 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
bo->flags & AMDGPU_GEM_CREATE_GFX12_DCC)
attach->peer2peer = false;
- /*
- * Disable peer-to-peer access for DCC-enabled VRAM surfaces on GFX12+.
- * Such buffers cannot be safely accessed over P2P due to device-local
- * compression metadata. Fallback to system-memory path instead.
- * Device supports GFX12 (GC 12.x or newer)
- * BO was created with the AMDGPU_GEM_CREATE_GFX12_DCC flag
- *
- */
- if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 0, 0) &&
- bo->flags & AMDGPU_GEM_CREATE_GFX12_DCC)
- attach->peer2peer = false;
-
if (!amdgpu_dmabuf_is_xgmi_accessible(attach_adev, bo) &&
pci_p2pdma_distance(adev->pdev, attach->dev, false) < 0)
attach->peer2peer = false;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 848e6b7db482..6ccb80e2d7c9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -247,6 +247,7 @@ int amdgpu_damage_clips = -1; /* auto */
int amdgpu_umsch_mm_fwlog;
int amdgpu_rebar = -1; /* auto */
int amdgpu_user_queue = -1;
+uint amdgpu_hdmi_hpd_debounce_delay_ms;
DECLARE_DYNDBG_CLASSMAP(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS, 0,
"DRM_UT_CORE",
@@ -1123,6 +1124,16 @@ module_param_named(rebar, amdgpu_rebar, int, 0444);
MODULE_PARM_DESC(user_queue, "Enable user queues (-1 = auto (default), 0 = disable, 1 = enable, 2 = enable UQs and disable KQs)");
module_param_named(user_queue, amdgpu_user_queue, int, 0444);
+/*
+ * DOC: hdmi_hpd_debounce_delay_ms (uint)
+ * HDMI HPD disconnect debounce delay in milliseconds.
+ *
+ * Used to filter short disconnect->reconnect HPD toggles some HDMI sinks
+ * generate while entering/leaving power save. Set to 0 to disable by default.
+ */
+MODULE_PARM_DESC(hdmi_hpd_debounce_delay_ms, "HDMI HPD disconnect debounce delay in milliseconds (0 to disable (by default), 1500 is common)");
+module_param_named(hdmi_hpd_debounce_delay_ms, amdgpu_hdmi_hpd_debounce_delay_ms, uint, 0644);
+
/* These devices are not supported by amdgpu.
* They are supported by the mach64, r128, radeon drivers
*/
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index 06c333b2213b..d78d9e7fb9d1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -763,7 +763,7 @@ void amdgpu_fence_save_wptr(struct amdgpu_fence *af)
}
static void amdgpu_ring_backup_unprocessed_command(struct amdgpu_ring *ring,
- u64 start_wptr, u32 end_wptr)
+ u64 start_wptr, u64 end_wptr)
{
unsigned int first_idx = start_wptr & ring->buf_mask;
unsigned int last_idx = end_wptr & ring->buf_mask;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
index d2237ce9da70..1485f4789440 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
@@ -375,7 +375,7 @@ void amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
* @start_page: first page to map in the GART aperture
* @num_pages: number of pages to be mapped
* @flags: page table entry flags
- * @dst: CPU address of the GART table
+ * @dst: valid CPU address of GART table, cannot be null
*
* Binds a BO that is allocated in VRAM to the GART page table
* (all ASICs).
@@ -396,7 +396,7 @@ void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
return;
for (i = 0; i < num_pages; ++i) {
- amdgpu_gmc_set_pte_pde(adev, adev->gart.ptr,
+ amdgpu_gmc_set_pte_pde(adev, dst,
start_page + i, pa + AMDGPU_GPU_PAGE_SIZE * i, flags);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index 869bceb0fe2c..7e623f91f2d7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -732,6 +732,12 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
return 0;
if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready) {
+
+ if (!adev->gmc.gmc_funcs->flush_gpu_tlb_pasid) {
+ r = 0;
+ goto error_unlock_reset;
+ }
+
if (adev->gmc.flush_tlb_needs_extra_type_2)
adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,
2, all_hub,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index 586a58facca1..72ec455fa932 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -302,7 +302,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
if (job && job->vmid)
amdgpu_vmid_reset(adev, ring->vm_hub, job->vmid);
amdgpu_ring_undo(ring);
- return r;
+ goto free_fence;
}
*f = &af->base;
/* get a ref for the job */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index 0a0dcbf0798d..7ccb724b2488 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -217,8 +217,11 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
if (!entity)
return 0;
- return drm_sched_job_init(&(*job)->base, entity, 1, owner,
- drm_client_id);
+ r = drm_sched_job_init(&(*job)->base, entity, 1, owner, drm_client_id);
+ if (!r)
+ return 0;
+
+ kfree((*job)->hw_vm_fence);
err_fence:
kfree((*job)->hw_fence);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
index 9a969175900e..58b26c78b642 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -885,12 +885,28 @@ static int amdgpu_userq_input_args_validate(struct drm_device *dev,
return 0;
}
+bool amdgpu_userq_enabled(struct drm_device *dev)
+{
+ struct amdgpu_device *adev = drm_to_adev(dev);
+ int i;
+
+ for (i = 0; i < AMDGPU_HW_IP_NUM; i++) {
+ if (adev->userq_funcs[i])
+ return true;
+ }
+
+ return false;
+}
+
int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp)
{
union drm_amdgpu_userq *args = data;
int r;
+ if (!amdgpu_userq_enabled(dev))
+ return -ENOTSUPP;
+
if (amdgpu_userq_input_args_validate(dev, args, filp) < 0)
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
index c37444427a14..b48b3bc293fc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
@@ -141,6 +141,7 @@ uint64_t amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
struct drm_file *filp);
u32 amdgpu_userq_get_supported_ip_mask(struct amdgpu_device *adev);
+bool amdgpu_userq_enabled(struct drm_device *dev);
int amdgpu_userq_suspend(struct amdgpu_device *adev);
int amdgpu_userq_resume(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
index eba9fb359047..85e9edc1cb6f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
@@ -141,6 +141,8 @@ static void amdgpu_userq_walk_and_drop_fence_drv(struct xarray *xa)
void
amdgpu_userq_fence_driver_free(struct amdgpu_usermode_queue *userq)
{
+ dma_fence_put(userq->last_fence);
+
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 */
@@ -471,6 +473,9 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
struct drm_exec exec;
u64 wptr;
+ if (!amdgpu_userq_enabled(dev))
+ return -ENOTSUPP;
+
num_syncobj_handles = args->num_syncobj_handles;
syncobj_handles = memdup_user(u64_to_user_ptr(args->syncobj_handles),
size_mul(sizeof(u32), num_syncobj_handles));
@@ -653,6 +658,9 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
int r, i, rentry, wentry, cnt;
struct drm_exec exec;
+ if (!amdgpu_userq_enabled(dev))
+ return -ENOTSUPP;
+
num_read_bo_handles = wait_info->num_bo_read_handles;
bo_handles_read = memdup_user(u64_to_user_ptr(wait_info->bo_read_handles),
size_mul(sizeof(u32), num_read_bo_handles));
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index c362d4dfb5bb..a67285118c37 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -1069,9 +1069,7 @@ amdgpu_vm_tlb_flush(struct amdgpu_vm_update_params *params,
}
/* Prepare a TLB flush fence to be attached to PTs */
- if (!params->unlocked &&
- /* SI doesn't support pasid or KIQ/MES */
- params->adev->family > AMDGPU_FAMILY_SI) {
+ if (!params->unlocked) {
amdgpu_vm_tlb_fence_create(params->adev, vm, fence);
/* Makes sure no PD/PT is freed before the flush */
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
index d01d2712cf57..b786967022d2 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
@@ -278,7 +278,6 @@ static void gfx_v12_0_select_se_sh(struct amdgpu_device *adev, u32 se_num,
u32 sh_num, u32 instance, int xcc_id);
static u32 gfx_v12_0_get_wgp_active_bitmap_per_sh(struct amdgpu_device *adev);
-static void gfx_v12_0_ring_emit_frame_cntl(struct amdgpu_ring *ring, bool start, bool secure);
static void gfx_v12_0_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg,
uint32_t val);
static int gfx_v12_0_wait_for_rlc_autoload_complete(struct amdgpu_device *adev);
@@ -4634,16 +4633,6 @@ static int gfx_v12_0_ring_preempt_ib(struct amdgpu_ring *ring)
return r;
}
-static void gfx_v12_0_ring_emit_frame_cntl(struct amdgpu_ring *ring,
- bool start,
- bool secure)
-{
- uint32_t v = secure ? FRAME_TMZ : 0;
-
- amdgpu_ring_write(ring, PACKET3(PACKET3_FRAME_CONTROL, 0));
- amdgpu_ring_write(ring, v | FRAME_CMD(start ? 0 : 1));
-}
-
static void gfx_v12_0_ring_emit_rreg(struct amdgpu_ring *ring, uint32_t reg,
uint32_t reg_val_offs)
{
@@ -5520,7 +5509,6 @@ static const struct amdgpu_ring_funcs gfx_v12_0_ring_funcs_gfx = {
.emit_cntxcntl = gfx_v12_0_ring_emit_cntxcntl,
.init_cond_exec = gfx_v12_0_ring_emit_init_cond_exec,
.preempt_ib = gfx_v12_0_ring_preempt_ib,
- .emit_frame_cntl = gfx_v12_0_ring_emit_frame_cntl,
.emit_wreg = gfx_v12_0_ring_emit_wreg,
.emit_reg_wait = gfx_v12_0_ring_emit_reg_wait,
.emit_reg_write_reg_wait = gfx_v12_0_ring_emit_reg_write_reg_wait,
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 8ad7519f7b58..f1ee3921d970 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -1235,16 +1235,16 @@ static void gmc_v9_0_get_vm_pte(struct amdgpu_device *adev,
*flags = AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_NC);
break;
case AMDGPU_VM_MTYPE_WC:
- *flags |= AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_WC);
+ *flags = AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_WC);
break;
case AMDGPU_VM_MTYPE_RW:
- *flags |= AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_RW);
+ *flags = AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_RW);
break;
case AMDGPU_VM_MTYPE_CC:
- *flags |= AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_CC);
+ *flags = AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_CC);
break;
case AMDGPU_VM_MTYPE_UC:
- *flags |= AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_UC);
+ *flags = AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_UC);
break;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_debug.h b/drivers/gpu/drm/amd/amdkfd/kfd_debug.h
index 27aa1a5b120f..fbb751821c69 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_debug.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_debug.h
@@ -120,8 +120,7 @@ static inline bool kfd_dbg_has_gws_support(struct kfd_node *dev)
&& dev->kfd->mec2_fw_version < 0x1b6) ||
(KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 1)
&& dev->kfd->mec2_fw_version < 0x30) ||
- (KFD_GC_VERSION(dev) >= IP_VERSION(11, 0, 0) &&
- KFD_GC_VERSION(dev) < IP_VERSION(12, 0, 0)))
+ kfd_dbg_has_cwsr_workaround(dev))
return false;
/* Assume debugging and cooperative launch supported otherwise. */
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index d7a2e7178ea9..625ea8ab7a74 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -1209,14 +1209,8 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm,
pr_debug_ratelimited("Evicting process pid %d queues\n",
pdd->process->lead_thread->pid);
- if (dqm->dev->kfd->shared_resources.enable_mes) {
+ if (dqm->dev->kfd->shared_resources.enable_mes)
pdd->last_evict_timestamp = get_jiffies_64();
- retval = suspend_all_queues_mes(dqm);
- if (retval) {
- dev_err(dev, "Suspending all queues failed");
- goto out;
- }
- }
/* Mark all queues as evicted. Deactivate all active queues on
* the qpd.
@@ -1246,10 +1240,6 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm,
KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES :
KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0,
USE_DEFAULT_GRACE_PERIOD);
- } else {
- retval = resume_all_queues_mes(dqm);
- if (retval)
- dev_err(dev, "Resuming all queues failed");
}
out:
@@ -2919,6 +2909,14 @@ static int allocate_hiq_sdma_mqd(struct device_queue_manager *dqm)
return retval;
}
+static void deallocate_hiq_sdma_mqd(struct kfd_node *dev,
+ struct kfd_mem_obj *mqd)
+{
+ WARN(!mqd, "No hiq sdma mqd trunk to free");
+
+ amdgpu_amdkfd_free_gtt_mem(dev->adev, &mqd->gtt_mem);
+}
+
struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev)
{
struct device_queue_manager *dqm;
@@ -3042,19 +3040,14 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev)
return dqm;
}
+ if (!dev->kfd->shared_resources.enable_mes)
+ deallocate_hiq_sdma_mqd(dev, &dqm->hiq_sdma_mqd);
+
out_free:
kfree(dqm);
return NULL;
}
-static void deallocate_hiq_sdma_mqd(struct kfd_node *dev,
- struct kfd_mem_obj *mqd)
-{
- WARN(!mqd, "No hiq sdma mqd trunk to free");
-
- amdgpu_amdkfd_free_gtt_mem(dev->adev, &mqd->gtt_mem);
-}
-
void device_queue_manager_uninit(struct device_queue_manager *dqm)
{
dqm->ops.stop(dqm);
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 740711ac1037..1ea5a250440f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5266,6 +5266,8 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
struct amdgpu_dm_backlight_caps *caps;
char bl_name[16];
int min, max;
+ int real_brightness;
+ int init_brightness;
if (aconnector->bl_idx == -1)
return;
@@ -5290,6 +5292,8 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
} else
props.brightness = props.max_brightness = MAX_BACKLIGHT_LEVEL;
+ init_brightness = props.brightness;
+
if (caps->data_points && !(amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE)) {
drm_info(drm, "Using custom brightness curve\n");
props.scale = BACKLIGHT_SCALE_NON_LINEAR;
@@ -5308,8 +5312,20 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
if (IS_ERR(dm->backlight_dev[aconnector->bl_idx])) {
drm_err(drm, "DM: Backlight registration failed!\n");
dm->backlight_dev[aconnector->bl_idx] = NULL;
- } else
+ } else {
+ /*
+ * dm->brightness[x] can be inconsistent just after startup until
+ * ops.get_brightness is called.
+ */
+ real_brightness =
+ amdgpu_dm_backlight_ops.get_brightness(dm->backlight_dev[aconnector->bl_idx]);
+
+ if (real_brightness != init_brightness) {
+ dm->actual_brightness[aconnector->bl_idx] = real_brightness;
+ dm->brightness[aconnector->bl_idx] = real_brightness;
+ }
drm_dbg_driver(drm, "DM: Registered Backlight device: %s\n", bl_name);
+ }
}
static int initialize_plane(struct amdgpu_display_manager *dm,
@@ -5626,7 +5642,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
if (psr_feature_enabled) {
amdgpu_dm_set_psr_caps(link);
- drm_info(adev_to_drm(adev), "PSR support %d, DC PSR ver %d, sink PSR ver %d DPCD caps 0x%x su_y_granularity %d\n",
+ drm_info(adev_to_drm(adev), "%s: PSR support %d, DC PSR ver %d, sink PSR ver %d DPCD caps 0x%x su_y_granularity %d\n",
+ aconnector->base.name,
link->psr_settings.psr_feature_enabled,
link->psr_settings.psr_version,
link->dpcd_caps.psr_info.psr_version,
@@ -8930,9 +8947,18 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
mutex_init(&aconnector->hpd_lock);
mutex_init(&aconnector->handle_mst_msg_ready);
- aconnector->hdmi_hpd_debounce_delay_ms = AMDGPU_DM_HDMI_HPD_DEBOUNCE_MS;
- INIT_DELAYED_WORK(&aconnector->hdmi_hpd_debounce_work, hdmi_hpd_debounce_work);
- aconnector->hdmi_prev_sink = NULL;
+ /*
+ * If HDMI HPD debounce delay is set, use the minimum between selected
+ * value and AMDGPU_DM_MAX_HDMI_HPD_DEBOUNCE_MS
+ */
+ if (amdgpu_hdmi_hpd_debounce_delay_ms) {
+ aconnector->hdmi_hpd_debounce_delay_ms = min(amdgpu_hdmi_hpd_debounce_delay_ms,
+ AMDGPU_DM_MAX_HDMI_HPD_DEBOUNCE_MS);
+ INIT_DELAYED_WORK(&aconnector->hdmi_hpd_debounce_work, hdmi_hpd_debounce_work);
+ aconnector->hdmi_prev_sink = NULL;
+ } else {
+ aconnector->hdmi_hpd_debounce_delay_ms = 0;
+ }
/*
* configure support HPD hot plug connector_>polled default value is 0
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 bd0403005f37..beb0d04d3e68 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -59,7 +59,10 @@
#define AMDGPU_HDR_MULT_DEFAULT (0x100000000LL)
-#define AMDGPU_DM_HDMI_HPD_DEBOUNCE_MS 1500
+/*
+ * Maximum HDMI HPD debounce delay in milliseconds
+ */
+#define AMDGPU_DM_MAX_HDMI_HPD_DEBOUNCE_MS 5000
/*
#include "include/amdgpu_dal_power_if.h"
#include "amdgpu_dm_irq.h"
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index d585618b8064..a2de3bba8346 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -79,7 +79,6 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
goto cleanup;
list->type = ops[i]->base.id;
- list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[i]->base.id);
i++;
@@ -197,6 +196,9 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
goto cleanup;
drm_colorop_set_next_property(ops[i-1], ops[i]);
+
+ list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[0]->base.id);
+
return 0;
cleanup:
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 697e232acebf..9fcd72d87d25 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
@@ -248,8 +248,6 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
struct vblank_control_work *vblank_work =
container_of(work, struct vblank_control_work, work);
struct amdgpu_display_manager *dm = vblank_work->dm;
- struct amdgpu_device *adev = drm_to_adev(dm->ddev);
- int r;
mutex_lock(&dm->dc_lock);
@@ -279,16 +277,7 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
if (dm->active_vblank_irq_count == 0) {
dc_post_update_surfaces_to_stream(dm->dc);
-
- r = amdgpu_dpm_pause_power_profile(adev, true);
- if (r)
- dev_warn(adev->dev, "failed to set default power profile mode\n");
-
dc_allow_idle_optimizations(dm->dc, true);
-
- r = amdgpu_dpm_pause_power_profile(adev, false);
- if (r)
- dev_warn(adev->dev, "failed to restore the power profile mode\n");
}
mutex_unlock(&dm->dc_lock);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
index 0a2a3f233a0e..e7b0928bd3db 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
@@ -915,13 +915,19 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
struct amdgpu_dm_connector *amdgpu_dm_connector;
const struct dc_link *dc_link;
- use_polling |= connector->polled != DRM_CONNECTOR_POLL_HPD;
-
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
continue;
amdgpu_dm_connector = to_amdgpu_dm_connector(connector);
+ /*
+ * Analog connectors may be hot-plugged unlike other connector
+ * types that don't support HPD. Only poll analog connectors.
+ */
+ use_polling |=
+ amdgpu_dm_connector->dc_link &&
+ dc_connector_supports_analog(amdgpu_dm_connector->dc_link->link_id.id);
+
dc_link = amdgpu_dm_connector->dc_link;
/*
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index 2e3ee78999d9..7c4496fb4b9d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1790,12 +1790,13 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
static int
dm_plane_init_colorops(struct drm_plane *plane)
{
- struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
+ struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES] = {};
struct drm_device *dev = plane->dev;
struct amdgpu_device *adev = drm_to_adev(dev);
struct dc *dc = adev->dm.dc;
int len = 0;
- int ret;
+ int ret = 0;
+ int i;
if (plane->type == DRM_PLANE_TYPE_CURSOR)
return 0;
@@ -1806,7 +1807,7 @@ dm_plane_init_colorops(struct drm_plane *plane)
if (ret) {
drm_err(plane->dev, "Failed to create color pipeline for plane %d: %d\n",
plane->base.id, ret);
- return ret;
+ goto out;
}
len++;
@@ -1814,7 +1815,11 @@ dm_plane_init_colorops(struct drm_plane *plane)
drm_plane_create_color_pipeline_property(plane, pipelines, len);
}
- return 0;
+out:
+ for (i = 0; i < len; i++)
+ kfree(pipelines[i].name);
+
+ return ret;
}
#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h b/drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h
index b015e80672ec..fcd3ab4b0045 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h
@@ -41,7 +41,7 @@
/* kHZ*/
#define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000
/* kHZ*/
-#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000
+#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 340000
struct dp_hdmi_dongle_signature_data {
int8_t id[15];/* "DP-HDMI ADAPTOR"*/
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
index e1940b8e5bc3..7fa6bc97a919 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
@@ -336,7 +336,7 @@ static void query_dp_dual_mode_adaptor(
/* Assume we have no valid DP passive dongle connected */
*dongle = DISPLAY_DONGLE_NONE;
- sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK;
+ sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK;
/* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/
if (!i2c_read(
@@ -392,6 +392,8 @@ static void query_dp_dual_mode_adaptor(
}
}
+ if (is_valid_hdmi_signature)
+ sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK;
if (is_type2_dongle) {
uint32_t max_tmds_clk =
diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
index 1f539cc65f41..695432d3045f 100644
--- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
+++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
@@ -2273,8 +2273,6 @@ static int si_populate_smc_tdp_limits(struct amdgpu_device *adev,
if (scaling_factor == 0)
return -EINVAL;
- memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE));
-
ret = si_calculate_adjusted_tdp_limits(adev,
false, /* ??? */
adev->pm.dpm.tdp_adjustment,
@@ -2283,6 +2281,12 @@ static int si_populate_smc_tdp_limits(struct amdgpu_device *adev,
if (ret)
return ret;
+ if (adev->pdev->device == 0x6611 && adev->pdev->revision == 0x87) {
+ /* Workaround buggy powertune on Radeon 430 and 520. */
+ tdp_limit = 32;
+ near_tdp_limit = 28;
+ }
+
smc_table->dpm2Params.TDPLimit =
cpu_to_be32(si_scale_power_for_smc(tdp_limit, scaling_factor) * 1000);
smc_table->dpm2Params.NearTDPLimit =
@@ -2328,16 +2332,8 @@ static int si_populate_smc_tdp_limits_2(struct amdgpu_device *adev,
if (ni_pi->enable_power_containment) {
SISLANDS_SMC_STATETABLE *smc_table = &si_pi->smc_statetable;
- u32 scaling_factor = si_get_smc_power_scaling_factor(adev);
int ret;
- memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE));
-
- smc_table->dpm2Params.NearTDPLimit =
- cpu_to_be32(si_scale_power_for_smc(adev->pm.dpm.near_tdp_limit_adjusted, scaling_factor) * 1000);
- smc_table->dpm2Params.SafePowerLimit =
- cpu_to_be32(si_scale_power_for_smc((adev->pm.dpm.near_tdp_limit_adjusted * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000);
-
ret = amdgpu_si_copy_bytes_to_smc(adev,
(si_pi->state_table_start +
offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) +
@@ -3473,10 +3469,15 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,
(adev->pdev->revision == 0x80) ||
(adev->pdev->revision == 0x81) ||
(adev->pdev->revision == 0x83) ||
- (adev->pdev->revision == 0x87) ||
+ (adev->pdev->revision == 0x87 &&
+ adev->pdev->device != 0x6611) ||
(adev->pdev->device == 0x6604) ||
(adev->pdev->device == 0x6605)) {
max_sclk = 75000;
+ } else if (adev->pdev->revision == 0x87 &&
+ adev->pdev->device == 0x6611) {
+ /* Radeon 430 and 520 */
+ max_sclk = 78000;
}
}
@@ -7600,12 +7601,12 @@ static int si_dpm_set_interrupt_state(struct amdgpu_device *adev,
case AMDGPU_IRQ_STATE_DISABLE:
cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);
cg_thermal_int |= CG_THERMAL_INT__THERM_INT_MASK_HIGH_MASK;
- WREG32_SMC(mmCG_THERMAL_INT, cg_thermal_int);
+ WREG32(mmCG_THERMAL_INT, cg_thermal_int);
break;
case AMDGPU_IRQ_STATE_ENABLE:
cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);
cg_thermal_int &= ~CG_THERMAL_INT__THERM_INT_MASK_HIGH_MASK;
- WREG32_SMC(mmCG_THERMAL_INT, cg_thermal_int);
+ WREG32(mmCG_THERMAL_INT, cg_thermal_int);
break;
default:
break;
@@ -7617,12 +7618,12 @@ static int si_dpm_set_interrupt_state(struct amdgpu_device *adev,
case AMDGPU_IRQ_STATE_DISABLE:
cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);
cg_thermal_int |= CG_THERMAL_INT__THERM_INT_MASK_LOW_MASK;
- WREG32_SMC(mmCG_THERMAL_INT, cg_thermal_int);
+ WREG32(mmCG_THERMAL_INT, cg_thermal_int);
break;
case AMDGPU_IRQ_STATE_ENABLE:
cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);
cg_thermal_int &= ~CG_THERMAL_INT__THERM_INT_MASK_LOW_MASK;
- WREG32_SMC(mmCG_THERMAL_INT, cg_thermal_int);
+ WREG32(mmCG_THERMAL_INT, cg_thermal_int);
break;
default:
break;
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 33c3cd2e1e24..d7642d388bc3 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
@@ -1702,8 +1702,9 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu,
table_context->power_play_table;
PPTable_t *pptable = table_context->driver_pptable;
CustomSkuTable_t *skutable = &pptable->CustomSkuTable;
- uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
+ int16_t od_percent_upper = 0, od_percent_lower = 0;
uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
+ uint32_t power_limit;
if (smu_v14_0_get_current_power_limit(smu, &power_limit))
power_limit = smu->adev->pm.ac_power ?
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-dp.c b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
index 82aaf74e1bc0..432342452484 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-dp.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
@@ -2062,33 +2062,41 @@ struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
}
ret = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
- if (ret)
+ if (ret) {
dev_err_probe(dev, ret, "Failed to attach bridge\n");
+ goto unregister_aux;
+ }
dw_dp_init_hw(dp);
ret = phy_init(dp->phy);
if (ret) {
dev_err_probe(dev, ret, "phy init failed\n");
- return ERR_PTR(ret);
+ goto unregister_aux;
}
ret = devm_add_action_or_reset(dev, dw_dp_phy_exit, dp);
if (ret)
- return ERR_PTR(ret);
+ goto unregister_aux;
dp->irq = platform_get_irq(pdev, 0);
- if (dp->irq < 0)
- return ERR_PTR(ret);
+ if (dp->irq < 0) {
+ ret = dp->irq;
+ goto unregister_aux;
+ }
ret = devm_request_threaded_irq(dev, dp->irq, NULL, dw_dp_irq,
IRQF_ONESHOT, dev_name(dev), dp);
if (ret) {
dev_err_probe(dev, ret, "failed to request irq\n");
- return ERR_PTR(ret);
+ goto unregister_aux;
}
return dp;
+
+unregister_aux:
+ drm_dp_aux_unregister(&dp->aux);
+ return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(dw_dp_bind);
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
index fe4c026280f0..60166919c5b5 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
@@ -163,6 +163,7 @@ struct dw_hdmi_qp {
unsigned long ref_clk_rate;
struct regmap *regm;
+ int main_irq;
unsigned long tmds_char_rate;
};
@@ -1271,6 +1272,7 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,
dw_hdmi_qp_init_hw(hdmi);
+ hdmi->main_irq = plat_data->main_irq;
ret = devm_request_threaded_irq(dev, plat_data->main_irq,
dw_hdmi_qp_main_hardirq, NULL,
IRQF_SHARED, dev_name(dev), hdmi);
@@ -1331,9 +1333,16 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,
}
EXPORT_SYMBOL_GPL(dw_hdmi_qp_bind);
+void dw_hdmi_qp_suspend(struct device *dev, struct dw_hdmi_qp *hdmi)
+{
+ disable_irq(hdmi->main_irq);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_qp_suspend);
+
void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi)
{
dw_hdmi_qp_init_hw(hdmi);
+ enable_irq(hdmi->main_irq);
}
EXPORT_SYMBOL_GPL(dw_hdmi_qp_resume);
diff --git a/drivers/gpu/drm/drm_gpuvm.c b/drivers/gpu/drm/drm_gpuvm.c
index 8a06d296561d..0de47e83d84d 100644
--- a/drivers/gpu/drm/drm_gpuvm.c
+++ b/drivers/gpu/drm/drm_gpuvm.c
@@ -1602,14 +1602,48 @@ drm_gpuvm_bo_create(struct drm_gpuvm *gpuvm,
}
EXPORT_SYMBOL_GPL(drm_gpuvm_bo_create);
+/*
+ * drm_gpuvm_bo_destroy_not_in_lists() - final part of drm_gpuvm_bo cleanup
+ * @vm_bo: the &drm_gpuvm_bo to destroy
+ *
+ * It is illegal to call this method if the @vm_bo is present in the GEMs gpuva
+ * list, the extobj list, or the evicted list.
+ *
+ * Note that this puts a refcount on the GEM object, which may destroy the GEM
+ * object if the refcount reaches zero. It's illegal for this to happen if the
+ * caller holds the GEMs gpuva mutex because it would free the mutex.
+ */
+static void
+drm_gpuvm_bo_destroy_not_in_lists(struct drm_gpuvm_bo *vm_bo)
+{
+ struct drm_gpuvm *gpuvm = vm_bo->vm;
+ const struct drm_gpuvm_ops *ops = gpuvm->ops;
+ struct drm_gem_object *obj = vm_bo->obj;
+
+ if (ops && ops->vm_bo_free)
+ ops->vm_bo_free(vm_bo);
+ else
+ kfree(vm_bo);
+
+ drm_gpuvm_put(gpuvm);
+ drm_gem_object_put(obj);
+}
+
+static void
+drm_gpuvm_bo_destroy_not_in_lists_kref(struct kref *kref)
+{
+ struct drm_gpuvm_bo *vm_bo = container_of(kref, struct drm_gpuvm_bo,
+ kref);
+
+ drm_gpuvm_bo_destroy_not_in_lists(vm_bo);
+}
+
static void
drm_gpuvm_bo_destroy(struct kref *kref)
{
struct drm_gpuvm_bo *vm_bo = container_of(kref, struct drm_gpuvm_bo,
kref);
struct drm_gpuvm *gpuvm = vm_bo->vm;
- const struct drm_gpuvm_ops *ops = gpuvm->ops;
- struct drm_gem_object *obj = vm_bo->obj;
bool lock = !drm_gpuvm_resv_protected(gpuvm);
if (!lock)
@@ -1618,16 +1652,10 @@ drm_gpuvm_bo_destroy(struct kref *kref)
drm_gpuvm_bo_list_del(vm_bo, extobj, lock);
drm_gpuvm_bo_list_del(vm_bo, evict, lock);
- drm_gem_gpuva_assert_lock_held(gpuvm, obj);
+ drm_gem_gpuva_assert_lock_held(gpuvm, vm_bo->obj);
list_del(&vm_bo->list.entry.gem);
- if (ops && ops->vm_bo_free)
- ops->vm_bo_free(vm_bo);
- else
- kfree(vm_bo);
-
- drm_gpuvm_put(gpuvm);
- drm_gem_object_put(obj);
+ drm_gpuvm_bo_destroy_not_in_lists(vm_bo);
}
/**
@@ -1745,9 +1773,7 @@ EXPORT_SYMBOL_GPL(drm_gpuvm_bo_put_deferred);
void
drm_gpuvm_bo_deferred_cleanup(struct drm_gpuvm *gpuvm)
{
- const struct drm_gpuvm_ops *ops = gpuvm->ops;
struct drm_gpuvm_bo *vm_bo;
- struct drm_gem_object *obj;
struct llist_node *bo_defer;
bo_defer = llist_del_all(&gpuvm->bo_defer);
@@ -1766,14 +1792,7 @@ drm_gpuvm_bo_deferred_cleanup(struct drm_gpuvm *gpuvm)
while (bo_defer) {
vm_bo = llist_entry(bo_defer, struct drm_gpuvm_bo, list.entry.bo_defer);
bo_defer = bo_defer->next;
- obj = vm_bo->obj;
- if (ops && ops->vm_bo_free)
- ops->vm_bo_free(vm_bo);
- else
- kfree(vm_bo);
-
- drm_gpuvm_put(gpuvm);
- drm_gem_object_put(obj);
+ drm_gpuvm_bo_destroy_not_in_lists(vm_bo);
}
}
EXPORT_SYMBOL_GPL(drm_gpuvm_bo_deferred_cleanup);
@@ -1861,6 +1880,9 @@ EXPORT_SYMBOL_GPL(drm_gpuvm_bo_obtain);
* count is decreased. If not found @__vm_bo is returned without further
* increase of the reference count.
*
+ * The provided @__vm_bo must not already be in the gpuva, evict, or extobj
+ * lists prior to calling this method.
+ *
* A new &drm_gpuvm_bo is added to the GEMs gpuva list.
*
* Returns: a pointer to the found &drm_gpuvm_bo or @__vm_bo if no existing
@@ -1873,14 +1895,19 @@ drm_gpuvm_bo_obtain_prealloc(struct drm_gpuvm_bo *__vm_bo)
struct drm_gem_object *obj = __vm_bo->obj;
struct drm_gpuvm_bo *vm_bo;
+ drm_WARN_ON(gpuvm->drm, !drm_gpuvm_immediate_mode(gpuvm));
+
+ mutex_lock(&obj->gpuva.lock);
vm_bo = drm_gpuvm_bo_find(gpuvm, obj);
if (vm_bo) {
- drm_gpuvm_bo_put(__vm_bo);
+ mutex_unlock(&obj->gpuva.lock);
+ kref_put(&__vm_bo->kref, drm_gpuvm_bo_destroy_not_in_lists_kref);
return vm_bo;
}
drm_gem_gpuva_assert_lock_held(gpuvm, obj);
list_add_tail(&__vm_bo->list.entry.gem, &obj->gpuva.list);
+ mutex_unlock(&obj->gpuva.lock);
return __vm_bo;
}
diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c
index 76d77a736d84..4b77be94348d 100644
--- a/drivers/gpu/drm/gud/gud_pipe.c
+++ b/drivers/gpu/drm/gud/gud_pipe.c
@@ -457,27 +457,20 @@ int gud_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
struct drm_crtc *crtc = new_plane_state->crtc;
- struct drm_crtc_state *crtc_state;
+ struct drm_crtc_state *crtc_state = NULL;
const struct drm_display_mode *mode;
struct drm_framebuffer *old_fb = old_plane_state->fb;
struct drm_connector_state *connector_state = NULL;
struct drm_framebuffer *fb = new_plane_state->fb;
- const struct drm_format_info *format = fb->format;
+ const struct drm_format_info *format;
struct drm_connector *connector;
unsigned int i, num_properties;
struct gud_state_req *req;
int idx, ret;
size_t len;
- if (drm_WARN_ON_ONCE(plane->dev, !fb))
- return -EINVAL;
-
- if (drm_WARN_ON_ONCE(plane->dev, !crtc))
- return -EINVAL;
-
- crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
-
- mode = &crtc_state->mode;
+ if (crtc)
+ crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
DRM_PLANE_NO_SCALING,
@@ -492,6 +485,9 @@ int gud_plane_atomic_check(struct drm_plane *plane,
if (old_plane_state->rotation != new_plane_state->rotation)
crtc_state->mode_changed = true;
+ mode = &crtc_state->mode;
+ format = fb->format;
+
if (old_fb && old_fb->format != format)
crtc_state->mode_changed = true;
@@ -598,7 +594,7 @@ void gud_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_helper_damage_iter iter;
int ret, idx;
- if (crtc->state->mode_changed || !crtc->state->enable) {
+ if (!crtc || crtc->state->mode_changed || !crtc->state->enable) {
cancel_work_sync(&gdrm->work);
mutex_lock(&gdrm->damage_lock);
if (gdrm->fb) {
diff --git a/drivers/gpu/drm/i915/display/intel_color_pipeline.c b/drivers/gpu/drm/i915/display/intel_color_pipeline.c
index 942d9b9c93ce..04af552b3648 100644
--- a/drivers/gpu/drm/i915/display/intel_color_pipeline.c
+++ b/drivers/gpu/drm/i915/display/intel_color_pipeline.c
@@ -34,11 +34,19 @@ int _intel_color_pipeline_plane_init(struct drm_plane *plane, struct drm_prop_en
return ret;
list->type = colorop->base.base.id;
- list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", colorop->base.base.id);
/* TODO: handle failures and clean up */
prev_op = &colorop->base;
+ colorop = intel_colorop_create(INTEL_PLANE_CB_CSC);
+ ret = drm_plane_colorop_ctm_3x4_init(dev, &colorop->base, plane,
+ DRM_COLOROP_FLAG_ALLOW_BYPASS);
+ if (ret)
+ return ret;
+
+ drm_colorop_set_next_property(prev_op, &colorop->base);
+ prev_op = &colorop->base;
+
if (DISPLAY_VER(display) >= 35 &&
intel_color_crtc_has_3dlut(display, pipe) &&
plane->type == DRM_PLANE_TYPE_PRIMARY) {
@@ -55,15 +63,6 @@ int _intel_color_pipeline_plane_init(struct drm_plane *plane, struct drm_prop_en
prev_op = &colorop->base;
}
- colorop = intel_colorop_create(INTEL_PLANE_CB_CSC);
- ret = drm_plane_colorop_ctm_3x4_init(dev, &colorop->base, plane,
- DRM_COLOROP_FLAG_ALLOW_BYPASS);
- if (ret)
- return ret;
-
- drm_colorop_set_next_property(prev_op, &colorop->base);
- prev_op = &colorop->base;
-
colorop = intel_colorop_create(INTEL_PLANE_CB_POST_CSC_LUT);
ret = drm_plane_colorop_curve_1d_lut_init(dev, &colorop->base, plane,
PLANE_GAMMA_SIZE,
@@ -74,6 +73,8 @@ int _intel_color_pipeline_plane_init(struct drm_plane *plane, struct drm_prop_en
drm_colorop_set_next_property(prev_op, &colorop->base);
+ list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", list->type);
+
return 0;
}
@@ -81,9 +82,10 @@ int intel_color_pipeline_plane_init(struct drm_plane *plane, enum pipe pipe)
{
struct drm_device *dev = plane->dev;
struct intel_display *display = to_intel_display(dev);
- struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
+ struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES] = {};
int len = 0;
- int ret;
+ int ret = 0;
+ int i;
/* Currently expose pipeline only for HDR planes */
if (!icl_is_hdr_plane(display, to_intel_plane(plane)->id))
@@ -92,8 +94,14 @@ int intel_color_pipeline_plane_init(struct drm_plane *plane, enum pipe pipe)
/* Add pipeline consisting of transfer functions */
ret = _intel_color_pipeline_plane_init(plane, &pipelines[len], pipe);
if (ret)
- return ret;
+ goto out;
len++;
- return drm_plane_create_color_pipeline_property(plane, pipelines, len);
+ ret = drm_plane_create_color_pipeline_property(plane, pipelines, len);
+
+ for (i = 0; i < len; i++)
+ kfree(pipelines[i].name);
+
+out:
+ return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 7582ef34bf3f..303d8d9b7775 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -686,7 +686,7 @@ static void err_print_guc_ctb(struct drm_i915_error_state_buf *m,
}
/* This list includes registers that are useful in debugging GuC hangs. */
-const struct {
+static const struct {
u32 start;
u32 count;
} guc_hw_reg_state[] = {
diff --git a/drivers/gpu/drm/imagination/pvr_fw_trace.c b/drivers/gpu/drm/imagination/pvr_fw_trace.c
index 8a56952f6730..99d681413eff 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_trace.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_trace.c
@@ -137,6 +137,7 @@ update_logtype(struct pvr_device *pvr_dev, u32 group_mask)
struct rogue_fwif_kccb_cmd cmd;
int idx;
int err;
+ int slot;
if (group_mask)
fw_trace->tracebuf_ctrl->log_type = ROGUE_FWIF_LOG_TYPE_TRACE | group_mask;
@@ -154,8 +155,13 @@ update_logtype(struct pvr_device *pvr_dev, u32 group_mask)
cmd.cmd_type = ROGUE_FWIF_KCCB_CMD_LOGTYPE_UPDATE;
cmd.kccb_flags = 0;
- err = pvr_kccb_send_cmd(pvr_dev, &cmd, NULL);
+ err = pvr_kccb_send_cmd(pvr_dev, &cmd, &slot);
+ if (err)
+ goto err_drm_dev_exit;
+
+ err = pvr_kccb_wait_for_completion(pvr_dev, slot, HZ, NULL);
+err_drm_dev_exit:
drm_dev_exit(idx);
err_up_read:
diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig
index 96188bf9274a..ad8c8b823681 100644
--- a/drivers/gpu/drm/mediatek/Kconfig
+++ b/drivers/gpu/drm/mediatek/Kconfig
@@ -8,7 +8,7 @@ config DRM_MEDIATEK
depends on OF
depends on MTK_MMSYS
select DRM_CLIENT_SELECTION
- select DRM_GEM_DMA_HELPER if DRM_FBDEV_EMULATION
+ select DRM_GEM_DMA_HELPER
select DRM_KMS_HELPER
select DRM_DISPLAY_HELPER
select DRM_BRIDGE_CONNECTOR
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index 61cab32e213a..53360b5d12ba 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -836,20 +836,6 @@ static int mtk_dpi_bridge_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
{
struct mtk_dpi *dpi = bridge_to_dpi(bridge);
- int ret;
-
- dpi->next_bridge = devm_drm_of_get_bridge(dpi->dev, dpi->dev->of_node, 1, -1);
- if (IS_ERR(dpi->next_bridge)) {
- ret = PTR_ERR(dpi->next_bridge);
- if (ret == -EPROBE_DEFER)
- return ret;
-
- /* Old devicetree has only one endpoint */
- dpi->next_bridge = devm_drm_of_get_bridge(dpi->dev, dpi->dev->of_node, 0, 0);
- if (IS_ERR(dpi->next_bridge))
- return dev_err_probe(dpi->dev, PTR_ERR(dpi->next_bridge),
- "Failed to get bridge\n");
- }
return drm_bridge_attach(encoder, dpi->next_bridge,
&dpi->bridge, flags);
@@ -1319,6 +1305,15 @@ static int mtk_dpi_probe(struct platform_device *pdev)
if (dpi->irq < 0)
return dpi->irq;
+ dpi->next_bridge = devm_drm_of_get_bridge(dpi->dev, dpi->dev->of_node, 1, -1);
+ if (IS_ERR(dpi->next_bridge) && PTR_ERR(dpi->next_bridge) == -ENODEV) {
+ /* Old devicetree has only one endpoint */
+ dpi->next_bridge = devm_drm_of_get_bridge(dpi->dev, dpi->dev->of_node, 0, 0);
+ }
+ if (IS_ERR(dpi->next_bridge))
+ return dev_err_probe(dpi->dev, PTR_ERR(dpi->next_bridge),
+ "Failed to get bridge\n");
+
platform_set_drvdata(pdev, dpi);
dpi->bridge.of_node = dev->of_node;
diff --git a/drivers/gpu/drm/mediatek/mtk_gem.c b/drivers/gpu/drm/mediatek/mtk_gem.c
index 024cc7e9036c..7525a9f9907a 100644
--- a/drivers/gpu/drm/mediatek/mtk_gem.c
+++ b/drivers/gpu/drm/mediatek/mtk_gem.c
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2015 MediaTek Inc.
+ * Copyright (c) 2025 Collabora Ltd.
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
*/
#include <linux/dma-buf.h>
@@ -18,24 +20,64 @@
static int mtk_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
-static const struct vm_operations_struct vm_ops = {
- .open = drm_gem_vm_open,
- .close = drm_gem_vm_close,
-};
+static void mtk_gem_free_object(struct drm_gem_object *obj)
+{
+ struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj);
+ struct mtk_drm_private *priv = obj->dev->dev_private;
+
+ if (dma_obj->sgt)
+ drm_prime_gem_destroy(obj, dma_obj->sgt);
+ else
+ dma_free_wc(priv->dma_dev, dma_obj->base.size,
+ dma_obj->vaddr, dma_obj->dma_addr);
+
+ /* release file pointer to gem object. */
+ drm_gem_object_release(obj);
+
+ kfree(dma_obj);
+}
+
+/*
+ * Allocate a sg_table for this GEM object.
+ * Note: Both the table's contents, and the sg_table itself must be freed by
+ * the caller.
+ * Returns a pointer to the newly allocated sg_table, or an ERR_PTR() error.
+ */
+static struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj)
+{
+ struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj);
+ struct mtk_drm_private *priv = obj->dev->dev_private;
+ struct sg_table *sgt;
+ int ret;
+
+ sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
+ if (!sgt)
+ return ERR_PTR(-ENOMEM);
+
+ ret = dma_get_sgtable(priv->dma_dev, sgt, dma_obj->vaddr,
+ dma_obj->dma_addr, obj->size);
+ if (ret) {
+ DRM_ERROR("failed to allocate sgt, %d\n", ret);
+ kfree(sgt);
+ return ERR_PTR(ret);
+ }
+
+ return sgt;
+}
static const struct drm_gem_object_funcs mtk_gem_object_funcs = {
.free = mtk_gem_free_object,
+ .print_info = drm_gem_dma_object_print_info,
.get_sg_table = mtk_gem_prime_get_sg_table,
- .vmap = mtk_gem_prime_vmap,
- .vunmap = mtk_gem_prime_vunmap,
+ .vmap = drm_gem_dma_object_vmap,
.mmap = mtk_gem_object_mmap,
- .vm_ops = &vm_ops,
+ .vm_ops = &drm_gem_dma_vm_ops,
};
-static struct mtk_gem_obj *mtk_gem_init(struct drm_device *dev,
- unsigned long size)
+static struct drm_gem_dma_object *mtk_gem_init(struct drm_device *dev,
+ unsigned long size, bool private)
{
- struct mtk_gem_obj *mtk_gem_obj;
+ struct drm_gem_dma_object *dma_obj;
int ret;
size = round_up(size, PAGE_SIZE);
@@ -43,86 +85,65 @@ static struct mtk_gem_obj *mtk_gem_init(struct drm_device *dev,
if (size == 0)
return ERR_PTR(-EINVAL);
- mtk_gem_obj = kzalloc(sizeof(*mtk_gem_obj), GFP_KERNEL);
- if (!mtk_gem_obj)
+ dma_obj = kzalloc(sizeof(*dma_obj), GFP_KERNEL);
+ if (!dma_obj)
return ERR_PTR(-ENOMEM);
- mtk_gem_obj->base.funcs = &mtk_gem_object_funcs;
+ dma_obj->base.funcs = &mtk_gem_object_funcs;
- ret = drm_gem_object_init(dev, &mtk_gem_obj->base, size);
- if (ret < 0) {
+ if (private) {
+ ret = 0;
+ drm_gem_private_object_init(dev, &dma_obj->base, size);
+ } else {
+ ret = drm_gem_object_init(dev, &dma_obj->base, size);
+ }
+ if (ret) {
DRM_ERROR("failed to initialize gem object\n");
- kfree(mtk_gem_obj);
+ kfree(dma_obj);
return ERR_PTR(ret);
}
- return mtk_gem_obj;
+ return dma_obj;
}
-struct mtk_gem_obj *mtk_gem_create(struct drm_device *dev,
- size_t size, bool alloc_kmap)
+static struct drm_gem_dma_object *mtk_gem_create(struct drm_device *dev, size_t size)
{
struct mtk_drm_private *priv = dev->dev_private;
- struct mtk_gem_obj *mtk_gem;
+ struct drm_gem_dma_object *dma_obj;
struct drm_gem_object *obj;
int ret;
- mtk_gem = mtk_gem_init(dev, size);
- if (IS_ERR(mtk_gem))
- return ERR_CAST(mtk_gem);
-
- obj = &mtk_gem->base;
+ dma_obj = mtk_gem_init(dev, size, false);
+ if (IS_ERR(dma_obj))
+ return ERR_CAST(dma_obj);
- mtk_gem->dma_attrs = DMA_ATTR_WRITE_COMBINE;
+ obj = &dma_obj->base;
- if (!alloc_kmap)
- mtk_gem->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
-
- mtk_gem->cookie = dma_alloc_attrs(priv->dma_dev, obj->size,
- &mtk_gem->dma_addr, GFP_KERNEL,
- mtk_gem->dma_attrs);
- if (!mtk_gem->cookie) {
+ dma_obj->vaddr = dma_alloc_wc(priv->dma_dev, obj->size,
+ &dma_obj->dma_addr,
+ GFP_KERNEL | __GFP_NOWARN);
+ if (!dma_obj->vaddr) {
DRM_ERROR("failed to allocate %zx byte dma buffer", obj->size);
ret = -ENOMEM;
goto err_gem_free;
}
- if (alloc_kmap)
- mtk_gem->kvaddr = mtk_gem->cookie;
-
- DRM_DEBUG_DRIVER("cookie = %p dma_addr = %pad size = %zu\n",
- mtk_gem->cookie, &mtk_gem->dma_addr,
+ DRM_DEBUG_DRIVER("vaddr = %p dma_addr = %pad size = %zu\n",
+ dma_obj->vaddr, &dma_obj->dma_addr,
size);
- return mtk_gem;
+ return dma_obj;
err_gem_free:
drm_gem_object_release(obj);
- kfree(mtk_gem);
+ kfree(dma_obj);
return ERR_PTR(ret);
}
-void mtk_gem_free_object(struct drm_gem_object *obj)
-{
- struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
- struct mtk_drm_private *priv = obj->dev->dev_private;
-
- if (mtk_gem->sg)
- drm_prime_gem_destroy(obj, mtk_gem->sg);
- else
- dma_free_attrs(priv->dma_dev, obj->size, mtk_gem->cookie,
- mtk_gem->dma_addr, mtk_gem->dma_attrs);
-
- /* release file pointer to gem object. */
- drm_gem_object_release(obj);
-
- kfree(mtk_gem);
-}
-
int mtk_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
struct drm_mode_create_dumb *args)
{
- struct mtk_gem_obj *mtk_gem;
+ struct drm_gem_dma_object *dma_obj;
int ret;
args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
@@ -135,25 +156,25 @@ int mtk_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
args->size = args->pitch;
args->size *= args->height;
- mtk_gem = mtk_gem_create(dev, args->size, false);
- if (IS_ERR(mtk_gem))
- return PTR_ERR(mtk_gem);
+ dma_obj = mtk_gem_create(dev, args->size);
+ if (IS_ERR(dma_obj))
+ return PTR_ERR(dma_obj);
/*
* allocate a id of idr table where the obj is registered
* and handle has the id what user can see.
*/
- ret = drm_gem_handle_create(file_priv, &mtk_gem->base, &args->handle);
+ ret = drm_gem_handle_create(file_priv, &dma_obj->base, &args->handle);
if (ret)
goto err_handle_create;
/* drop reference from allocate - handle holds it now. */
- drm_gem_object_put(&mtk_gem->base);
+ drm_gem_object_put(&dma_obj->base);
return 0;
err_handle_create:
- mtk_gem_free_object(&mtk_gem->base);
+ mtk_gem_free_object(&dma_obj->base);
return ret;
}
@@ -161,129 +182,50 @@ static int mtk_gem_object_mmap(struct drm_gem_object *obj,
struct vm_area_struct *vma)
{
- int ret;
- struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
+ struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj);
struct mtk_drm_private *priv = obj->dev->dev_private;
+ int ret;
/*
* Set vm_pgoff (used as a fake buffer offset by DRM) to 0 and map the
* whole buffer from the start.
*/
- vma->vm_pgoff = 0;
+ vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node);
/*
* dma_alloc_attrs() allocated a struct page table for mtk_gem, so clear
* VM_PFNMAP flag that was set by drm_gem_mmap_obj()/drm_gem_mmap().
*/
- vm_flags_set(vma, VM_IO | VM_DONTEXPAND | VM_DONTDUMP);
+ vm_flags_mod(vma, VM_IO | VM_DONTEXPAND | VM_DONTDUMP, VM_PFNMAP);
+
vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
- ret = dma_mmap_attrs(priv->dma_dev, vma, mtk_gem->cookie,
- mtk_gem->dma_addr, obj->size, mtk_gem->dma_attrs);
+ ret = dma_mmap_wc(priv->dma_dev, vma, dma_obj->vaddr,
+ dma_obj->dma_addr, obj->size);
+ if (ret)
+ drm_gem_vm_close(vma);
return ret;
}
-/*
- * Allocate a sg_table for this GEM object.
- * Note: Both the table's contents, and the sg_table itself must be freed by
- * the caller.
- * Returns a pointer to the newly allocated sg_table, or an ERR_PTR() error.
- */
-struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj)
-{
- struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
- struct mtk_drm_private *priv = obj->dev->dev_private;
- struct sg_table *sgt;
- int ret;
-
- sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
- if (!sgt)
- return ERR_PTR(-ENOMEM);
-
- ret = dma_get_sgtable_attrs(priv->dma_dev, sgt, mtk_gem->cookie,
- mtk_gem->dma_addr, obj->size,
- mtk_gem->dma_attrs);
- if (ret) {
- DRM_ERROR("failed to allocate sgt, %d\n", ret);
- kfree(sgt);
- return ERR_PTR(ret);
- }
-
- return sgt;
-}
-
struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev,
- struct dma_buf_attachment *attach, struct sg_table *sg)
+ struct dma_buf_attachment *attach, struct sg_table *sgt)
{
- struct mtk_gem_obj *mtk_gem;
+ struct drm_gem_dma_object *dma_obj;
/* check if the entries in the sg_table are contiguous */
- if (drm_prime_get_contiguous_size(sg) < attach->dmabuf->size) {
+ if (drm_prime_get_contiguous_size(sgt) < attach->dmabuf->size) {
DRM_ERROR("sg_table is not contiguous");
return ERR_PTR(-EINVAL);
}
- mtk_gem = mtk_gem_init(dev, attach->dmabuf->size);
- if (IS_ERR(mtk_gem))
- return ERR_CAST(mtk_gem);
-
- mtk_gem->dma_addr = sg_dma_address(sg->sgl);
- mtk_gem->sg = sg;
-
- return &mtk_gem->base;
-}
-
-int mtk_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map)
-{
- struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
- struct sg_table *sgt = NULL;
- unsigned int npages;
-
- if (mtk_gem->kvaddr)
- goto out;
-
- sgt = mtk_gem_prime_get_sg_table(obj);
- if (IS_ERR(sgt))
- return PTR_ERR(sgt);
-
- npages = obj->size >> PAGE_SHIFT;
- mtk_gem->pages = kcalloc(npages, sizeof(*mtk_gem->pages), GFP_KERNEL);
- if (!mtk_gem->pages) {
- sg_free_table(sgt);
- kfree(sgt);
- return -ENOMEM;
- }
-
- drm_prime_sg_to_page_array(sgt, mtk_gem->pages, npages);
-
- mtk_gem->kvaddr = vmap(mtk_gem->pages, npages, VM_MAP,
- pgprot_writecombine(PAGE_KERNEL));
- if (!mtk_gem->kvaddr) {
- sg_free_table(sgt);
- kfree(sgt);
- kfree(mtk_gem->pages);
- return -ENOMEM;
- }
- sg_free_table(sgt);
- kfree(sgt);
-
-out:
- iosys_map_set_vaddr(map, mtk_gem->kvaddr);
-
- return 0;
-}
-
-void mtk_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map)
-{
- struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
- void *vaddr = map->vaddr;
+ dma_obj = mtk_gem_init(dev, attach->dmabuf->size, true);
+ if (IS_ERR(dma_obj))
+ return ERR_CAST(dma_obj);
- if (!mtk_gem->pages)
- return;
+ dma_obj->dma_addr = sg_dma_address(sgt->sgl);
+ dma_obj->sgt = sgt;
- vunmap(vaddr);
- mtk_gem->kvaddr = NULL;
- kfree(mtk_gem->pages);
+ return &dma_obj->base;
}
diff --git a/drivers/gpu/drm/mediatek/mtk_gem.h b/drivers/gpu/drm/mediatek/mtk_gem.h
index 66e5f154f698..afebc3a970a8 100644
--- a/drivers/gpu/drm/mediatek/mtk_gem.h
+++ b/drivers/gpu/drm/mediatek/mtk_gem.h
@@ -7,42 +7,11 @@
#define _MTK_GEM_H_
#include <drm/drm_gem.h>
+#include <drm/drm_gem_dma_helper.h>
-/*
- * mtk drm buffer structure.
- *
- * @base: a gem object.
- * - a new handle to this gem object would be created
- * by drm_gem_handle_create().
- * @cookie: the return value of dma_alloc_attrs(), keep it for dma_free_attrs()
- * @kvaddr: kernel virtual address of gem buffer.
- * @dma_addr: dma address of gem buffer.
- * @dma_attrs: dma attributes of gem buffer.
- *
- * P.S. this object would be transferred to user as kms_bo.handle so
- * user can access the buffer through kms_bo.handle.
- */
-struct mtk_gem_obj {
- struct drm_gem_object base;
- void *cookie;
- void *kvaddr;
- dma_addr_t dma_addr;
- unsigned long dma_attrs;
- struct sg_table *sg;
- struct page **pages;
-};
-
-#define to_mtk_gem_obj(x) container_of(x, struct mtk_gem_obj, base)
-
-void mtk_gem_free_object(struct drm_gem_object *gem);
-struct mtk_gem_obj *mtk_gem_create(struct drm_device *dev, size_t size,
- bool alloc_kmap);
int mtk_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
struct drm_mode_create_dumb *args);
-struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj);
struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach, struct sg_table *sg);
-int mtk_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map);
-void mtk_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map);
#endif
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_common.c b/drivers/gpu/drm/mediatek/mtk_hdmi_common.c
index e78eb0876f16..bd7f8c56ec9c 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi_common.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi_common.c
@@ -303,7 +303,7 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, struct platform_device
return dev_err_probe(dev, ret, "Failed to get clocks\n");
hdmi->irq = platform_get_irq(pdev, 0);
- if (!hdmi->irq)
+ if (hdmi->irq < 0)
return hdmi->irq;
hdmi->regs = device_node_to_regmap(dev->of_node);
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_common.h b/drivers/gpu/drm/mediatek/mtk_hdmi_common.h
index de5e064585f8..7a644bbf5843 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi_common.h
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi_common.h
@@ -168,7 +168,7 @@ struct mtk_hdmi {
bool audio_enable;
bool powered;
bool enabled;
- unsigned int irq;
+ int irq;
enum hdmi_hpd_state hpd;
hdmi_codec_plugged_cb plugged_cb;
struct device *codec_dev;
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c
index b844e2c10f28..d937219fdb7e 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c
@@ -66,11 +66,19 @@ static int mtk_ddc_check_and_rise_low_bus(struct mtk_hdmi_ddc *ddc)
return 0;
}
-static int mtk_ddc_wr_one(struct mtk_hdmi_ddc *ddc, u16 addr_id,
- u16 offset_id, u8 *wr_data)
+static int mtk_ddcm_write_hdmi(struct mtk_hdmi_ddc *ddc, u16 addr_id,
+ u16 offset_id, u16 data_cnt, u8 *wr_data)
{
u32 val;
- int ret;
+ int ret, i;
+
+ /* Don't allow transfer with a size over than the transfer fifo size
+ * (16 byte)
+ */
+ if (data_cnt > 16) {
+ dev_err(ddc->dev, "Invalid DDCM write request\n");
+ return -EINVAL;
+ }
/* If down, rise bus for write operation */
mtk_ddc_check_and_rise_low_bus(ddc);
@@ -78,16 +86,21 @@ static int mtk_ddc_wr_one(struct mtk_hdmi_ddc *ddc, u16 addr_id,
regmap_update_bits(ddc->regs, HPD_DDC_CTRL, HPD_DDC_DELAY_CNT,
FIELD_PREP(HPD_DDC_DELAY_CNT, DDC2_DLY_CNT));
+ /* In case there is no payload data, just do a single write for the
+ * address only
+ */
if (wr_data) {
- regmap_write(ddc->regs, SI2C_CTRL,
- FIELD_PREP(SI2C_ADDR, SI2C_ADDR_READ) |
- FIELD_PREP(SI2C_WDATA, *wr_data) |
- SI2C_WR);
+ /* Fill transfer fifo with payload data */
+ for (i = 0; i < data_cnt; i++) {
+ regmap_write(ddc->regs, SI2C_CTRL,
+ FIELD_PREP(SI2C_ADDR, SI2C_ADDR_READ) |
+ FIELD_PREP(SI2C_WDATA, wr_data[i]) |
+ SI2C_WR);
+ }
}
-
regmap_write(ddc->regs, DDC_CTRL,
FIELD_PREP(DDC_CTRL_CMD, DDC_CMD_SEQ_WRITE) |
- FIELD_PREP(DDC_CTRL_DIN_CNT, wr_data == NULL ? 0 : 1) |
+ FIELD_PREP(DDC_CTRL_DIN_CNT, wr_data == NULL ? 0 : data_cnt) |
FIELD_PREP(DDC_CTRL_OFFSET, offset_id) |
FIELD_PREP(DDC_CTRL_ADDR, addr_id));
usleep_range(1000, 1250);
@@ -96,6 +109,11 @@ static int mtk_ddc_wr_one(struct mtk_hdmi_ddc *ddc, u16 addr_id,
!(val & DDC_I2C_IN_PROG), 500, 1000);
if (ret) {
dev_err(ddc->dev, "DDC I2C write timeout\n");
+
+ /* Abort transfer if it is still in progress */
+ regmap_update_bits(ddc->regs, DDC_CTRL, DDC_CTRL_CMD,
+ FIELD_PREP(DDC_CTRL_CMD, DDC_CMD_ABORT_XFER));
+
return ret;
}
@@ -179,6 +197,11 @@ static int mtk_ddcm_read_hdmi(struct mtk_hdmi_ddc *ddc, u16 uc_dev,
500 * (temp_length + 5));
if (ret) {
dev_err(ddc->dev, "Timeout waiting for DDC I2C\n");
+
+ /* Abort transfer if it is still in progress */
+ regmap_update_bits(ddc->regs, DDC_CTRL, DDC_CTRL_CMD,
+ FIELD_PREP(DDC_CTRL_CMD, DDC_CMD_ABORT_XFER));
+
return ret;
}
@@ -250,24 +273,9 @@ static int mtk_hdmi_fg_ddc_data_read(struct mtk_hdmi_ddc *ddc, u16 b_dev,
static int mtk_hdmi_ddc_fg_data_write(struct mtk_hdmi_ddc *ddc, u16 b_dev,
u8 data_addr, u16 data_cnt, u8 *pr_data)
{
- int i, ret;
-
regmap_set_bits(ddc->regs, HDCP2X_POL_CTRL, HDCP2X_DIS_POLL_EN);
- /*
- * In case there is no payload data, just do a single write for the
- * address only
- */
- if (data_cnt == 0)
- return mtk_ddc_wr_one(ddc, b_dev, data_addr, NULL);
- i = 0;
- do {
- ret = mtk_ddc_wr_one(ddc, b_dev, data_addr + i, pr_data + i);
- if (ret)
- return ret;
- } while (++i < data_cnt);
-
- return 0;
+ return mtk_ddcm_write_hdmi(ddc, b_dev, data_addr, data_cnt, pr_data);
}
static int mtk_hdmi_ddc_v2_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_v2.c b/drivers/gpu/drm/mediatek/mtk_hdmi_v2.c
index c272e1e74b7d..454b8b93b834 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi_v2.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi_v2.c
@@ -1120,9 +1120,10 @@ static void mtk_hdmi_v2_hpd_disable(struct drm_bridge *bridge)
mtk_hdmi_v2_disable(hdmi);
}
-static int mtk_hdmi_v2_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge,
- const struct drm_display_mode *mode,
- unsigned long long tmds_rate)
+static enum drm_mode_status
+mtk_hdmi_v2_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge,
+ const struct drm_display_mode *mode,
+ unsigned long long tmds_rate)
{
if (mode->clock < MTK_HDMI_V2_CLOCK_MIN)
return MODE_CLOCK_LOW;
diff --git a/drivers/gpu/drm/mediatek/mtk_plane.c b/drivers/gpu/drm/mediatek/mtk_plane.c
index 5043e0377270..fcd10d7e8342 100644
--- a/drivers/gpu/drm/mediatek/mtk_plane.c
+++ b/drivers/gpu/drm/mediatek/mtk_plane.c
@@ -11,13 +11,13 @@
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_print.h>
#include <linux/align.h>
#include "mtk_crtc.h"
#include "mtk_ddp_comp.h"
#include "mtk_drm_drv.h"
-#include "mtk_gem.h"
#include "mtk_plane.h"
static const u64 modifiers[] = {
@@ -114,8 +114,8 @@ static void mtk_plane_update_new_state(struct drm_plane_state *new_state,
struct mtk_plane_state *mtk_plane_state)
{
struct drm_framebuffer *fb = new_state->fb;
+ struct drm_gem_dma_object *dma_obj;
struct drm_gem_object *gem;
- struct mtk_gem_obj *mtk_gem;
unsigned int pitch, format;
u64 modifier;
dma_addr_t addr;
@@ -124,8 +124,8 @@ static void mtk_plane_update_new_state(struct drm_plane_state *new_state,
int offset;
gem = fb->obj[0];
- mtk_gem = to_mtk_gem_obj(gem);
- addr = mtk_gem->dma_addr;
+ dma_obj = to_drm_gem_dma_obj(gem);
+ addr = dma_obj->dma_addr;
pitch = fb->pitches[0];
format = fb->format->format;
modifier = fb->modifier;
diff --git a/drivers/gpu/drm/nouveau/dispnv50/curs507a.c b/drivers/gpu/drm/nouveau/dispnv50/curs507a.c
index a95ee5dcc2e3..1a889139cb05 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/curs507a.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/curs507a.c
@@ -84,6 +84,7 @@ curs507a_prepare(struct nv50_wndw *wndw, struct nv50_head_atom *asyh,
asyh->curs.handle = handle;
asyh->curs.offset = offset;
asyh->set.curs = asyh->curs.visible;
+ nv50_atom(asyh->state.state)->lock_core = true;
}
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c
index 3dd742b4f823..e32ed1db6c56 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/head.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/head.c
@@ -43,6 +43,9 @@ nv50_head_flush_clr(struct nv50_head *head,
union nv50_head_atom_mask clr = {
.mask = asyh->clr.mask & ~(flush ? 0 : asyh->set.mask),
};
+
+ lockdep_assert_held(&head->disp->mutex);
+
if (clr.crc) nv50_crc_atomic_clr(head);
if (clr.olut) head->func->olut_clr(head);
if (clr.core) head->func->core_clr(head);
@@ -65,6 +68,8 @@ nv50_head_flush_set_wndw(struct nv50_head *head, struct nv50_head_atom *asyh)
void
nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{
+ lockdep_assert_held(&head->disp->mutex);
+
if (asyh->set.view ) head->func->view (head, asyh);
if (asyh->set.mode ) head->func->mode (head, asyh);
if (asyh->set.core ) head->func->core_set(head, asyh);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h
index d1beaad0c82b..834ed6587aa5 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h
@@ -1,28 +1,81 @@
/* SPDX-License-Identifier: MIT */
#ifndef __NVBIOS_CONN_H__
#define __NVBIOS_CONN_H__
+
+/*
+ * An enumerator representing all of the possible VBIOS connector types defined
+ * by Nvidia at
+ * https://nvidia.github.io/open-gpu-doc/DCB/DCB-4.x-Specification.html.
+ *
+ * [1] Nvidia's documentation actually claims DCB_CONNECTOR_HDMI_0 is a "3-Pin
+ * DIN Stereo Connector". This seems very likely to be a documentation typo
+ * or some sort of funny historical baggage, because we've treated this
+ * connector type as HDMI for years without issue.
+ * TODO: Check with Nvidia what's actually happening here.
+ */
enum dcb_connector_type {
- DCB_CONNECTOR_VGA = 0x00,
- DCB_CONNECTOR_TV_0 = 0x10,
- DCB_CONNECTOR_TV_1 = 0x11,
- DCB_CONNECTOR_TV_3 = 0x13,
- DCB_CONNECTOR_DVI_I = 0x30,
- DCB_CONNECTOR_DVI_D = 0x31,
- DCB_CONNECTOR_DMS59_0 = 0x38,
- DCB_CONNECTOR_DMS59_1 = 0x39,
- DCB_CONNECTOR_LVDS = 0x40,
- DCB_CONNECTOR_LVDS_SPWG = 0x41,
- DCB_CONNECTOR_DP = 0x46,
- DCB_CONNECTOR_eDP = 0x47,
- DCB_CONNECTOR_mDP = 0x48,
- DCB_CONNECTOR_HDMI_0 = 0x60,
- DCB_CONNECTOR_HDMI_1 = 0x61,
- DCB_CONNECTOR_HDMI_C = 0x63,
- DCB_CONNECTOR_DMS59_DP0 = 0x64,
- DCB_CONNECTOR_DMS59_DP1 = 0x65,
- DCB_CONNECTOR_WFD = 0x70,
- DCB_CONNECTOR_USB_C = 0x71,
- DCB_CONNECTOR_NONE = 0xff
+ /* Analog outputs */
+ DCB_CONNECTOR_VGA = 0x00, // VGA 15-pin connector
+ DCB_CONNECTOR_DVI_A = 0x01, // DVI-A
+ DCB_CONNECTOR_POD_VGA = 0x02, // Pod - VGA 15-pin connector
+ DCB_CONNECTOR_TV_0 = 0x10, // TV - Composite Out
+ DCB_CONNECTOR_TV_1 = 0x11, // TV - S-Video Out
+ DCB_CONNECTOR_TV_2 = 0x12, // TV - S-Video Breakout - Composite
+ DCB_CONNECTOR_TV_3 = 0x13, // HDTV Component - YPrPb
+ DCB_CONNECTOR_TV_SCART = 0x14, // TV - SCART Connector
+ DCB_CONNECTOR_TV_SCART_D = 0x16, // TV - Composite SCART over D-connector
+ DCB_CONNECTOR_TV_DTERM = 0x17, // HDTV - D-connector (EIAJ4120)
+ DCB_CONNECTOR_POD_TV_3 = 0x18, // Pod - HDTV - YPrPb
+ DCB_CONNECTOR_POD_TV_1 = 0x19, // Pod - S-Video
+ DCB_CONNECTOR_POD_TV_0 = 0x1a, // Pod - Composite
+
+ /* DVI digital outputs */
+ DCB_CONNECTOR_DVI_I_TV_1 = 0x20, // DVI-I-TV-S-Video
+ DCB_CONNECTOR_DVI_I_TV_0 = 0x21, // DVI-I-TV-Composite
+ DCB_CONNECTOR_DVI_I_TV_2 = 0x22, // DVI-I-TV-S-Video Breakout-Composite
+ DCB_CONNECTOR_DVI_I = 0x30, // DVI-I
+ DCB_CONNECTOR_DVI_D = 0x31, // DVI-D
+ DCB_CONNECTOR_DVI_ADC = 0x32, // Apple Display Connector (ADC)
+ DCB_CONNECTOR_DMS59_0 = 0x38, // LFH-DVI-I-1
+ DCB_CONNECTOR_DMS59_1 = 0x39, // LFH-DVI-I-2
+ DCB_CONNECTOR_BNC = 0x3c, // BNC Connector [for SDI?]
+
+ /* LVDS / TMDS digital outputs */
+ DCB_CONNECTOR_LVDS = 0x40, // LVDS-SPWG-Attached [is this name correct?]
+ DCB_CONNECTOR_LVDS_SPWG = 0x41, // LVDS-OEM-Attached (non-removable)
+ DCB_CONNECTOR_LVDS_REM = 0x42, // LVDS-SPWG-Detached [following naming above]
+ DCB_CONNECTOR_LVDS_SPWG_REM = 0x43, // LVDS-OEM-Detached (removable)
+ DCB_CONNECTOR_TMDS = 0x45, // TMDS-OEM-Attached (non-removable)
+
+ /* DP digital outputs */
+ DCB_CONNECTOR_DP = 0x46, // DisplayPort External Connector
+ DCB_CONNECTOR_eDP = 0x47, // DisplayPort Internal Connector
+ DCB_CONNECTOR_mDP = 0x48, // DisplayPort (Mini) External Connector
+
+ /* Dock outputs (not used) */
+ DCB_CONNECTOR_DOCK_VGA_0 = 0x50, // VGA 15-pin if not docked
+ DCB_CONNECTOR_DOCK_VGA_1 = 0x51, // VGA 15-pin if docked
+ DCB_CONNECTOR_DOCK_DVI_I_0 = 0x52, // DVI-I if not docked
+ DCB_CONNECTOR_DOCK_DVI_I_1 = 0x53, // DVI-I if docked
+ DCB_CONNECTOR_DOCK_DVI_D_0 = 0x54, // DVI-D if not docked
+ DCB_CONNECTOR_DOCK_DVI_D_1 = 0x55, // DVI-D if docked
+ DCB_CONNECTOR_DOCK_DP_0 = 0x56, // DisplayPort if not docked
+ DCB_CONNECTOR_DOCK_DP_1 = 0x57, // DisplayPort if docked
+ DCB_CONNECTOR_DOCK_mDP_0 = 0x58, // DisplayPort (Mini) if not docked
+ DCB_CONNECTOR_DOCK_mDP_1 = 0x59, // DisplayPort (Mini) if docked
+
+ /* HDMI? digital outputs */
+ DCB_CONNECTOR_HDMI_0 = 0x60, // HDMI? See [1] in top-level enum comment above
+ DCB_CONNECTOR_HDMI_1 = 0x61, // HDMI-A connector
+ DCB_CONNECTOR_SPDIF = 0x62, // Audio S/PDIF connector
+ DCB_CONNECTOR_HDMI_C = 0x63, // HDMI-C (Mini) connector
+
+ /* Misc. digital outputs */
+ DCB_CONNECTOR_DMS59_DP0 = 0x64, // LFH-DP-1
+ DCB_CONNECTOR_DMS59_DP1 = 0x65, // LFH-DP-2
+ DCB_CONNECTOR_WFD = 0x70, // Virtual connector for Wifi Display (WFD)
+ DCB_CONNECTOR_USB_C = 0x71, // [DP over USB-C; not present in docs]
+ DCB_CONNECTOR_NONE = 0xff // Skip Entry
};
struct nvbios_connT {
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 00515623a2cc..829c2b573971 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -352,6 +352,8 @@ nouveau_user_framebuffer_create(struct drm_device *dev,
static const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
.fb_create = nouveau_user_framebuffer_create,
+ .atomic_commit = drm_atomic_helper_commit,
+ .atomic_check = drm_atomic_helper_check,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
index 2dab6612c4fc..23d1e5c27bb1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
@@ -191,27 +191,60 @@ nvkm_uconn_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nv
spin_lock(&disp->client.lock);
if (!conn->object.func) {
switch (conn->info.type) {
- case DCB_CONNECTOR_VGA : args->v0.type = NVIF_CONN_V0_VGA; break;
- case DCB_CONNECTOR_TV_0 :
- case DCB_CONNECTOR_TV_1 :
- case DCB_CONNECTOR_TV_3 : args->v0.type = NVIF_CONN_V0_TV; break;
- case DCB_CONNECTOR_DMS59_0 :
- case DCB_CONNECTOR_DMS59_1 :
- case DCB_CONNECTOR_DVI_I : args->v0.type = NVIF_CONN_V0_DVI_I; break;
- case DCB_CONNECTOR_DVI_D : args->v0.type = NVIF_CONN_V0_DVI_D; break;
- case DCB_CONNECTOR_LVDS : args->v0.type = NVIF_CONN_V0_LVDS; break;
- case DCB_CONNECTOR_LVDS_SPWG: args->v0.type = NVIF_CONN_V0_LVDS_SPWG; break;
- case DCB_CONNECTOR_DMS59_DP0:
- case DCB_CONNECTOR_DMS59_DP1:
- case DCB_CONNECTOR_DP :
- case DCB_CONNECTOR_mDP :
- case DCB_CONNECTOR_USB_C : args->v0.type = NVIF_CONN_V0_DP; break;
- case DCB_CONNECTOR_eDP : args->v0.type = NVIF_CONN_V0_EDP; break;
- case DCB_CONNECTOR_HDMI_0 :
- case DCB_CONNECTOR_HDMI_1 :
- case DCB_CONNECTOR_HDMI_C : args->v0.type = NVIF_CONN_V0_HDMI; break;
+ /* VGA */
+ case DCB_CONNECTOR_DVI_A :
+ case DCB_CONNECTOR_POD_VGA :
+ case DCB_CONNECTOR_VGA : args->v0.type = NVIF_CONN_V0_VGA; break;
+
+ /* TV */
+ case DCB_CONNECTOR_TV_0 :
+ case DCB_CONNECTOR_TV_1 :
+ case DCB_CONNECTOR_TV_2 :
+ case DCB_CONNECTOR_TV_SCART :
+ case DCB_CONNECTOR_TV_SCART_D :
+ case DCB_CONNECTOR_TV_DTERM :
+ case DCB_CONNECTOR_POD_TV_3 :
+ case DCB_CONNECTOR_POD_TV_1 :
+ case DCB_CONNECTOR_POD_TV_0 :
+ case DCB_CONNECTOR_TV_3 : args->v0.type = NVIF_CONN_V0_TV; break;
+
+ /* DVI */
+ case DCB_CONNECTOR_DVI_I_TV_1 :
+ case DCB_CONNECTOR_DVI_I_TV_0 :
+ case DCB_CONNECTOR_DVI_I_TV_2 :
+ case DCB_CONNECTOR_DVI_ADC :
+ case DCB_CONNECTOR_DMS59_0 :
+ case DCB_CONNECTOR_DMS59_1 :
+ case DCB_CONNECTOR_DVI_I : args->v0.type = NVIF_CONN_V0_DVI_I; break;
+ case DCB_CONNECTOR_TMDS :
+ case DCB_CONNECTOR_DVI_D : args->v0.type = NVIF_CONN_V0_DVI_D; break;
+
+ /* LVDS */
+ case DCB_CONNECTOR_LVDS : args->v0.type = NVIF_CONN_V0_LVDS; break;
+ case DCB_CONNECTOR_LVDS_SPWG : args->v0.type = NVIF_CONN_V0_LVDS_SPWG; break;
+
+ /* DP */
+ case DCB_CONNECTOR_DMS59_DP0 :
+ case DCB_CONNECTOR_DMS59_DP1 :
+ case DCB_CONNECTOR_DP :
+ case DCB_CONNECTOR_mDP :
+ case DCB_CONNECTOR_USB_C : args->v0.type = NVIF_CONN_V0_DP; break;
+ case DCB_CONNECTOR_eDP : args->v0.type = NVIF_CONN_V0_EDP; break;
+
+ /* HDMI */
+ case DCB_CONNECTOR_HDMI_0 :
+ case DCB_CONNECTOR_HDMI_1 :
+ case DCB_CONNECTOR_HDMI_C : args->v0.type = NVIF_CONN_V0_HDMI; break;
+
+ /*
+ * Dock & unused outputs.
+ * BNC, SPDIF, WFD, and detached LVDS go here.
+ */
default:
- WARN_ON(1);
+ nvkm_warn(&disp->engine.subdev,
+ "unimplemented connector type 0x%02x\n",
+ conn->info.type);
+ args->v0.type = NVIF_CONN_V0_VGA;
ret = -EINVAL;
break;
}
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index b26b682826bc..162cc58c7b8f 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -623,49 +623,6 @@ static struct panel_simple *panel_simple_probe(struct device *dev)
if (IS_ERR(desc))
return ERR_CAST(desc);
- panel = devm_drm_panel_alloc(dev, struct panel_simple, base,
- &panel_simple_funcs, desc->connector_type);
- if (IS_ERR(panel))
- return ERR_CAST(panel);
-
- panel->desc = desc;
-
- panel->supply = devm_regulator_get(dev, "power");
- if (IS_ERR(panel->supply))
- return ERR_CAST(panel->supply);
-
- panel->enable_gpio = devm_gpiod_get_optional(dev, "enable",
- GPIOD_OUT_LOW);
- if (IS_ERR(panel->enable_gpio))
- return dev_err_cast_probe(dev, panel->enable_gpio,
- "failed to request GPIO\n");
-
- err = of_drm_get_panel_orientation(dev->of_node, &panel->orientation);
- if (err) {
- dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, err);
- return ERR_PTR(err);
- }
-
- ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0);
- if (ddc) {
- panel->ddc = of_find_i2c_adapter_by_node(ddc);
- of_node_put(ddc);
-
- if (!panel->ddc)
- return ERR_PTR(-EPROBE_DEFER);
- }
-
- if (!of_device_is_compatible(dev->of_node, "panel-dpi") &&
- !of_get_display_timing(dev->of_node, "panel-timing", &dt))
- panel_simple_parse_panel_timing_node(dev, panel, &dt);
-
- if (desc->connector_type == DRM_MODE_CONNECTOR_LVDS) {
- /* Optional data-mapping property for overriding bus format */
- err = panel_simple_override_nondefault_lvds_datamapping(dev, panel);
- if (err)
- goto free_ddc;
- }
-
connector_type = desc->connector_type;
/* Catch common mistakes for panels. */
switch (connector_type) {
@@ -690,8 +647,7 @@ static struct panel_simple *panel_simple_probe(struct device *dev)
break;
case DRM_MODE_CONNECTOR_eDP:
dev_warn(dev, "eDP panels moved to panel-edp\n");
- err = -EINVAL;
- goto free_ddc;
+ return ERR_PTR(-EINVAL);
case DRM_MODE_CONNECTOR_DSI:
if (desc->bpc != 6 && desc->bpc != 8)
dev_warn(dev, "Expected bpc in {6,8} but got: %u\n", desc->bpc);
@@ -720,6 +676,49 @@ static struct panel_simple *panel_simple_probe(struct device *dev)
break;
}
+ panel = devm_drm_panel_alloc(dev, struct panel_simple, base,
+ &panel_simple_funcs, connector_type);
+ if (IS_ERR(panel))
+ return ERR_CAST(panel);
+
+ panel->desc = desc;
+
+ panel->supply = devm_regulator_get(dev, "power");
+ if (IS_ERR(panel->supply))
+ return ERR_CAST(panel->supply);
+
+ panel->enable_gpio = devm_gpiod_get_optional(dev, "enable",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(panel->enable_gpio))
+ return dev_err_cast_probe(dev, panel->enable_gpio,
+ "failed to request GPIO\n");
+
+ err = of_drm_get_panel_orientation(dev->of_node, &panel->orientation);
+ if (err) {
+ dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, err);
+ return ERR_PTR(err);
+ }
+
+ ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0);
+ if (ddc) {
+ panel->ddc = of_find_i2c_adapter_by_node(ddc);
+ of_node_put(ddc);
+
+ if (!panel->ddc)
+ return ERR_PTR(-EPROBE_DEFER);
+ }
+
+ if (!of_device_is_compatible(dev->of_node, "panel-dpi") &&
+ !of_get_display_timing(dev->of_node, "panel-timing", &dt))
+ panel_simple_parse_panel_timing_node(dev, panel, &dt);
+
+ if (desc->connector_type == DRM_MODE_CONNECTOR_LVDS) {
+ /* Optional data-mapping property for overriding bus format */
+ err = panel_simple_override_nondefault_lvds_datamapping(dev, panel);
+ if (err)
+ goto free_ddc;
+ }
+
dev_set_drvdata(dev, panel);
/*
@@ -1900,6 +1899,7 @@ static const struct panel_desc dataimage_scf0700c48ggu18 = {
},
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
+ .connector_type = DRM_MODE_CONNECTOR_DPI,
};
static const struct display_timing dlc_dlc0700yzg_1_timing = {
diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c
index d4839d282689..f6339963e496 100644
--- a/drivers/gpu/drm/panthor/panthor_mmu.c
+++ b/drivers/gpu/drm/panthor/panthor_mmu.c
@@ -1252,17 +1252,7 @@ static int panthor_vm_prepare_map_op_ctx(struct panthor_vm_op_ctx *op_ctx,
goto err_cleanup;
}
- /* drm_gpuvm_bo_obtain_prealloc() will call drm_gpuvm_bo_put() on our
- * pre-allocated BO if the <BO,VM> association exists. Given we
- * only have one ref on preallocated_vm_bo, drm_gpuvm_bo_destroy() will
- * be called immediately, and we have to hold the VM resv lock when
- * calling this function.
- */
- dma_resv_lock(panthor_vm_resv(vm), NULL);
- mutex_lock(&bo->base.base.gpuva.lock);
op_ctx->map.vm_bo = drm_gpuvm_bo_obtain_prealloc(preallocated_vm_bo);
- mutex_unlock(&bo->base.base.gpuva.lock);
- dma_resv_unlock(panthor_vm_resv(vm));
op_ctx->map.bo_offset = offset;
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
index c9fe6aa3e3e3..8604342f9943 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
@@ -121,7 +121,7 @@ static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder)
struct drm_crtc *crtc = encoder->crtc;
/* Unconditionally switch to TMDS as FRL is not yet supported */
- gpiod_set_value(hdmi->frl_enable_gpio, 0);
+ gpiod_set_value_cansleep(hdmi->frl_enable_gpio, 0);
if (!crtc || !crtc->state)
return;
@@ -640,6 +640,15 @@ static void dw_hdmi_qp_rockchip_remove(struct platform_device *pdev)
component_del(&pdev->dev, &dw_hdmi_qp_rockchip_ops);
}
+static int __maybe_unused dw_hdmi_qp_rockchip_suspend(struct device *dev)
+{
+ struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
+
+ dw_hdmi_qp_suspend(dev, hdmi->hdmi);
+
+ return 0;
+}
+
static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev)
{
struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
@@ -655,7 +664,8 @@ static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev)
}
static const struct dev_pm_ops dw_hdmi_qp_rockchip_pm = {
- SET_SYSTEM_SLEEP_PM_OPS(NULL, dw_hdmi_qp_rockchip_resume)
+ SET_SYSTEM_SLEEP_PM_OPS(dw_hdmi_qp_rockchip_suspend,
+ dw_hdmi_qp_rockchip_resume)
};
struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver = {
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
index cd8380f0eddc..f3950e8476a7 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
@@ -2104,7 +2104,7 @@ static void rk3568_vop2_wait_for_port_mux_done(struct vop2 *vop2)
* Spin until the previous port_mux figuration is done.
*/
ret = readx_poll_timeout_atomic(rk3568_vop2_read_port_mux, vop2, port_mux_sel,
- port_mux_sel == vop2->old_port_sel, 0, 50 * 1000);
+ port_mux_sel == vop2->old_port_sel, 10, 50 * 1000);
if (ret)
DRM_DEV_ERROR(vop2->dev, "wait port_mux done timeout: 0x%x--0x%x\n",
port_mux_sel, vop2->old_port_sel);
@@ -2124,7 +2124,7 @@ static void rk3568_vop2_wait_for_layer_cfg_done(struct vop2 *vop2, u32 cfg)
* Spin until the previous layer configuration is done.
*/
ret = readx_poll_timeout_atomic(rk3568_vop2_read_layer_cfg, vop2, atv_layer_cfg,
- atv_layer_cfg == cfg, 0, 50 * 1000);
+ atv_layer_cfg == cfg, 10, 50 * 1000);
if (ret)
DRM_DEV_ERROR(vop2->dev, "wait layer cfg done timeout: 0x%x--0x%x\n",
atv_layer_cfg, cfg);
@@ -2144,6 +2144,7 @@ static void rk3568_vop2_setup_layer_mixer(struct vop2_video_port *vp)
u8 layer_sel_id;
unsigned int ofs;
u32 ovl_ctrl;
+ u32 cfg_done;
int i;
struct vop2_video_port *vp0 = &vop2->vps[0];
struct vop2_video_port *vp1 = &vop2->vps[1];
@@ -2298,8 +2299,16 @@ static void rk3568_vop2_setup_layer_mixer(struct vop2_video_port *vp)
rk3568_vop2_wait_for_port_mux_done(vop2);
}
- if (layer_sel != old_layer_sel && atv_layer_sel != old_layer_sel)
- rk3568_vop2_wait_for_layer_cfg_done(vop2, vop2->old_layer_sel);
+ if (layer_sel != old_layer_sel && atv_layer_sel != old_layer_sel) {
+ cfg_done = vop2_readl(vop2, RK3568_REG_CFG_DONE);
+ cfg_done &= (BIT(vop2->data->nr_vps) - 1);
+ cfg_done &= ~BIT(vp->id);
+ /*
+ * Changes of other VPs' overlays have not taken effect
+ */
+ if (cfg_done)
+ rk3568_vop2_wait_for_layer_cfg_done(vop2, vop2->old_layer_sel);
+ }
vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel);
mutex_unlock(&vop2->ovl_lock);
diff --git a/drivers/gpu/drm/sysfb/drm_sysfb_helper.h b/drivers/gpu/drm/sysfb/drm_sysfb_helper.h
index da670d7eeb2e..de96bfe7562c 100644
--- a/drivers/gpu/drm/sysfb/drm_sysfb_helper.h
+++ b/drivers/gpu/drm/sysfb/drm_sysfb_helper.h
@@ -55,15 +55,6 @@ const struct drm_format_info *drm_sysfb_get_format_si(struct drm_device *dev,
#endif
/*
- * Input parsing
- */
-
-int drm_sysfb_get_validated_int(struct drm_device *dev, const char *name,
- u64 value, u32 max);
-int drm_sysfb_get_validated_int0(struct drm_device *dev, const char *name,
- u64 value, u32 max);
-
-/*
* Display modes
*/
diff --git a/drivers/gpu/drm/vkms/vkms_colorop.c b/drivers/gpu/drm/vkms/vkms_colorop.c
index 5c3ffc78aea0..d03a1f2e9c41 100644
--- a/drivers/gpu/drm/vkms/vkms_colorop.c
+++ b/drivers/gpu/drm/vkms/vkms_colorop.c
@@ -37,7 +37,6 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
goto cleanup;
list->type = ops[i]->base.id;
- list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[i]->base.id);
i++;
@@ -88,6 +87,8 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
drm_colorop_set_next_property(ops[i - 1], ops[i]);
+ list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[0]->base.id);
+
return 0;
cleanup:
@@ -103,18 +104,18 @@ cleanup:
int vkms_initialize_colorops(struct drm_plane *plane)
{
- struct drm_prop_enum_list pipeline;
- int ret;
+ struct drm_prop_enum_list pipeline = {};
+ int ret = 0;
/* Add color pipeline */
ret = vkms_initialize_color_pipeline(plane, &pipeline);
if (ret)
- return ret;
+ goto out;
/* Create COLOR_PIPELINE property and attach */
ret = drm_plane_create_color_pipeline_property(plane, &pipeline, 1);
- if (ret)
- return ret;
- return 0;
+ kfree(pipeline.name);
+out:
+ return ret;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
index f031a312c783..b22887e8c881 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
@@ -32,9 +32,15 @@
#include <drm/ttm/ttm_placement.h>
-static void vmw_bo_release(struct vmw_bo *vbo)
+/**
+ * vmw_bo_free - vmw_bo destructor
+ *
+ * @bo: Pointer to the embedded struct ttm_buffer_object
+ */
+static void vmw_bo_free(struct ttm_buffer_object *bo)
{
struct vmw_resource *res;
+ struct vmw_bo *vbo = to_vmw_bo(&bo->base);
WARN_ON(kref_read(&vbo->tbo.base.refcount) != 0);
vmw_bo_unmap(vbo);
@@ -62,20 +68,8 @@ static void vmw_bo_release(struct vmw_bo *vbo)
}
vmw_surface_unreference(&vbo->dumb_surface);
}
- drm_gem_object_release(&vbo->tbo.base);
-}
-
-/**
- * vmw_bo_free - vmw_bo destructor
- *
- * @bo: Pointer to the embedded struct ttm_buffer_object
- */
-static void vmw_bo_free(struct ttm_buffer_object *bo)
-{
- struct vmw_bo *vbo = to_vmw_bo(&bo->base);
-
WARN_ON(!RB_EMPTY_ROOT(&vbo->res_tree));
- vmw_bo_release(vbo);
+ drm_gem_object_release(&vbo->tbo.base);
WARN_ON(vbo->dirty);
kfree(vbo);
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
index 00be92da5509..85795082fef9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
@@ -515,12 +515,12 @@ int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data,
/**
* vmw_event_fence_action_seq_passed
*
- * @action: The struct vmw_fence_action embedded in a struct
- * vmw_event_fence_action.
+ * @f: The struct dma_fence which provides timestamp for the action event
+ * @cb: The struct dma_fence_cb callback for the action event.
*
- * This function is called when the seqno of the fence where @action is
- * attached has passed. It queues the event on the submitter's event list.
- * This function is always called from atomic context.
+ * This function is called when the seqno of the fence has passed
+ * and it is always called from atomic context.
+ * It queues the event on the submitter's event list.
*/
static void vmw_event_fence_action_seq_passed(struct dma_fence *f,
struct dma_fence_cb *cb)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index d32ce1cb579e..bc51b5d55e38 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -766,13 +766,15 @@ err_out:
return ERR_PTR(ret);
}
- ttm_bo_reserve(&bo->tbo, false, false, NULL);
- ret = vmw_bo_dirty_add(bo);
- if (!ret && surface && surface->res.func->dirty_alloc) {
- surface->res.coherent = true;
- ret = surface->res.func->dirty_alloc(&surface->res);
+ if (bo) {
+ ttm_bo_reserve(&bo->tbo, false, false, NULL);
+ ret = vmw_bo_dirty_add(bo);
+ if (!ret && surface && surface->res.func->dirty_alloc) {
+ surface->res.coherent = true;
+ ret = surface->res.func->dirty_alloc(&surface->res);
+ }
+ ttm_bo_unreserve(&bo->tbo);
}
- ttm_bo_unreserve(&bo->tbo);
return &vfb->base;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
index 69dfe69ce0f8..a8c8c9375d29 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
@@ -923,8 +923,10 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv,
ttm_bo_unreserve(&buf->tbo);
res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type);
- if (unlikely(ret != 0))
+ if (IS_ERR(res)) {
+ ret = PTR_ERR(res);
goto no_reserve;
+ }
ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_shader,
vmw_shader_key(user_key, shader_type),
diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig
index 4b288eb3f5b0..4d7dcaff2b91 100644
--- a/drivers/gpu/drm/xe/Kconfig
+++ b/drivers/gpu/drm/xe/Kconfig
@@ -39,7 +39,7 @@ config DRM_XE
select DRM_TTM
select DRM_TTM_HELPER
select DRM_EXEC
- select DRM_GPUSVM if !UML && DEVICE_PRIVATE
+ select DRM_GPUSVM if !UML
select DRM_GPUVM
select DRM_SCHED
select MMU_NOTIFIER
@@ -80,8 +80,9 @@ config DRM_XE_GPUSVM
bool "Enable CPU to GPU address mirroring"
depends on DRM_XE
depends on !UML
- depends on DEVICE_PRIVATE
+ depends on ZONE_DEVICE
default y
+ select DEVICE_PRIVATE
select DRM_GPUSVM
help
Enable this option if you want support for CPU to GPU address
diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index bf4ee976b680..71acd45aa33b 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -1055,6 +1055,7 @@ static long xe_bo_shrink_purge(struct ttm_operation_ctx *ctx,
unsigned long *scanned)
{
struct xe_device *xe = ttm_to_xe_device(bo->bdev);
+ struct ttm_tt *tt = bo->ttm;
long lret;
/* Fake move to system, without copying data. */
@@ -1079,8 +1080,10 @@ static long xe_bo_shrink_purge(struct ttm_operation_ctx *ctx,
.writeback = false,
.allow_move = false});
- if (lret > 0)
+ if (lret > 0) {
xe_ttm_tt_account_subtract(xe, bo->ttm);
+ update_global_total_pages(bo->bdev, -(long)tt->num_pages);
+ }
return lret;
}
@@ -1166,8 +1169,10 @@ long xe_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo,
if (needs_rpm)
xe_pm_runtime_put(xe);
- if (lret > 0)
+ if (lret > 0) {
xe_ttm_tt_account_subtract(xe, tt);
+ update_global_total_pages(bo->bdev, -(long)tt->num_pages);
+ }
out_unref:
xe_bo_put(xe_bo);
diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c
index e91da9589c5f..63fd8bf13c70 100644
--- a/drivers/gpu/drm/xe/xe_debugfs.c
+++ b/drivers/gpu/drm/xe/xe_debugfs.c
@@ -256,14 +256,64 @@ static ssize_t wedged_mode_show(struct file *f, char __user *ubuf,
return simple_read_from_buffer(ubuf, size, pos, buf, len);
}
+static int __wedged_mode_set_reset_policy(struct xe_gt *gt, enum xe_wedged_mode mode)
+{
+ bool enable_engine_reset;
+ int ret;
+
+ enable_engine_reset = (mode != XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET);
+ ret = xe_guc_ads_scheduler_policy_toggle_reset(&gt->uc.guc.ads,
+ enable_engine_reset);
+ if (ret)
+ xe_gt_err(gt, "Failed to update GuC ADS scheduler policy (%pe)\n", ERR_PTR(ret));
+
+ return ret;
+}
+
+static int wedged_mode_set_reset_policy(struct xe_device *xe, enum xe_wedged_mode mode)
+{
+ struct xe_gt *gt;
+ int ret;
+ u8 id;
+
+ guard(xe_pm_runtime)(xe);
+ for_each_gt(gt, xe, id) {
+ ret = __wedged_mode_set_reset_policy(gt, mode);
+ if (ret) {
+ if (id > 0) {
+ xe->wedged.inconsistent_reset = true;
+ drm_err(&xe->drm, "Inconsistent reset policy state between GTs\n");
+ }
+ return ret;
+ }
+ }
+
+ xe->wedged.inconsistent_reset = false;
+
+ return 0;
+}
+
+static bool wedged_mode_needs_policy_update(struct xe_device *xe, enum xe_wedged_mode mode)
+{
+ if (xe->wedged.inconsistent_reset)
+ return true;
+
+ if (xe->wedged.mode == mode)
+ return false;
+
+ if (xe->wedged.mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET ||
+ mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET)
+ return true;
+
+ return false;
+}
+
static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf,
size_t size, loff_t *pos)
{
struct xe_device *xe = file_inode(f)->i_private;
- struct xe_gt *gt;
u32 wedged_mode;
ssize_t ret;
- u8 id;
ret = kstrtouint_from_user(ubuf, size, 0, &wedged_mode);
if (ret)
@@ -272,22 +322,14 @@ static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf,
if (wedged_mode > 2)
return -EINVAL;
- if (xe->wedged.mode == wedged_mode)
- return size;
+ if (wedged_mode_needs_policy_update(xe, wedged_mode)) {
+ ret = wedged_mode_set_reset_policy(xe, wedged_mode);
+ if (ret)
+ return ret;
+ }
xe->wedged.mode = wedged_mode;
- xe_pm_runtime_get(xe);
- for_each_gt(gt, xe, id) {
- ret = xe_guc_ads_scheduler_policy_toggle_reset(&gt->uc.guc.ads);
- if (ret) {
- xe_gt_err(gt, "Failed to update GuC ADS scheduler policy. GuC may still cause engine reset even with wedged_mode=2\n");
- xe_pm_runtime_put(xe);
- return -EIO;
- }
- }
- xe_pm_runtime_put(xe);
-
return size;
}
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 0b2fa7c56d38..047e86e22133 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -44,6 +44,22 @@ struct xe_pat_ops;
struct xe_pxp;
struct xe_vram_region;
+/**
+ * enum xe_wedged_mode - possible wedged modes
+ * @XE_WEDGED_MODE_NEVER: Device will never be declared wedged.
+ * @XE_WEDGED_MODE_UPON_CRITICAL_ERROR: Device will be declared wedged only
+ * when critical error occurs like GT reset failure or firmware failure.
+ * This is the default mode.
+ * @XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET: Device will be declared wedged on
+ * any hang. In this mode, engine resets are disabled to avoid automatic
+ * recovery attempts. This mode is primarily intended for debugging hangs.
+ */
+enum xe_wedged_mode {
+ XE_WEDGED_MODE_NEVER = 0,
+ XE_WEDGED_MODE_UPON_CRITICAL_ERROR = 1,
+ XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET = 2,
+};
+
#define XE_BO_INVALID_OFFSET LONG_MAX
#define GRAPHICS_VER(xe) ((xe)->info.graphics_verx100 / 100)
@@ -587,6 +603,8 @@ struct xe_device {
int mode;
/** @wedged.method: Recovery method to be sent in the drm device wedged uevent */
unsigned long method;
+ /** @wedged.inconsistent_reset: Inconsistent reset policy state between GTs */
+ bool inconsistent_reset;
} wedged;
/** @bo_device: Struct to control async free of BOs */
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index 8724f8de67e2..779d7e7e2d2e 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -328,6 +328,7 @@ struct xe_exec_queue *xe_exec_queue_create_class(struct xe_device *xe, struct xe
* @xe: Xe device.
* @tile: tile which bind exec queue belongs to.
* @flags: exec queue creation flags
+ * @user_vm: The user VM which this exec queue belongs to
* @extensions: exec queue creation extensions
*
* Normalize bind exec queue creation. Bind exec queue is tied to migration VM
@@ -341,6 +342,7 @@ struct xe_exec_queue *xe_exec_queue_create_class(struct xe_device *xe, struct xe
*/
struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe,
struct xe_tile *tile,
+ struct xe_vm *user_vm,
u32 flags, u64 extensions)
{
struct xe_gt *gt = tile->primary_gt;
@@ -377,6 +379,9 @@ struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe,
xe_exec_queue_put(q);
return ERR_PTR(err);
}
+
+ if (user_vm)
+ q->user_vm = xe_vm_get(user_vm);
}
return q;
@@ -407,6 +412,11 @@ void xe_exec_queue_destroy(struct kref *ref)
xe_exec_queue_put(eq);
}
+ if (q->user_vm) {
+ xe_vm_put(q->user_vm);
+ q->user_vm = NULL;
+ }
+
q->ops->destroy(q);
}
@@ -742,6 +752,22 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
XE_IOCTL_DBG(xe, eci[0].engine_instance != 0))
return -EINVAL;
+ vm = xe_vm_lookup(xef, args->vm_id);
+ if (XE_IOCTL_DBG(xe, !vm))
+ return -ENOENT;
+
+ err = down_read_interruptible(&vm->lock);
+ if (err) {
+ xe_vm_put(vm);
+ return err;
+ }
+
+ if (XE_IOCTL_DBG(xe, xe_vm_is_closed_or_banned(vm))) {
+ up_read(&vm->lock);
+ xe_vm_put(vm);
+ return -ENOENT;
+ }
+
for_each_tile(tile, xe, id) {
struct xe_exec_queue *new;
@@ -749,9 +775,11 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
if (id)
flags |= EXEC_QUEUE_FLAG_BIND_ENGINE_CHILD;
- new = xe_exec_queue_create_bind(xe, tile, flags,
+ new = xe_exec_queue_create_bind(xe, tile, vm, flags,
args->extensions);
if (IS_ERR(new)) {
+ up_read(&vm->lock);
+ xe_vm_put(vm);
err = PTR_ERR(new);
if (q)
goto put_exec_queue;
@@ -763,6 +791,8 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
list_add_tail(&new->multi_gt_list,
&q->multi_gt_link);
}
+ up_read(&vm->lock);
+ xe_vm_put(vm);
} else {
logical_mask = calc_validate_logical_mask(xe, eci,
args->width,
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.h b/drivers/gpu/drm/xe/xe_exec_queue.h
index fda4d4f9bda8..37a9da22f420 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.h
+++ b/drivers/gpu/drm/xe/xe_exec_queue.h
@@ -28,6 +28,7 @@ struct xe_exec_queue *xe_exec_queue_create_class(struct xe_device *xe, struct xe
u32 flags, u64 extensions);
struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe,
struct xe_tile *tile,
+ struct xe_vm *user_vm,
u32 flags, u64 extensions);
void xe_exec_queue_fini(struct xe_exec_queue *q);
diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
index 771ffe35cd0c..3a4263c92b3d 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
+++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
@@ -54,6 +54,12 @@ struct xe_exec_queue {
struct kref refcount;
/** @vm: VM (address space) for this exec queue */
struct xe_vm *vm;
+ /**
+ * @user_vm: User VM (address space) for this exec queue (bind queues
+ * only)
+ */
+ struct xe_vm *user_vm;
+
/** @class: class of this exec queue */
enum xe_engine_class class;
/**
diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c
index ef481b334af4..793d7324a395 100644
--- a/drivers/gpu/drm/xe/xe_ggtt.c
+++ b/drivers/gpu/drm/xe/xe_ggtt.c
@@ -322,7 +322,7 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt)
else
ggtt->pt_ops = &xelp_pt_ops;
- ggtt->wq = alloc_workqueue("xe-ggtt-wq", 0, WQ_MEM_RECLAIM);
+ ggtt->wq = alloc_workqueue("xe-ggtt-wq", WQ_MEM_RECLAIM, 0);
if (!ggtt->wq)
return -ENOMEM;
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h
index 420b0e6089de..e8897a77ba19 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h
@@ -41,10 +41,10 @@ struct xe_gt_sriov_vf_runtime {
};
/**
- * xe_gt_sriov_vf_migration - VF migration data.
+ * struct xe_gt_sriov_vf_migration - VF migration data.
*/
struct xe_gt_sriov_vf_migration {
- /** @migration: VF migration recovery worker */
+ /** @worker: VF migration recovery worker */
struct work_struct worker;
/** @lock: Protects recovery_queued, teardown */
spinlock_t lock;
diff --git a/drivers/gpu/drm/xe/xe_guc_ads.c b/drivers/gpu/drm/xe/xe_guc_ads.c
index bcb85a1bf26d..3f7f1b5602d5 100644
--- a/drivers/gpu/drm/xe/xe_guc_ads.c
+++ b/drivers/gpu/drm/xe/xe_guc_ads.c
@@ -983,16 +983,17 @@ static int guc_ads_action_update_policies(struct xe_guc_ads *ads, u32 policy_off
/**
* xe_guc_ads_scheduler_policy_toggle_reset - Toggle reset policy
* @ads: Additional data structures object
+ * @enable_engine_reset: true to enable engine resets, false otherwise
*
- * This function update the GuC's engine reset policy based on wedged.mode.
+ * This function update the GuC's engine reset policy.
*
* Return: 0 on success, and negative error code otherwise.
*/
-int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads)
+int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads,
+ bool enable_engine_reset)
{
struct guc_policies *policies;
struct xe_guc *guc = ads_to_guc(ads);
- struct xe_device *xe = ads_to_xe(ads);
CLASS(xe_guc_buf, buf)(&guc->buf, sizeof(*policies));
if (!xe_guc_buf_is_valid(buf))
@@ -1004,10 +1005,11 @@ int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads)
policies->dpc_promote_time = ads_blob_read(ads, policies.dpc_promote_time);
policies->max_num_work_items = ads_blob_read(ads, policies.max_num_work_items);
policies->is_valid = 1;
- if (xe->wedged.mode == 2)
- policies->global_flags |= GLOBAL_POLICY_DISABLE_ENGINE_RESET;
- else
+
+ if (enable_engine_reset)
policies->global_flags &= ~GLOBAL_POLICY_DISABLE_ENGINE_RESET;
+ else
+ policies->global_flags |= GLOBAL_POLICY_DISABLE_ENGINE_RESET;
return guc_ads_action_update_policies(ads, xe_guc_buf_flush(buf));
}
diff --git a/drivers/gpu/drm/xe/xe_guc_ads.h b/drivers/gpu/drm/xe/xe_guc_ads.h
index 2e6674c760ff..7a39f361cb17 100644
--- a/drivers/gpu/drm/xe/xe_guc_ads.h
+++ b/drivers/gpu/drm/xe/xe_guc_ads.h
@@ -6,6 +6,8 @@
#ifndef _XE_GUC_ADS_H_
#define _XE_GUC_ADS_H_
+#include <linux/types.h>
+
struct xe_guc_ads;
int xe_guc_ads_init(struct xe_guc_ads *ads);
@@ -13,6 +15,7 @@ int xe_guc_ads_init_post_hwconfig(struct xe_guc_ads *ads);
void xe_guc_ads_populate(struct xe_guc_ads *ads);
void xe_guc_ads_populate_minimal(struct xe_guc_ads *ads);
void xe_guc_ads_populate_post_load(struct xe_guc_ads *ads);
-int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads);
+int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads,
+ bool enable_engine_reset);
#endif
diff --git a/drivers/gpu/drm/xe/xe_late_bind_fw_types.h b/drivers/gpu/drm/xe/xe_late_bind_fw_types.h
index 0f5da89ce98b..2a8a985c37e7 100644
--- a/drivers/gpu/drm/xe/xe_late_bind_fw_types.h
+++ b/drivers/gpu/drm/xe/xe_late_bind_fw_types.h
@@ -15,10 +15,12 @@
#define XE_LB_MAX_PAYLOAD_SIZE SZ_4K
/**
- * xe_late_bind_fw_id - enum to determine late binding fw index
+ * enum xe_late_bind_fw_id - enum to determine late binding fw index
*/
enum xe_late_bind_fw_id {
+ /** @XE_LB_FW_FAN_CONTROL: Fan control */
XE_LB_FW_FAN_CONTROL = 0,
+ /** @XE_LB_FW_MAX_ID: Number of IDs */
XE_LB_FW_MAX_ID
};
diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c
index b5083c99dd50..281286f2b5f9 100644
--- a/drivers/gpu/drm/xe/xe_lrc.c
+++ b/drivers/gpu/drm/xe/xe_lrc.c
@@ -1050,6 +1050,9 @@ static ssize_t setup_utilization_wa(struct xe_lrc *lrc,
{
u32 *cmd = batch;
+ if (IS_SRIOV_VF(gt_to_xe(lrc->gt)))
+ return 0;
+
if (xe_gt_WARN_ON(lrc->gt, max_len < 12))
return -ENOSPC;
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index 5a95b08a4723..d8ee76aab4e4 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -2445,7 +2445,7 @@ void xe_migrate_job_lock(struct xe_migrate *m, struct xe_exec_queue *q)
if (is_migrate)
mutex_lock(&m->job_mutex);
else
- xe_vm_assert_held(q->vm); /* User queues VM's should be locked */
+ xe_vm_assert_held(q->user_vm); /* User queues VM's should be locked */
}
/**
@@ -2463,7 +2463,7 @@ void xe_migrate_job_unlock(struct xe_migrate *m, struct xe_exec_queue *q)
if (is_migrate)
mutex_unlock(&m->job_mutex);
else
- xe_vm_assert_held(q->vm); /* User queues VM's should be locked */
+ xe_vm_assert_held(q->user_vm); /* User queues VM's should be locked */
}
#if IS_ENABLED(CONFIG_PROVE_LOCKING)
diff --git a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c
index 797a4b866226..d963231b5135 100644
--- a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c
+++ b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c
@@ -346,7 +346,7 @@ int xe_sriov_vf_ccs_init(struct xe_device *xe)
flags = EXEC_QUEUE_FLAG_KERNEL |
EXEC_QUEUE_FLAG_PERMANENT |
EXEC_QUEUE_FLAG_MIGRATE;
- q = xe_exec_queue_create_bind(xe, tile, flags, 0);
+ q = xe_exec_queue_create_bind(xe, tile, NULL, flags, 0);
if (IS_ERR(q)) {
err = PTR_ERR(q);
goto err_ret;
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 79ab6c512d3e..095bb197e8b0 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -1617,7 +1617,7 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef)
if (!vm->pt_root[id])
continue;
- q = xe_exec_queue_create_bind(xe, tile, create_flags, 0);
+ q = xe_exec_queue_create_bind(xe, tile, vm, create_flags, 0);
if (IS_ERR(q)) {
err = PTR_ERR(q);
goto err_close;
@@ -3578,6 +3578,11 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
}
}
+ if (XE_IOCTL_DBG(xe, q && vm != q->user_vm)) {
+ err = -EINVAL;
+ goto put_exec_queue;
+ }
+
/* Ensure all UNMAPs visible */
xe_svm_flush(vm);
diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
index ef8a5019574e..016f6786134c 100644
--- a/drivers/gpu/drm/xe/xe_vm.h
+++ b/drivers/gpu/drm/xe/xe_vm.h
@@ -379,7 +379,7 @@ static inline void xe_vm_set_validation_exec(struct xe_vm *vm, struct drm_exec *
}
/**
- * xe_vm_set_validation_exec() - Accessor to read the drm_exec object
+ * xe_vm_validation_exec() - Accessor to read the drm_exec object
* @vm: The vm we want to register a drm_exec object with.
*
* Return: The drm_exec object used to lock the vm's resv. The value