From 9fc97277eb2d17492de636b68cf7d2f5c4f15c1b Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Tue, 25 Jun 2024 17:26:52 -0300 Subject: drm/i915: Skip programming FIA link enable bits for MTL+ Starting with Xe_LPD+, although FIA is still used to readout Type-C pin assignment, part of Type-C support is moved to PICA and programming PORT_TX_DFLEXDPMLE1(*) registers is not applicable anymore like it was for previous display IPs (e.g. see BSpec 49190). v2: - Mention Bspec 49190 as a reference of instructions for previous IPs. (Shekhar Chauhan) - s/Xe_LPDP/Xe_LPD+/ in the commit message. (Matt Roper) - Update commit message to be more accurate to the changes in the IP. (Imre Deak) Bspec: 65750, 65448 Reviewed-by: Shekhar Chauhan Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20240625202652.315936-1-gustavo.sousa@intel.com Signed-off-by: Gustavo Sousa --- drivers/gpu/drm/i915/display/intel_tc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c index 9887967b2ca5..6f2ee7dbc43b 100644 --- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -393,6 +393,9 @@ void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port, bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL; u32 val; + if (DISPLAY_VER(i915) >= 14) + return; + drm_WARN_ON(&i915->drm, lane_reversal && tc->mode != TC_PORT_LEGACY); -- cgit v1.2.3 From 7c0389c615b5c6aef1b0e38e30db759b3cbff885 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 1 Jul 2024 21:30:30 +0200 Subject: drm/xe/guc: Demote GuC IDs usage message to debug Printing message at INFO level about available GuC IDs is not that important, DEBUG level is enough. It will also match message about available doorbells: [ ] xe ... [drm:xe_guc_id_mgr_init [xe]] GT0: using 65535 GuC IDs [ ] xe ... [drm:xe_guc_db_mgr_init [xe]] GT0: using 256 doorbells While at it, use proper "GuC" name. Signed-off-by: Michal Wajdeczko Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20240701193030.978-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_guc_id_mgr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_id_mgr.c b/drivers/gpu/drm/xe/xe_guc_id_mgr.c index cd0549d0ef89..e845425d670b 100644 --- a/drivers/gpu/drm/xe/xe_guc_id_mgr.c +++ b/drivers/gpu/drm/xe/xe_guc_id_mgr.c @@ -97,8 +97,8 @@ int xe_guc_id_mgr_init(struct xe_guc_id_mgr *idm, unsigned int limit) if (ret) return ret; - xe_gt_info(idm_to_gt(idm), "using %u GUC ID%s\n", - idm->total, str_plural(idm->total)); + xe_gt_dbg(idm_to_gt(idm), "using %u GuC ID%s\n", + idm->total, str_plural(idm->total)); return 0; } -- cgit v1.2.3 From 627c961d672d3304564455ba471f5e4405170eec Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Tue, 25 Jun 2024 17:41:37 -0700 Subject: drm/xe: Add timeout to preempt fences To adhere to dma fencing rules that fences must signal within a reasonable amount of time, add a 5 second timeout to preempt fences. If this timeout occurs, kill the associated VM as this fatal to the VM. v2: - Add comment for smp_wmb (Checkpatch) - Fix kernel doc typo (Inspection) - Add comment for killed check (Niranjana) v3: - Drop smp_wmb (Matthew Auld) - Don't take vm->lock in preempt fence worker (Matthew Auld) - Drop RB given changes to patch v4: - Add WRITE/READ_ONCE (Niranjana) - Don't export xe_vm_kill (Niranjana) Cc: Matthew Auld Cc: Niranjana Vishwanathapura Signed-off-by: Matthew Brost Tested-by: Stuart Summers Reviewed-by: Niranjana Vishwanathapura Link: https://patchwork.freedesktop.org/patch/msgid/20240626004137.4060806-1-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_exec_queue_types.h | 6 +++-- drivers/gpu/drm/xe/xe_execlist.c | 3 ++- drivers/gpu/drm/xe/xe_guc_submit.c | 39 +++++++++++++++++++++++++++----- drivers/gpu/drm/xe/xe_preempt_fence.c | 12 +++++++--- drivers/gpu/drm/xe/xe_vm.c | 12 +++++++++- 5 files changed, 59 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h index 201588ec33c3..ded9f9396429 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h @@ -172,9 +172,11 @@ struct xe_exec_queue_ops { int (*suspend)(struct xe_exec_queue *q); /** * @suspend_wait: Wait for an exec queue to suspend executing, should be - * call after suspend. + * call after suspend. In dma-fencing path thus must return within a + * reasonable amount of time. -ETIME return shall indicate an error + * waiting for suspend resulting in associated VM getting killed. */ - void (*suspend_wait)(struct xe_exec_queue *q); + int (*suspend_wait)(struct xe_exec_queue *q); /** * @resume: Resume exec queue execution, exec queue must be in a suspended * state and dma fence returned from most recent suspend call must be diff --git a/drivers/gpu/drm/xe/xe_execlist.c b/drivers/gpu/drm/xe/xe_execlist.c index db906117db6d..7502e3486eaf 100644 --- a/drivers/gpu/drm/xe/xe_execlist.c +++ b/drivers/gpu/drm/xe/xe_execlist.c @@ -422,10 +422,11 @@ static int execlist_exec_queue_suspend(struct xe_exec_queue *q) return 0; } -static void execlist_exec_queue_suspend_wait(struct xe_exec_queue *q) +static int execlist_exec_queue_suspend_wait(struct xe_exec_queue *q) { /* NIY */ + return 0; } static void execlist_exec_queue_resume(struct xe_exec_queue *q) diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 373447758a60..6392381e8e69 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -1301,6 +1301,15 @@ static void __guc_exec_queue_process_msg_set_sched_props(struct xe_sched_msg *ms kfree(msg); } +static void __suspend_fence_signal(struct xe_exec_queue *q) +{ + if (!q->guc->suspend_pending) + return; + + WRITE_ONCE(q->guc->suspend_pending, false); + wake_up(&q->guc->suspend_wait); +} + static void suspend_fence_signal(struct xe_exec_queue *q) { struct xe_guc *guc = exec_queue_to_guc(q); @@ -1310,9 +1319,7 @@ static void suspend_fence_signal(struct xe_exec_queue *q) guc_read_stopped(guc)); xe_assert(xe, q->guc->suspend_pending); - q->guc->suspend_pending = false; - smp_wmb(); - wake_up(&q->guc->suspend_wait); + __suspend_fence_signal(q); } static void __guc_exec_queue_process_msg_suspend(struct xe_sched_msg *msg) @@ -1465,6 +1472,7 @@ static void guc_exec_queue_kill(struct xe_exec_queue *q) { trace_xe_exec_queue_kill(q); set_exec_queue_killed(q); + __suspend_fence_signal(q); xe_guc_exec_queue_trigger_cleanup(q); } @@ -1561,12 +1569,31 @@ static int guc_exec_queue_suspend(struct xe_exec_queue *q) return 0; } -static void guc_exec_queue_suspend_wait(struct xe_exec_queue *q) +static int guc_exec_queue_suspend_wait(struct xe_exec_queue *q) { struct xe_guc *guc = exec_queue_to_guc(q); + int ret; + + /* + * Likely don't need to check exec_queue_killed() as we clear + * suspend_pending upon kill but to be paranoid but races in which + * suspend_pending is set after kill also check kill here. + */ + ret = wait_event_timeout(q->guc->suspend_wait, + !READ_ONCE(q->guc->suspend_pending) || + exec_queue_killed(q) || + guc_read_stopped(guc), + HZ * 5); - wait_event(q->guc->suspend_wait, !q->guc->suspend_pending || - guc_read_stopped(guc)); + if (!ret) { + xe_gt_warn(guc_to_gt(guc), + "Suspend fence, guc_id=%d, failed to respond", + q->guc->id); + /* XXX: Trigger GT reset? */ + return -ETIME; + } + + return 0; } static void guc_exec_queue_resume(struct xe_exec_queue *q) diff --git a/drivers/gpu/drm/xe/xe_preempt_fence.c b/drivers/gpu/drm/xe/xe_preempt_fence.c index e8b8ae5c6485..56e709d2fb30 100644 --- a/drivers/gpu/drm/xe/xe_preempt_fence.c +++ b/drivers/gpu/drm/xe/xe_preempt_fence.c @@ -17,10 +17,16 @@ static void preempt_fence_work_func(struct work_struct *w) container_of(w, typeof(*pfence), preempt_work); struct xe_exec_queue *q = pfence->q; - if (pfence->error) + if (pfence->error) { dma_fence_set_error(&pfence->base, pfence->error); - else - q->ops->suspend_wait(q); + } else if (!q->ops->reset_status(q)) { + int err = q->ops->suspend_wait(q); + + if (err) + dma_fence_set_error(&pfence->base, err); + } else { + dma_fence_set_error(&pfence->base, -ENOENT); + } dma_fence_signal(&pfence->base); /* diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 5b166fa03684..0c764647a552 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -133,8 +133,10 @@ static int wait_for_existing_preempt_fences(struct xe_vm *vm) if (q->lr.pfence) { long timeout = dma_fence_wait(q->lr.pfence, false); - if (timeout < 0) + /* Only -ETIME on fence indicates VM needs to be killed */ + if (timeout < 0 || q->lr.pfence->error == -ETIME) return -ETIME; + dma_fence_put(q->lr.pfence); q->lr.pfence = NULL; } @@ -311,6 +313,14 @@ int __xe_vm_userptr_needs_repin(struct xe_vm *vm) #define XE_VM_REBIND_RETRY_TIMEOUT_MS 1000 +/* + * xe_vm_kill() - VM Kill + * @vm: The VM. + * @unlocked: Flag indicates the VM's dma-resv is not held + * + * Kill the VM by setting banned flag indicated VM is no longer available for + * use. If in preempt fence mode, also kill all exec queue attached to the VM. + */ static void xe_vm_kill(struct xe_vm *vm, bool unlocked) { struct xe_exec_queue *q; -- cgit v1.2.3 From 8169b2097d88d99d7e4a72e20e4b549efe9eb8d7 Mon Sep 17 00:00:00 2001 From: Ashutosh Dixit Date: Wed, 3 Jul 2024 09:48:01 -0700 Subject: drm/xe/uapi: Rename xe perf layer as xe observation layer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In Xe, the perf layer allows capture of HW counter streams. These HW counters are generally performance related but don't have to be necessarily so. Also, the name "perf" is a carryover from i915 and is not preferred. Here we propose the name "observation" for this common layer which allows capture of different types of these counter streams. v2: Rename observability layer to observation layer (Lucas/Rodrigo) v3: Rename sysctl file to "observation_paranoid" (Jose) Fixes: 52c2e956dceb ("drm/xe/perf/uapi: "Perf" layer to support multiple perf counter stream types") Fixes: fe8929bdf835 ("drm/xe/perf/uapi: Add perf_stream_paranoid sysctl") Acked-by: Lucas De Marchi Acked-by: Rodrigo Vivi Signed-off-by: Ashutosh Dixit Reviewed-by: Umesh Nerlige Ramappa Acked-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20240703164801.2561423-1-ashutosh.dixit@intel.com --- drivers/gpu/drm/xe/Makefile | 2 +- drivers/gpu/drm/xe/xe_device.c | 4 +- drivers/gpu/drm/xe/xe_device_types.h | 2 +- drivers/gpu/drm/xe/xe_gt_types.h | 2 +- drivers/gpu/drm/xe/xe_module.c | 6 +-- drivers/gpu/drm/xe/xe_oa.c | 34 ++++++------ drivers/gpu/drm/xe/xe_observation.c | 93 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_observation.h | 20 +++++++ drivers/gpu/drm/xe/xe_perf.c | 92 ------------------------------- drivers/gpu/drm/xe/xe_perf.h | 20 ------- include/uapi/drm/xe_drm.h | 102 ++++++++++++++++++----------------- 11 files changed, 190 insertions(+), 187 deletions(-) create mode 100644 drivers/gpu/drm/xe/xe_observation.c create mode 100644 drivers/gpu/drm/xe/xe_observation.h delete mode 100644 drivers/gpu/drm/xe/xe_perf.c delete mode 100644 drivers/gpu/drm/xe/xe_perf.h diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index b1e03bfe4a68..628c245c4822 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -96,10 +96,10 @@ xe-y += xe_bb.o \ xe_mocs.o \ xe_module.o \ xe_oa.o \ + xe_observation.o \ xe_pat.o \ xe_pci.o \ xe_pcode.o \ - xe_perf.o \ xe_pm.o \ xe_preempt_fence.o \ xe_pt.o \ diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index cfda7cb5df2c..03492fbcb8fb 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -42,9 +42,9 @@ #include "xe_memirq.h" #include "xe_mmio.h" #include "xe_module.h" +#include "xe_observation.h" #include "xe_pat.h" #include "xe_pcode.h" -#include "xe_perf.h" #include "xe_pm.h" #include "xe_query.h" #include "xe_sriov.h" @@ -142,7 +142,7 @@ static const struct drm_ioctl_desc xe_ioctls[] = { DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(XE_WAIT_USER_FENCE, xe_wait_user_fence_ioctl, DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(XE_PERF, xe_perf_ioctl, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl, DRM_RENDER_ALLOW), }; static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index c37be471d11c..3bca6d344744 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -463,7 +463,7 @@ struct xe_device { /** @heci_gsc: graphics security controller */ struct xe_heci_gsc heci_gsc; - /** @oa: oa perf counter subsystem */ + /** @oa: oa observation subsystem */ struct xe_oa oa; /** @needs_flr_on_fini: requests function-reset on fini */ diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h index 24bb95de920f..6b5e0b45efb0 100644 --- a/drivers/gpu/drm/xe/xe_gt_types.h +++ b/drivers/gpu/drm/xe/xe_gt_types.h @@ -389,7 +389,7 @@ struct xe_gt { u8 instances_per_class[XE_ENGINE_CLASS_MAX]; } user_engines; - /** @oa: oa perf counter subsystem per gt info */ + /** @oa: oa observation subsystem per gt info */ struct xe_oa_gt oa; }; diff --git a/drivers/gpu/drm/xe/xe_module.c b/drivers/gpu/drm/xe/xe_module.c index 893858a2eea0..499540add465 100644 --- a/drivers/gpu/drm/xe/xe_module.c +++ b/drivers/gpu/drm/xe/xe_module.c @@ -11,7 +11,7 @@ #include "xe_drv.h" #include "xe_hw_fence.h" #include "xe_pci.h" -#include "xe_perf.h" +#include "xe_observation.h" #include "xe_sched_job.h" struct xe_modparam xe_modparam = { @@ -80,8 +80,8 @@ static const struct init_funcs init_funcs[] = { .exit = xe_unregister_pci_driver, }, { - .init = xe_perf_sysctl_register, - .exit = xe_perf_sysctl_unregister, + .init = xe_observation_sysctl_register, + .exit = xe_observation_sysctl_unregister, }, }; diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c index 4188516a7816..6d69f751bf78 100644 --- a/drivers/gpu/drm/xe/xe_oa.c +++ b/drivers/gpu/drm/xe/xe_oa.c @@ -32,7 +32,7 @@ #include "xe_macros.h" #include "xe_mmio.h" #include "xe_oa.h" -#include "xe_perf.h" +#include "xe_observation.h" #include "xe_pm.h" #include "xe_sched_job.h" #include "xe_sriov.h" @@ -481,7 +481,7 @@ static int __xe_oa_read(struct xe_oa_stream *stream, char __user *buf, OASTATUS_RELEVANT_BITS, 0); /* * Signal to userspace that there is non-zero OA status to read via - * @DRM_XE_PERF_IOCTL_STATUS perf fd ioctl + * @DRM_XE_OBSERVATION_IOCTL_STATUS observation stream fd ioctl */ if (stream->oa_status & OASTATUS_RELEVANT_BITS) return -EIO; @@ -1158,15 +1158,15 @@ static long xe_oa_ioctl_locked(struct xe_oa_stream *stream, unsigned long arg) { switch (cmd) { - case DRM_XE_PERF_IOCTL_ENABLE: + case DRM_XE_OBSERVATION_IOCTL_ENABLE: return xe_oa_enable_locked(stream); - case DRM_XE_PERF_IOCTL_DISABLE: + case DRM_XE_OBSERVATION_IOCTL_DISABLE: return xe_oa_disable_locked(stream); - case DRM_XE_PERF_IOCTL_CONFIG: + case DRM_XE_OBSERVATION_IOCTL_CONFIG: return xe_oa_config_locked(stream, arg); - case DRM_XE_PERF_IOCTL_STATUS: + case DRM_XE_OBSERVATION_IOCTL_STATUS: return xe_oa_status_locked(stream, arg); - case DRM_XE_PERF_IOCTL_INFO: + case DRM_XE_OBSERVATION_IOCTL_INFO: return xe_oa_info_locked(stream, arg); } @@ -1209,7 +1209,7 @@ static int xe_oa_release(struct inode *inode, struct file *file) xe_oa_destroy_locked(stream); mutex_unlock(>->oa.gt_lock); - /* Release the reference the perf stream kept on the driver */ + /* Release the reference the OA stream kept on the driver */ drm_dev_put(>_to_xe(gt)->drm); return 0; @@ -1222,7 +1222,7 @@ static int xe_oa_mmap(struct file *file, struct vm_area_struct *vma) unsigned long start = vma->vm_start; int i, ret; - if (xe_perf_stream_paranoid && !perfmon_capable()) { + if (xe_observation_paranoid && !perfmon_capable()) { drm_dbg(&stream->oa->xe->drm, "Insufficient privilege to map OA buffer\n"); return -EACCES; } @@ -1789,8 +1789,8 @@ static int xe_oa_user_extensions(struct xe_oa *oa, u64 extension, int ext_number * @file: @drm_file * * The functions opens an OA stream. An OA stream, opened with specified - * properties, enables perf counter samples to be collected, either - * periodically (time based sampling), or on request (using perf queries) + * properties, enables OA counter samples to be collected, either + * periodically (time based sampling), or on request (using OA queries) */ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *file) { @@ -1836,8 +1836,8 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *f privileged_op = true; } - if (privileged_op && xe_perf_stream_paranoid && !perfmon_capable()) { - drm_dbg(&oa->xe->drm, "Insufficient privileges to open xe perf stream\n"); + if (privileged_op && xe_observation_paranoid && !perfmon_capable()) { + drm_dbg(&oa->xe->drm, "Insufficient privileges to open xe OA stream\n"); ret = -EACCES; goto err_exec_q; } @@ -2097,7 +2097,7 @@ int xe_oa_add_config_ioctl(struct drm_device *dev, u64 data, struct drm_file *fi return -ENODEV; } - if (xe_perf_stream_paranoid && !perfmon_capable()) { + if (xe_observation_paranoid && !perfmon_capable()) { drm_dbg(&oa->xe->drm, "Insufficient privileges to add xe OA config\n"); return -EACCES; } @@ -2181,7 +2181,7 @@ reg_err: /** * xe_oa_remove_config_ioctl - Removes one OA config * @dev: @drm_device - * @data: pointer to struct @drm_xe_perf_param + * @data: pointer to struct @drm_xe_observation_param * @file: @drm_file */ int xe_oa_remove_config_ioctl(struct drm_device *dev, u64 data, struct drm_file *file) @@ -2197,7 +2197,7 @@ int xe_oa_remove_config_ioctl(struct drm_device *dev, u64 data, struct drm_file return -ENODEV; } - if (xe_perf_stream_paranoid && !perfmon_capable()) { + if (xe_observation_paranoid && !perfmon_capable()) { drm_dbg(&oa->xe->drm, "Insufficient privileges to remove xe OA config\n"); return -EACCES; } @@ -2381,7 +2381,7 @@ static int xe_oa_init_gt(struct xe_gt *gt) /* * Fused off engines can result in oa_unit's with num_engines == 0. These units - * will appear in OA unit query, but no perf streams can be opened on them. + * will appear in OA unit query, but no OA streams can be opened on them. */ gt->oa.num_oa_units = num_oa_units; gt->oa.oa_unit = u; diff --git a/drivers/gpu/drm/xe/xe_observation.c b/drivers/gpu/drm/xe/xe_observation.c new file mode 100644 index 000000000000..fcb584b42a7d --- /dev/null +++ b/drivers/gpu/drm/xe/xe_observation.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023-2024 Intel Corporation + */ + +#include +#include + +#include + +#include "xe_oa.h" +#include "xe_observation.h" + +u32 xe_observation_paranoid = true; +static struct ctl_table_header *sysctl_header; + +static int xe_oa_ioctl(struct drm_device *dev, struct drm_xe_observation_param *arg, + struct drm_file *file) +{ + switch (arg->observation_op) { + case DRM_XE_OBSERVATION_OP_STREAM_OPEN: + return xe_oa_stream_open_ioctl(dev, arg->param, file); + case DRM_XE_OBSERVATION_OP_ADD_CONFIG: + return xe_oa_add_config_ioctl(dev, arg->param, file); + case DRM_XE_OBSERVATION_OP_REMOVE_CONFIG: + return xe_oa_remove_config_ioctl(dev, arg->param, file); + default: + return -EINVAL; + } +} + +/** + * xe_observation_ioctl - The top level observation layer ioctl + * @dev: @drm_device + * @data: pointer to struct @drm_xe_observation_param + * @file: @drm_file + * + * The function is called for different observation streams types and + * allows execution of different operations supported by those stream + * types. + * + * Return: 0 on success or a negative error code on failure. + */ +int xe_observation_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +{ + struct drm_xe_observation_param *arg = data; + + if (arg->extensions) + return -EINVAL; + + switch (arg->observation_type) { + case DRM_XE_OBSERVATION_TYPE_OA: + return xe_oa_ioctl(dev, arg, file); + default: + return -EINVAL; + } +} + +static struct ctl_table observation_ctl_table[] = { + { + .procname = "observation_paranoid", + .data = &xe_observation_paranoid, + .maxlen = sizeof(xe_observation_paranoid), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }, + {} +}; + +/** + * xe_observation_sysctl_register - Register xe_observation_paranoid sysctl + * + * Normally only superuser/root can access observation stream + * data. However, superuser can set xe_observation_paranoid sysctl to 0 to + * allow non-privileged users to also access observation data. + * + * Return: always returns 0 + */ +int xe_observation_sysctl_register(void) +{ + sysctl_header = register_sysctl("dev/xe", observation_ctl_table); + return 0; +} + +/** + * xe_observation_sysctl_unregister - Unregister xe_observation_paranoid sysctl + */ +void xe_observation_sysctl_unregister(void) +{ + unregister_sysctl_table(sysctl_header); +} diff --git a/drivers/gpu/drm/xe/xe_observation.h b/drivers/gpu/drm/xe/xe_observation.h new file mode 100644 index 000000000000..17816998e966 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_observation.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023-2024 Intel Corporation + */ + +#ifndef _XE_OBSERVATION_H_ +#define _XE_OBSERVATION_H_ + +#include + +struct drm_device; +struct drm_file; + +extern u32 xe_observation_paranoid; + +int xe_observation_ioctl(struct drm_device *dev, void *data, struct drm_file *file); +int xe_observation_sysctl_register(void); +void xe_observation_sysctl_unregister(void); + +#endif diff --git a/drivers/gpu/drm/xe/xe_perf.c b/drivers/gpu/drm/xe/xe_perf.c deleted file mode 100644 index d6cd74cadf34..000000000000 --- a/drivers/gpu/drm/xe/xe_perf.c +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright © 2023-2024 Intel Corporation - */ - -#include -#include - -#include - -#include "xe_oa.h" -#include "xe_perf.h" - -u32 xe_perf_stream_paranoid = true; -static struct ctl_table_header *sysctl_header; - -static int xe_oa_ioctl(struct drm_device *dev, struct drm_xe_perf_param *arg, - struct drm_file *file) -{ - switch (arg->perf_op) { - case DRM_XE_PERF_OP_STREAM_OPEN: - return xe_oa_stream_open_ioctl(dev, arg->param, file); - case DRM_XE_PERF_OP_ADD_CONFIG: - return xe_oa_add_config_ioctl(dev, arg->param, file); - case DRM_XE_PERF_OP_REMOVE_CONFIG: - return xe_oa_remove_config_ioctl(dev, arg->param, file); - default: - return -EINVAL; - } -} - -/** - * xe_perf_ioctl - The top level perf layer ioctl - * @dev: @drm_device - * @data: pointer to struct @drm_xe_perf_param - * @file: @drm_file - * - * The function is called for different perf streams types and allows execution - * of different operations supported by those perf stream types. - * - * Return: 0 on success or a negative error code on failure. - */ -int xe_perf_ioctl(struct drm_device *dev, void *data, struct drm_file *file) -{ - struct drm_xe_perf_param *arg = data; - - if (arg->extensions) - return -EINVAL; - - switch (arg->perf_type) { - case DRM_XE_PERF_TYPE_OA: - return xe_oa_ioctl(dev, arg, file); - default: - return -EINVAL; - } -} - -static struct ctl_table perf_ctl_table[] = { - { - .procname = "perf_stream_paranoid", - .data = &xe_perf_stream_paranoid, - .maxlen = sizeof(xe_perf_stream_paranoid), - .mode = 0644, - .proc_handler = proc_dointvec_minmax, - .extra1 = SYSCTL_ZERO, - .extra2 = SYSCTL_ONE, - }, - {} -}; - -/** - * xe_perf_sysctl_register - Register "perf_stream_paranoid" sysctl - * - * Normally only superuser/root can access perf counter data. However, - * superuser can set perf_stream_paranoid sysctl to 0 to allow non-privileged - * users to also access perf data. - * - * Return: always returns 0 - */ -int xe_perf_sysctl_register(void) -{ - sysctl_header = register_sysctl("dev/xe", perf_ctl_table); - return 0; -} - -/** - * xe_perf_sysctl_unregister - Unregister "perf_stream_paranoid" sysctl - */ -void xe_perf_sysctl_unregister(void) -{ - unregister_sysctl_table(sysctl_header); -} diff --git a/drivers/gpu/drm/xe/xe_perf.h b/drivers/gpu/drm/xe/xe_perf.h deleted file mode 100644 index 53a8377a1bb1..000000000000 --- a/drivers/gpu/drm/xe/xe_perf.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023-2024 Intel Corporation - */ - -#ifndef _XE_PERF_H_ -#define _XE_PERF_H_ - -#include - -struct drm_device; -struct drm_file; - -extern u32 xe_perf_stream_paranoid; - -int xe_perf_ioctl(struct drm_device *dev, void *data, struct drm_file *file); -int xe_perf_sysctl_register(void); -void xe_perf_sysctl_unregister(void); - -#endif diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index 12eaa8532b5c..33544ef78d3e 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -80,7 +80,7 @@ extern "C" { * - &DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY * - &DRM_IOCTL_XE_EXEC * - &DRM_IOCTL_XE_WAIT_USER_FENCE - * - &DRM_IOCTL_XE_PERF + * - &DRM_IOCTL_XE_OBSERVATION */ /* @@ -101,7 +101,7 @@ extern "C" { #define DRM_XE_EXEC_QUEUE_GET_PROPERTY 0x08 #define DRM_XE_EXEC 0x09 #define DRM_XE_WAIT_USER_FENCE 0x0a -#define DRM_XE_PERF 0x0b +#define DRM_XE_OBSERVATION 0x0b /* Must be kept compact -- no holes */ @@ -116,7 +116,7 @@ extern "C" { #define DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_EXEC_QUEUE_GET_PROPERTY, struct drm_xe_exec_queue_get_property) #define DRM_IOCTL_XE_EXEC DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC, struct drm_xe_exec) #define DRM_IOCTL_XE_WAIT_USER_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE, struct drm_xe_wait_user_fence) -#define DRM_IOCTL_XE_PERF DRM_IOW(DRM_COMMAND_BASE + DRM_XE_PERF, struct drm_xe_perf_param) +#define DRM_IOCTL_XE_OBSERVATION DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION, struct drm_xe_observation_param) /** * DOC: Xe IOCTL Extensions @@ -1376,66 +1376,67 @@ struct drm_xe_wait_user_fence { }; /** - * enum drm_xe_perf_type - Perf stream types + * enum drm_xe_observation_type - Observation stream types */ -enum drm_xe_perf_type { - /** @DRM_XE_PERF_TYPE_OA: OA perf stream type */ - DRM_XE_PERF_TYPE_OA, +enum drm_xe_observation_type { + /** @DRM_XE_OBSERVATION_TYPE_OA: OA observation stream type */ + DRM_XE_OBSERVATION_TYPE_OA, }; /** - * enum drm_xe_perf_op - Perf stream ops + * enum drm_xe_observation_op - Observation stream ops */ -enum drm_xe_perf_op { - /** @DRM_XE_PERF_OP_STREAM_OPEN: Open a perf counter stream */ - DRM_XE_PERF_OP_STREAM_OPEN, +enum drm_xe_observation_op { + /** @DRM_XE_OBSERVATION_OP_STREAM_OPEN: Open an observation stream */ + DRM_XE_OBSERVATION_OP_STREAM_OPEN, - /** @DRM_XE_PERF_OP_ADD_CONFIG: Add perf stream config */ - DRM_XE_PERF_OP_ADD_CONFIG, + /** @DRM_XE_OBSERVATION_OP_ADD_CONFIG: Add observation stream config */ + DRM_XE_OBSERVATION_OP_ADD_CONFIG, - /** @DRM_XE_PERF_OP_REMOVE_CONFIG: Remove perf stream config */ - DRM_XE_PERF_OP_REMOVE_CONFIG, + /** @DRM_XE_OBSERVATION_OP_REMOVE_CONFIG: Remove observation stream config */ + DRM_XE_OBSERVATION_OP_REMOVE_CONFIG, }; /** - * struct drm_xe_perf_param - Input of &DRM_XE_PERF + * struct drm_xe_observation_param - Input of &DRM_XE_OBSERVATION * - * The perf layer enables multiplexing perf counter streams of multiple - * types. The actual params for a particular stream operation are supplied - * via the @param pointer (use __copy_from_user to get these params). + * The observation layer enables multiplexing observation streams of + * multiple types. The actual params for a particular stream operation are + * supplied via the @param pointer (use __copy_from_user to get these + * params). */ -struct drm_xe_perf_param { +struct drm_xe_observation_param { /** @extensions: Pointer to the first extension struct, if any */ __u64 extensions; - /** @perf_type: Perf stream type, of enum @drm_xe_perf_type */ - __u64 perf_type; - /** @perf_op: Perf op, of enum @drm_xe_perf_op */ - __u64 perf_op; + /** @observation_type: observation stream type, of enum @drm_xe_observation_type */ + __u64 observation_type; + /** @observation_op: observation stream op, of enum @drm_xe_observation_op */ + __u64 observation_op; /** @param: Pointer to actual stream params */ __u64 param; }; /** - * enum drm_xe_perf_ioctls - Perf fd ioctl's + * enum drm_xe_observation_ioctls - Observation stream fd ioctl's * - * Information exchanged between userspace and kernel for perf fd ioctl's - * is stream type specific + * Information exchanged between userspace and kernel for observation fd + * ioctl's is stream type specific */ -enum drm_xe_perf_ioctls { - /** @DRM_XE_PERF_IOCTL_ENABLE: Enable data capture for a stream */ - DRM_XE_PERF_IOCTL_ENABLE = _IO('i', 0x0), +enum drm_xe_observation_ioctls { + /** @DRM_XE_OBSERVATION_IOCTL_ENABLE: Enable data capture for an observation stream */ + DRM_XE_OBSERVATION_IOCTL_ENABLE = _IO('i', 0x0), - /** @DRM_XE_PERF_IOCTL_DISABLE: Disable data capture for a stream */ - DRM_XE_PERF_IOCTL_DISABLE = _IO('i', 0x1), + /** @DRM_XE_OBSERVATION_IOCTL_DISABLE: Disable data capture for a observation stream */ + DRM_XE_OBSERVATION_IOCTL_DISABLE = _IO('i', 0x1), - /** @DRM_XE_PERF_IOCTL_CONFIG: Change stream configuration */ - DRM_XE_PERF_IOCTL_CONFIG = _IO('i', 0x2), + /** @DRM_XE_OBSERVATION_IOCTL_CONFIG: Change observation stream configuration */ + DRM_XE_OBSERVATION_IOCTL_CONFIG = _IO('i', 0x2), - /** @DRM_XE_PERF_IOCTL_STATUS: Return stream status */ - DRM_XE_PERF_IOCTL_STATUS = _IO('i', 0x3), + /** @DRM_XE_OBSERVATION_IOCTL_STATUS: Return observation stream status */ + DRM_XE_OBSERVATION_IOCTL_STATUS = _IO('i', 0x3), - /** @DRM_XE_PERF_IOCTL_INFO: Return stream info */ - DRM_XE_PERF_IOCTL_INFO = _IO('i', 0x4), + /** @DRM_XE_OBSERVATION_IOCTL_INFO: Return observation stream info */ + DRM_XE_OBSERVATION_IOCTL_INFO = _IO('i', 0x4), }; /** @@ -1546,12 +1547,12 @@ enum drm_xe_oa_format_type { * Stream params are specified as a chain of @drm_xe_ext_set_property * struct's, with @property values from enum @drm_xe_oa_property_id and * @drm_xe_user_extension base.name set to @DRM_XE_OA_EXTENSION_SET_PROPERTY. - * @param field in struct @drm_xe_perf_param points to the first + * @param field in struct @drm_xe_observation_param points to the first * @drm_xe_ext_set_property struct. * - * Exactly the same mechanism is also used for stream reconfiguration using - * the @DRM_XE_PERF_IOCTL_CONFIG perf fd ioctl, though only a subset of - * properties below can be specified for stream reconfiguration. + * Exactly the same mechanism is also used for stream reconfiguration using the + * @DRM_XE_OBSERVATION_IOCTL_CONFIG observation stream fd ioctl, though only a + * subset of properties below can be specified for stream reconfiguration. */ enum drm_xe_oa_property_id { #define DRM_XE_OA_EXTENSION_SET_PROPERTY 0 @@ -1571,11 +1572,11 @@ enum drm_xe_oa_property_id { /** * @DRM_XE_OA_PROPERTY_OA_METRIC_SET: OA metrics defining contents of OA - * reports, previously added via @DRM_XE_PERF_OP_ADD_CONFIG. + * reports, previously added via @DRM_XE_OBSERVATION_OP_ADD_CONFIG. */ DRM_XE_OA_PROPERTY_OA_METRIC_SET, - /** @DRM_XE_OA_PROPERTY_OA_FORMAT: Perf counter report format */ + /** @DRM_XE_OA_PROPERTY_OA_FORMAT: OA counter report format */ DRM_XE_OA_PROPERTY_OA_FORMAT, /* * OA_FORMAT's are specified the same way as in PRM/Bspec 52198/60942, @@ -1596,13 +1597,13 @@ enum drm_xe_oa_property_id { /** * @DRM_XE_OA_PROPERTY_OA_DISABLED: A value of 1 will open the OA - * stream in a DISABLED state (see @DRM_XE_PERF_IOCTL_ENABLE). + * stream in a DISABLED state (see @DRM_XE_OBSERVATION_IOCTL_ENABLE). */ DRM_XE_OA_PROPERTY_OA_DISABLED, /** * @DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID: Open the stream for a specific - * @exec_queue_id. Perf queries can be executed on this exec queue. + * @exec_queue_id. OA queries can be executed on this exec queue. */ DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID, @@ -1622,7 +1623,7 @@ enum drm_xe_oa_property_id { /** * struct drm_xe_oa_config - OA metric configuration * - * Multiple OA configs can be added using @DRM_XE_PERF_OP_ADD_CONFIG. A + * Multiple OA configs can be added using @DRM_XE_OBSERVATION_OP_ADD_CONFIG. A * particular config can be specified when opening an OA stream using * @DRM_XE_OA_PROPERTY_OA_METRIC_SET property. */ @@ -1645,8 +1646,9 @@ struct drm_xe_oa_config { /** * struct drm_xe_oa_stream_status - OA stream status returned from - * @DRM_XE_PERF_IOCTL_STATUS perf fd ioctl. Userspace can call the ioctl to - * query stream status in response to EIO errno from perf fd read(). + * @DRM_XE_OBSERVATION_IOCTL_STATUS observation stream fd ioctl. Userspace can + * call the ioctl to query stream status in response to EIO errno from + * observation fd read(). */ struct drm_xe_oa_stream_status { /** @extensions: Pointer to the first extension struct, if any */ @@ -1665,7 +1667,7 @@ struct drm_xe_oa_stream_status { /** * struct drm_xe_oa_stream_info - OA stream info returned from - * @DRM_XE_PERF_IOCTL_INFO perf fd ioctl + * @DRM_XE_OBSERVATION_IOCTL_INFO observation stream fd ioctl */ struct drm_xe_oa_stream_info { /** @extensions: Pointer to the first extension struct, if any */ -- cgit v1.2.3 From 67d90d679eb3447f73e2a1fe55f7e6c6a44c9fa1 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Wed, 3 Jul 2024 21:16:46 -0700 Subject: drm/xe: s/xe_tile_migrate_engine/xe_tile_migrate_exec_queue Engine is old nomenclature, replace with exec queue. Signed-off-by: Matthew Brost Reviewed-by: Jonathan Cavitt Link: https://patchwork.freedesktop.org/patch/msgid/20240704041652.272920-2-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_migrate.c | 9 ++++----- drivers/gpu/drm/xe/xe_migrate.h | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c index c9f5673353ee..ef5ad0efc5dd 100644 --- a/drivers/gpu/drm/xe/xe_migrate.c +++ b/drivers/gpu/drm/xe/xe_migrate.c @@ -84,15 +84,14 @@ struct xe_migrate { #define MAX_PTE_PER_SDI 0x1FE /** - * xe_tile_migrate_engine() - Get this tile's migrate engine. + * xe_tile_migrate_exec_queue() - Get this tile's migrate exec queue. * @tile: The tile. * - * Returns the default migrate engine of this tile. - * TODO: Perhaps this function is slightly misplaced, and even unneeded? + * Returns the default migrate exec queue of this tile. * - * Return: The default migrate engine + * Return: The default migrate exec queue */ -struct xe_exec_queue *xe_tile_migrate_engine(struct xe_tile *tile) +struct xe_exec_queue *xe_tile_migrate_exec_queue(struct xe_tile *tile) { return tile->migrate->q; } diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h index 951f19318ea4..a5bcaafe4a99 100644 --- a/drivers/gpu/drm/xe/xe_migrate.h +++ b/drivers/gpu/drm/xe/xe_migrate.h @@ -106,5 +106,5 @@ xe_migrate_update_pgtables(struct xe_migrate *m, void xe_migrate_wait(struct xe_migrate *m); -struct xe_exec_queue *xe_tile_migrate_engine(struct xe_tile *tile); +struct xe_exec_queue *xe_tile_migrate_exec_queue(struct xe_tile *tile); #endif -- cgit v1.2.3 From 2e524668c440104633af1effcc85d1d6234c7ccf Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Wed, 3 Jul 2024 21:16:47 -0700 Subject: drm/xe: Add xe_vm_pgtable_update_op to xe_vma_ops Each xe_vma_op resolves to 0-3 pt_ops. Add storage for the pt_ops to xe_vma_ops which is dynamically allocated based the number and types of xe_vma_op in the xe_vma_ops list. Allocation only implemented in this patch. This will help with converting xe_vma_ops (multiple xe_vma_op) in a atomic update unit. Signed-off-by: Matthew Brost Reviewed-by: Jonathan Cavitt Link: https://patchwork.freedesktop.org/patch/msgid/20240704041652.272920-3-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_pt_types.h | 12 ++++++++ drivers/gpu/drm/xe/xe_vm.c | 66 ++++++++++++++++++++++++++++++++++++++-- drivers/gpu/drm/xe/xe_vm_types.h | 8 +++++ 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_pt_types.h b/drivers/gpu/drm/xe/xe_pt_types.h index cee70cb0f014..2093150f461e 100644 --- a/drivers/gpu/drm/xe/xe_pt_types.h +++ b/drivers/gpu/drm/xe/xe_pt_types.h @@ -74,4 +74,16 @@ struct xe_vm_pgtable_update { u32 flags; }; +/** struct xe_vm_pgtable_update_op - Page table update operation */ +struct xe_vm_pgtable_update_op { + /** @entries: entries to update for this operation */ + struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1]; + /** @num_entries: number of entries for this update operation */ + u32 num_entries; + /** @bind: is a bind */ + bool bind; + /** @rebind: is a rebind */ + bool rebind; +}; + #endif diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 0c764647a552..6677874af5a4 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -718,6 +718,42 @@ int xe_vm_userptr_check_repin(struct xe_vm *vm) list_empty_careful(&vm->userptr.invalidated)) ? 0 : -EAGAIN; } +static int xe_vma_ops_alloc(struct xe_vma_ops *vops) +{ + int i; + + for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) { + if (!vops->pt_update_ops[i].num_ops) + continue; + + vops->pt_update_ops[i].ops = + kmalloc_array(vops->pt_update_ops[i].num_ops, + sizeof(*vops->pt_update_ops[i].ops), + GFP_KERNEL); + if (!vops->pt_update_ops[i].ops) + return -ENOMEM; + } + + return 0; +} + +static void xe_vma_ops_fini(struct xe_vma_ops *vops) +{ + int i; + + for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) + kfree(vops->pt_update_ops[i].ops); +} + +static void xe_vma_ops_incr_pt_update_ops(struct xe_vma_ops *vops, u8 tile_mask) +{ + int i; + + for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) + if (BIT(i) & tile_mask) + ++vops->pt_update_ops[i].num_ops; +} + static void xe_vm_populate_rebind(struct xe_vma_op *op, struct xe_vma *vma, u8 tile_mask) { @@ -745,6 +781,7 @@ static int xe_vm_ops_add_rebind(struct xe_vma_ops *vops, struct xe_vma *vma, xe_vm_populate_rebind(op, vma, tile_mask); list_add_tail(&op->link, &vops->list); + xe_vma_ops_incr_pt_update_ops(vops, tile_mask); return 0; } @@ -785,6 +822,10 @@ int xe_vm_rebind(struct xe_vm *vm, bool rebind_worker) goto free_ops; } + err = xe_vma_ops_alloc(&vops); + if (err) + goto free_ops; + fence = ops_execute(vm, &vops); if (IS_ERR(fence)) { err = PTR_ERR(fence); @@ -799,6 +840,7 @@ free_ops: list_del(&op->link); kfree(op); } + xe_vma_ops_fini(&vops); return err; } @@ -820,12 +862,20 @@ struct dma_fence *xe_vma_rebind(struct xe_vm *vm, struct xe_vma *vma, u8 tile_ma if (err) return ERR_PTR(err); + err = xe_vma_ops_alloc(&vops); + if (err) { + fence = ERR_PTR(err); + goto free_ops; + } + fence = ops_execute(vm, &vops); +free_ops: list_for_each_entry_safe(op, next_op, &vops.list, link) { list_del(&op->link); kfree(op); } + xe_vma_ops_fini(&vops); return fence; } @@ -2287,7 +2337,6 @@ static int xe_vma_op_commit(struct xe_vm *vm, struct xe_vma_op *op) return err; } - static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q, struct drm_gpuva_ops *ops, struct xe_sync_entry *syncs, u32 num_syncs, @@ -2339,6 +2388,9 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q, return PTR_ERR(vma); op->map.vma = vma; + if (op->map.immediate || !xe_vm_in_fault_mode(vm)) + xe_vma_ops_incr_pt_update_ops(vops, + op->tile_mask); break; } case DRM_GPUVA_OP_REMAP: @@ -2383,6 +2435,8 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q, vm_dbg(&xe->drm, "REMAP:SKIP_PREV: addr=0x%016llx, range=0x%016llx", (ULL)op->remap.start, (ULL)op->remap.range); + } else { + xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); } } @@ -2419,13 +2473,16 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q, vm_dbg(&xe->drm, "REMAP:SKIP_NEXT: addr=0x%016llx, range=0x%016llx", (ULL)op->remap.start, (ULL)op->remap.range); + } else { + xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); } } + xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); break; } case DRM_GPUVA_OP_UNMAP: case DRM_GPUVA_OP_PREFETCH: - /* Nothing to do */ + xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); break; default: drm_warn(&vm->xe->drm, "NOT POSSIBLE"); @@ -3272,11 +3329,16 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) goto unwind_ops; } + err = xe_vma_ops_alloc(&vops); + if (err) + goto unwind_ops; + err = vm_bind_ioctl_ops_execute(vm, &vops); unwind_ops: if (err && err != -ENODATA) vm_bind_ioctl_ops_unwind(vm, ops, args->num_binds); + xe_vma_ops_fini(&vops); for (i = args->num_binds - 1; i >= 0; --i) if (ops[i]) drm_gpuva_ops_free(&vm->gpuvm, ops[i]); diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h index ce1a63a5e3e7..211c88801182 100644 --- a/drivers/gpu/drm/xe/xe_vm_types.h +++ b/drivers/gpu/drm/xe/xe_vm_types.h @@ -21,6 +21,7 @@ struct xe_bo; struct xe_sync_entry; struct xe_user_fence; struct xe_vm; +struct xe_vm_pgtable_update_op; #define XE_VMA_READ_ONLY DRM_GPUVA_USERBITS #define XE_VMA_DESTROYED (DRM_GPUVA_USERBITS << 1) @@ -368,6 +369,13 @@ struct xe_vma_ops { struct xe_sync_entry *syncs; /** @num_syncs: number of syncs */ u32 num_syncs; + /** @pt_update_ops: page table update operations */ + struct { + /** @ops: operations */ + struct xe_vm_pgtable_update_op *ops; + /** @num_ops: number of operations */ + u32 num_ops; + } pt_update_ops[XE_MAX_TILES_PER_DEVICE]; }; #endif -- cgit v1.2.3 From 96e7ebb220f8a873321cfc5a87bc4533d36ec444 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Wed, 3 Jul 2024 21:16:48 -0700 Subject: drm/xe: Add xe_exec_queue_last_fence_test_dep Helpful to determine if a bind can immediately use CPU or needs to be deferred a drm scheduler job. v7: - Better wording in kernel doc (Matthew Auld) Signed-off-by: Matthew Brost Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20240704041652.272920-4-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_exec_queue.c | 23 +++++++++++++++++++++++ drivers/gpu/drm/xe/xe_exec_queue.h | 2 ++ 2 files changed, 25 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c index 0ba37835849b..3336a01a1006 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.c +++ b/drivers/gpu/drm/xe/xe_exec_queue.c @@ -906,3 +906,26 @@ void xe_exec_queue_last_fence_set(struct xe_exec_queue *q, struct xe_vm *vm, xe_exec_queue_last_fence_put(q, vm); q->last_fence = dma_fence_get(fence); } + +/** + * xe_exec_queue_last_fence_test_dep - Test last fence dependency of queue + * @q: The exec queue + * @vm: The VM the engine does a bind or exec for + * + * Returns: + * -ETIME if there exists an unsignalled last fence dependency, zero otherwise. + */ +int xe_exec_queue_last_fence_test_dep(struct xe_exec_queue *q, struct xe_vm *vm) +{ + struct dma_fence *fence; + int err = 0; + + fence = xe_exec_queue_last_fence_get(q, vm); + if (fence) { + err = test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags) ? + 0 : -ETIME; + dma_fence_put(fence); + } + + return err; +} diff --git a/drivers/gpu/drm/xe/xe_exec_queue.h b/drivers/gpu/drm/xe/xe_exec_queue.h index 289a3a51d2a2..ded77b0f3b90 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.h +++ b/drivers/gpu/drm/xe/xe_exec_queue.h @@ -75,6 +75,8 @@ struct dma_fence *xe_exec_queue_last_fence_get(struct xe_exec_queue *e, struct xe_vm *vm); void xe_exec_queue_last_fence_set(struct xe_exec_queue *e, struct xe_vm *vm, struct dma_fence *fence); +int xe_exec_queue_last_fence_test_dep(struct xe_exec_queue *q, + struct xe_vm *vm); void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q); #endif -- cgit v1.2.3 From e8babb280b5ef904df54b3a90e5a7e3a9600c4a9 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Wed, 3 Jul 2024 21:16:49 -0700 Subject: drm/xe: Convert multiple bind ops into single job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This aligns with the uAPI of an array of binds or single bind that results in multiple GPUVA ops to be considered a single atomic operations. The design is roughly: - xe_vma_ops is a list of xe_vma_op (GPUVA op) - each xe_vma_op resolves to 0-3 PT ops - xe_vma_ops creates a single job - if at any point during binding a failure occurs, xe_vma_ops contains the information necessary unwind the PT and VMA (GPUVA) state v2: - add missing dma-resv slot reservation (CI, testing) v4: - Fix TLB invalidation (Paulo) - Add missing xe_sched_job_last_fence_add/test_dep check (Inspection) v5: - Invert i, j usage (Matthew Auld) - Add helper to test and add job dep (Matthew Auld) - Return on anything but -ETIME for cpu bind (Matthew Auld) - Return -ENOBUFS if suballoc of BB fails due to size (Matthew Auld) - s/do/Do (Matthew Auld) - Add missing comma (Matthew Auld) - Do not assign return value to xe_range_fence_insert (Matthew Auld) v6: - s/0x1ff/MAX_PTE_PER_SDI (Matthew Auld, CI) - Check to large of SA in Xe to avoid triggering WARN (Matthew Auld) - Fix checkpatch issues v7: - Rebase - Support more than 510 PTEs updates in a bind job (Paulo, mesa testing) v8: - Rebase Cc: Thomas Hellström Signed-off-by: Matthew Brost Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20240704041652.272920-5-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_bo_types.h | 2 + drivers/gpu/drm/xe/xe_migrate.c | 333 ++++++------ drivers/gpu/drm/xe/xe_migrate.h | 32 +- drivers/gpu/drm/xe/xe_pt.c | 1096 ++++++++++++++++++++++++-------------- drivers/gpu/drm/xe/xe_pt.h | 14 +- drivers/gpu/drm/xe/xe_pt_types.h | 36 ++ drivers/gpu/drm/xe/xe_sa.c | 7 + drivers/gpu/drm/xe/xe_vm.c | 521 ++++-------------- drivers/gpu/drm/xe/xe_vm.h | 2 + drivers/gpu/drm/xe/xe_vm_types.h | 45 +- 10 files changed, 1063 insertions(+), 1025 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_bo_types.h b/drivers/gpu/drm/xe/xe_bo_types.h index 86422e113d39..02d68873558a 100644 --- a/drivers/gpu/drm/xe/xe_bo_types.h +++ b/drivers/gpu/drm/xe/xe_bo_types.h @@ -58,6 +58,8 @@ struct xe_bo { #endif /** @freed: List node for delayed put. */ struct llist_node freed; + /** @update_index: Update index if PT BO */ + int update_index; /** @created: Whether the bo has passed initial creation */ bool created; diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c index ef5ad0efc5dd..fa23a7e7ec43 100644 --- a/drivers/gpu/drm/xe/xe_migrate.c +++ b/drivers/gpu/drm/xe/xe_migrate.c @@ -1125,6 +1125,7 @@ err_sync: } static void write_pgtable(struct xe_tile *tile, struct xe_bb *bb, u64 ppgtt_ofs, + const struct xe_vm_pgtable_update_op *pt_op, const struct xe_vm_pgtable_update *update, struct xe_migrate_pt_update *pt_update) { @@ -1159,8 +1160,12 @@ static void write_pgtable(struct xe_tile *tile, struct xe_bb *bb, u64 ppgtt_ofs, bb->cs[bb->len++] = MI_STORE_DATA_IMM | MI_SDI_NUM_QW(chunk); bb->cs[bb->len++] = lower_32_bits(addr); bb->cs[bb->len++] = upper_32_bits(addr); - ops->populate(pt_update, tile, NULL, bb->cs + bb->len, ofs, chunk, - update); + if (pt_op->bind) + ops->populate(pt_update, tile, NULL, bb->cs + bb->len, + ofs, chunk, update); + else + ops->clear(pt_update, tile, NULL, bb->cs + bb->len, + ofs, chunk, update); bb->len += chunk * 2; ofs += chunk; @@ -1185,114 +1190,58 @@ struct migrate_test_params { static struct dma_fence * xe_migrate_update_pgtables_cpu(struct xe_migrate *m, - struct xe_vm *vm, struct xe_bo *bo, - const struct xe_vm_pgtable_update *updates, - u32 num_updates, bool wait_vm, struct xe_migrate_pt_update *pt_update) { XE_TEST_DECLARE(struct migrate_test_params *test = to_migrate_test_params (xe_cur_kunit_priv(XE_TEST_LIVE_MIGRATE));) const struct xe_migrate_pt_update_ops *ops = pt_update->ops; - struct dma_fence *fence; + struct xe_vm *vm = pt_update->vops->vm; + struct xe_vm_pgtable_update_ops *pt_update_ops = + &pt_update->vops->pt_update_ops[pt_update->tile_id]; int err; - u32 i; + u32 i, j; if (XE_TEST_ONLY(test && test->force_gpu)) return ERR_PTR(-ETIME); - if (bo && !dma_resv_test_signaled(bo->ttm.base.resv, - DMA_RESV_USAGE_KERNEL)) - return ERR_PTR(-ETIME); - - if (wait_vm && !dma_resv_test_signaled(xe_vm_resv(vm), - DMA_RESV_USAGE_BOOKKEEP)) - return ERR_PTR(-ETIME); - if (ops->pre_commit) { pt_update->job = NULL; err = ops->pre_commit(pt_update); if (err) return ERR_PTR(err); } - for (i = 0; i < num_updates; i++) { - const struct xe_vm_pgtable_update *update = &updates[i]; - - ops->populate(pt_update, m->tile, &update->pt_bo->vmap, NULL, - update->ofs, update->qwords, update); - } - - if (vm) { - trace_xe_vm_cpu_bind(vm); - xe_device_wmb(vm->xe); - } - - fence = dma_fence_get_stub(); - - return fence; -} -static bool no_in_syncs(struct xe_vm *vm, struct xe_exec_queue *q, - struct xe_sync_entry *syncs, u32 num_syncs) -{ - struct dma_fence *fence; - int i; - - for (i = 0; i < num_syncs; i++) { - fence = syncs[i].fence; - - if (fence && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, - &fence->flags)) - return false; - } - if (q) { - fence = xe_exec_queue_last_fence_get(q, vm); - if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { - dma_fence_put(fence); - return false; + for (i = 0; i < pt_update_ops->num_ops; ++i) { + const struct xe_vm_pgtable_update_op *pt_op = + &pt_update_ops->ops[i]; + + for (j = 0; j < pt_op->num_entries; j++) { + const struct xe_vm_pgtable_update *update = + &pt_op->entries[j]; + + if (pt_op->bind) + ops->populate(pt_update, m->tile, + &update->pt_bo->vmap, NULL, + update->ofs, update->qwords, + update); + else + ops->clear(pt_update, m->tile, + &update->pt_bo->vmap, NULL, + update->ofs, update->qwords, update); } - dma_fence_put(fence); } - return true; + trace_xe_vm_cpu_bind(vm); + xe_device_wmb(vm->xe); + + return dma_fence_get_stub(); } -/** - * xe_migrate_update_pgtables() - Pipelined page-table update - * @m: The migrate context. - * @vm: The vm we'll be updating. - * @bo: The bo whose dma-resv we will await before updating, or NULL if userptr. - * @q: The exec queue to be used for the update or NULL if the default - * migration engine is to be used. - * @updates: An array of update descriptors. - * @num_updates: Number of descriptors in @updates. - * @syncs: Array of xe_sync_entry to await before updating. Note that waits - * will block the engine timeline. - * @num_syncs: Number of entries in @syncs. - * @pt_update: Pointer to a struct xe_migrate_pt_update, which contains - * pointers to callback functions and, if subclassed, private arguments to - * those. - * - * Perform a pipelined page-table update. The update descriptors are typically - * built under the same lock critical section as a call to this function. If - * using the default engine for the updates, they will be performed in the - * order they grab the job_mutex. If different engines are used, external - * synchronization is needed for overlapping updates to maintain page-table - * consistency. Note that the meaing of "overlapping" is that the updates - * touch the same page-table, which might be a higher-level page-directory. - * If no pipelining is needed, then updates may be performed by the cpu. - * - * Return: A dma_fence that, when signaled, indicates the update completion. - */ -struct dma_fence * -xe_migrate_update_pgtables(struct xe_migrate *m, - struct xe_vm *vm, - struct xe_bo *bo, - struct xe_exec_queue *q, - const struct xe_vm_pgtable_update *updates, - u32 num_updates, - struct xe_sync_entry *syncs, u32 num_syncs, - struct xe_migrate_pt_update *pt_update) +static struct dma_fence * +__xe_migrate_update_pgtables(struct xe_migrate *m, + struct xe_migrate_pt_update *pt_update, + struct xe_vm_pgtable_update_ops *pt_update_ops) { const struct xe_migrate_pt_update_ops *ops = pt_update->ops; struct xe_tile *tile = m->tile; @@ -1301,59 +1250,53 @@ xe_migrate_update_pgtables(struct xe_migrate *m, struct xe_sched_job *job; struct dma_fence *fence; struct drm_suballoc *sa_bo = NULL; - struct xe_vma *vma = pt_update->vma; struct xe_bb *bb; - u32 i, batch_size, ppgtt_ofs, update_idx, page_ofs = 0; + u32 i, j, batch_size = 0, ppgtt_ofs, update_idx, page_ofs = 0; + u32 num_updates = 0, current_update = 0; u64 addr; int err = 0; - bool usm = !q && xe->info.has_usm; - bool first_munmap_rebind = vma && - vma->gpuva.flags & XE_VMA_FIRST_REBIND; - struct xe_exec_queue *q_override = !q ? m->q : q; - u16 pat_index = xe->pat.idx[XE_CACHE_WB]; + bool is_migrate = pt_update_ops->q == m->q; + bool usm = is_migrate && xe->info.has_usm; + + for (i = 0; i < pt_update_ops->num_ops; ++i) { + struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[i]; + struct xe_vm_pgtable_update *updates = pt_op->entries; + + num_updates += pt_op->num_entries; + for (j = 0; j < pt_op->num_entries; ++j) { + u32 num_cmds = DIV_ROUND_UP(updates[j].qwords, + MAX_PTE_PER_SDI); - /* Use the CPU if no in syncs and engine is idle */ - if (no_in_syncs(vm, q, syncs, num_syncs) && xe_exec_queue_is_idle(q_override)) { - fence = xe_migrate_update_pgtables_cpu(m, vm, bo, updates, - num_updates, - first_munmap_rebind, - pt_update); - if (!IS_ERR(fence) || fence == ERR_PTR(-EAGAIN)) - return fence; + /* align noop + MI_STORE_DATA_IMM cmd prefix */ + batch_size += 4 * num_cmds + updates[j].qwords * 2; + } } /* fixed + PTE entries */ if (IS_DGFX(xe)) - batch_size = 2; + batch_size += 2; else - batch_size = 6 + num_updates * 2; - - for (i = 0; i < num_updates; i++) { - u32 num_cmds = DIV_ROUND_UP(updates[i].qwords, MAX_PTE_PER_SDI); + batch_size += 6 * (num_updates / MAX_PTE_PER_SDI + 1) + + num_updates * 2; - /* align noop + MI_STORE_DATA_IMM cmd prefix */ - batch_size += 4 * num_cmds + updates[i].qwords * 2; - } - - /* - * XXX: Create temp bo to copy from, if batch_size becomes too big? - * - * Worst case: Sum(2 * (each lower level page size) + (top level page size)) - * Should be reasonably bound.. - */ - xe_tile_assert(tile, batch_size < SZ_128K); - - bb = xe_bb_new(gt, batch_size, !q && xe->info.has_usm); + bb = xe_bb_new(gt, batch_size, usm); if (IS_ERR(bb)) return ERR_CAST(bb); /* For sysmem PTE's, need to map them in our hole.. */ if (!IS_DGFX(xe)) { + u32 ptes, ofs; + ppgtt_ofs = NUM_KERNEL_PDE - 1; - if (q) { - xe_tile_assert(tile, num_updates <= NUM_VMUSA_WRITES_PER_UNIT); + if (!is_migrate) { + u32 num_units = DIV_ROUND_UP(num_updates, + NUM_VMUSA_WRITES_PER_UNIT); - sa_bo = drm_suballoc_new(&m->vm_update_sa, 1, + if (num_units > m->vm_update_sa.size) { + err = -ENOBUFS; + goto err_bb; + } + sa_bo = drm_suballoc_new(&m->vm_update_sa, num_units, GFP_KERNEL, true, 0); if (IS_ERR(sa_bo)) { err = PTR_ERR(sa_bo); @@ -1369,18 +1312,49 @@ xe_migrate_update_pgtables(struct xe_migrate *m, } /* Map our PT's to gtt */ - bb->cs[bb->len++] = MI_STORE_DATA_IMM | MI_SDI_NUM_QW(num_updates); - bb->cs[bb->len++] = ppgtt_ofs * XE_PAGE_SIZE + page_ofs; - bb->cs[bb->len++] = 0; /* upper_32_bits */ - - for (i = 0; i < num_updates; i++) { - struct xe_bo *pt_bo = updates[i].pt_bo; + i = 0; + j = 0; + ptes = num_updates; + ofs = ppgtt_ofs * XE_PAGE_SIZE + page_ofs; + while (ptes) { + u32 chunk = min(MAX_PTE_PER_SDI, ptes); + u32 idx = 0; + + bb->cs[bb->len++] = MI_STORE_DATA_IMM | + MI_SDI_NUM_QW(chunk); + bb->cs[bb->len++] = ofs; + bb->cs[bb->len++] = 0; /* upper_32_bits */ + + for (; i < pt_update_ops->num_ops; ++i) { + struct xe_vm_pgtable_update_op *pt_op = + &pt_update_ops->ops[i]; + struct xe_vm_pgtable_update *updates = pt_op->entries; + + for (; j < pt_op->num_entries; ++j, ++current_update, ++idx) { + struct xe_vm *vm = pt_update->vops->vm; + struct xe_bo *pt_bo = updates[j].pt_bo; + + if (idx == chunk) + goto next_cmd; + + xe_tile_assert(tile, pt_bo->size == SZ_4K); + + /* Map a PT at most once */ + if (pt_bo->update_index < 0) + pt_bo->update_index = current_update; + + addr = vm->pt_ops->pte_encode_bo(pt_bo, 0, + XE_CACHE_WB, 0); + bb->cs[bb->len++] = lower_32_bits(addr); + bb->cs[bb->len++] = upper_32_bits(addr); + } - xe_tile_assert(tile, pt_bo->size == SZ_4K); + j = 0; + } - addr = vm->pt_ops->pte_encode_bo(pt_bo, 0, pat_index, 0); - bb->cs[bb->len++] = lower_32_bits(addr); - bb->cs[bb->len++] = upper_32_bits(addr); +next_cmd: + ptes -= chunk; + ofs += chunk * sizeof(u64); } bb->cs[bb->len++] = MI_BATCH_BUFFER_END; @@ -1388,19 +1362,36 @@ xe_migrate_update_pgtables(struct xe_migrate *m, addr = xe_migrate_vm_addr(ppgtt_ofs, 0) + (page_ofs / sizeof(u64)) * XE_PAGE_SIZE; - for (i = 0; i < num_updates; i++) - write_pgtable(tile, bb, addr + i * XE_PAGE_SIZE, - &updates[i], pt_update); + for (i = 0; i < pt_update_ops->num_ops; ++i) { + struct xe_vm_pgtable_update_op *pt_op = + &pt_update_ops->ops[i]; + struct xe_vm_pgtable_update *updates = pt_op->entries; + + for (j = 0; j < pt_op->num_entries; ++j) { + struct xe_bo *pt_bo = updates[j].pt_bo; + + write_pgtable(tile, bb, addr + + pt_bo->update_index * XE_PAGE_SIZE, + pt_op, &updates[j], pt_update); + } + } } else { /* phys pages, no preamble required */ bb->cs[bb->len++] = MI_BATCH_BUFFER_END; update_idx = bb->len; - for (i = 0; i < num_updates; i++) - write_pgtable(tile, bb, 0, &updates[i], pt_update); + for (i = 0; i < pt_update_ops->num_ops; ++i) { + struct xe_vm_pgtable_update_op *pt_op = + &pt_update_ops->ops[i]; + struct xe_vm_pgtable_update *updates = pt_op->entries; + + for (j = 0; j < pt_op->num_entries; ++j) + write_pgtable(tile, bb, 0, pt_op, &updates[j], + pt_update); + } } - job = xe_bb_create_migration_job(q ?: m->q, bb, + job = xe_bb_create_migration_job(pt_update_ops->q, bb, xe_migrate_batch_base(m, usm), update_idx); if (IS_ERR(job)) { @@ -1408,46 +1399,20 @@ xe_migrate_update_pgtables(struct xe_migrate *m, goto err_sa; } - /* Wait on BO move */ - if (bo) { - err = xe_sched_job_add_deps(job, bo->ttm.base.resv, - DMA_RESV_USAGE_KERNEL); - if (err) - goto err_job; - } - - /* - * Munmap style VM unbind, need to wait for all jobs to be complete / - * trigger preempts before moving forward - */ - if (first_munmap_rebind) { - err = xe_sched_job_add_deps(job, xe_vm_resv(vm), - DMA_RESV_USAGE_BOOKKEEP); - if (err) - goto err_job; - } - - err = xe_sched_job_last_fence_add_dep(job, vm); - for (i = 0; !err && i < num_syncs; i++) - err = xe_sync_entry_add_deps(&syncs[i], job); - - if (err) - goto err_job; - if (ops->pre_commit) { pt_update->job = job; err = ops->pre_commit(pt_update); if (err) goto err_job; } - if (!q) + if (is_migrate) mutex_lock(&m->job_mutex); xe_sched_job_arm(job); fence = dma_fence_get(&job->drm.s_fence->finished); xe_sched_job_push(job); - if (!q) + if (is_migrate) mutex_unlock(&m->job_mutex); xe_bb_free(bb, fence); @@ -1464,6 +1429,40 @@ err_bb: return ERR_PTR(err); } +/** + * xe_migrate_update_pgtables() - Pipelined page-table update + * @m: The migrate context. + * @pt_update: PT update arguments + * + * Perform a pipelined page-table update. The update descriptors are typically + * built under the same lock critical section as a call to this function. If + * using the default engine for the updates, they will be performed in the + * order they grab the job_mutex. If different engines are used, external + * synchronization is needed for overlapping updates to maintain page-table + * consistency. Note that the meaing of "overlapping" is that the updates + * touch the same page-table, which might be a higher-level page-directory. + * If no pipelining is needed, then updates may be performed by the cpu. + * + * Return: A dma_fence that, when signaled, indicates the update completion. + */ +struct dma_fence * +xe_migrate_update_pgtables(struct xe_migrate *m, + struct xe_migrate_pt_update *pt_update) + +{ + struct xe_vm_pgtable_update_ops *pt_update_ops = + &pt_update->vops->pt_update_ops[pt_update->tile_id]; + struct dma_fence *fence; + + fence = xe_migrate_update_pgtables_cpu(m, pt_update); + + /* -ETIME indicates a job is needed, anything else is legit error */ + if (!IS_ERR(fence) || PTR_ERR(fence) != -ETIME) + return fence; + + return __xe_migrate_update_pgtables(m, pt_update, pt_update_ops); +} + /** * xe_migrate_wait() - Complete all operations using the xe_migrate context * @m: Migrate context to wait for. diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h index a5bcaafe4a99..453e0ecf5034 100644 --- a/drivers/gpu/drm/xe/xe_migrate.h +++ b/drivers/gpu/drm/xe/xe_migrate.h @@ -47,6 +47,24 @@ struct xe_migrate_pt_update_ops { struct xe_tile *tile, struct iosys_map *map, void *pos, u32 ofs, u32 num_qwords, const struct xe_vm_pgtable_update *update); + /** + * @clear: Clear a command buffer or page-table with ptes. + * @pt_update: Embeddable callback argument. + * @tile: The tile for the current operation. + * @map: struct iosys_map into the memory to be populated. + * @pos: If @map is NULL, map into the memory to be populated. + * @ofs: qword offset into @map, unused if @map is NULL. + * @num_qwords: Number of qwords to write. + * @update: Information about the PTEs to be inserted. + * + * This interface is intended to be used as a callback into the + * page-table system to populate command buffers or shared + * page-tables with PTEs. + */ + void (*clear)(struct xe_migrate_pt_update *pt_update, + struct xe_tile *tile, struct iosys_map *map, + void *pos, u32 ofs, u32 num_qwords, + const struct xe_vm_pgtable_update *update); /** * @pre_commit: Callback to be called just before arming the @@ -67,14 +85,10 @@ struct xe_migrate_pt_update_ops { struct xe_migrate_pt_update { /** @ops: Pointer to the struct xe_migrate_pt_update_ops callbacks */ const struct xe_migrate_pt_update_ops *ops; - /** @vma: The vma we're updating the pagetable for. */ - struct xe_vma *vma; + /** @vops: VMA operations */ + struct xe_vma_ops *vops; /** @job: The job if a GPU page-table update. NULL otherwise */ struct xe_sched_job *job; - /** @start: Start of update for the range fence */ - u64 start; - /** @last: Last of update for the range fence */ - u64 last; /** @tile_id: Tile ID of the update */ u8 tile_id; }; @@ -96,12 +110,6 @@ struct xe_vm *xe_migrate_get_vm(struct xe_migrate *m); struct dma_fence * xe_migrate_update_pgtables(struct xe_migrate *m, - struct xe_vm *vm, - struct xe_bo *bo, - struct xe_exec_queue *q, - const struct xe_vm_pgtable_update *updates, - u32 num_updates, - struct xe_sync_entry *syncs, u32 num_syncs, struct xe_migrate_pt_update *pt_update); void xe_migrate_wait(struct xe_migrate *m); diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index ade9e7a3a0ad..f46f46d46819 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -9,12 +9,15 @@ #include "xe_bo.h" #include "xe_device.h" #include "xe_drm_client.h" +#include "xe_exec_queue.h" #include "xe_gt.h" #include "xe_gt_tlb_invalidation.h" #include "xe_migrate.h" #include "xe_pt_types.h" #include "xe_pt_walk.h" #include "xe_res_cursor.h" +#include "xe_sched_job.h" +#include "xe_sync.h" #include "xe_trace.h" #include "xe_ttm_stolen_mgr.h" #include "xe_vm.h" @@ -325,6 +328,7 @@ xe_pt_new_shared(struct xe_walk_update *wupd, struct xe_pt *parent, entry->pt = parent; entry->flags = 0; entry->qwords = 0; + entry->pt_bo->update_index = -1; if (alloc_entries) { entry->pt_entries = kmalloc_array(XE_PDES, @@ -864,9 +868,7 @@ static void xe_pt_commit_locks_assert(struct xe_vma *vma) lockdep_assert_held(&vm->lock); - if (xe_vma_is_userptr(vma)) - lockdep_assert_held_read(&vm->userptr.notifier_lock); - else if (!xe_vma_is_null(vma)) + if (!xe_vma_is_userptr(vma) && !xe_vma_is_null(vma)) dma_resv_assert_held(xe_vma_bo(vma)->ttm.base.resv); xe_vm_assert_held(vm); @@ -888,10 +890,8 @@ static void xe_pt_commit_bind(struct xe_vma *vma, if (!rebind) pt->num_live += entries[i].qwords; - if (!pt->level) { - kfree(entries[i].pt_entries); + if (!pt->level) continue; - } pt_dir = as_xe_pt_dir(pt); for (j = 0; j < entries[i].qwords; j++) { @@ -904,10 +904,18 @@ static void xe_pt_commit_bind(struct xe_vma *vma, pt_dir->children[j_] = &newpte->base; } - kfree(entries[i].pt_entries); } } +static void xe_pt_free_bind(struct xe_vm_pgtable_update *entries, + u32 num_entries) +{ + u32 i; + + for (i = 0; i < num_entries; i++) + kfree(entries[i].pt_entries); +} + static int xe_pt_prepare_bind(struct xe_tile *tile, struct xe_vma *vma, struct xe_vm_pgtable_update *entries, u32 *num_entries) @@ -926,12 +934,13 @@ xe_pt_prepare_bind(struct xe_tile *tile, struct xe_vma *vma, static void xe_vm_dbg_print_entries(struct xe_device *xe, const struct xe_vm_pgtable_update *entries, - unsigned int num_entries) + unsigned int num_entries, bool bind) #if (IS_ENABLED(CONFIG_DRM_XE_DEBUG_VM)) { unsigned int i; - vm_dbg(&xe->drm, "%u entries to update\n", num_entries); + vm_dbg(&xe->drm, "%s: %u entries to update\n", bind ? "bind" : "unbind", + num_entries); for (i = 0; i < num_entries; i++) { const struct xe_vm_pgtable_update *entry = &entries[i]; struct xe_pt *xe_pt = entry->pt; @@ -952,66 +961,108 @@ static void xe_vm_dbg_print_entries(struct xe_device *xe, {} #endif -#ifdef CONFIG_DRM_XE_USERPTR_INVAL_INJECT - -static int xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma) +static bool no_in_syncs(struct xe_sync_entry *syncs, u32 num_syncs) { - u32 divisor = uvma->userptr.divisor ? uvma->userptr.divisor : 2; - static u32 count; + int i; - if (count++ % divisor == divisor - 1) { - struct xe_vm *vm = xe_vma_vm(&uvma->vma); + for (i = 0; i < num_syncs; i++) { + struct dma_fence *fence = syncs[i].fence; - uvma->userptr.divisor = divisor << 1; - spin_lock(&vm->userptr.invalidated_lock); - list_move_tail(&uvma->userptr.invalidate_link, - &vm->userptr.invalidated); - spin_unlock(&vm->userptr.invalidated_lock); - return true; + if (fence && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, + &fence->flags)) + return false; } - return false; + return true; } -#else +static int job_test_add_deps(struct xe_sched_job *job, + struct dma_resv *resv, + enum dma_resv_usage usage) +{ + if (!job) { + if (!dma_resv_test_signaled(resv, usage)) + return -ETIME; -static bool xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma) + return 0; + } + + return xe_sched_job_add_deps(job, resv, usage); +} + +static int vma_add_deps(struct xe_vma *vma, struct xe_sched_job *job) { - return false; + struct xe_bo *bo = xe_vma_bo(vma); + + xe_bo_assert_held(bo); + + if (bo && !bo->vm) + return job_test_add_deps(job, bo->ttm.base.resv, + DMA_RESV_USAGE_KERNEL); + + return 0; } -#endif +static int op_add_deps(struct xe_vm *vm, struct xe_vma_op *op, + struct xe_sched_job *job) +{ + int err = 0; -/** - * struct xe_pt_migrate_pt_update - Callback argument for pre-commit callbacks - * @base: Base we derive from. - * @bind: Whether this is a bind or an unbind operation. A bind operation - * makes the pre-commit callback error with -EAGAIN if it detects a - * pending invalidation. - * @locked: Whether the pre-commit callback locked the userptr notifier lock - * and it needs unlocking. - */ -struct xe_pt_migrate_pt_update { - struct xe_migrate_pt_update base; - bool bind; - bool locked; -}; + switch (op->base.op) { + case DRM_GPUVA_OP_MAP: + if (!op->map.immediate && xe_vm_in_fault_mode(vm)) + break; + + err = vma_add_deps(op->map.vma, job); + break; + case DRM_GPUVA_OP_REMAP: + if (op->remap.prev) + err = vma_add_deps(op->remap.prev, job); + if (!err && op->remap.next) + err = vma_add_deps(op->remap.next, job); + break; + case DRM_GPUVA_OP_UNMAP: + break; + case DRM_GPUVA_OP_PREFETCH: + err = vma_add_deps(gpuva_to_vma(op->base.prefetch.va), job); + break; + default: + drm_warn(&vm->xe->drm, "NOT POSSIBLE"); + } + + return err; +} -/* - * This function adds the needed dependencies to a page-table update job - * to make sure racing jobs for separate bind engines don't race writing - * to the same page-table range, wreaking havoc. Initially use a single - * fence for the entire VM. An optimization would use smaller granularity. - */ static int xe_pt_vm_dependencies(struct xe_sched_job *job, - struct xe_range_fence_tree *rftree, - u64 start, u64 last) + struct xe_vm *vm, + struct xe_vma_ops *vops, + struct xe_vm_pgtable_update_ops *pt_update_ops, + struct xe_range_fence_tree *rftree) { struct xe_range_fence *rtfence; struct dma_fence *fence; - int err; + struct xe_vma_op *op; + int err = 0, i; + + xe_vm_assert_held(vm); + + if (!job && !no_in_syncs(vops->syncs, vops->num_syncs)) + return -ETIME; - rtfence = xe_range_fence_tree_first(rftree, start, last); + if (!job && !xe_exec_queue_is_idle(pt_update_ops->q)) + return -ETIME; + + if (pt_update_ops->wait_vm_bookkeep || pt_update_ops->wait_vm_kernel) { + err = job_test_add_deps(job, xe_vm_resv(vm), + pt_update_ops->wait_vm_bookkeep ? + DMA_RESV_USAGE_BOOKKEEP : + DMA_RESV_USAGE_KERNEL); + if (err) + return err; + } + + rtfence = xe_range_fence_tree_first(rftree, pt_update_ops->start, + pt_update_ops->last); while (rtfence) { fence = rtfence->fence; @@ -1029,80 +1080,173 @@ static int xe_pt_vm_dependencies(struct xe_sched_job *job, return err; } - rtfence = xe_range_fence_tree_next(rtfence, start, last); + rtfence = xe_range_fence_tree_next(rtfence, + pt_update_ops->start, + pt_update_ops->last); } - return 0; + list_for_each_entry(op, &vops->list, link) { + err = op_add_deps(vm, op, job); + if (err) + return err; + } + + if (job) + err = xe_sched_job_last_fence_add_dep(job, vm); + else + err = xe_exec_queue_last_fence_test_dep(pt_update_ops->q, vm); + + for (i = 0; job && !err && i < vops->num_syncs; i++) + err = xe_sync_entry_add_deps(&vops->syncs[i], job); + + return err; } static int xe_pt_pre_commit(struct xe_migrate_pt_update *pt_update) { - struct xe_range_fence_tree *rftree = - &xe_vma_vm(pt_update->vma)->rftree[pt_update->tile_id]; + struct xe_vma_ops *vops = pt_update->vops; + struct xe_vm *vm = vops->vm; + struct xe_range_fence_tree *rftree = &vm->rftree[pt_update->tile_id]; + struct xe_vm_pgtable_update_ops *pt_update_ops = + &vops->pt_update_ops[pt_update->tile_id]; + + return xe_pt_vm_dependencies(pt_update->job, vm, pt_update->vops, + pt_update_ops, rftree); +} + +#ifdef CONFIG_DRM_XE_USERPTR_INVAL_INJECT + +static bool xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma) +{ + u32 divisor = uvma->userptr.divisor ? uvma->userptr.divisor : 2; + static u32 count; + + if (count++ % divisor == divisor - 1) { + uvma->userptr.divisor = divisor << 1; + return true; + } - return xe_pt_vm_dependencies(pt_update->job, rftree, - pt_update->start, pt_update->last); + return false; } -static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update) +#else + +static bool xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma) { - struct xe_pt_migrate_pt_update *userptr_update = - container_of(pt_update, typeof(*userptr_update), base); - struct xe_userptr_vma *uvma = to_userptr_vma(pt_update->vma); - unsigned long notifier_seq = uvma->userptr.notifier_seq; - struct xe_vm *vm = xe_vma_vm(&uvma->vma); - int err = xe_pt_vm_dependencies(pt_update->job, - &vm->rftree[pt_update->tile_id], - pt_update->start, - pt_update->last); + return false; +} - if (err) - return err; +#endif - userptr_update->locked = false; +static int vma_check_userptr(struct xe_vm *vm, struct xe_vma *vma, + struct xe_vm_pgtable_update_ops *pt_update) +{ + struct xe_userptr_vma *uvma; + unsigned long notifier_seq; - /* - * Wait until nobody is running the invalidation notifier, and - * since we're exiting the loop holding the notifier lock, - * nobody can proceed invalidating either. - * - * Note that we don't update the vma->userptr.notifier_seq since - * we don't update the userptr pages. - */ - do { - down_read(&vm->userptr.notifier_lock); - if (!mmu_interval_read_retry(&uvma->userptr.notifier, - notifier_seq)) - break; + lockdep_assert_held_read(&vm->userptr.notifier_lock); - up_read(&vm->userptr.notifier_lock); + if (!xe_vma_is_userptr(vma)) + return 0; + + uvma = to_userptr_vma(vma); + notifier_seq = uvma->userptr.notifier_seq; - if (userptr_update->bind) - return -EAGAIN; + if (uvma->userptr.initial_bind && !xe_vm_in_fault_mode(vm)) + return 0; - notifier_seq = mmu_interval_read_begin(&uvma->userptr.notifier); - } while (true); + if (!mmu_interval_read_retry(&uvma->userptr.notifier, + notifier_seq) && + !xe_pt_userptr_inject_eagain(uvma)) + return 0; - /* Inject errors to test_whether they are handled correctly */ - if (userptr_update->bind && xe_pt_userptr_inject_eagain(uvma)) { - up_read(&vm->userptr.notifier_lock); + if (xe_vm_in_fault_mode(vm)) { return -EAGAIN; - } + } else { + spin_lock(&vm->userptr.invalidated_lock); + list_move_tail(&uvma->userptr.invalidate_link, + &vm->userptr.invalidated); + spin_unlock(&vm->userptr.invalidated_lock); - userptr_update->locked = true; + if (xe_vm_in_preempt_fence_mode(vm)) { + struct dma_resv_iter cursor; + struct dma_fence *fence; + long err; + + dma_resv_iter_begin(&cursor, xe_vm_resv(vm), + DMA_RESV_USAGE_BOOKKEEP); + dma_resv_for_each_fence_unlocked(&cursor, fence) + dma_fence_enable_sw_signaling(fence); + dma_resv_iter_end(&cursor); + + err = dma_resv_wait_timeout(xe_vm_resv(vm), + DMA_RESV_USAGE_BOOKKEEP, + false, MAX_SCHEDULE_TIMEOUT); + XE_WARN_ON(err <= 0); + } + } return 0; } -static const struct xe_migrate_pt_update_ops bind_ops = { - .populate = xe_vm_populate_pgtable, - .pre_commit = xe_pt_pre_commit, -}; +static int op_check_userptr(struct xe_vm *vm, struct xe_vma_op *op, + struct xe_vm_pgtable_update_ops *pt_update) +{ + int err = 0; -static const struct xe_migrate_pt_update_ops userptr_bind_ops = { - .populate = xe_vm_populate_pgtable, - .pre_commit = xe_pt_userptr_pre_commit, -}; + lockdep_assert_held_read(&vm->userptr.notifier_lock); + + switch (op->base.op) { + case DRM_GPUVA_OP_MAP: + if (!op->map.immediate && xe_vm_in_fault_mode(vm)) + break; + + err = vma_check_userptr(vm, op->map.vma, pt_update); + break; + case DRM_GPUVA_OP_REMAP: + if (op->remap.prev) + err = vma_check_userptr(vm, op->remap.prev, pt_update); + if (!err && op->remap.next) + err = vma_check_userptr(vm, op->remap.next, pt_update); + break; + case DRM_GPUVA_OP_UNMAP: + break; + case DRM_GPUVA_OP_PREFETCH: + err = vma_check_userptr(vm, gpuva_to_vma(op->base.prefetch.va), + pt_update); + break; + default: + drm_warn(&vm->xe->drm, "NOT POSSIBLE"); + } + + return err; +} + +static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update) +{ + struct xe_vm *vm = pt_update->vops->vm; + struct xe_vma_ops *vops = pt_update->vops; + struct xe_vm_pgtable_update_ops *pt_update_ops = + &vops->pt_update_ops[pt_update->tile_id]; + struct xe_vma_op *op; + int err; + + err = xe_pt_pre_commit(pt_update); + if (err) + return err; + + down_read(&vm->userptr.notifier_lock); + + list_for_each_entry(op, &vops->list, link) { + err = op_check_userptr(vm, op, pt_update_ops); + if (err) { + up_read(&vm->userptr.notifier_lock); + break; + } + } + + return err; +} struct invalidation_fence { struct xe_gt_tlb_invalidation_fence base; @@ -1200,190 +1344,6 @@ static int invalidation_fence_init(struct xe_gt *gt, return ret && ret != -ENOENT ? ret : 0; } -static void xe_pt_calc_rfence_interval(struct xe_vma *vma, - struct xe_pt_migrate_pt_update *update, - struct xe_vm_pgtable_update *entries, - u32 num_entries) -{ - int i, level = 0; - - for (i = 0; i < num_entries; i++) { - const struct xe_vm_pgtable_update *entry = &entries[i]; - - if (entry->pt->level > level) - level = entry->pt->level; - } - - /* Greedy (non-optimal) calculation but simple */ - update->base.start = ALIGN_DOWN(xe_vma_start(vma), - 0x1ull << xe_pt_shift(level)); - update->base.last = ALIGN(xe_vma_end(vma), - 0x1ull << xe_pt_shift(level)) - 1; -} - -/** - * __xe_pt_bind_vma() - Build and connect a page-table tree for the vma - * address range. - * @tile: The tile to bind for. - * @vma: The vma to bind. - * @q: The exec_queue with which to do pipelined page-table updates. - * @syncs: Entries to sync on before binding the built tree to the live vm tree. - * @num_syncs: Number of @sync entries. - * @rebind: Whether we're rebinding this vma to the same address range without - * an unbind in-between. - * - * This function builds a page-table tree (see xe_pt_stage_bind() for more - * information on page-table building), and the xe_vm_pgtable_update entries - * abstracting the operations needed to attach it to the main vm tree. It - * then takes the relevant locks and updates the metadata side of the main - * vm tree and submits the operations for pipelined attachment of the - * gpu page-table to the vm main tree, (which can be done either by the - * cpu and the GPU). - * - * Return: A valid dma-fence representing the pipelined attachment operation - * on success, an error pointer on error. - */ -struct dma_fence * -__xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queue *q, - struct xe_sync_entry *syncs, u32 num_syncs, - bool rebind) -{ - struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1]; - struct xe_pt_migrate_pt_update bind_pt_update = { - .base = { - .ops = xe_vma_is_userptr(vma) ? &userptr_bind_ops : &bind_ops, - .vma = vma, - .tile_id = tile->id, - }, - .bind = true, - }; - struct xe_vm *vm = xe_vma_vm(vma); - u32 num_entries; - struct dma_fence *fence; - struct invalidation_fence *ifence = NULL; - struct xe_range_fence *rfence; - int err; - - bind_pt_update.locked = false; - xe_bo_assert_held(xe_vma_bo(vma)); - xe_vm_assert_held(vm); - - vm_dbg(&xe_vma_vm(vma)->xe->drm, - "Preparing bind, with range [%llx...%llx) engine %p.\n", - xe_vma_start(vma), xe_vma_end(vma), q); - - err = xe_pt_prepare_bind(tile, vma, entries, &num_entries); - if (err) - goto err; - - err = dma_resv_reserve_fences(xe_vm_resv(vm), 1); - if (!err && !xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm) - err = dma_resv_reserve_fences(xe_vma_bo(vma)->ttm.base.resv, 1); - if (err) - goto err; - - xe_tile_assert(tile, num_entries <= ARRAY_SIZE(entries)); - - xe_vm_dbg_print_entries(tile_to_xe(tile), entries, num_entries); - xe_pt_calc_rfence_interval(vma, &bind_pt_update, entries, - num_entries); - - /* - * If rebind, we have to invalidate TLB on !LR vms to invalidate - * cached PTEs point to freed memory. on LR vms this is done - * automatically when the context is re-enabled by the rebind worker, - * or in fault mode it was invalidated on PTE zapping. - * - * If !rebind, and scratch enabled VMs, there is a chance the scratch - * PTE is already cached in the TLB so it needs to be invalidated. - * on !LR VMs this is done in the ring ops preceding a batch, but on - * non-faulting LR, in particular on user-space batch buffer chaining, - * it needs to be done here. - */ - if ((!rebind && xe_vm_has_scratch(vm) && xe_vm_in_preempt_fence_mode(vm))) { - ifence = kzalloc(sizeof(*ifence), GFP_KERNEL); - if (!ifence) - return ERR_PTR(-ENOMEM); - } else if (rebind && !xe_vm_in_lr_mode(vm)) { - /* We bump also if batch_invalidate_tlb is true */ - vm->tlb_flush_seqno++; - } - - rfence = kzalloc(sizeof(*rfence), GFP_KERNEL); - if (!rfence) { - kfree(ifence); - return ERR_PTR(-ENOMEM); - } - - fence = xe_migrate_update_pgtables(tile->migrate, - vm, xe_vma_bo(vma), q, - entries, num_entries, - syncs, num_syncs, - &bind_pt_update.base); - if (!IS_ERR(fence)) { - bool last_munmap_rebind = vma->gpuva.flags & XE_VMA_LAST_REBIND; - LLIST_HEAD(deferred); - int err; - - err = xe_range_fence_insert(&vm->rftree[tile->id], rfence, - &xe_range_fence_kfree_ops, - bind_pt_update.base.start, - bind_pt_update.base.last, fence); - if (err) - dma_fence_wait(fence, false); - - /* TLB invalidation must be done before signaling rebind */ - if (ifence) { - int err = invalidation_fence_init(tile->primary_gt, - ifence, fence, - xe_vma_start(vma), - xe_vma_end(vma), - xe_vma_vm(vma)->usm.asid); - if (err) { - dma_fence_put(fence); - kfree(ifence); - return ERR_PTR(err); - } - fence = &ifence->base.base; - } - - /* add shared fence now for pagetable delayed destroy */ - dma_resv_add_fence(xe_vm_resv(vm), fence, rebind || - last_munmap_rebind ? - DMA_RESV_USAGE_KERNEL : - DMA_RESV_USAGE_BOOKKEEP); - - if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm) - dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv, fence, - DMA_RESV_USAGE_BOOKKEEP); - xe_pt_commit_bind(vma, entries, num_entries, rebind, - bind_pt_update.locked ? &deferred : NULL); - - /* This vma is live (again?) now */ - vma->tile_present |= BIT(tile->id); - - if (bind_pt_update.locked) { - to_userptr_vma(vma)->userptr.initial_bind = true; - up_read(&vm->userptr.notifier_lock); - xe_bo_put_commit(&deferred); - } - if (!rebind && last_munmap_rebind && - xe_vm_in_preempt_fence_mode(vm)) - xe_vm_queue_rebind_worker(vm); - } else { - kfree(rfence); - kfree(ifence); - if (bind_pt_update.locked) - up_read(&vm->userptr.notifier_lock); - xe_pt_abort_bind(vma, entries, num_entries); - } - - return fence; - -err: - return ERR_PTR(err); -} - struct xe_pt_stage_unbind_walk { /** @base: The pagewalk base-class. */ struct xe_pt_walk base; @@ -1534,8 +1494,8 @@ xe_migrate_clear_pgtable_callback(struct xe_migrate_pt_update *pt_update, void *ptr, u32 qword_ofs, u32 num_qwords, const struct xe_vm_pgtable_update *update) { - struct xe_vma *vma = pt_update->vma; - u64 empty = __xe_pt_empty_pte(tile, xe_vma_vm(vma), update->pt->level); + struct xe_vm *vm = pt_update->vops->vm; + u64 empty = __xe_pt_empty_pte(tile, vm, update->pt->level); int i; if (map && map->is_iomem) @@ -1579,151 +1539,487 @@ xe_pt_commit_unbind(struct xe_vma *vma, } } -static const struct xe_migrate_pt_update_ops unbind_ops = { - .populate = xe_migrate_clear_pgtable_callback, +static void +xe_pt_update_ops_rfence_interval(struct xe_vm_pgtable_update_ops *pt_update_ops, + struct xe_vma *vma) +{ + u32 current_op = pt_update_ops->current_op; + struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[current_op]; + int i, level = 0; + u64 start, last; + + for (i = 0; i < pt_op->num_entries; i++) { + const struct xe_vm_pgtable_update *entry = &pt_op->entries[i]; + + if (entry->pt->level > level) + level = entry->pt->level; + } + + /* Greedy (non-optimal) calculation but simple */ + start = ALIGN_DOWN(xe_vma_start(vma), 0x1ull << xe_pt_shift(level)); + last = ALIGN(xe_vma_end(vma), 0x1ull << xe_pt_shift(level)) - 1; + + if (start < pt_update_ops->start) + pt_update_ops->start = start; + if (last > pt_update_ops->last) + pt_update_ops->last = last; +} + +static int vma_reserve_fences(struct xe_device *xe, struct xe_vma *vma) +{ + if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm) + return dma_resv_reserve_fences(xe_vma_bo(vma)->ttm.base.resv, + xe->info.tile_count); + + return 0; +} + +static int bind_op_prepare(struct xe_vm *vm, struct xe_tile *tile, + struct xe_vm_pgtable_update_ops *pt_update_ops, + struct xe_vma *vma) +{ + u32 current_op = pt_update_ops->current_op; + struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[current_op]; + struct llist_head *deferred = &pt_update_ops->deferred; + int err; + + xe_bo_assert_held(xe_vma_bo(vma)); + + vm_dbg(&xe_vma_vm(vma)->xe->drm, + "Preparing bind, with range [%llx...%llx)\n", + xe_vma_start(vma), xe_vma_end(vma) - 1); + + pt_op->vma = NULL; + pt_op->bind = true; + pt_op->rebind = BIT(tile->id) & vma->tile_present; + + err = vma_reserve_fences(tile_to_xe(tile), vma); + if (err) + return err; + + err = xe_pt_prepare_bind(tile, vma, pt_op->entries, + &pt_op->num_entries); + if (!err) { + xe_tile_assert(tile, pt_op->num_entries <= + ARRAY_SIZE(pt_op->entries)); + xe_vm_dbg_print_entries(tile_to_xe(tile), pt_op->entries, + pt_op->num_entries, true); + + xe_pt_update_ops_rfence_interval(pt_update_ops, vma); + ++pt_update_ops->current_op; + pt_update_ops->needs_userptr_lock |= xe_vma_is_userptr(vma); + + /* + * If rebind, we have to invalidate TLB on !LR vms to invalidate + * cached PTEs point to freed memory. On LR vms this is done + * automatically when the context is re-enabled by the rebind worker, + * or in fault mode it was invalidated on PTE zapping. + * + * If !rebind, and scratch enabled VMs, there is a chance the scratch + * PTE is already cached in the TLB so it needs to be invalidated. + * On !LR VMs this is done in the ring ops preceding a batch, but on + * non-faulting LR, in particular on user-space batch buffer chaining, + * it needs to be done here. + */ + if ((!pt_op->rebind && xe_vm_has_scratch(vm) && + xe_vm_in_preempt_fence_mode(vm))) + pt_update_ops->needs_invalidation = true; + else if (pt_op->rebind && !xe_vm_in_lr_mode(vm)) + /* We bump also if batch_invalidate_tlb is true */ + vm->tlb_flush_seqno++; + + /* FIXME: Don't commit right away */ + vma->tile_staged |= BIT(tile->id); + pt_op->vma = vma; + xe_pt_commit_bind(vma, pt_op->entries, pt_op->num_entries, + pt_op->rebind, deferred); + } + + return err; +} + +static int unbind_op_prepare(struct xe_tile *tile, + struct xe_vm_pgtable_update_ops *pt_update_ops, + struct xe_vma *vma) +{ + u32 current_op = pt_update_ops->current_op; + struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[current_op]; + struct llist_head *deferred = &pt_update_ops->deferred; + int err; + + if (!((vma->tile_present | vma->tile_staged) & BIT(tile->id))) + return 0; + + xe_bo_assert_held(xe_vma_bo(vma)); + + vm_dbg(&xe_vma_vm(vma)->xe->drm, + "Preparing unbind, with range [%llx...%llx)\n", + xe_vma_start(vma), xe_vma_end(vma) - 1); + + /* + * Wait for invalidation to complete. Can corrupt internal page table + * state if an invalidation is running while preparing an unbind. + */ + if (xe_vma_is_userptr(vma) && xe_vm_in_fault_mode(xe_vma_vm(vma))) + mmu_interval_read_begin(&to_userptr_vma(vma)->userptr.notifier); + + pt_op->vma = vma; + pt_op->bind = false; + pt_op->rebind = false; + + err = vma_reserve_fences(tile_to_xe(tile), vma); + if (err) + return err; + + pt_op->num_entries = xe_pt_stage_unbind(tile, vma, pt_op->entries); + + xe_vm_dbg_print_entries(tile_to_xe(tile), pt_op->entries, + pt_op->num_entries, false); + xe_pt_update_ops_rfence_interval(pt_update_ops, vma); + ++pt_update_ops->current_op; + pt_update_ops->needs_userptr_lock |= xe_vma_is_userptr(vma); + pt_update_ops->needs_invalidation = true; + + /* FIXME: Don't commit right away */ + xe_pt_commit_unbind(vma, pt_op->entries, pt_op->num_entries, + deferred); + + return 0; +} + +static int op_prepare(struct xe_vm *vm, + struct xe_tile *tile, + struct xe_vm_pgtable_update_ops *pt_update_ops, + struct xe_vma_op *op) +{ + int err = 0; + + xe_vm_assert_held(vm); + + switch (op->base.op) { + case DRM_GPUVA_OP_MAP: + if (!op->map.immediate && xe_vm_in_fault_mode(vm)) + break; + + err = bind_op_prepare(vm, tile, pt_update_ops, op->map.vma); + pt_update_ops->wait_vm_kernel = true; + break; + case DRM_GPUVA_OP_REMAP: + err = unbind_op_prepare(tile, pt_update_ops, + gpuva_to_vma(op->base.remap.unmap->va)); + + if (!err && op->remap.prev) { + err = bind_op_prepare(vm, tile, pt_update_ops, + op->remap.prev); + pt_update_ops->wait_vm_bookkeep = true; + } + if (!err && op->remap.next) { + err = bind_op_prepare(vm, tile, pt_update_ops, + op->remap.next); + pt_update_ops->wait_vm_bookkeep = true; + } + break; + case DRM_GPUVA_OP_UNMAP: + err = unbind_op_prepare(tile, pt_update_ops, + gpuva_to_vma(op->base.unmap.va)); + break; + case DRM_GPUVA_OP_PREFETCH: + err = bind_op_prepare(vm, tile, pt_update_ops, + gpuva_to_vma(op->base.prefetch.va)); + pt_update_ops->wait_vm_kernel = true; + break; + default: + drm_warn(&vm->xe->drm, "NOT POSSIBLE"); + } + + return err; +} + +static void +xe_pt_update_ops_init(struct xe_vm_pgtable_update_ops *pt_update_ops) +{ + init_llist_head(&pt_update_ops->deferred); + pt_update_ops->start = ~0x0ull; + pt_update_ops->last = 0x0ull; +} + +/** + * xe_pt_update_ops_prepare() - Prepare PT update operations + * @tile: Tile of PT update operations + * @vops: VMA operationa + * + * Prepare PT update operations which includes updating internal PT state, + * allocate memory for page tables, populate page table being pruned in, and + * create PT update operations for leaf insertion / removal. + * + * Return: 0 on success, negative error code on error. + */ +int xe_pt_update_ops_prepare(struct xe_tile *tile, struct xe_vma_ops *vops) +{ + struct xe_vm_pgtable_update_ops *pt_update_ops = + &vops->pt_update_ops[tile->id]; + struct xe_vma_op *op; + int err; + + lockdep_assert_held(&vops->vm->lock); + xe_vm_assert_held(vops->vm); + + xe_pt_update_ops_init(pt_update_ops); + + err = dma_resv_reserve_fences(xe_vm_resv(vops->vm), + tile_to_xe(tile)->info.tile_count); + if (err) + return err; + + list_for_each_entry(op, &vops->list, link) { + err = op_prepare(vops->vm, tile, pt_update_ops, op); + + if (err) + return err; + } + + xe_tile_assert(tile, pt_update_ops->current_op <= + pt_update_ops->num_ops); + + return 0; +} + +static void bind_op_commit(struct xe_vm *vm, struct xe_tile *tile, + struct xe_vm_pgtable_update_ops *pt_update_ops, + struct xe_vma *vma, struct dma_fence *fence) +{ + if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm) + dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv, fence, + pt_update_ops->wait_vm_bookkeep ? + DMA_RESV_USAGE_KERNEL : + DMA_RESV_USAGE_BOOKKEEP); + vma->tile_present |= BIT(tile->id); + vma->tile_staged &= ~BIT(tile->id); + if (xe_vma_is_userptr(vma)) { + lockdep_assert_held_read(&vm->userptr.notifier_lock); + to_userptr_vma(vma)->userptr.initial_bind = true; + } + + /* + * Kick rebind worker if this bind triggers preempt fences and not in + * the rebind worker + */ + if (pt_update_ops->wait_vm_bookkeep && + xe_vm_in_preempt_fence_mode(vm) && + !current->mm) + xe_vm_queue_rebind_worker(vm); +} + +static void unbind_op_commit(struct xe_vm *vm, struct xe_tile *tile, + struct xe_vm_pgtable_update_ops *pt_update_ops, + struct xe_vma *vma, struct dma_fence *fence) +{ + if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm) + dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv, fence, + pt_update_ops->wait_vm_bookkeep ? + DMA_RESV_USAGE_KERNEL : + DMA_RESV_USAGE_BOOKKEEP); + vma->tile_present &= ~BIT(tile->id); + if (!vma->tile_present) { + list_del_init(&vma->combined_links.rebind); + if (xe_vma_is_userptr(vma)) { + lockdep_assert_held_read(&vm->userptr.notifier_lock); + + spin_lock(&vm->userptr.invalidated_lock); + list_del_init(&to_userptr_vma(vma)->userptr.invalidate_link); + spin_unlock(&vm->userptr.invalidated_lock); + } + } +} + +static void op_commit(struct xe_vm *vm, + struct xe_tile *tile, + struct xe_vm_pgtable_update_ops *pt_update_ops, + struct xe_vma_op *op, struct dma_fence *fence) +{ + xe_vm_assert_held(vm); + + switch (op->base.op) { + case DRM_GPUVA_OP_MAP: + if (!op->map.immediate && xe_vm_in_fault_mode(vm)) + break; + + bind_op_commit(vm, tile, pt_update_ops, op->map.vma, fence); + break; + case DRM_GPUVA_OP_REMAP: + unbind_op_commit(vm, tile, pt_update_ops, + gpuva_to_vma(op->base.remap.unmap->va), fence); + + if (op->remap.prev) + bind_op_commit(vm, tile, pt_update_ops, op->remap.prev, + fence); + if (op->remap.next) + bind_op_commit(vm, tile, pt_update_ops, op->remap.next, + fence); + break; + case DRM_GPUVA_OP_UNMAP: + unbind_op_commit(vm, tile, pt_update_ops, + gpuva_to_vma(op->base.unmap.va), fence); + break; + case DRM_GPUVA_OP_PREFETCH: + bind_op_commit(vm, tile, pt_update_ops, + gpuva_to_vma(op->base.prefetch.va), fence); + break; + default: + drm_warn(&vm->xe->drm, "NOT POSSIBLE"); + } +} + +static const struct xe_migrate_pt_update_ops migrate_ops = { + .populate = xe_vm_populate_pgtable, + .clear = xe_migrate_clear_pgtable_callback, .pre_commit = xe_pt_pre_commit, }; -static const struct xe_migrate_pt_update_ops userptr_unbind_ops = { - .populate = xe_migrate_clear_pgtable_callback, +static const struct xe_migrate_pt_update_ops userptr_migrate_ops = { + .populate = xe_vm_populate_pgtable, + .clear = xe_migrate_clear_pgtable_callback, .pre_commit = xe_pt_userptr_pre_commit, }; /** - * __xe_pt_unbind_vma() - Disconnect and free a page-table tree for the vma - * address range. - * @tile: The tile to unbind for. - * @vma: The vma to unbind. - * @q: The exec_queue with which to do pipelined page-table updates. - * @syncs: Entries to sync on before disconnecting the tree to be destroyed. - * @num_syncs: Number of @sync entries. + * xe_pt_update_ops_run() - Run PT update operations + * @tile: Tile of PT update operations + * @vops: VMA operationa * - * This function builds a the xe_vm_pgtable_update entries abstracting the - * operations needed to detach the page-table tree to be destroyed from the - * man vm tree. - * It then takes the relevant locks and submits the operations for - * pipelined detachment of the gpu page-table from the vm main tree, - * (which can be done either by the cpu and the GPU), Finally it frees the - * detached page-table tree. + * Run PT update operations which includes committing internal PT state changes, + * creating job for PT update operations for leaf insertion / removal, and + * installing job fence in various places. * - * Return: A valid dma-fence representing the pipelined detachment operation - * on success, an error pointer on error. + * Return: fence on success, negative ERR_PTR on error. */ struct dma_fence * -__xe_pt_unbind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queue *q, - struct xe_sync_entry *syncs, u32 num_syncs) +xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops) { - struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1]; - struct xe_pt_migrate_pt_update unbind_pt_update = { - .base = { - .ops = xe_vma_is_userptr(vma) ? &userptr_unbind_ops : - &unbind_ops, - .vma = vma, - .tile_id = tile->id, - }, - }; - struct xe_vm *vm = xe_vma_vm(vma); - u32 num_entries; - struct dma_fence *fence = NULL; - struct invalidation_fence *ifence; + struct xe_vm *vm = vops->vm; + struct xe_vm_pgtable_update_ops *pt_update_ops = + &vops->pt_update_ops[tile->id]; + struct dma_fence *fence; + struct invalidation_fence *ifence = NULL; struct xe_range_fence *rfence; - int err; - - LLIST_HEAD(deferred); + struct xe_vma_op *op; + int err = 0; + struct xe_migrate_pt_update update = { + .ops = pt_update_ops->needs_userptr_lock ? + &userptr_migrate_ops : + &migrate_ops, + .vops = vops, + .tile_id = tile->id, + }; - xe_bo_assert_held(xe_vma_bo(vma)); + lockdep_assert_held(&vm->lock); xe_vm_assert_held(vm); - vm_dbg(&xe_vma_vm(vma)->xe->drm, - "Preparing unbind, with range [%llx...%llx) engine %p.\n", - xe_vma_start(vma), xe_vma_end(vma), q); - - num_entries = xe_pt_stage_unbind(tile, vma, entries); - xe_tile_assert(tile, num_entries <= ARRAY_SIZE(entries)); - - xe_vm_dbg_print_entries(tile_to_xe(tile), entries, num_entries); - xe_pt_calc_rfence_interval(vma, &unbind_pt_update, entries, - num_entries); + if (!pt_update_ops->current_op) { + xe_tile_assert(tile, xe_vm_in_fault_mode(vm)); - err = dma_resv_reserve_fences(xe_vm_resv(vm), 1); - if (!err && !xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm) - err = dma_resv_reserve_fences(xe_vma_bo(vma)->ttm.base.resv, 1); - if (err) - return ERR_PTR(err); + return dma_fence_get_stub(); + } - ifence = kzalloc(sizeof(*ifence), GFP_KERNEL); - if (!ifence) - return ERR_PTR(-ENOMEM); + if (pt_update_ops->needs_invalidation) { + ifence = kzalloc(sizeof(*ifence), GFP_KERNEL); + if (!ifence) + return ERR_PTR(-ENOMEM); + } rfence = kzalloc(sizeof(*rfence), GFP_KERNEL); if (!rfence) { - kfree(ifence); - return ERR_PTR(-ENOMEM); + err = -ENOMEM; + goto free_ifence; } - /* - * Even if we were already evicted and unbind to destroy, we need to - * clear again here. The eviction may have updated pagetables at a - * lower level, because it needs to be more conservative. - */ - fence = xe_migrate_update_pgtables(tile->migrate, - vm, NULL, q ? q : - vm->q[tile->id], - entries, num_entries, - syncs, num_syncs, - &unbind_pt_update.base); - if (!IS_ERR(fence)) { - int err; - - err = xe_range_fence_insert(&vm->rftree[tile->id], rfence, - &xe_range_fence_kfree_ops, - unbind_pt_update.base.start, - unbind_pt_update.base.last, fence); - if (err) - dma_fence_wait(fence, false); + fence = xe_migrate_update_pgtables(tile->migrate, &update); + if (IS_ERR(fence)) { + err = PTR_ERR(fence); + goto free_rfence; + } - /* TLB invalidation must be done before signaling unbind */ + if (xe_range_fence_insert(&vm->rftree[tile->id], rfence, + &xe_range_fence_kfree_ops, + pt_update_ops->start, + pt_update_ops->last, fence)) + dma_fence_wait(fence, false); + + /* tlb invalidation must be done before signaling rebind */ + if (ifence) { err = invalidation_fence_init(tile->primary_gt, ifence, fence, - xe_vma_start(vma), - xe_vma_end(vma), - xe_vma_vm(vma)->usm.asid); - if (err) { - dma_fence_put(fence); - kfree(ifence); - return ERR_PTR(err); - } + pt_update_ops->start, + pt_update_ops->last, + vm->usm.asid); + if (err) + goto put_fence; fence = &ifence->base.base; + } - /* add shared fence now for pagetable delayed destroy */ - dma_resv_add_fence(xe_vm_resv(vm), fence, - DMA_RESV_USAGE_BOOKKEEP); + dma_resv_add_fence(xe_vm_resv(vm), fence, + pt_update_ops->wait_vm_bookkeep ? + DMA_RESV_USAGE_KERNEL : + DMA_RESV_USAGE_BOOKKEEP); - /* This fence will be installed by caller when doing eviction */ - if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm) - dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv, fence, - DMA_RESV_USAGE_BOOKKEEP); - xe_pt_commit_unbind(vma, entries, num_entries, - unbind_pt_update.locked ? &deferred : NULL); - vma->tile_present &= ~BIT(tile->id); - } else { - kfree(rfence); - kfree(ifence); - } + list_for_each_entry(op, &vops->list, link) + op_commit(vops->vm, tile, pt_update_ops, op, fence); - if (!vma->tile_present) - list_del_init(&vma->combined_links.rebind); + if (pt_update_ops->needs_userptr_lock) + up_read(&vm->userptr.notifier_lock); - if (unbind_pt_update.locked) { - xe_tile_assert(tile, xe_vma_is_userptr(vma)); + return fence; - if (!vma->tile_present) { - spin_lock(&vm->userptr.invalidated_lock); - list_del_init(&to_userptr_vma(vma)->userptr.invalidate_link); - spin_unlock(&vm->userptr.invalidated_lock); - } +put_fence: + if (pt_update_ops->needs_userptr_lock) up_read(&vm->userptr.notifier_lock); - xe_bo_put_commit(&deferred); + dma_fence_put(fence); +free_rfence: + kfree(rfence); +free_ifence: + kfree(ifence); + + return ERR_PTR(err); +} + +/** + * xe_pt_update_ops_fini() - Finish PT update operations + * @tile: Tile of PT update operations + * @vops: VMA operations + * + * Finish PT update operations by committing to destroy page table memory + */ +void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops) +{ + struct xe_vm_pgtable_update_ops *pt_update_ops = + &vops->pt_update_ops[tile->id]; + int i; + + lockdep_assert_held(&vops->vm->lock); + xe_vm_assert_held(vops->vm); + + /* FIXME: Not 100% correct */ + for (i = 0; i < pt_update_ops->num_ops; ++i) { + struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[i]; + + if (pt_op->bind) + xe_pt_free_bind(pt_op->entries, pt_op->num_entries); } + xe_bo_put_commit(&vops->pt_update_ops[tile->id].deferred); +} - return fence; +/** + * xe_pt_update_ops_abort() - Abort PT update operations + * @tile: Tile of PT update operations + * @vops: VMA operationa + * + * Abort PT update operations by unwinding internal PT state + */ +void xe_pt_update_ops_abort(struct xe_tile *tile, struct xe_vma_ops *vops) +{ + lockdep_assert_held(&vops->vm->lock); + xe_vm_assert_held(vops->vm); + + /* FIXME: Just kill VM for now + cleanup PTs */ + xe_bo_put_commit(&vops->pt_update_ops[tile->id].deferred); + xe_vm_kill(vops->vm, false); } diff --git a/drivers/gpu/drm/xe/xe_pt.h b/drivers/gpu/drm/xe/xe_pt.h index 71a4fbfcff43..9ab386431cad 100644 --- a/drivers/gpu/drm/xe/xe_pt.h +++ b/drivers/gpu/drm/xe/xe_pt.h @@ -17,6 +17,7 @@ struct xe_sync_entry; struct xe_tile; struct xe_vm; struct xe_vma; +struct xe_vma_ops; /* Largest huge pte is currently 1GiB. May become device dependent. */ #define MAX_HUGEPTE_LEVEL 2 @@ -34,14 +35,11 @@ void xe_pt_populate_empty(struct xe_tile *tile, struct xe_vm *vm, void xe_pt_destroy(struct xe_pt *pt, u32 flags, struct llist_head *deferred); -struct dma_fence * -__xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queue *q, - struct xe_sync_entry *syncs, u32 num_syncs, - bool rebind); - -struct dma_fence * -__xe_pt_unbind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queue *q, - struct xe_sync_entry *syncs, u32 num_syncs); +int xe_pt_update_ops_prepare(struct xe_tile *tile, struct xe_vma_ops *vops); +struct dma_fence *xe_pt_update_ops_run(struct xe_tile *tile, + struct xe_vma_ops *vops); +void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops); +void xe_pt_update_ops_abort(struct xe_tile *tile, struct xe_vma_ops *vops); bool xe_pt_zap_ptes(struct xe_tile *tile, struct xe_vma *vma); diff --git a/drivers/gpu/drm/xe/xe_pt_types.h b/drivers/gpu/drm/xe/xe_pt_types.h index 2093150f461e..384cc04de719 100644 --- a/drivers/gpu/drm/xe/xe_pt_types.h +++ b/drivers/gpu/drm/xe/xe_pt_types.h @@ -78,6 +78,8 @@ struct xe_vm_pgtable_update { struct xe_vm_pgtable_update_op { /** @entries: entries to update for this operation */ struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1]; + /** @vma: VMA for operation, operation not valid if NULL */ + struct xe_vma *vma; /** @num_entries: number of entries for this update operation */ u32 num_entries; /** @bind: is a bind */ @@ -86,4 +88,38 @@ struct xe_vm_pgtable_update_op { bool rebind; }; +/** struct xe_vm_pgtable_update_ops: page table update operations */ +struct xe_vm_pgtable_update_ops { + /** @ops: operations */ + struct xe_vm_pgtable_update_op *ops; + /** @deferred: deferred list to destroy PT entries */ + struct llist_head deferred; + /** @q: exec queue for PT operations */ + struct xe_exec_queue *q; + /** @start: start address of ops */ + u64 start; + /** @last: last address of ops */ + u64 last; + /** @num_ops: number of operations */ + u32 num_ops; + /** @current_op: current operations */ + u32 current_op; + /** @needs_userptr_lock: Needs userptr lock */ + bool needs_userptr_lock; + /** @needs_invalidation: Needs invalidation */ + bool needs_invalidation; + /** + * @wait_vm_bookkeep: PT operations need to wait until VM is idle + * (bookkeep dma-resv slots are idle) and stage all future VM activity + * behind these operations (install PT operations into VM kernel + * dma-resv slot). + */ + bool wait_vm_bookkeep; + /** + * @wait_vm_kernel: PT operations need to wait until VM kernel dma-resv + * slots are idle. + */ + bool wait_vm_kernel; +}; + #endif diff --git a/drivers/gpu/drm/xe/xe_sa.c b/drivers/gpu/drm/xe/xe_sa.c index 8941522b7705..f3060979e63f 100644 --- a/drivers/gpu/drm/xe/xe_sa.c +++ b/drivers/gpu/drm/xe/xe_sa.c @@ -84,6 +84,13 @@ struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 struct drm_suballoc *xe_sa_bo_new(struct xe_sa_manager *sa_manager, unsigned int size) { + /* + * BB to large, return -ENOBUFS indicating user should split + * array of binds into smaller chunks. + */ + if (size > sa_manager->base.size) + return ERR_PTR(-ENOBUFS); + return drm_suballoc_new(&sa_manager->base, size, GFP_KERNEL, true, 0); } diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 6677874af5a4..73cc6b0efcef 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -313,7 +313,7 @@ int __xe_vm_userptr_needs_repin(struct xe_vm *vm) #define XE_VM_REBIND_RETRY_TIMEOUT_MS 1000 -/* +/** * xe_vm_kill() - VM Kill * @vm: The VM. * @unlocked: Flag indicates the VM's dma-resv is not held @@ -321,7 +321,7 @@ int __xe_vm_userptr_needs_repin(struct xe_vm *vm) * Kill the VM by setting banned flag indicated VM is no longer available for * use. If in preempt fence mode, also kill all exec queue attached to the VM. */ -static void xe_vm_kill(struct xe_vm *vm, bool unlocked) +void xe_vm_kill(struct xe_vm *vm, bool unlocked) { struct xe_exec_queue *q; @@ -798,7 +798,7 @@ int xe_vm_rebind(struct xe_vm *vm, bool rebind_worker) struct xe_vma *vma, *next; struct xe_vma_ops vops; struct xe_vma_op *op, *next_op; - int err; + int err, i; lockdep_assert_held(&vm->lock); if ((xe_vm_in_lr_mode(vm) && !rebind_worker) || @@ -806,6 +806,8 @@ int xe_vm_rebind(struct xe_vm *vm, bool rebind_worker) return 0; xe_vma_ops_init(&vops, vm, NULL, NULL, 0); + for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) + vops.pt_update_ops[i].wait_vm_bookkeep = true; xe_vm_assert_held(vm); list_for_each_entry(vma, &vm->rebind_list, combined_links.rebind) { @@ -850,6 +852,8 @@ struct dma_fence *xe_vma_rebind(struct xe_vm *vm, struct xe_vma *vma, u8 tile_ma struct dma_fence *fence = NULL; struct xe_vma_ops vops; struct xe_vma_op *op, *next_op; + struct xe_tile *tile; + u8 id; int err; lockdep_assert_held(&vm->lock); @@ -857,6 +861,11 @@ struct dma_fence *xe_vma_rebind(struct xe_vm *vm, struct xe_vma *vma, u8 tile_ma xe_assert(vm->xe, xe_vm_in_fault_mode(vm)); xe_vma_ops_init(&vops, vm, NULL, NULL, 0); + for_each_tile(tile, vm->xe, id) { + vops.pt_update_ops[id].wait_vm_bookkeep = true; + vops.pt_update_ops[tile->id].q = + xe_tile_migrate_exec_queue(tile); + } err = xe_vm_ops_add_rebind(&vops, vma, tile_mask); if (err) @@ -1697,147 +1706,6 @@ to_wait_exec_queue(struct xe_vm *vm, struct xe_exec_queue *q) return q ? q : vm->q[0]; } -static struct dma_fence * -xe_vm_unbind_vma(struct xe_vma *vma, struct xe_exec_queue *q, - struct xe_sync_entry *syncs, u32 num_syncs, - bool first_op, bool last_op) -{ - struct xe_vm *vm = xe_vma_vm(vma); - struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm, q); - struct xe_tile *tile; - struct dma_fence *fence = NULL; - struct dma_fence **fences = NULL; - struct dma_fence_array *cf = NULL; - int cur_fence = 0; - int number_tiles = hweight8(vma->tile_present); - int err; - u8 id; - - trace_xe_vma_unbind(vma); - - if (number_tiles > 1) { - fences = kmalloc_array(number_tiles, sizeof(*fences), - GFP_KERNEL); - if (!fences) - return ERR_PTR(-ENOMEM); - } - - for_each_tile(tile, vm->xe, id) { - if (!(vma->tile_present & BIT(id))) - goto next; - - fence = __xe_pt_unbind_vma(tile, vma, q ? q : vm->q[id], - first_op ? syncs : NULL, - first_op ? num_syncs : 0); - if (IS_ERR(fence)) { - err = PTR_ERR(fence); - goto err_fences; - } - - if (fences) - fences[cur_fence++] = fence; - -next: - if (q && vm->pt_root[id] && !list_empty(&q->multi_gt_list)) - q = list_next_entry(q, multi_gt_list); - } - - if (fences) { - cf = dma_fence_array_create(number_tiles, fences, - vm->composite_fence_ctx, - vm->composite_fence_seqno++, - false); - if (!cf) { - --vm->composite_fence_seqno; - err = -ENOMEM; - goto err_fences; - } - } - - fence = cf ? &cf->base : !fence ? - xe_exec_queue_last_fence_get(wait_exec_queue, vm) : fence; - - return fence; - -err_fences: - if (fences) { - while (cur_fence) - dma_fence_put(fences[--cur_fence]); - kfree(fences); - } - - return ERR_PTR(err); -} - -static struct dma_fence * -xe_vm_bind_vma(struct xe_vma *vma, struct xe_exec_queue *q, - struct xe_sync_entry *syncs, u32 num_syncs, - u8 tile_mask, bool first_op, bool last_op) -{ - struct xe_tile *tile; - struct dma_fence *fence; - struct dma_fence **fences = NULL; - struct dma_fence_array *cf = NULL; - struct xe_vm *vm = xe_vma_vm(vma); - int cur_fence = 0; - int number_tiles = hweight8(tile_mask); - int err; - u8 id; - - trace_xe_vma_bind(vma); - - if (number_tiles > 1) { - fences = kmalloc_array(number_tiles, sizeof(*fences), - GFP_KERNEL); - if (!fences) - return ERR_PTR(-ENOMEM); - } - - for_each_tile(tile, vm->xe, id) { - if (!(tile_mask & BIT(id))) - goto next; - - fence = __xe_pt_bind_vma(tile, vma, q ? q : vm->q[id], - first_op ? syncs : NULL, - first_op ? num_syncs : 0, - vma->tile_present & BIT(id)); - if (IS_ERR(fence)) { - err = PTR_ERR(fence); - goto err_fences; - } - - if (fences) - fences[cur_fence++] = fence; - -next: - if (q && vm->pt_root[id] && !list_empty(&q->multi_gt_list)) - q = list_next_entry(q, multi_gt_list); - } - - if (fences) { - cf = dma_fence_array_create(number_tiles, fences, - vm->composite_fence_ctx, - vm->composite_fence_seqno++, - false); - if (!cf) { - --vm->composite_fence_seqno; - err = -ENOMEM; - goto err_fences; - } - } - - return cf ? &cf->base : fence; - -err_fences: - if (fences) { - while (cur_fence) - dma_fence_put(fences[--cur_fence]); - kfree(fences); - } - - return ERR_PTR(err); -} - static struct xe_user_fence * find_ufence_get(struct xe_sync_entry *syncs, u32 num_syncs) { @@ -1853,48 +1721,6 @@ find_ufence_get(struct xe_sync_entry *syncs, u32 num_syncs) return NULL; } -static struct dma_fence * -xe_vm_bind(struct xe_vm *vm, struct xe_vma *vma, struct xe_exec_queue *q, - struct xe_bo *bo, struct xe_sync_entry *syncs, u32 num_syncs, - u8 tile_mask, bool immediate, bool first_op, bool last_op) -{ - struct dma_fence *fence; - struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm, q); - - xe_vm_assert_held(vm); - xe_bo_assert_held(bo); - - if (immediate) { - fence = xe_vm_bind_vma(vma, q, syncs, num_syncs, tile_mask, - first_op, last_op); - if (IS_ERR(fence)) - return fence; - } else { - xe_assert(vm->xe, xe_vm_in_fault_mode(vm)); - - fence = xe_exec_queue_last_fence_get(wait_exec_queue, vm); - } - - return fence; -} - -static struct dma_fence * -xe_vm_unbind(struct xe_vm *vm, struct xe_vma *vma, - struct xe_exec_queue *q, struct xe_sync_entry *syncs, - u32 num_syncs, bool first_op, bool last_op) -{ - struct dma_fence *fence; - - xe_vm_assert_held(vm); - xe_bo_assert_held(xe_vma_bo(vma)); - - fence = xe_vm_unbind_vma(vma, q, syncs, num_syncs, first_op, last_op); - if (IS_ERR(fence)) - return fence; - - return fence; -} - #define ALL_DRM_XE_VM_CREATE_FLAGS (DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE | \ DRM_XE_VM_CREATE_FLAG_LR_MODE | \ DRM_XE_VM_CREATE_FLAG_FAULT_MODE) @@ -2035,21 +1861,6 @@ static const u32 region_to_mem_type[] = { XE_PL_VRAM1, }; -static struct dma_fence * -xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma, - struct xe_exec_queue *q, struct xe_sync_entry *syncs, - u32 num_syncs, bool first_op, bool last_op) -{ - struct xe_exec_queue *wait_exec_queue = to_wait_exec_queue(vm, q); - - if (vma->tile_mask != (vma->tile_present & ~vma->tile_invalidated)) { - return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs, num_syncs, - vma->tile_mask, true, first_op, last_op); - } else { - return xe_exec_queue_last_fence_get(wait_exec_queue, vm); - } -} - static void prep_vma_destroy(struct xe_vm *vm, struct xe_vma *vma, bool post_commit) { @@ -2337,13 +2148,10 @@ static int xe_vma_op_commit(struct xe_vm *vm, struct xe_vma_op *op) return err; } -static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q, - struct drm_gpuva_ops *ops, - struct xe_sync_entry *syncs, u32 num_syncs, - struct xe_vma_ops *vops, bool last) +static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, + struct xe_vma_ops *vops) { struct xe_device *xe = vm->xe; - struct xe_vma_op *last_op = NULL; struct drm_gpuva_op *__op; struct xe_tile *tile; u8 id, tile_mask = 0; @@ -2357,19 +2165,10 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q, drm_gpuva_for_each_op(__op, ops) { struct xe_vma_op *op = gpuva_op_to_vma_op(__op); struct xe_vma *vma; - bool first = list_empty(&vops->list); unsigned int flags = 0; INIT_LIST_HEAD(&op->link); list_add_tail(&op->link, &vops->list); - - if (first) { - op->flags |= XE_VMA_OP_FIRST; - op->num_syncs = num_syncs; - op->syncs = syncs; - } - - op->q = q; op->tile_mask = tile_mask; switch (op->base.op) { @@ -2482,197 +2281,21 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q, } case DRM_GPUVA_OP_UNMAP: case DRM_GPUVA_OP_PREFETCH: + /* FIXME: Need to skip some prefetch ops */ xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); break; default: drm_warn(&vm->xe->drm, "NOT POSSIBLE"); } - last_op = op; - err = xe_vma_op_commit(vm, op); if (err) return err; } - /* FIXME: Unhandled corner case */ - XE_WARN_ON(!last_op && last && !list_empty(&vops->list)); - - if (!last_op) - return 0; - - if (last) { - last_op->flags |= XE_VMA_OP_LAST; - last_op->num_syncs = num_syncs; - last_op->syncs = syncs; - } - return 0; } -static struct dma_fence *op_execute(struct xe_vm *vm, struct xe_vma *vma, - struct xe_vma_op *op) -{ - struct dma_fence *fence = NULL; - - lockdep_assert_held(&vm->lock); - - xe_vm_assert_held(vm); - xe_bo_assert_held(xe_vma_bo(vma)); - - switch (op->base.op) { - case DRM_GPUVA_OP_MAP: - fence = xe_vm_bind(vm, vma, op->q, xe_vma_bo(vma), - op->syncs, op->num_syncs, - op->tile_mask, - op->map.immediate || !xe_vm_in_fault_mode(vm), - op->flags & XE_VMA_OP_FIRST, - op->flags & XE_VMA_OP_LAST); - break; - case DRM_GPUVA_OP_REMAP: - { - bool prev = !!op->remap.prev; - bool next = !!op->remap.next; - - if (!op->remap.unmap_done) { - if (prev || next) - vma->gpuva.flags |= XE_VMA_FIRST_REBIND; - fence = xe_vm_unbind(vm, vma, op->q, op->syncs, - op->num_syncs, - op->flags & XE_VMA_OP_FIRST, - op->flags & XE_VMA_OP_LAST && - !prev && !next); - if (IS_ERR(fence)) - break; - op->remap.unmap_done = true; - } - - if (prev) { - op->remap.prev->gpuva.flags |= XE_VMA_LAST_REBIND; - dma_fence_put(fence); - fence = xe_vm_bind(vm, op->remap.prev, op->q, - xe_vma_bo(op->remap.prev), op->syncs, - op->num_syncs, - op->remap.prev->tile_mask, true, - false, - op->flags & XE_VMA_OP_LAST && !next); - op->remap.prev->gpuva.flags &= ~XE_VMA_LAST_REBIND; - if (IS_ERR(fence)) - break; - op->remap.prev = NULL; - } - - if (next) { - op->remap.next->gpuva.flags |= XE_VMA_LAST_REBIND; - dma_fence_put(fence); - fence = xe_vm_bind(vm, op->remap.next, op->q, - xe_vma_bo(op->remap.next), - op->syncs, op->num_syncs, - op->remap.next->tile_mask, true, - false, op->flags & XE_VMA_OP_LAST); - op->remap.next->gpuva.flags &= ~XE_VMA_LAST_REBIND; - if (IS_ERR(fence)) - break; - op->remap.next = NULL; - } - - break; - } - case DRM_GPUVA_OP_UNMAP: - fence = xe_vm_unbind(vm, vma, op->q, op->syncs, - op->num_syncs, op->flags & XE_VMA_OP_FIRST, - op->flags & XE_VMA_OP_LAST); - break; - case DRM_GPUVA_OP_PREFETCH: - fence = xe_vm_prefetch(vm, vma, op->q, op->syncs, op->num_syncs, - op->flags & XE_VMA_OP_FIRST, - op->flags & XE_VMA_OP_LAST); - break; - default: - drm_warn(&vm->xe->drm, "NOT POSSIBLE"); - } - - if (IS_ERR(fence)) - trace_xe_vma_fail(vma); - - return fence; -} - -static struct dma_fence * -__xe_vma_op_execute(struct xe_vm *vm, struct xe_vma *vma, - struct xe_vma_op *op) -{ - struct dma_fence *fence; - int err; - -retry_userptr: - fence = op_execute(vm, vma, op); - if (IS_ERR(fence) && PTR_ERR(fence) == -EAGAIN) { - lockdep_assert_held_write(&vm->lock); - - if (op->base.op == DRM_GPUVA_OP_REMAP) { - if (!op->remap.unmap_done) - vma = gpuva_to_vma(op->base.remap.unmap->va); - else if (op->remap.prev) - vma = op->remap.prev; - else - vma = op->remap.next; - } - - if (xe_vma_is_userptr(vma)) { - err = xe_vma_userptr_pin_pages(to_userptr_vma(vma)); - if (!err) - goto retry_userptr; - - fence = ERR_PTR(err); - trace_xe_vma_fail(vma); - } - } - - return fence; -} - -static struct dma_fence * -xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op) -{ - struct dma_fence *fence = ERR_PTR(-ENOMEM); - - lockdep_assert_held(&vm->lock); - - switch (op->base.op) { - case DRM_GPUVA_OP_MAP: - fence = __xe_vma_op_execute(vm, op->map.vma, op); - break; - case DRM_GPUVA_OP_REMAP: - { - struct xe_vma *vma; - - if (!op->remap.unmap_done) - vma = gpuva_to_vma(op->base.remap.unmap->va); - else if (op->remap.prev) - vma = op->remap.prev; - else - vma = op->remap.next; - - fence = __xe_vma_op_execute(vm, vma, op); - break; - } - case DRM_GPUVA_OP_UNMAP: - fence = __xe_vma_op_execute(vm, gpuva_to_vma(op->base.unmap.va), - op); - break; - case DRM_GPUVA_OP_PREFETCH: - fence = __xe_vma_op_execute(vm, - gpuva_to_vma(op->base.prefetch.va), - op); - break; - default: - drm_warn(&vm->xe->drm, "NOT POSSIBLE"); - } - - return fence; -} - static void xe_vma_op_unwind(struct xe_vm *vm, struct xe_vma_op *op, bool post_commit, bool prev_post_commit, bool next_post_commit) @@ -2858,23 +2481,110 @@ static int vm_bind_ioctl_ops_lock_and_prep(struct drm_exec *exec, return 0; } +static int vm_ops_setup_tile_args(struct xe_vm *vm, struct xe_vma_ops *vops) +{ + struct xe_exec_queue *q = vops->q; + struct xe_tile *tile; + int number_tiles = 0; + u8 id; + + for_each_tile(tile, vm->xe, id) { + if (vops->pt_update_ops[id].num_ops) + ++number_tiles; + + if (vops->pt_update_ops[id].q) + continue; + + if (q) { + vops->pt_update_ops[id].q = q; + if (vm->pt_root[id] && !list_empty(&q->multi_gt_list)) + q = list_next_entry(q, multi_gt_list); + } else { + vops->pt_update_ops[id].q = vm->q[id]; + } + } + + return number_tiles; +} + static struct dma_fence *ops_execute(struct xe_vm *vm, struct xe_vma_ops *vops) { - struct xe_vma_op *op, *next; + struct xe_tile *tile; struct dma_fence *fence = NULL; + struct dma_fence **fences = NULL; + struct dma_fence_array *cf = NULL; + int number_tiles = 0, current_fence = 0, err; + u8 id; - list_for_each_entry_safe(op, next, &vops->list, link) { - dma_fence_put(fence); - fence = xe_vma_op_execute(vm, op); - if (IS_ERR(fence)) { - drm_warn(&vm->xe->drm, "VM op(%d) failed with %ld", - op->base.op, PTR_ERR(fence)); - fence = ERR_PTR(-ENOSPC); - break; + number_tiles = vm_ops_setup_tile_args(vm, vops); + if (number_tiles == 0) + return ERR_PTR(-ENODATA); + + if (number_tiles > 1) { + fences = kmalloc_array(number_tiles, sizeof(*fences), + GFP_KERNEL); + if (!fences) + return ERR_PTR(-ENOMEM); + } + + for_each_tile(tile, vm->xe, id) { + if (!vops->pt_update_ops[id].num_ops) + continue; + + err = xe_pt_update_ops_prepare(tile, vops); + if (err) { + fence = ERR_PTR(err); + goto err_out; } } + for_each_tile(tile, vm->xe, id) { + if (!vops->pt_update_ops[id].num_ops) + continue; + + fence = xe_pt_update_ops_run(tile, vops); + if (IS_ERR(fence)) + goto err_out; + + if (fences) + fences[current_fence++] = fence; + } + + if (fences) { + cf = dma_fence_array_create(number_tiles, fences, + vm->composite_fence_ctx, + vm->composite_fence_seqno++, + false); + if (!cf) { + --vm->composite_fence_seqno; + fence = ERR_PTR(-ENOMEM); + goto err_out; + } + fence = &cf->base; + } + + for_each_tile(tile, vm->xe, id) { + if (!vops->pt_update_ops[id].num_ops) + continue; + + xe_pt_update_ops_fini(tile, vops); + } + + return fence; + +err_out: + for_each_tile(tile, vm->xe, id) { + if (!vops->pt_update_ops[id].num_ops) + continue; + + xe_pt_update_ops_abort(tile, vops); + } + while (current_fence) + dma_fence_put(fences[--current_fence]); + kfree(fences); + kfree(cf); + return fence; } @@ -2955,12 +2665,10 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm *vm, fence = ops_execute(vm, vops); if (IS_ERR(fence)) { err = PTR_ERR(fence); - /* FIXME: Killing VM rather than proper error handling */ - xe_vm_kill(vm, false); goto unlock; - } else { - vm_bind_ioctl_ops_fini(vm, vops, fence); } + + vm_bind_ioctl_ops_fini(vm, vops, fence); } unlock: @@ -3317,8 +3025,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) goto unwind_ops; } - err = vm_bind_ioctl_ops_parse(vm, q, ops[i], syncs, num_syncs, - &vops, i == args->num_binds - 1); + err = vm_bind_ioctl_ops_parse(vm, ops[i], &vops); if (err) goto unwind_ops; } diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h index b481608b12f1..c864dba35e1d 100644 --- a/drivers/gpu/drm/xe/xe_vm.h +++ b/drivers/gpu/drm/xe/xe_vm.h @@ -259,6 +259,8 @@ static inline struct dma_resv *xe_vm_resv(struct xe_vm *vm) return drm_gpuvm_resv(&vm->gpuvm); } +void xe_vm_kill(struct xe_vm *vm, bool unlocked); + /** * xe_vm_assert_held(vm) - Assert that the vm's reservation object is held. * @vm: The vm diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h index 211c88801182..27d651093d30 100644 --- a/drivers/gpu/drm/xe/xe_vm_types.h +++ b/drivers/gpu/drm/xe/xe_vm_types.h @@ -26,14 +26,12 @@ struct xe_vm_pgtable_update_op; #define XE_VMA_READ_ONLY DRM_GPUVA_USERBITS #define XE_VMA_DESTROYED (DRM_GPUVA_USERBITS << 1) #define XE_VMA_ATOMIC_PTE_BIT (DRM_GPUVA_USERBITS << 2) -#define XE_VMA_FIRST_REBIND (DRM_GPUVA_USERBITS << 3) -#define XE_VMA_LAST_REBIND (DRM_GPUVA_USERBITS << 4) -#define XE_VMA_PTE_4K (DRM_GPUVA_USERBITS << 5) -#define XE_VMA_PTE_2M (DRM_GPUVA_USERBITS << 6) -#define XE_VMA_PTE_1G (DRM_GPUVA_USERBITS << 7) -#define XE_VMA_PTE_64K (DRM_GPUVA_USERBITS << 8) -#define XE_VMA_PTE_COMPACT (DRM_GPUVA_USERBITS << 9) -#define XE_VMA_DUMPABLE (DRM_GPUVA_USERBITS << 10) +#define XE_VMA_PTE_4K (DRM_GPUVA_USERBITS << 3) +#define XE_VMA_PTE_2M (DRM_GPUVA_USERBITS << 4) +#define XE_VMA_PTE_1G (DRM_GPUVA_USERBITS << 5) +#define XE_VMA_PTE_64K (DRM_GPUVA_USERBITS << 6) +#define XE_VMA_PTE_COMPACT (DRM_GPUVA_USERBITS << 7) +#define XE_VMA_DUMPABLE (DRM_GPUVA_USERBITS << 8) /** struct xe_userptr - User pointer */ struct xe_userptr { @@ -100,6 +98,9 @@ struct xe_vma { */ u8 tile_present; + /** @tile_staged: bind is staged for this VMA */ + u8 tile_staged; + /** * @pat_index: The pat index to use when encoding the PTEs for this vma. */ @@ -315,31 +316,18 @@ struct xe_vma_op_prefetch { /** enum xe_vma_op_flags - flags for VMA operation */ enum xe_vma_op_flags { - /** @XE_VMA_OP_FIRST: first VMA operation for a set of syncs */ - XE_VMA_OP_FIRST = BIT(0), - /** @XE_VMA_OP_LAST: last VMA operation for a set of syncs */ - XE_VMA_OP_LAST = BIT(1), /** @XE_VMA_OP_COMMITTED: VMA operation committed */ - XE_VMA_OP_COMMITTED = BIT(2), + XE_VMA_OP_COMMITTED = BIT(0), /** @XE_VMA_OP_PREV_COMMITTED: Previous VMA operation committed */ - XE_VMA_OP_PREV_COMMITTED = BIT(3), + XE_VMA_OP_PREV_COMMITTED = BIT(1), /** @XE_VMA_OP_NEXT_COMMITTED: Next VMA operation committed */ - XE_VMA_OP_NEXT_COMMITTED = BIT(4), + XE_VMA_OP_NEXT_COMMITTED = BIT(2), }; /** struct xe_vma_op - VMA operation */ struct xe_vma_op { /** @base: GPUVA base operation */ struct drm_gpuva_op base; - /** @q: exec queue for this operation */ - struct xe_exec_queue *q; - /** - * @syncs: syncs for this operation, only used on first and last - * operation - */ - struct xe_sync_entry *syncs; - /** @num_syncs: number of syncs */ - u32 num_syncs; /** @link: async operation link */ struct list_head link; /** @flags: operation flags */ @@ -363,19 +351,14 @@ struct xe_vma_ops { struct list_head list; /** @vm: VM */ struct xe_vm *vm; - /** @q: exec queue these operations */ + /** @q: exec queue for VMA operations */ struct xe_exec_queue *q; /** @syncs: syncs these operation */ struct xe_sync_entry *syncs; /** @num_syncs: number of syncs */ u32 num_syncs; /** @pt_update_ops: page table update operations */ - struct { - /** @ops: operations */ - struct xe_vm_pgtable_update_op *ops; - /** @num_ops: number of operations */ - u32 num_ops; - } pt_update_ops[XE_MAX_TILES_PER_DEVICE]; + struct xe_vm_pgtable_update_ops pt_update_ops[XE_MAX_TILES_PER_DEVICE]; }; #endif -- cgit v1.2.3 From 282e6f846d8c3fcf36293f68f38d814645c3b852 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Wed, 3 Jul 2024 21:16:50 -0700 Subject: drm/xe: Update VM trace events The trace events have changed moving to a single job per VM bind IOCTL, update the trace events align with old behavior as much as possible. Signed-off-by: Matthew Brost Reviewed-by: Jonathan Cavitt Link: https://patchwork.freedesktop.org/patch/msgid/20240704041652.272920-6-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_trace_bo.h | 10 +++++----- drivers/gpu/drm/xe/xe_vm.c | 42 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_trace_bo.h b/drivers/gpu/drm/xe/xe_trace_bo.h index f39f09ed3495..9b1a1d4304ae 100644 --- a/drivers/gpu/drm/xe/xe_trace_bo.h +++ b/drivers/gpu/drm/xe/xe_trace_bo.h @@ -117,11 +117,6 @@ DEFINE_EVENT(xe_vma, xe_vma_acc, TP_ARGS(vma) ); -DEFINE_EVENT(xe_vma, xe_vma_fail, - TP_PROTO(struct xe_vma *vma), - TP_ARGS(vma) -); - DEFINE_EVENT(xe_vma, xe_vma_bind, TP_PROTO(struct xe_vma *vma), TP_ARGS(vma) @@ -237,6 +232,11 @@ DEFINE_EVENT(xe_vm, xe_vm_rebind_worker_exit, TP_ARGS(vm) ); +DEFINE_EVENT(xe_vm, xe_vm_ops_fail, + TP_PROTO(struct xe_vm *vm), + TP_ARGS(vm) +); + #endif /* This part must be outside protection */ diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 73cc6b0efcef..5232856cc3fb 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -2481,6 +2481,38 @@ static int vm_bind_ioctl_ops_lock_and_prep(struct drm_exec *exec, return 0; } +static void op_trace(struct xe_vma_op *op) +{ + switch (op->base.op) { + case DRM_GPUVA_OP_MAP: + trace_xe_vma_bind(op->map.vma); + break; + case DRM_GPUVA_OP_REMAP: + trace_xe_vma_unbind(gpuva_to_vma(op->base.remap.unmap->va)); + if (op->remap.prev) + trace_xe_vma_bind(op->remap.prev); + if (op->remap.next) + trace_xe_vma_bind(op->remap.next); + break; + case DRM_GPUVA_OP_UNMAP: + trace_xe_vma_unbind(gpuva_to_vma(op->base.unmap.va)); + break; + case DRM_GPUVA_OP_PREFETCH: + trace_xe_vma_bind(gpuva_to_vma(op->base.prefetch.va)); + break; + default: + XE_WARN_ON("NOT POSSIBLE"); + } +} + +static void trace_xe_vm_ops_execute(struct xe_vma_ops *vops) +{ + struct xe_vma_op *op; + + list_for_each_entry(op, &vops->list, link) + op_trace(op); +} + static int vm_ops_setup_tile_args(struct xe_vm *vm, struct xe_vma_ops *vops) { struct xe_exec_queue *q = vops->q; @@ -2524,8 +2556,10 @@ static struct dma_fence *ops_execute(struct xe_vm *vm, if (number_tiles > 1) { fences = kmalloc_array(number_tiles, sizeof(*fences), GFP_KERNEL); - if (!fences) - return ERR_PTR(-ENOMEM); + if (!fences) { + fence = ERR_PTR(-ENOMEM); + goto err_trace; + } } for_each_tile(tile, vm->xe, id) { @@ -2539,6 +2573,8 @@ static struct dma_fence *ops_execute(struct xe_vm *vm, } } + trace_xe_vm_ops_execute(vops); + for_each_tile(tile, vm->xe, id) { if (!vops->pt_update_ops[id].num_ops) continue; @@ -2585,6 +2621,8 @@ err_out: kfree(fences); kfree(cf); +err_trace: + trace_xe_vm_ops_fail(vm); return fence; } -- cgit v1.2.3 From a708f6501c692551e3d4ea618c44021f436730d9 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Wed, 3 Jul 2024 21:16:51 -0700 Subject: drm/xe: Update PT layer with better error handling Update PT layer so if a memory allocation for a PTE fails the error can be propagated to the user without requiring the VM to be killed. v5: - change return value invalidation_fence_init to void (Matthew Auld) v7: - Invert i,j usage in two places (Matthew Auld) - s/0/NULL (Matthew Auld) - Don't ignore return value of xe_pt_new_shared (Matthew Auld) - Don't check for NULL in xe_pt_entry (Matthew Auld) Signed-off-by: Matthew Brost Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20240704041652.272920-7-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_pt.c | 232 ++++++++++++++++++++++++++++++++------------- 1 file changed, 167 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index f46f46d46819..44356903accb 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -846,19 +846,27 @@ xe_vm_populate_pgtable(struct xe_migrate_pt_update *pt_update, struct xe_tile *t } } -static void xe_pt_abort_bind(struct xe_vma *vma, - struct xe_vm_pgtable_update *entries, - u32 num_entries) +static void xe_pt_cancel_bind(struct xe_vma *vma, + struct xe_vm_pgtable_update *entries, + u32 num_entries) { u32 i, j; for (i = 0; i < num_entries; i++) { - if (!entries[i].pt_entries) + struct xe_pt *pt = entries[i].pt; + + if (!pt) continue; - for (j = 0; j < entries[i].qwords; j++) - xe_pt_destroy(entries[i].pt_entries[j].pt, xe_vma_vm(vma)->flags, NULL); + if (pt->level) { + for (j = 0; j < entries[i].qwords; j++) + xe_pt_destroy(entries[i].pt_entries[j].pt, + xe_vma_vm(vma)->flags, NULL); + } + kfree(entries[i].pt_entries); + entries[i].pt_entries = NULL; + entries[i].qwords = 0; } } @@ -874,10 +882,61 @@ static void xe_pt_commit_locks_assert(struct xe_vma *vma) xe_vm_assert_held(vm); } -static void xe_pt_commit_bind(struct xe_vma *vma, - struct xe_vm_pgtable_update *entries, - u32 num_entries, bool rebind, - struct llist_head *deferred) +static void xe_pt_commit(struct xe_vma *vma, + struct xe_vm_pgtable_update *entries, + u32 num_entries, struct llist_head *deferred) +{ + u32 i, j; + + xe_pt_commit_locks_assert(vma); + + for (i = 0; i < num_entries; i++) { + struct xe_pt *pt = entries[i].pt; + + if (!pt->level) + continue; + + for (j = 0; j < entries[i].qwords; j++) { + struct xe_pt *oldpte = entries[i].pt_entries[j].pt; + + xe_pt_destroy(oldpte, xe_vma_vm(vma)->flags, deferred); + } + } +} + +static void xe_pt_abort_bind(struct xe_vma *vma, + struct xe_vm_pgtable_update *entries, + u32 num_entries, bool rebind) +{ + int i, j; + + xe_pt_commit_locks_assert(vma); + + for (i = num_entries - 1; i >= 0; --i) { + struct xe_pt *pt = entries[i].pt; + struct xe_pt_dir *pt_dir; + + if (!rebind) + pt->num_live -= entries[i].qwords; + + if (!pt->level) + continue; + + pt_dir = as_xe_pt_dir(pt); + for (j = 0; j < entries[i].qwords; j++) { + u32 j_ = j + entries[i].ofs; + struct xe_pt *newpte = xe_pt_entry(pt_dir, j_); + struct xe_pt *oldpte = entries[i].pt_entries[j].pt; + + pt_dir->children[j_] = oldpte ? &oldpte->base : 0; + xe_pt_destroy(newpte, xe_vma_vm(vma)->flags, NULL); + } + } +} + +static void xe_pt_commit_prepare_bind(struct xe_vma *vma, + struct xe_vm_pgtable_update *entries, + u32 num_entries, bool rebind) { u32 i, j; @@ -897,12 +956,13 @@ static void xe_pt_commit_bind(struct xe_vma *vma, for (j = 0; j < entries[i].qwords; j++) { u32 j_ = j + entries[i].ofs; struct xe_pt *newpte = entries[i].pt_entries[j].pt; + struct xe_pt *oldpte = NULL; if (xe_pt_entry(pt_dir, j_)) - xe_pt_destroy(xe_pt_entry(pt_dir, j_), - xe_vma_vm(vma)->flags, deferred); + oldpte = xe_pt_entry(pt_dir, j_); pt_dir->children[j_] = &newpte->base; + entries[i].pt_entries[j].pt = oldpte; } } } @@ -926,8 +986,6 @@ xe_pt_prepare_bind(struct xe_tile *tile, struct xe_vma *vma, err = xe_pt_stage_bind(tile, vma, entries, num_entries); if (!err) xe_tile_assert(tile, *num_entries); - else /* abort! */ - xe_pt_abort_bind(vma, entries, *num_entries); return err; } @@ -1305,10 +1363,10 @@ static void invalidation_fence_work_func(struct work_struct *w) ifence->end, ifence->asid); } -static int invalidation_fence_init(struct xe_gt *gt, - struct invalidation_fence *ifence, - struct dma_fence *fence, - u64 start, u64 end, u32 asid) +static void invalidation_fence_init(struct xe_gt *gt, + struct invalidation_fence *ifence, + struct dma_fence *fence, + u64 start, u64 end, u32 asid) { int ret; @@ -1340,8 +1398,6 @@ static int invalidation_fence_init(struct xe_gt *gt, } xe_gt_assert(gt, !ret || ret == -ENOENT); - - return ret && ret != -ENOENT ? ret : 0; } struct xe_pt_stage_unbind_walk { @@ -1426,6 +1482,7 @@ xe_pt_stage_unbind_post_descend(struct xe_ptw *parent, pgoff_t offset, struct xe_pt *xe_child = container_of(*child, typeof(*xe_child), base); pgoff_t end_offset; u64 size = 1ull << walk->shifts[--level]; + int err; if (!IS_ALIGNED(addr, size)) addr = xe_walk->modified_start; @@ -1441,7 +1498,10 @@ xe_pt_stage_unbind_post_descend(struct xe_ptw *parent, pgoff_t offset, &end_offset)) return 0; - (void)xe_pt_new_shared(&xe_walk->wupd, xe_child, offset, false); + err = xe_pt_new_shared(&xe_walk->wupd, xe_child, offset, true); + if (err) + return err; + xe_walk->wupd.updates[level].update->qwords = end_offset - offset; return 0; @@ -1509,32 +1569,54 @@ xe_migrate_clear_pgtable_callback(struct xe_migrate_pt_update *pt_update, memset64(ptr, empty, num_qwords); } +static void xe_pt_abort_unbind(struct xe_vma *vma, + struct xe_vm_pgtable_update *entries, + u32 num_entries) +{ + int i, j; + + xe_pt_commit_locks_assert(vma); + + for (i = num_entries - 1; i >= 0; --i) { + struct xe_vm_pgtable_update *entry = &entries[i]; + struct xe_pt *pt = entry->pt; + struct xe_pt_dir *pt_dir = as_xe_pt_dir(pt); + + pt->num_live += entry->qwords; + + if (!pt->level) + continue; + + for (j = entry->ofs; j < entry->ofs + entry->qwords; j++) + pt_dir->children[i] = + entries[i].pt_entries[j - entry->ofs].pt ? + &entries[i].pt_entries[j - entry->ofs].pt->base : NULL; + } +} + static void -xe_pt_commit_unbind(struct xe_vma *vma, - struct xe_vm_pgtable_update *entries, u32 num_entries, - struct llist_head *deferred) +xe_pt_commit_prepare_unbind(struct xe_vma *vma, + struct xe_vm_pgtable_update *entries, + u32 num_entries) { - u32 j; + int i, j; xe_pt_commit_locks_assert(vma); - for (j = 0; j < num_entries; ++j) { - struct xe_vm_pgtable_update *entry = &entries[j]; + for (i = 0; i < num_entries; ++i) { + struct xe_vm_pgtable_update *entry = &entries[i]; struct xe_pt *pt = entry->pt; + struct xe_pt_dir *pt_dir; pt->num_live -= entry->qwords; - if (pt->level) { - struct xe_pt_dir *pt_dir = as_xe_pt_dir(pt); - u32 i; - - for (i = entry->ofs; i < entry->ofs + entry->qwords; - i++) { - if (xe_pt_entry(pt_dir, i)) - xe_pt_destroy(xe_pt_entry(pt_dir, i), - xe_vma_vm(vma)->flags, deferred); + if (!pt->level) + continue; - pt_dir->children[i] = NULL; - } + pt_dir = as_xe_pt_dir(pt); + for (j = entry->ofs; j < entry->ofs + entry->qwords; j++) { + entry->pt_entries[j - entry->ofs].pt = + xe_pt_entry(pt_dir, j); + pt_dir->children[j] = NULL; } } } @@ -1580,7 +1662,6 @@ static int bind_op_prepare(struct xe_vm *vm, struct xe_tile *tile, { u32 current_op = pt_update_ops->current_op; struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[current_op]; - struct llist_head *deferred = &pt_update_ops->deferred; int err; xe_bo_assert_held(xe_vma_bo(vma)); @@ -1628,11 +1709,12 @@ static int bind_op_prepare(struct xe_vm *vm, struct xe_tile *tile, /* We bump also if batch_invalidate_tlb is true */ vm->tlb_flush_seqno++; - /* FIXME: Don't commit right away */ vma->tile_staged |= BIT(tile->id); pt_op->vma = vma; - xe_pt_commit_bind(vma, pt_op->entries, pt_op->num_entries, - pt_op->rebind, deferred); + xe_pt_commit_prepare_bind(vma, pt_op->entries, + pt_op->num_entries, pt_op->rebind); + } else { + xe_pt_cancel_bind(vma, pt_op->entries, pt_op->num_entries); } return err; @@ -1644,7 +1726,6 @@ static int unbind_op_prepare(struct xe_tile *tile, { u32 current_op = pt_update_ops->current_op; struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[current_op]; - struct llist_head *deferred = &pt_update_ops->deferred; int err; if (!((vma->tile_present | vma->tile_staged) & BIT(tile->id))) @@ -1680,9 +1761,7 @@ static int unbind_op_prepare(struct xe_tile *tile, pt_update_ops->needs_userptr_lock |= xe_vma_is_userptr(vma); pt_update_ops->needs_invalidation = true; - /* FIXME: Don't commit right away */ - xe_pt_commit_unbind(vma, pt_op->entries, pt_op->num_entries, - deferred); + xe_pt_commit_prepare_unbind(vma, pt_op->entries, pt_op->num_entries); return 0; } @@ -1903,7 +1982,7 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops) struct invalidation_fence *ifence = NULL; struct xe_range_fence *rfence; struct xe_vma_op *op; - int err = 0; + int err = 0, i; struct xe_migrate_pt_update update = { .ops = pt_update_ops->needs_userptr_lock ? &userptr_migrate_ops : @@ -1923,8 +2002,10 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops) if (pt_update_ops->needs_invalidation) { ifence = kzalloc(sizeof(*ifence), GFP_KERNEL); - if (!ifence) - return ERR_PTR(-ENOMEM); + if (!ifence) { + err = -ENOMEM; + goto kill_vm_tile1; + } } rfence = kzalloc(sizeof(*rfence), GFP_KERNEL); @@ -1939,6 +2020,15 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops) goto free_rfence; } + /* Point of no return - VM killed if failure after this */ + for (i = 0; i < pt_update_ops->current_op; ++i) { + struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[i]; + + xe_pt_commit(pt_op->vma, pt_op->entries, + pt_op->num_entries, &pt_update_ops->deferred); + pt_op->vma = NULL; /* skip in xe_pt_update_ops_abort */ + } + if (xe_range_fence_insert(&vm->rftree[tile->id], rfence, &xe_range_fence_kfree_ops, pt_update_ops->start, @@ -1947,12 +2037,9 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops) /* tlb invalidation must be done before signaling rebind */ if (ifence) { - err = invalidation_fence_init(tile->primary_gt, ifence, fence, - pt_update_ops->start, - pt_update_ops->last, - vm->usm.asid); - if (err) - goto put_fence; + invalidation_fence_init(tile->primary_gt, ifence, fence, + pt_update_ops->start, + pt_update_ops->last, vm->usm.asid); fence = &ifence->base.base; } @@ -1969,14 +2056,13 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops) return fence; -put_fence: - if (pt_update_ops->needs_userptr_lock) - up_read(&vm->userptr.notifier_lock); - dma_fence_put(fence); free_rfence: kfree(rfence); free_ifence: kfree(ifence); +kill_vm_tile1: + if (err != -EAGAIN && tile->id) + xe_vm_kill(vops->vm, false); return ERR_PTR(err); } @@ -1997,12 +2083,10 @@ void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops) lockdep_assert_held(&vops->vm->lock); xe_vm_assert_held(vops->vm); - /* FIXME: Not 100% correct */ - for (i = 0; i < pt_update_ops->num_ops; ++i) { + for (i = 0; i < pt_update_ops->current_op; ++i) { struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[i]; - if (pt_op->bind) - xe_pt_free_bind(pt_op->entries, pt_op->num_entries); + xe_pt_free_bind(pt_op->entries, pt_op->num_entries); } xe_bo_put_commit(&vops->pt_update_ops[tile->id].deferred); } @@ -2016,10 +2100,28 @@ void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops) */ void xe_pt_update_ops_abort(struct xe_tile *tile, struct xe_vma_ops *vops) { + struct xe_vm_pgtable_update_ops *pt_update_ops = + &vops->pt_update_ops[tile->id]; + int i; + lockdep_assert_held(&vops->vm->lock); xe_vm_assert_held(vops->vm); - /* FIXME: Just kill VM for now + cleanup PTs */ + for (i = pt_update_ops->num_ops - 1; i >= 0; --i) { + struct xe_vm_pgtable_update_op *pt_op = + &pt_update_ops->ops[i]; + + if (!pt_op->vma || i >= pt_update_ops->current_op) + continue; + + if (pt_op->bind) + xe_pt_abort_bind(pt_op->vma, pt_op->entries, + pt_op->num_entries, + pt_op->rebind); + else + xe_pt_abort_unbind(pt_op->vma, pt_op->entries, + pt_op->num_entries); + } + xe_bo_put_commit(&vops->pt_update_ops[tile->id].deferred); - xe_vm_kill(vops->vm, false); } -- cgit v1.2.3 From 04e9c0ce19ac68afd8be7fd54772db3b0356cf75 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Wed, 3 Jul 2024 21:16:52 -0700 Subject: drm/xe: Add VM bind IOCTL error injection Add VM bind IOCTL error injection which steals MSB of the bind flags field which if set injects errors at various points in the VM bind IOCTL. Intended to validate error paths. Enabled by CONFIG_DRM_XE_DEBUG. v4: - Change define layout (Jonathan) Signed-off-by: Matthew Brost Reviewed-by: Jonathan Cavitt Link: https://patchwork.freedesktop.org/patch/msgid/20240704041652.272920-8-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_device_types.h | 12 ++++++++++++ drivers/gpu/drm/xe/xe_pt.c | 12 ++++++++++++ drivers/gpu/drm/xe/xe_vm.c | 24 +++++++++++++++++++++++- drivers/gpu/drm/xe/xe_vm_types.h | 14 ++++++++++++++ 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 3bca6d344744..f0cf9020e463 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -23,6 +23,10 @@ #include "xe_sriov_types.h" #include "xe_step_types.h" +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG) +#define TEST_VM_OPS_ERROR +#endif + #if IS_ENABLED(CONFIG_DRM_XE_DISPLAY) #include "soc/intel_pch.h" #include "intel_display_core.h" @@ -477,6 +481,14 @@ struct xe_device { int mode; } wedged; +#ifdef TEST_VM_OPS_ERROR + /** + * @vm_inject_error_position: inject errors at different places in VM + * bind IOCTL based on this value + */ + u8 vm_inject_error_position; +#endif + /* private: */ #if IS_ENABLED(CONFIG_DRM_XE_DISPLAY) diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index 44356903accb..f391de908033 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -1860,6 +1860,12 @@ int xe_pt_update_ops_prepare(struct xe_tile *tile, struct xe_vma_ops *vops) xe_tile_assert(tile, pt_update_ops->current_op <= pt_update_ops->num_ops); +#ifdef TEST_VM_OPS_ERROR + if (vops->inject_error && + vops->vm->xe->vm_inject_error_position == FORCE_OP_ERROR_PREPARE) + return -ENOSPC; +#endif + return 0; } @@ -2000,6 +2006,12 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops) return dma_fence_get_stub(); } +#ifdef TEST_VM_OPS_ERROR + if (vops->inject_error && + vm->xe->vm_inject_error_position == FORCE_OP_ERROR_RUN) + return ERR_PTR(-ENOSPC); +#endif + if (pt_update_ops->needs_invalidation) { ifence = kzalloc(sizeof(*ifence), GFP_KERNEL); if (!ifence) { diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 5232856cc3fb..cf3aea5d8cdc 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -2478,6 +2478,12 @@ static int vm_bind_ioctl_ops_lock_and_prep(struct drm_exec *exec, return err; } +#ifdef TEST_VM_OPS_ERROR + if (vops->inject_error && + vm->xe->vm_inject_error_position == FORCE_OP_ERROR_LOCK) + return -ENOSPC; +#endif + return 0; } @@ -2714,11 +2720,18 @@ unlock: return err; } -#define SUPPORTED_FLAGS \ +#define SUPPORTED_FLAGS_STUB \ (DRM_XE_VM_BIND_FLAG_READONLY | \ DRM_XE_VM_BIND_FLAG_IMMEDIATE | \ DRM_XE_VM_BIND_FLAG_NULL | \ DRM_XE_VM_BIND_FLAG_DUMPABLE) + +#ifdef TEST_VM_OPS_ERROR +#define SUPPORTED_FLAGS (SUPPORTED_FLAGS_STUB | FORCE_OP_ERROR) +#else +#define SUPPORTED_FLAGS SUPPORTED_FLAGS_STUB +#endif + #define XE_64K_PAGE_MASK 0xffffull #define ALL_DRM_XE_SYNCS_FLAGS (DRM_XE_SYNCS_FLAG_WAIT_FOR_OP) @@ -3066,6 +3079,15 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) err = vm_bind_ioctl_ops_parse(vm, ops[i], &vops); if (err) goto unwind_ops; + +#ifdef TEST_VM_OPS_ERROR + if (flags & FORCE_OP_ERROR) { + vops.inject_error = true; + vm->xe->vm_inject_error_position = + (vm->xe->vm_inject_error_position + 1) % + FORCE_OP_ERROR_COUNT; + } +#endif } /* Nothing to do */ diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h index 27d651093d30..7f9a303e51d8 100644 --- a/drivers/gpu/drm/xe/xe_vm_types.h +++ b/drivers/gpu/drm/xe/xe_vm_types.h @@ -23,6 +23,16 @@ struct xe_user_fence; struct xe_vm; struct xe_vm_pgtable_update_op; +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG) +#define TEST_VM_OPS_ERROR +#define FORCE_OP_ERROR BIT(31) + +#define FORCE_OP_ERROR_LOCK 0 +#define FORCE_OP_ERROR_PREPARE 1 +#define FORCE_OP_ERROR_RUN 2 +#define FORCE_OP_ERROR_COUNT 3 +#endif + #define XE_VMA_READ_ONLY DRM_GPUVA_USERBITS #define XE_VMA_DESTROYED (DRM_GPUVA_USERBITS << 1) #define XE_VMA_ATOMIC_PTE_BIT (DRM_GPUVA_USERBITS << 2) @@ -359,6 +369,10 @@ struct xe_vma_ops { u32 num_syncs; /** @pt_update_ops: page table update operations */ struct xe_vm_pgtable_update_ops pt_update_ops[XE_MAX_TILES_PER_DEVICE]; +#ifdef TEST_VM_OPS_ERROR + /** @inject_error: inject error to test error handling */ + bool inject_error; +#endif }; #endif -- cgit v1.2.3 From 9dae9751c7b0086963f5cbb82424b5e4cf58f123 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 2 Jul 2024 20:37:02 +0200 Subject: drm/xe: Fix register definition order in xe_regs.h Swap XEHP_CLOCK_GATE_DIS(0x101014) with GU_DEBUG(x101018). Signed-off-by: Michal Wajdeczko Reviewed-by: Matt Roper Reviewed-by: Himal Prasad Ghimiray Link: https://patchwork.freedesktop.org/patch/msgid/20240702183704.1022-2-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/regs/xe_regs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/regs/xe_regs.h b/drivers/gpu/drm/xe/regs/xe_regs.h index 23e33ec84902..23ecba38ed41 100644 --- a/drivers/gpu/drm/xe/regs/xe_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_regs.h @@ -24,12 +24,12 @@ #define LMEM_INIT REG_BIT(7) #define DRIVERFLR REG_BIT(31) -#define GU_DEBUG XE_REG(0x101018) -#define DRIVERFLR_STATUS REG_BIT(31) - #define XEHP_CLOCK_GATE_DIS XE_REG(0x101014) #define SGSI_SIDECLK_DIS REG_BIT(17) +#define GU_DEBUG XE_REG(0x101018) +#define DRIVERFLR_STATUS REG_BIT(31) + #define XEHP_MTCFG_ADDR XE_REG(0x101800) #define TILE_COUNT REG_GENMASK(15, 8) -- cgit v1.2.3 From 466a6c3855cf00653c14a92a6e9f8ae50077b77d Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 2 Jul 2024 20:37:03 +0200 Subject: drm/xe: Kill regs/xe_sriov_regs.h There is no real benefit to maintain a separate file. The register definitions related to SR-IOV can be placed in existing headers. Signed-off-by: Michal Wajdeczko Reviewed-by: Matt Roper Reviewed-by: Himal Prasad Ghimiray Link: https://patchwork.freedesktop.org/patch/msgid/20240702183704.1022-3-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/regs/xe_gt_regs.h | 6 ++++++ drivers/gpu/drm/xe/regs/xe_regs.h | 6 ++++++ drivers/gpu/drm/xe/regs/xe_sriov_regs.h | 23 ----------------------- drivers/gpu/drm/xe/xe_gt_sriov_pf.c | 2 +- drivers/gpu/drm/xe/xe_lmtt.c | 2 +- drivers/gpu/drm/xe/xe_sriov.c | 2 +- 6 files changed, 15 insertions(+), 26 deletions(-) delete mode 100644 drivers/gpu/drm/xe/regs/xe_sriov_regs.h diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h index d44564bad009..141d0e0faa21 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -88,6 +88,8 @@ #define VE1_AUX_INV XE_REG(0x42b8) #define AUX_INV REG_BIT(0) +#define XE2_LMEM_CFG XE_REG(0x48b0) + #define XEHP_TILE_ADDR_RANGE(_idx) XE_REG_MCR(0x4900 + (_idx) * 4) #define XEHP_FLAT_CCS_BASE_ADDR XE_REG_MCR(0x4910) #define XEHP_FLAT_CCS_PTR REG_GENMASK(31, 8) @@ -395,6 +397,10 @@ #define INVALIDATION_BROADCAST_MODE_DIS REG_BIT(12) #define GLOBAL_INVALIDATION_MODE REG_BIT(2) +#define LMEM_CFG XE_REG(0xcf58) +#define LMEM_EN REG_BIT(31) +#define LMTT_DIR_PTR REG_GENMASK(30, 0) /* in multiples of 64KB */ + #define HALF_SLICE_CHICKEN5 XE_REG_MCR(0xe188, XE_REG_OPTION_MASKED) #define DISABLE_SAMPLE_G_PERFORMANCE REG_BIT(0) diff --git a/drivers/gpu/drm/xe/regs/xe_regs.h b/drivers/gpu/drm/xe/regs/xe_regs.h index 23ecba38ed41..55bf47c99016 100644 --- a/drivers/gpu/drm/xe/regs/xe_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_regs.h @@ -30,6 +30,9 @@ #define GU_DEBUG XE_REG(0x101018) #define DRIVERFLR_STATUS REG_BIT(31) +#define VIRTUAL_CTRL_REG XE_REG(0x10108c) +#define GUEST_GTT_UPDATE_EN REG_BIT(8) + #define XEHP_MTCFG_ADDR XE_REG(0x101800) #define TILE_COUNT REG_GENMASK(15, 8) @@ -66,6 +69,9 @@ #define DISPLAY_IRQ REG_BIT(16) #define GT_DW_IRQ(x) REG_BIT(x) +#define VF_CAP_REG XE_REG(0x1901f8, XE_REG_OPTION_VF) +#define VF_CAP REG_BIT(0) + #define PVC_RP_STATE_CAP XE_REG(0x281014) #endif diff --git a/drivers/gpu/drm/xe/regs/xe_sriov_regs.h b/drivers/gpu/drm/xe/regs/xe_sriov_regs.h deleted file mode 100644 index 017b4ddd1ecf..000000000000 --- a/drivers/gpu/drm/xe/regs/xe_sriov_regs.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#ifndef _REGS_XE_SRIOV_REGS_H_ -#define _REGS_XE_SRIOV_REGS_H_ - -#include "regs/xe_reg_defs.h" - -#define XE2_LMEM_CFG XE_REG(0x48b0) - -#define LMEM_CFG XE_REG(0xcf58) -#define LMEM_EN REG_BIT(31) -#define LMTT_DIR_PTR REG_GENMASK(30, 0) /* in multiples of 64KB */ - -#define VIRTUAL_CTRL_REG XE_REG(0x10108c) -#define GUEST_GTT_UPDATE_EN REG_BIT(8) - -#define VF_CAP_REG XE_REG(0x1901f8, XE_REG_OPTION_VF) -#define VF_CAP REG_BIT(0) - -#endif diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c index 9dbba9ab7a9a..ef239440963c 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c @@ -5,7 +5,7 @@ #include -#include "regs/xe_sriov_regs.h" +#include "regs/xe_regs.h" #include "xe_gt_sriov_pf.h" #include "xe_gt_sriov_pf_config.h" diff --git a/drivers/gpu/drm/xe/xe_lmtt.c b/drivers/gpu/drm/xe/xe_lmtt.c index 418661a88918..c5fdb36b6d33 100644 --- a/drivers/gpu/drm/xe/xe_lmtt.c +++ b/drivers/gpu/drm/xe/xe_lmtt.c @@ -7,7 +7,7 @@ #include -#include "regs/xe_sriov_regs.h" +#include "regs/xe_gt_regs.h" #include "xe_assert.h" #include "xe_bo.h" diff --git a/drivers/gpu/drm/xe/xe_sriov.c b/drivers/gpu/drm/xe/xe_sriov.c index a274a5fb1401..5a1d65e4f19f 100644 --- a/drivers/gpu/drm/xe/xe_sriov.c +++ b/drivers/gpu/drm/xe/xe_sriov.c @@ -5,7 +5,7 @@ #include -#include "regs/xe_sriov_regs.h" +#include "regs/xe_regs.h" #include "xe_assert.h" #include "xe_device.h" -- cgit v1.2.3 From 3078d9c8b6a0939bc732fd1c36ef86c0178127dd Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 2 Jul 2024 20:37:04 +0200 Subject: drm/xe: Use VF_CAP_REG for device wmb To force a write barrier on the device memory, we write to the SOFTWARE_FLAGS_SPR33 register, but this particular register was selected because it was one of the writable and unused register. Since a write barrier should also work if we use the read-only register, switch to VF_CAP_REG register that is also marked as accessible for VFs. While at it, add simple kernel-doc for xe_device_wmb() function. Signed-off-by: Michal Wajdeczko Cc: Matt Roper Reviewed-by: Matt Roper Reviewed-by: Himal Prasad Ghimiray Link: https://patchwork.freedesktop.org/patch/msgid/20240702183704.1022-4-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_device.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 03492fbcb8fb..db513175b29e 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -744,13 +744,22 @@ void xe_device_shutdown(struct xe_device *xe) { } +/** + * xe_device_wmb() - Device specific write memory barrier + * @xe: the &xe_device + * + * While wmb() is sufficient for a barrier if we use system memory, on discrete + * platforms with device memory we additionally need to issue a register write. + * Since it doesn't matter which register we write to, use the read-only VF_CAP + * register that is also marked as accessible by the VFs. + */ void xe_device_wmb(struct xe_device *xe) { struct xe_gt *gt = xe_root_mmio_gt(xe); wmb(); if (IS_DGFX(xe)) - xe_mmio_write32(gt, SOFTWARE_FLAGS_SPR33, 0); + xe_mmio_write32(gt, VF_CAP_REG, 0); } /** -- cgit v1.2.3 From 1fea3e2656595fe8a9d9485aaae1bfa3a14f2d31 Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Wed, 3 Jul 2024 15:13:41 -0400 Subject: MAINTAINERS: add an entry for AMD DC DML We want all DML changes to be reviewed by Chaitanya or Jun. So, add an entry for DML to MAINTAINERS. Suggested-by: Rodrigo Siqueira Acked-by: Alex Deucher Signed-off-by: Hamza Mahfooz Link: https://patchwork.freedesktop.org/patch/msgid/20240703191341.239296-1-hamza.mahfooz@amd.com --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index f2d8bc44bb52..71b739b40921 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1000,6 +1000,13 @@ S: Supported T: git https://gitlab.freedesktop.org/agd5f/linux.git F: drivers/gpu/drm/amd/display/ +AMD DISPLAY CORE - DML +M: Chaitanya Dhere +M: Jun Lei +S: Supported +F: drivers/gpu/drm/amd/display/dc/dml/ +F: drivers/gpu/drm/amd/display/dc/dml2/ + AMD FAM15H PROCESSOR POWER MONITORING DRIVER M: Huang Rui L: linux-hwmon@vger.kernel.org -- cgit v1.2.3 From 01570b446939c3538b1aa3d059837f49fa14a3ae Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Wed, 3 Jul 2024 13:43:38 +0100 Subject: drm/xe/bmg: implement Wa_16023588340 This involves enabling l2 caching of host side memory access to VRAM through the CPU BAR. The main fallout here is with display since VRAM writes from CPU can now be cached in GPU l2, and display is never coherent with caches, so needs various manual flushing. In the case of fbc we disable it due to complications in getting this to work correctly (in a later patch). Signed-off-by: Matthew Auld Cc: Jonathan Cavitt Cc: Matt Roper Cc: Lucas De Marchi Cc: Vinod Govindapillai Reviewed-by: Jonathan Cavitt Link: https://patchwork.freedesktop.org/patch/msgid/20240703124338.208220-3-matthew.auld@intel.com --- drivers/gpu/drm/xe/Makefile | 2 ++ drivers/gpu/drm/xe/display/xe_dsb_buffer.c | 8 +++++ drivers/gpu/drm/xe/display/xe_fb_pin.c | 3 ++ drivers/gpu/drm/xe/regs/xe_gt_regs.h | 8 +++++ drivers/gpu/drm/xe/xe_device.c | 30 +++++++++++++++++ drivers/gpu/drm/xe/xe_device.h | 1 + drivers/gpu/drm/xe/xe_gt.c | 54 ++++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_pat.c | 11 +++++- drivers/gpu/drm/xe/xe_wa_oob.rules | 1 + 9 files changed, 117 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 628c245c4822..e97c9da451b3 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -25,12 +25,14 @@ $(obj)/generated/%_wa_oob.c $(obj)/generated/%_wa_oob.h: $(obj)/xe_gen_wa_oob \ uses_generated_oob := \ $(obj)/xe_ggtt.o \ + $(obj)/xe_device.o \ $(obj)/xe_gsc.o \ $(obj)/xe_gt.o \ $(obj)/xe_guc.o \ $(obj)/xe_guc_ads.o \ $(obj)/xe_guc_pc.o \ $(obj)/xe_migrate.o \ + $(obj)/xe_pat.o \ $(obj)/xe_ring_ops.o \ $(obj)/xe_vm.o \ $(obj)/xe_wa.o \ diff --git a/drivers/gpu/drm/xe/display/xe_dsb_buffer.c b/drivers/gpu/drm/xe/display/xe_dsb_buffer.c index 9e860c61f4b3..ccd0d87d438a 100644 --- a/drivers/gpu/drm/xe/display/xe_dsb_buffer.c +++ b/drivers/gpu/drm/xe/display/xe_dsb_buffer.c @@ -7,6 +7,8 @@ #include "intel_display_types.h" #include "intel_dsb_buffer.h" #include "xe_bo.h" +#include "xe_device.h" +#include "xe_device_types.h" #include "xe_gt.h" u32 intel_dsb_buffer_ggtt_offset(struct intel_dsb_buffer *dsb_buf) @@ -16,7 +18,10 @@ u32 intel_dsb_buffer_ggtt_offset(struct intel_dsb_buffer *dsb_buf) void intel_dsb_buffer_write(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val) { + struct xe_device *xe = dsb_buf->vma->bo->tile->xe; + iosys_map_wr(&dsb_buf->vma->bo->vmap, idx * 4, u32, val); + xe_device_l2_flush(xe); } u32 intel_dsb_buffer_read(struct intel_dsb_buffer *dsb_buf, u32 idx) @@ -26,9 +31,12 @@ u32 intel_dsb_buffer_read(struct intel_dsb_buffer *dsb_buf, u32 idx) void intel_dsb_buffer_memset(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val, size_t size) { + struct xe_device *xe = dsb_buf->vma->bo->tile->xe; + WARN_ON(idx > (dsb_buf->buf_size - size) / sizeof(*dsb_buf->cmd_buf)); iosys_map_memset(&dsb_buf->vma->bo->vmap, idx * 4, val, size); + xe_device_l2_flush(xe); } bool intel_dsb_buffer_create(struct intel_crtc *crtc, struct intel_dsb_buffer *dsb_buf, size_t size) diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index d270bcd11686..ea83d180ab70 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -10,6 +10,7 @@ #include "intel_fb.h" #include "intel_fb_pin.h" #include "xe_bo.h" +#include "xe_device.h" #include "xe_ggtt.h" #include "xe_gt.h" #include "xe_pm.h" @@ -304,6 +305,8 @@ static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb, if (ret) goto err_unpin; + /* Ensure DPT writes are flushed */ + xe_device_l2_flush(xe); return vma; err_unpin: diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h index 141d0e0faa21..8a94a94d2267 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -80,6 +80,9 @@ #define LE_CACHEABILITY_MASK REG_GENMASK(1, 0) #define LE_CACHEABILITY(value) REG_FIELD_PREP(LE_CACHEABILITY_MASK, value) +#define XE2_GAMREQSTRM_CTRL XE_REG(0x4194) +#define CG_DIS_CNTLBUS REG_BIT(6) + #define CCS_AUX_INV XE_REG(0x4208) #define VD0_AUX_INV XE_REG(0x4218) @@ -374,6 +377,11 @@ #define XEHPC_L3CLOS_MASK(i) XE_REG_MCR(0xb194 + (i) * 8) +#define XE2_GLOBAL_INVAL XE_REG(0xb404) + +#define SCRATCH1LPFC XE_REG(0xb474) +#define EN_L3_RW_CCS_CACHE_FLUSH REG_BIT(0) + #define XE2LPM_L3SQCREG5 XE_REG_MCR(0xb658) #define XE2_TDF_CTRL XE_REG(0xb418) diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index db513175b29e..64aea962afd5 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -54,6 +54,9 @@ #include "xe_vm.h" #include "xe_vram.h" #include "xe_wait_user_fence.h" +#include "xe_wa.h" + +#include static int xe_file_open(struct drm_device *dev, struct drm_file *file) { @@ -788,6 +791,11 @@ void xe_device_td_flush(struct xe_device *xe) if (!IS_DGFX(xe) || GRAPHICS_VER(xe) < 20) return; + if (XE_WA(xe_root_mmio_gt(xe), 16023588340)) { + xe_device_l2_flush(xe); + return; + } + for_each_gt(gt, xe, id) { if (xe_gt_is_media_type(gt)) continue; @@ -811,6 +819,28 @@ void xe_device_td_flush(struct xe_device *xe) } } +void xe_device_l2_flush(struct xe_device *xe) +{ + struct xe_gt *gt; + int err; + + gt = xe_root_mmio_gt(xe); + + if (!XE_WA(gt, 16023588340)) + return; + + err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); + if (err) + return; + + xe_mmio_write32(gt, XE2_GLOBAL_INVAL, 0x1); + + if (xe_mmio_wait32(gt, XE2_GLOBAL_INVAL, 0x1, 0x0, 150, NULL, true)) + xe_gt_err_once(gt, "Global invalidation timeout\n"); + + xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); +} + u32 xe_device_ccs_bytes(struct xe_device *xe, u64 size) { return xe_device_has_flat_ccs(xe) ? diff --git a/drivers/gpu/drm/xe/xe_device.h b/drivers/gpu/drm/xe/xe_device.h index bb07f5669dbb..0a2a3e7fd402 100644 --- a/drivers/gpu/drm/xe/xe_device.h +++ b/drivers/gpu/drm/xe/xe_device.h @@ -162,6 +162,7 @@ u64 xe_device_canonicalize_addr(struct xe_device *xe, u64 address); u64 xe_device_uncanonicalize_addr(struct xe_device *xe, u64 address); void xe_device_td_flush(struct xe_device *xe); +void xe_device_l2_flush(struct xe_device *xe); static inline bool xe_device_wedged(struct xe_device *xe) { diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index 0ba2e2d0289b..ce8994b808fe 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -11,6 +11,8 @@ #include #include +#include + #include "instructions/xe_gfxpipe_commands.h" #include "instructions/xe_mi_commands.h" #include "regs/xe_gt_regs.h" @@ -95,6 +97,51 @@ void xe_gt_sanitize(struct xe_gt *gt) gt->uc.guc.submission_state.enabled = false; } +static void xe_gt_enable_host_l2_vram(struct xe_gt *gt) +{ + u32 reg; + int err; + + if (!XE_WA(gt, 16023588340)) + return; + + err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); + if (WARN_ON(err)) + return; + + if (!xe_gt_is_media_type(gt)) { + xe_mmio_write32(gt, SCRATCH1LPFC, EN_L3_RW_CCS_CACHE_FLUSH); + reg = xe_mmio_read32(gt, XE2_GAMREQSTRM_CTRL); + reg |= CG_DIS_CNTLBUS; + xe_mmio_write32(gt, XE2_GAMREQSTRM_CTRL, reg); + } + + xe_gt_mcr_multicast_write(gt, XEHPC_L3CLOS_MASK(3), 0x3); + xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); +} + +static void xe_gt_disable_host_l2_vram(struct xe_gt *gt) +{ + u32 reg; + int err; + + if (!XE_WA(gt, 16023588340)) + return; + + if (xe_gt_is_media_type(gt)) + return; + + err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); + if (WARN_ON(err)) + return; + + reg = xe_mmio_read32(gt, XE2_GAMREQSTRM_CTRL); + reg &= ~CG_DIS_CNTLBUS; + xe_mmio_write32(gt, XE2_GAMREQSTRM_CTRL, reg); + + xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); +} + /** * xe_gt_remove() - Clean up the GT structures before driver removal * @gt: the GT object @@ -111,6 +158,8 @@ void xe_gt_remove(struct xe_gt *gt) for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) xe_hw_fence_irq_finish(>->fence_irq[i]); + + xe_gt_disable_host_l2_vram(gt); } static void gt_reset_worker(struct work_struct *w); @@ -508,6 +557,7 @@ int xe_gt_init_hwconfig(struct xe_gt *gt) xe_gt_mcr_init_early(gt); xe_pat_init(gt); + xe_gt_enable_host_l2_vram(gt); err = xe_uc_init(>->uc); if (err) @@ -643,6 +693,8 @@ static int do_gt_restart(struct xe_gt *gt) xe_pat_init(gt); + xe_gt_enable_host_l2_vram(gt); + xe_gt_mcr_set_implicit_defaults(gt); xe_reg_sr_apply_mmio(>->reg_sr, gt); @@ -796,6 +848,8 @@ int xe_gt_suspend(struct xe_gt *gt) xe_gt_idle_disable_pg(gt); + xe_gt_disable_host_l2_vram(gt); + XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); xe_gt_dbg(gt, "suspended\n"); diff --git a/drivers/gpu/drm/xe/xe_pat.c b/drivers/gpu/drm/xe/xe_pat.c index 4ee32ee1cc88..722278cc23fc 100644 --- a/drivers/gpu/drm/xe/xe_pat.c +++ b/drivers/gpu/drm/xe/xe_pat.c @@ -7,6 +7,8 @@ #include +#include + #include "regs/xe_reg_defs.h" #include "xe_assert.h" #include "xe_device.h" @@ -15,6 +17,7 @@ #include "xe_gt_mcr.h" #include "xe_mmio.h" #include "xe_sriov.h" +#include "xe_wa.h" #define _PAT_ATS 0x47fc #define _PAT_INDEX(index) _PICK_EVEN_2RANGES(index, 8, \ @@ -382,7 +385,13 @@ void xe_pat_init_early(struct xe_device *xe) if (GRAPHICS_VER(xe) == 20) { xe->pat.ops = &xe2_pat_ops; xe->pat.table = xe2_pat_table; - xe->pat.n_entries = ARRAY_SIZE(xe2_pat_table); + + /* Wa_16023588340. XXX: Should use XE_WA */ + if (GRAPHICS_VERx100(xe) == 2001) + xe->pat.n_entries = 28; /* Disable CLOS3 */ + else + xe->pat.n_entries = ARRAY_SIZE(xe2_pat_table); + xe->pat.idx[XE_CACHE_NONE] = 3; xe->pat.idx[XE_CACHE_WT] = 15; xe->pat.idx[XE_CACHE_WB] = 2; diff --git a/drivers/gpu/drm/xe/xe_wa_oob.rules b/drivers/gpu/drm/xe/xe_wa_oob.rules index 26066beb4f6f..08f7336881e3 100644 --- a/drivers/gpu/drm/xe/xe_wa_oob.rules +++ b/drivers/gpu/drm/xe/xe_wa_oob.rules @@ -29,3 +29,4 @@ 13011645652 GRAPHICS_VERSION(2004) 22019338487 MEDIA_VERSION(2000) GRAPHICS_VERSION(2001) +16023588340 GRAPHICS_VERSION(2001) -- cgit v1.2.3 From c55f79f317ab428ae6d005965bc07e37496f209f Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Wed, 3 Jul 2024 13:43:39 +0100 Subject: drm/i915: disable fbc due to Wa_16023588340 On BMG-G21 we need to disable fbc due to complications around the WA. v2: - Try to handle with i915_drv.h and compat layer. (Rodrigo) v3: - For simplicity retreat back to the original design for now. - Drop the extra \ from the Makefile (Jani) Signed-off-by: Matthew Auld Cc: Jonathan Cavitt Cc: Matt Roper Cc: Lucas De Marchi Cc: Vinod Govindapillai Cc: Jani Nikula Cc: intel-gfx@lists.freedesktop.org Reviewed-by: Jonathan Cavitt Acked-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20240703124338.208220-4-matthew.auld@intel.com --- drivers/gpu/drm/i915/display/intel_display_wa.h | 8 ++++++++ drivers/gpu/drm/i915/display/intel_fbc.c | 6 ++++++ drivers/gpu/drm/xe/Makefile | 4 +++- drivers/gpu/drm/xe/display/xe_display_wa.c | 16 ++++++++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/xe/display/xe_display_wa.c diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.h b/drivers/gpu/drm/i915/display/intel_display_wa.h index 63201d09852c..be644ab6ae00 100644 --- a/drivers/gpu/drm/i915/display/intel_display_wa.h +++ b/drivers/gpu/drm/i915/display/intel_display_wa.h @@ -6,8 +6,16 @@ #ifndef __INTEL_DISPLAY_WA_H__ #define __INTEL_DISPLAY_WA_H__ +#include + struct drm_i915_private; void intel_display_wa_apply(struct drm_i915_private *i915); +#ifdef I915 +static inline bool intel_display_needs_wa_16023588340(struct drm_i915_private *i915) { return false; } +#else +bool intel_display_needs_wa_16023588340(struct drm_i915_private *i915); +#endif + #endif diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 67116c9f1464..8488f82143a4 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -56,6 +56,7 @@ #include "intel_display_device.h" #include "intel_display_trace.h" #include "intel_display_types.h" +#include "intel_display_wa.h" #include "intel_fbc.h" #include "intel_fbc_regs.h" #include "intel_frontbuffer.h" @@ -1237,6 +1238,11 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, return 0; } + if (intel_display_needs_wa_16023588340(i915)) { + plane_state->no_fbc_reason = "Wa_16023588340"; + return 0; + } + /* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */ if (i915_vtd_active(i915) && (IS_SKYLAKE(i915) || IS_BROXTON(i915))) { plane_state->no_fbc_reason = "VT-d enabled"; diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index e97c9da451b3..0eb0acc4f198 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -36,7 +36,8 @@ uses_generated_oob := \ $(obj)/xe_ring_ops.o \ $(obj)/xe_vm.o \ $(obj)/xe_wa.o \ - $(obj)/xe_ttm_stolen_mgr.o + $(obj)/xe_ttm_stolen_mgr.o \ + $(obj)/display/xe_display_wa.o $(uses_generated_oob): $(generated_oob) @@ -194,6 +195,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ display/xe_display.o \ display/xe_display_misc.o \ display/xe_display_rps.o \ + display/xe_display_wa.o \ display/xe_dsb_buffer.o \ display/xe_fb_pin.o \ display/xe_hdcp_gsc.o \ diff --git a/drivers/gpu/drm/xe/display/xe_display_wa.c b/drivers/gpu/drm/xe/display/xe_display_wa.c new file mode 100644 index 000000000000..68e3d1959ad6 --- /dev/null +++ b/drivers/gpu/drm/xe/display/xe_display_wa.c @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2024 Intel Corporation + */ + +#include "intel_display_wa.h" + +#include "xe_device.h" +#include "xe_wa.h" + +#include + +bool intel_display_needs_wa_16023588340(struct drm_i915_private *i915) +{ + return XE_WA(xe_root_mmio_gt(i915), 16023588340); +} -- cgit v1.2.3 From c41ef1b42af789dca5846493a4a9b6df398fc0ad Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 30 Mar 2024 21:38:28 +0100 Subject: drm/sti: dvo: drop driver owner assignment Core in platform_driver_register() already sets the .owner, so driver does not need to. Whatever is set here will be anyway overwritten by main driver calling platform_driver_register(). Signed-off-by: Krzysztof Kozlowski Acked-by: Alain Volmat Link: https://patchwork.freedesktop.org/patch/msgid/20240330203831.87003-1-krzysztof.kozlowski@linaro.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sti/sti_dvo.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c index 48a5d49fc131..68b8197b3dd1 100644 --- a/drivers/gpu/drm/sti/sti_dvo.c +++ b/drivers/gpu/drm/sti/sti_dvo.c @@ -582,7 +582,6 @@ MODULE_DEVICE_TABLE(of, dvo_of_match); struct platform_driver sti_dvo_driver = { .driver = { .name = "sti-dvo", - .owner = THIS_MODULE, .of_match_table = dvo_of_match, }, .probe = sti_dvo_probe, -- cgit v1.2.3 From 5223ba83c4d79c6f62ac62f6def42727a8e53d7e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 30 Mar 2024 21:38:29 +0100 Subject: drm/sti: hda: drop driver owner assignment Core in platform_driver_register() already sets the .owner, so driver does not need to. Whatever is set here will be anyway overwritten by main driver calling platform_driver_register(). Signed-off-by: Krzysztof Kozlowski Acked-by: Alain Volmat Link: https://patchwork.freedesktop.org/patch/msgid/20240330203831.87003-2-krzysztof.kozlowski@linaro.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sti/sti_hda.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c index 6ee35612a14e..f18faad974aa 100644 --- a/drivers/gpu/drm/sti/sti_hda.c +++ b/drivers/gpu/drm/sti/sti_hda.c @@ -807,7 +807,6 @@ MODULE_DEVICE_TABLE(of, hda_of_match); struct platform_driver sti_hda_driver = { .driver = { .name = "sti-hda", - .owner = THIS_MODULE, .of_match_table = hda_of_match, }, .probe = sti_hda_probe, -- cgit v1.2.3 From 8e3772161ce4a89c6b5d33d3b0155b57712ea5da Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 30 Mar 2024 21:38:30 +0100 Subject: drm/sti: tvout: drop driver owner assignment Core in platform_driver_register() already sets the .owner, so driver does not need to. Whatever is set here will be anyway overwritten by main driver calling platform_driver_register(). Signed-off-by: Krzysztof Kozlowski Acked-by: Alain Volmat Link: https://patchwork.freedesktop.org/patch/msgid/20240330203831.87003-3-krzysztof.kozlowski@linaro.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sti/sti_tvout.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c index 64615638b79a..e714c232026c 100644 --- a/drivers/gpu/drm/sti/sti_tvout.c +++ b/drivers/gpu/drm/sti/sti_tvout.c @@ -886,7 +886,6 @@ MODULE_DEVICE_TABLE(of, tvout_of_match); struct platform_driver sti_tvout_driver = { .driver = { .name = "sti-tvout", - .owner = THIS_MODULE, .of_match_table = tvout_of_match, }, .probe = sti_tvout_probe, -- cgit v1.2.3 From 4864402d98936f55646fa3b47ad49ff499d87c9c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 30 Mar 2024 21:38:31 +0100 Subject: drm/sti: vtg: drop driver owner assignment Core in platform_driver_register() already sets the .owner, so driver does not need to. Whatever is set here will be anyway overwritten by main driver calling platform_driver_register(). Signed-off-by: Krzysztof Kozlowski Acked-by: Alain Volmat Link: https://patchwork.freedesktop.org/patch/msgid/20240330203831.87003-4-krzysztof.kozlowski@linaro.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sti/sti_vtg.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/sti/sti_vtg.c b/drivers/gpu/drm/sti/sti_vtg.c index 5e5f82b6a5d9..5ba469b711b5 100644 --- a/drivers/gpu/drm/sti/sti_vtg.c +++ b/drivers/gpu/drm/sti/sti_vtg.c @@ -431,7 +431,6 @@ MODULE_DEVICE_TABLE(of, vtg_of_match); struct platform_driver sti_vtg_driver = { .driver = { .name = "sti-vtg", - .owner = THIS_MODULE, .of_match_table = vtg_of_match, }, .probe = vtg_probe, -- cgit v1.2.3 From f87f19b8106d6a93272edd398e5f8807693bf6dd Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 30 Mar 2024 21:57:21 +0100 Subject: drm/sti: hdmi: drop driver owner assignment Core in platform_driver_register() already sets the .owner, so driver does not need to. Whatever is set here will be anyway overwritten by main driver calling platform_driver_register(). Signed-off-by: Krzysztof Kozlowski Acked-by: Alain Volmat Link: https://patchwork.freedesktop.org/patch/msgid/20240330205722.93801-1-krzysztof.kozlowski@linaro.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sti/sti_hdmi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index 500936d5743c..b0d84440a87b 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -1485,7 +1485,6 @@ static void sti_hdmi_remove(struct platform_device *pdev) struct platform_driver sti_hdmi_driver = { .driver = { .name = "sti-hdmi", - .owner = THIS_MODULE, .of_match_table = hdmi_of_match, }, .probe = sti_hdmi_probe, -- cgit v1.2.3 From 2bf506b46d38e253693fb22e62469df4af4cbff1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 30 Mar 2024 21:57:22 +0100 Subject: drm/sti: hqvdp: drop driver owner assignment Core in platform_driver_register() already sets the .owner, so driver does not need to. Whatever is set here will be anyway overwritten by main driver calling platform_driver_register(). Signed-off-by: Krzysztof Kozlowski Acked-by: Alain Volmat Link: https://patchwork.freedesktop.org/patch/msgid/20240330205722.93801-2-krzysztof.kozlowski@linaro.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sti/sti_hqvdp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index 0fb48ac044d8..acbf70b95aeb 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -1414,7 +1414,6 @@ MODULE_DEVICE_TABLE(of, hqvdp_of_match); struct platform_driver sti_hqvdp_driver = { .driver = { .name = "sti-hqvdp", - .owner = THIS_MODULE, .of_match_table = hqvdp_of_match, }, .probe = sti_hqvdp_probe, -- cgit v1.2.3 From 01e0cfc994be484ddcb9e121e353e51d8bb837c0 Mon Sep 17 00:00:00 2001 From: Thomas Hellström Date: Fri, 5 Jul 2024 15:28:28 +0200 Subject: drm/xe: Use write-back caching mode for system memory on DGFX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The caching mode for buffer objects with VRAM as a possible placement was forced to write-combined, regardless of placement. However, write-combined system memory is expensive to allocate and even though it is pooled, the pool is expensive to shrink, since it involves global CPU TLB flushes. Moreover write-combined system memory from TTM is only reliably available on x86 and DGFX doesn't have an x86 restriction. So regardless of the cpu caching mode selected for a bo, internally use write-back caching mode for system memory on DGFX. Coherency is maintained, but user-space clients may perceive a difference in cpu access speeds. v2: - Update RB- and Ack tags. - Rephrase wording in xe_drm.h (Matt Roper) v3: - Really rephrase wording. Signed-off-by: Thomas Hellström Fixes: 622f709ca629 ("drm/xe/uapi: Add support for CPU caching mode") Cc: Pallavi Mishra Cc: Matthew Auld Cc: dri-devel@lists.freedesktop.org Cc: Joonas Lahtinen Cc: Effie Yu Cc: Matthew Brost Cc: Maarten Lankhorst Cc: Jose Souza Cc: Michal Mrozek Cc: # v6.8+ Acked-by: Matthew Auld Acked-by: José Roberto de Souza Reviewed-by: Rodrigo Vivi Fixes: 622f709ca629 ("drm/xe/uapi: Add support for CPU caching mode") Acked-by: Michal Mrozek Acked-by: Effie Yu #On chat Link: https://patchwork.freedesktop.org/patch/msgid/20240705132828.27714-1-thomas.hellstrom@linux.intel.com --- drivers/gpu/drm/xe/xe_bo.c | 47 ++++++++++++++++++++++++---------------- drivers/gpu/drm/xe/xe_bo_types.h | 3 ++- include/uapi/drm/xe_drm.h | 8 ++++++- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index 65c696966e96..31192d983d9e 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -343,7 +343,7 @@ static struct ttm_tt *xe_ttm_tt_create(struct ttm_buffer_object *ttm_bo, struct xe_device *xe = xe_bo_device(bo); struct xe_ttm_tt *tt; unsigned long extra_pages; - enum ttm_caching caching; + enum ttm_caching caching = ttm_cached; int err; tt = kzalloc(sizeof(*tt), GFP_KERNEL); @@ -357,26 +357,35 @@ static struct ttm_tt *xe_ttm_tt_create(struct ttm_buffer_object *ttm_bo, extra_pages = DIV_ROUND_UP(xe_device_ccs_bytes(xe, bo->size), PAGE_SIZE); - switch (bo->cpu_caching) { - case DRM_XE_GEM_CPU_CACHING_WC: - caching = ttm_write_combined; - break; - default: - caching = ttm_cached; - break; - } - - WARN_ON((bo->flags & XE_BO_FLAG_USER) && !bo->cpu_caching); - /* - * Display scanout is always non-coherent with the CPU cache. - * - * For Xe_LPG and beyond, PPGTT PTE lookups are also non-coherent and - * require a CPU:WC mapping. + * DGFX system memory is always WB / ttm_cached, since + * other caching modes are only supported on x86. DGFX + * GPU system memory accesses are always coherent with the + * CPU. */ - if ((!bo->cpu_caching && bo->flags & XE_BO_FLAG_SCANOUT) || - (xe->info.graphics_verx100 >= 1270 && bo->flags & XE_BO_FLAG_PAGETABLE)) - caching = ttm_write_combined; + if (!IS_DGFX(xe)) { + switch (bo->cpu_caching) { + case DRM_XE_GEM_CPU_CACHING_WC: + caching = ttm_write_combined; + break; + default: + caching = ttm_cached; + break; + } + + WARN_ON((bo->flags & XE_BO_FLAG_USER) && !bo->cpu_caching); + + /* + * Display scanout is always non-coherent with the CPU cache. + * + * For Xe_LPG and beyond, PPGTT PTE lookups are also + * non-coherent and require a CPU:WC mapping. + */ + if ((!bo->cpu_caching && bo->flags & XE_BO_FLAG_SCANOUT) || + (xe->info.graphics_verx100 >= 1270 && + bo->flags & XE_BO_FLAG_PAGETABLE)) + caching = ttm_write_combined; + } if (bo->flags & XE_BO_FLAG_NEEDS_UC) { /* diff --git a/drivers/gpu/drm/xe/xe_bo_types.h b/drivers/gpu/drm/xe/xe_bo_types.h index 02d68873558a..ebc8abf7930a 100644 --- a/drivers/gpu/drm/xe/xe_bo_types.h +++ b/drivers/gpu/drm/xe/xe_bo_types.h @@ -68,7 +68,8 @@ struct xe_bo { /** * @cpu_caching: CPU caching mode. Currently only used for userspace - * objects. + * objects. Exceptions are system memory on DGFX, which is always + * WB. */ u16 cpu_caching; diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index 33544ef78d3e..19619d4952a8 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -783,7 +783,13 @@ struct drm_xe_gem_create { #define DRM_XE_GEM_CPU_CACHING_WC 2 /** * @cpu_caching: The CPU caching mode to select for this object. If - * mmaping the object the mode selected here will also be used. + * mmaping the object the mode selected here will also be used. The + * exception is when mapping system memory (including data evicted + * to system) on discrete GPUs. The caching mode selected will + * then be overridden to DRM_XE_GEM_CPU_CACHING_WB, and coherency + * between GPU- and CPU is guaranteed. The caching mode of + * existing CPU-mappings will be updated transparently to + * user-space clients. */ __u16 cpu_caching; /** @pad: MBZ */ -- cgit v1.2.3 From f3a47a269119ade7ea22d0465c7fbe518ca1bdfc Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 3 Jul 2024 12:04:58 -0400 Subject: drm/vkms: Remove event from vkms_output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While working on rvkms, I noticed that there's no code that actually uses the drm_pending_vblank_event that's embedded in vkms_output. So, just drop the member from the struct. Signed-off-by: Lyude Paul Reviewed-by: Louis Chauvet Tested-by: Louis Chauvet Reviewed-by: Maíra Canal Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20240703160458.1303872-1-lyude@redhat.com --- drivers/gpu/drm/vkms/vkms_drv.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 8f5710debb1e..5e46ea5b96dc 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -103,7 +103,6 @@ struct vkms_output { struct drm_writeback_connector wb_connector; struct hrtimer vblank_hrtimer; ktime_t period_ns; - struct drm_pending_vblank_event *event; /* ordered wq for composer_work */ struct workqueue_struct *composer_workq; /* protects concurrent access to composer */ -- cgit v1.2.3 From 5a716b06b329bd2108c95a4f04c71bbe491729f2 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Mon, 1 Jul 2024 14:23:04 +0800 Subject: drm/stm: Remove unnecessary .owner for lvds_platform_driver Remove .owner field if calls are used which set it automatically. ./drivers/gpu/drm/stm/lvds.c:1213:3-8: No need to set .owner here. The core will do it. Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=9457 Signed-off-by: Jiapeng Chong Acked-by: Raphael Gallais-Pou Signed-off-by: Philippe Cornu Link: https://patchwork.freedesktop.org/patch/msgid/20240701062304.42844-1-jiapeng.chong@linux.alibaba.com --- drivers/gpu/drm/stm/lvds.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/stm/lvds.c b/drivers/gpu/drm/stm/lvds.c index bfc8cb13fbc5..916f2562b170 100644 --- a/drivers/gpu/drm/stm/lvds.c +++ b/drivers/gpu/drm/stm/lvds.c @@ -1212,7 +1212,6 @@ static struct platform_driver lvds_platform_driver = { .remove = lvds_remove, .driver = { .name = "stm32-display-lvds", - .owner = THIS_MODULE, .of_match_table = lvds_dt_ids, }, }; -- cgit v1.2.3 From 74e3076800067c6dc0dcff5b75344cec064c20eb Mon Sep 17 00:00:00 2001 From: Ngai-Mint Kwan Date: Mon, 1 Jul 2024 11:46:37 -0700 Subject: drm/xe/xe2lpm: Extend Wa_16021639441 Wa_16021639441 applies to Xe2_LPM. Signed-off-by: Ngai-Mint Kwan Reviewed-by: Matt Roper Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20240701184637.531794-1-ngai-mint.kwan@linux.intel.com --- drivers/gpu/drm/xe/xe_wa.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c index c7bf0862b231..6c52d9d02b5f 100644 --- a/drivers/gpu/drm/xe/xe_wa.c +++ b/drivers/gpu/drm/xe/xe_wa.c @@ -539,6 +539,16 @@ static const struct xe_rtp_entry_sr engine_was[] = { XE_RTP_ACTIONS(SET(HALF_SLICE_CHICKEN7, CLEAR_OPTIMIZATION_DISABLE)) }, + /* Xe2_LPM */ + + { XE_RTP_NAME("16021639441"), + XE_RTP_RULES(MEDIA_VERSION(2000)), + XE_RTP_ACTIONS(SET(CSFE_CHICKEN1(0), + GHWSP_CSB_REPORT_DIS | + PPHWSP_CSB_AND_TIMESTAMP_REPORT_DIS, + XE_RTP_ACTION_FLAG(ENGINE_BASE))) + }, + /* Xe2_HPM */ { XE_RTP_NAME("16021639441"), -- cgit v1.2.3 From bc5846d3d3dff9f057e2897a736b51584785da30 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Wed, 12 Jun 2024 15:23:43 -0700 Subject: drm/tegra: Call drm_atomic_helper_shutdown() at shutdown time Based on grepping through the source code this driver appears to be missing a call to drm_atomic_helper_shutdown() at system shutdown time. Among other things, this means that if a panel is in use that it won't be cleanly powered off at system shutdown time. The fact that we should call drm_atomic_helper_shutdown() in the case of OS shutdown/restart comes straight out of the kernel doc "driver instance overview" in drm_drv.c. Suggested-by: Maxime Ripard Reviewed-by: Maxime Ripard Acked-by: Thierry Reding Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20240612152336.v2.3.Ifb4450979b62976fd5a98847dade2e5b377d47c8@changeid --- drivers/gpu/drm/tegra/drm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 03d1c76aec2d..d9f0728c3afd 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -1330,6 +1330,11 @@ static int host1x_drm_remove(struct host1x_device *dev) return 0; } +static void host1x_drm_shutdown(struct host1x_device *dev) +{ + drm_atomic_helper_shutdown(dev_get_drvdata(&dev->dev)); +} + #ifdef CONFIG_PM_SLEEP static int host1x_drm_suspend(struct device *dev) { @@ -1398,6 +1403,7 @@ static struct host1x_driver host1x_drm_driver = { }, .probe = host1x_drm_probe, .remove = host1x_drm_remove, + .shutdown = host1x_drm_shutdown, .subdevs = host1x_drm_subdevs, }; -- cgit v1.2.3 From caaf1f44a6a27bae33eee189842c4d8fc21c3b02 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Mon, 8 Jul 2024 14:10:08 -0700 Subject: drm/xe: Drop trace_xe_hw_fence_free MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fence->ctx may be stale memory when trace_xe_hw_fence_free is called resuling UAF bug when deriving the device name. This tracepoint is not all that useful, so just drop it. Fixes: 501c4255c409 ("drm/xe/trace: Print device_id in xe_trace events") Cc: Ville Syrjälä Cc: Lucas De Marchi Cc: Gustavo Sousa Cc: Radhakrishna Sripada Cc: Matt Roper Signed-off-by: Matthew Brost Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20240708211008.956384-1-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_hw_fence.c | 1 - drivers/gpu/drm/xe/xe_trace.h | 5 ----- 2 files changed, 6 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_hw_fence.c b/drivers/gpu/drm/xe/xe_hw_fence.c index 35c0063a831a..45a9789cf501 100644 --- a/drivers/gpu/drm/xe/xe_hw_fence.c +++ b/drivers/gpu/drm/xe/xe_hw_fence.c @@ -187,7 +187,6 @@ static void xe_hw_fence_release(struct dma_fence *dma_fence) { struct xe_hw_fence *fence = to_xe_hw_fence(dma_fence); - trace_xe_hw_fence_free(fence); XE_WARN_ON(!list_empty(&fence->irq_link)); call_rcu(&dma_fence->rcu, fence_free); } diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h index 09ca1ad057b0..baba14fb1e32 100644 --- a/drivers/gpu/drm/xe/xe_trace.h +++ b/drivers/gpu/drm/xe/xe_trace.h @@ -341,11 +341,6 @@ DEFINE_EVENT(xe_hw_fence, xe_hw_fence_try_signal, TP_ARGS(fence) ); -DEFINE_EVENT(xe_hw_fence, xe_hw_fence_free, - TP_PROTO(struct xe_hw_fence *fence), - TP_ARGS(fence) -); - TRACE_EVENT(xe_reg_rw, TP_PROTO(struct xe_gt *gt, bool write, u32 reg, u64 val, int len), -- cgit v1.2.3 From f592e01664b4a57b109fcf6f6916145517f94bd7 Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Tue, 2 Jul 2024 16:30:16 +0200 Subject: drm/drm_connector: Document Colorspace property variants The initial idea of the Colorspace prop was that this maps 1:1 to InfoFrames/SDP but KMS does not give user space enough information nor control over the output format to figure out which variants can be used for a given KMS commit. At the same time, properties like Broadcast RGB expect full range quantization range being produced by user space from the CRTC and drivers to convert to the range expected by the sink for the chosen output format, mode, InfoFrames, etc. This change documents the reality of the Colorspace property. The Default variant unfortunately is very much driver specific and not reflected by the EDID. The BT2020 variants are in active use by generic compositors which have expectations from the driver about the conversions it has to do when selecting certain output formats. Everything else is also marked as undefined. Coming up with valid behavior that makes it usable from user space and consistent with other KMS properties for those variants is left as an exercise for whoever wants to use them. v2: * Talk about "pixel operation properties" that user space configures * Mention that user space is responsible for checking the EDID for sink support * Make it clear that drivers can choose between RGB and YCbCr on their own Signed-off-by: Sebastian Wick Reviewed-by: Pekka Paalanen Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20240702143017.2429975-1-sebastian.wick@redhat.com --- drivers/gpu/drm/drm_connector.c | 79 +++++++++++++++++++++++++++++++---------- include/drm/drm_connector.h | 8 ----- 2 files changed, 61 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index ab6ab7ff7ea8..b4f4d2f908d1 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -2315,24 +2315,67 @@ EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property); * DOC: standard connector properties * * Colorspace: - * This property helps select a suitable colorspace based on the sink - * capability. Modern sink devices support wider gamut like BT2020. - * This helps switch to BT2020 mode if the BT2020 encoded video stream - * is being played by the user, same for any other colorspace. Thereby - * giving a good visual experience to users. - * - * The expectation from userspace is that it should parse the EDID - * and get supported colorspaces. Use this property and switch to the - * one supported. Sink supported colorspaces should be retrieved by - * userspace from EDID and driver will not explicitly expose them. - * - * Basically the expectation from userspace is: - * - Set up CRTC DEGAMMA/CTM/GAMMA to convert to some sink - * colorspace - * - Set this new property to let the sink know what it - * converted the CRTC output to. - * - This property is just to inform sink what colorspace - * source is trying to drive. + * This property is used to inform the driver about the color encoding + * user space configured the pixel operation properties to produce. + * The variants set the colorimetry, transfer characteristics, and which + * YCbCr conversion should be used when necessary. + * The transfer characteristics from HDR_OUTPUT_METADATA takes precedence + * over this property. + * User space always configures the pixel operation properties to produce + * full quantization range data (see the Broadcast RGB property). + * + * Drivers inform the sink about what colorimetry, transfer + * characteristics, YCbCr conversion, and quantization range to expect + * (this can depend on the output mode, output format and other + * properties). Drivers also convert the user space provided data to what + * the sink expects. + * + * User space has to check if the sink supports all of the possible + * colorimetries that the driver is allowed to pick by parsing the EDID. + * + * For historical reasons this property exposes a number of variants which + * result in undefined behavior. + * + * Default: + * The behavior is driver-specific. + * BT2020_RGB: + * BT2020_YCC: + * User space configures the pixel operation properties to produce + * RGB content with Rec. ITU-R BT.2020 colorimetry, Rec. + * ITU-R BT.2020 (Table 4, RGB) transfer characteristics and full + * quantization range. + * User space can use the HDR_OUTPUT_METADATA property to set the + * transfer characteristics to PQ (Rec. ITU-R BT.2100 Table 4) or + * HLG (Rec. ITU-R BT.2100 Table 5) in which case, user space + * configures pixel operation properties to produce content with + * the respective transfer characteristics. + * User space has to make sure the sink supports Rec. + * ITU-R BT.2020 R'G'B' and Rec. ITU-R BT.2020 Y'C'BC'R + * colorimetry. + * Drivers can configure the sink to use an RGB format, tell the + * sink to expect Rec. ITU-R BT.2020 R'G'B' colorimetry and convert + * to the appropriate quantization range. + * Drivers can configure the sink to use a YCbCr format, tell the + * sink to expect Rec. ITU-R BT.2020 Y'C'BC'R colorimetry, convert + * to YCbCr using the Rec. ITU-R BT.2020 non-constant luminance + * conversion matrix and convert to the appropriate quantization + * range. + * The variants BT2020_RGB and BT2020_YCC are equivalent and the + * driver chooses between RGB and YCbCr on its own. + * SMPTE_170M_YCC: + * BT709_YCC: + * XVYCC_601: + * XVYCC_709: + * SYCC_601: + * opYCC_601: + * opRGB: + * BT2020_CYCC: + * DCI-P3_RGB_D65: + * DCI-P3_RGB_Theater: + * RGB_WIDE_FIXED: + * RGB_WIDE_FLOAT: + * BT601_YCC: + * The behavior is undefined. * * Because between HDMI and DP have different colorspaces, * drm_mode_create_hdmi_colorspace_property() is used for HDMI connector and diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index c754651044d4..e3fa43291f44 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -471,14 +471,6 @@ enum drm_privacy_screen_status { * * DP definitions come from the DP v2.0 spec * HDMI definitions come from the CTA-861-H spec - * - * A note on YCC and RGB variants: - * - * Since userspace is not aware of the encoding on the wire - * (RGB or YCbCr), drivers are free to pick the appropriate - * variant, regardless of what userspace selects. E.g., if - * BT2020_RGB is selected by userspace a driver will pick - * BT2020_YCC if the encoding on the wire is YUV444 or YUV420. * * @DRM_MODE_COLORIMETRY_DEFAULT: * Driver specific behavior. -- cgit v1.2.3 From ce7c90bfda2656418c69ba0dd8f8a7536b8928d4 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 6 Jan 2024 17:54:32 +0100 Subject: drm/stm: Fix an error handling path in stm_drm_platform_probe() If drm_dev_register() fails, a call to drv_load() must be undone, as already done in the remove function. Fixes: b759012c5fa7 ("drm/stm: Add STM32 LTDC driver") Signed-off-by: Christophe JAILLET Acked-by: Raphael Gallais-Pou Link: https://patchwork.freedesktop.org/patch/msgid/20fff7f853f20a48a96db8ff186124470ec4d976.1704560028.git.christophe.jaillet@wanadoo.fr Signed-off-by: Raphael Gallais-Pou --- drivers/gpu/drm/stm/drv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c index e8523abef27a..4d2db079ad4f 100644 --- a/drivers/gpu/drm/stm/drv.c +++ b/drivers/gpu/drm/stm/drv.c @@ -203,12 +203,14 @@ static int stm_drm_platform_probe(struct platform_device *pdev) ret = drm_dev_register(ddev, 0); if (ret) - goto err_put; + goto err_unload; drm_fbdev_dma_setup(ddev, 16); return 0; +err_unload: + drv_unload(ddev); err_put: drm_dev_put(ddev); -- cgit v1.2.3 From 6be74ddd0609959b4005f88b6a4d4af678e4a71f Mon Sep 17 00:00:00 2001 From: Thomas Hellström Date: Fri, 5 Jul 2024 17:31:59 +0200 Subject: drm/ttm: Allow TTM LRU list nodes of different types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To be able to handle list unlocking while traversing the LRU list, we want the iterators not only to point to the next position of the list traversal, but to insert themselves as list nodes at that point to work around the fact that the next node might otherwise disappear from the list while the iterator is pointing to it. These list nodes need to be easily distinguishable from other list nodes so that others traversing the list can skip over them. So declare a struct ttm_lru_item, with a struct list_head member and a type enum. This will slightly increase the size of a struct ttm_resource. Changes in previous series: - Update enum ttm_lru_item_type documentation. v3: - Introduce ttm_lru_first_res_or_null() (Christian König, Thomas Hellström) v5: - Update also the TTM test code (Xe CI). Cc: Christian König Cc: Somalapuram Amaranath Cc: Matthew Brost Cc: Signed-off-by: Thomas Hellström Reviewed-by: Matthew Brost Reviewed-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20240705153206.68526-2-thomas.hellstrom@linux.intel.com Signed-off-by: Christian König --- drivers/gpu/drm/ttm/tests/ttm_bo_test.c | 6 +- drivers/gpu/drm/ttm/tests/ttm_resource_test.c | 2 +- drivers/gpu/drm/ttm/ttm_device.c | 4 +- drivers/gpu/drm/ttm/ttm_resource.c | 89 +++++++++++++++++++++------ include/drm/ttm/ttm_resource.h | 54 +++++++++++++++- 5 files changed, 129 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/ttm/tests/ttm_bo_test.c b/drivers/gpu/drm/ttm/tests/ttm_bo_test.c index d1b32303d051..f0a7eb62116c 100644 --- a/drivers/gpu/drm/ttm/tests/ttm_bo_test.c +++ b/drivers/gpu/drm/ttm/tests/ttm_bo_test.c @@ -271,7 +271,7 @@ static void ttm_bo_unreserve_basic(struct kunit *test) man = ttm_manager_type(priv->ttm_dev, mem_type); KUNIT_ASSERT_EQ(test, - list_is_last(&res1->lru, &man->lru[bo->priority]), 1); + list_is_last(&res1->lru.link, &man->lru[bo->priority]), 1); ttm_resource_free(bo, &res2); ttm_resource_free(bo, &res1); @@ -308,11 +308,11 @@ static void ttm_bo_unreserve_pinned(struct kunit *test) err = ttm_resource_alloc(bo, place, &res2); KUNIT_ASSERT_EQ(test, err, 0); KUNIT_ASSERT_EQ(test, - list_is_last(&res2->lru, &priv->ttm_dev->pinned), 1); + list_is_last(&res2->lru.link, &priv->ttm_dev->pinned), 1); ttm_bo_unreserve(bo); KUNIT_ASSERT_EQ(test, - list_is_last(&res1->lru, &priv->ttm_dev->pinned), 1); + list_is_last(&res1->lru.link, &priv->ttm_dev->pinned), 1); ttm_resource_free(bo, &res1); ttm_resource_free(bo, &res2); diff --git a/drivers/gpu/drm/ttm/tests/ttm_resource_test.c b/drivers/gpu/drm/ttm/tests/ttm_resource_test.c index 9c2f13e53162..22260e7aea58 100644 --- a/drivers/gpu/drm/ttm/tests/ttm_resource_test.c +++ b/drivers/gpu/drm/ttm/tests/ttm_resource_test.c @@ -198,7 +198,7 @@ static void ttm_resource_fini_basic(struct kunit *test) ttm_resource_init(bo, place, res); ttm_resource_fini(man, res); - KUNIT_ASSERT_TRUE(test, list_empty(&res->lru)); + KUNIT_ASSERT_TRUE(test, list_empty(&res->lru.link)); KUNIT_ASSERT_EQ(test, man->usage, 0); } diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c index 434cf0258000..09411978a13a 100644 --- a/drivers/gpu/drm/ttm/ttm_device.c +++ b/drivers/gpu/drm/ttm/ttm_device.c @@ -274,14 +274,14 @@ static void ttm_device_clear_lru_dma_mappings(struct ttm_device *bdev, struct ttm_resource *res; spin_lock(&bdev->lru_lock); - while ((res = list_first_entry_or_null(list, typeof(*res), lru))) { + while ((res = ttm_lru_first_res_or_null(list))) { struct ttm_buffer_object *bo = res->bo; /* Take ref against racing releases once lru_lock is unlocked */ if (!ttm_bo_get_unless_zero(bo)) continue; - list_del_init(&res->lru); + list_del_init(&bo->resource->lru.link); spin_unlock(&bdev->lru_lock); if (bo->ttm) diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 4a66b851b67d..db9a7a3717c4 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -70,8 +70,8 @@ void ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move *bulk) dma_resv_assert_held(pos->last->bo->base.resv); man = ttm_manager_type(pos->first->bo->bdev, i); - list_bulk_move_tail(&man->lru[j], &pos->first->lru, - &pos->last->lru); + list_bulk_move_tail(&man->lru[j], &pos->first->lru.link, + &pos->last->lru.link); } } } @@ -84,14 +84,38 @@ ttm_lru_bulk_move_pos(struct ttm_lru_bulk_move *bulk, struct ttm_resource *res) return &bulk->pos[res->mem_type][res->bo->priority]; } +/* Return the previous resource on the list (skip over non-resource list items) */ +static struct ttm_resource *ttm_lru_prev_res(struct ttm_resource *cur) +{ + struct ttm_lru_item *lru = &cur->lru; + + do { + lru = list_prev_entry(lru, link); + } while (!ttm_lru_item_is_res(lru)); + + return ttm_lru_item_to_res(lru); +} + +/* Return the next resource on the list (skip over non-resource list items) */ +static struct ttm_resource *ttm_lru_next_res(struct ttm_resource *cur) +{ + struct ttm_lru_item *lru = &cur->lru; + + do { + lru = list_next_entry(lru, link); + } while (!ttm_lru_item_is_res(lru)); + + return ttm_lru_item_to_res(lru); +} + /* Move the resource to the tail of the bulk move range */ static void ttm_lru_bulk_move_pos_tail(struct ttm_lru_bulk_move_pos *pos, struct ttm_resource *res) { if (pos->last != res) { if (pos->first == res) - pos->first = list_next_entry(res, lru); - list_move(&res->lru, &pos->last->lru); + pos->first = ttm_lru_next_res(res); + list_move(&res->lru.link, &pos->last->lru.link); pos->last = res; } } @@ -122,11 +146,11 @@ static void ttm_lru_bulk_move_del(struct ttm_lru_bulk_move *bulk, pos->first = NULL; pos->last = NULL; } else if (pos->first == res) { - pos->first = list_next_entry(res, lru); + pos->first = ttm_lru_next_res(res); } else if (pos->last == res) { - pos->last = list_prev_entry(res, lru); + pos->last = ttm_lru_prev_res(res); } else { - list_move(&res->lru, &pos->last->lru); + list_move(&res->lru.link, &pos->last->lru.link); } } @@ -155,7 +179,7 @@ void ttm_resource_move_to_lru_tail(struct ttm_resource *res) lockdep_assert_held(&bo->bdev->lru_lock); if (bo->pin_count) { - list_move_tail(&res->lru, &bdev->pinned); + list_move_tail(&res->lru.link, &bdev->pinned); } else if (bo->bulk_move) { struct ttm_lru_bulk_move_pos *pos = @@ -166,7 +190,7 @@ void ttm_resource_move_to_lru_tail(struct ttm_resource *res) struct ttm_resource_manager *man; man = ttm_manager_type(bdev, res->mem_type); - list_move_tail(&res->lru, &man->lru[bo->priority]); + list_move_tail(&res->lru.link, &man->lru[bo->priority]); } } @@ -197,9 +221,9 @@ void ttm_resource_init(struct ttm_buffer_object *bo, man = ttm_manager_type(bo->bdev, place->mem_type); spin_lock(&bo->bdev->lru_lock); if (bo->pin_count) - list_add_tail(&res->lru, &bo->bdev->pinned); + list_add_tail(&res->lru.link, &bo->bdev->pinned); else - list_add_tail(&res->lru, &man->lru[bo->priority]); + list_add_tail(&res->lru.link, &man->lru[bo->priority]); man->usage += res->size; spin_unlock(&bo->bdev->lru_lock); } @@ -221,7 +245,7 @@ void ttm_resource_fini(struct ttm_resource_manager *man, struct ttm_device *bdev = man->bdev; spin_lock(&bdev->lru_lock); - list_del_init(&res->lru); + list_del_init(&res->lru.link); man->usage -= res->size; spin_unlock(&bdev->lru_lock); } @@ -472,14 +496,16 @@ struct ttm_resource * ttm_resource_manager_first(struct ttm_resource_manager *man, struct ttm_resource_cursor *cursor) { - struct ttm_resource *res; + struct ttm_lru_item *lru; lockdep_assert_held(&man->bdev->lru_lock); for (cursor->priority = 0; cursor->priority < TTM_MAX_BO_PRIORITY; ++cursor->priority) - list_for_each_entry(res, &man->lru[cursor->priority], lru) - return res; + list_for_each_entry(lru, &man->lru[cursor->priority], link) { + if (ttm_lru_item_is_res(lru)) + return ttm_lru_item_to_res(lru); + } return NULL; } @@ -498,15 +524,40 @@ ttm_resource_manager_next(struct ttm_resource_manager *man, struct ttm_resource_cursor *cursor, struct ttm_resource *res) { + struct ttm_lru_item *lru = &res->lru; + lockdep_assert_held(&man->bdev->lru_lock); - list_for_each_entry_continue(res, &man->lru[cursor->priority], lru) - return res; + list_for_each_entry_continue(lru, &man->lru[cursor->priority], link) { + if (ttm_lru_item_is_res(lru)) + return ttm_lru_item_to_res(lru); + } for (++cursor->priority; cursor->priority < TTM_MAX_BO_PRIORITY; ++cursor->priority) - list_for_each_entry(res, &man->lru[cursor->priority], lru) - return res; + list_for_each_entry(lru, &man->lru[cursor->priority], link) { + if (ttm_lru_item_is_res(lru)) + ttm_lru_item_to_res(lru); + } + + return NULL; +} + +/** + * ttm_lru_first_res_or_null() - Return the first resource on an lru list + * @head: The list head of the lru list. + * + * Return: Pointer to the first resource on the lru list or NULL if + * there is none. + */ +struct ttm_resource *ttm_lru_first_res_or_null(struct list_head *head) +{ + struct ttm_lru_item *lru; + + list_for_each_entry(lru, head, link) { + if (ttm_lru_item_is_res(lru)) + return ttm_lru_item_to_res(lru); + } return NULL; } diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index 69769355139f..1511d91e290d 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -49,6 +49,43 @@ struct io_mapping; struct sg_table; struct scatterlist; +/** + * enum ttm_lru_item_type - enumerate ttm_lru_item subclasses + */ +enum ttm_lru_item_type { + /** @TTM_LRU_RESOURCE: The resource subclass */ + TTM_LRU_RESOURCE, + /** @TTM_LRU_HITCH: The iterator hitch subclass */ + TTM_LRU_HITCH +}; + +/** + * struct ttm_lru_item - The TTM lru list node base class + * @link: The list link + * @type: The subclass type + */ +struct ttm_lru_item { + struct list_head link; + enum ttm_lru_item_type type; +}; + +/** + * ttm_lru_item_init() - initialize a struct ttm_lru_item + * @item: The item to initialize + * @type: The subclass type + */ +static inline void ttm_lru_item_init(struct ttm_lru_item *item, + enum ttm_lru_item_type type) +{ + item->type = type; + INIT_LIST_HEAD(&item->link); +} + +static inline bool ttm_lru_item_is_res(const struct ttm_lru_item *item) +{ + return item->type == TTM_LRU_RESOURCE; +} + struct ttm_resource_manager_func { /** * struct ttm_resource_manager_func member alloc @@ -217,9 +254,21 @@ struct ttm_resource { /** * @lru: Least recently used list, see &ttm_resource_manager.lru */ - struct list_head lru; + struct ttm_lru_item lru; }; +/** + * ttm_lru_item_to_res() - Downcast a struct ttm_lru_item to a struct ttm_resource + * @item: The struct ttm_lru_item to downcast + * + * Return: Pointer to the embedding struct ttm_resource + */ +static inline struct ttm_resource * +ttm_lru_item_to_res(struct ttm_lru_item *item) +{ + return container_of(item, struct ttm_resource, lru); +} + /** * struct ttm_resource_cursor * @@ -393,6 +442,9 @@ ttm_resource_manager_next(struct ttm_resource_manager *man, struct ttm_resource_cursor *cursor, struct ttm_resource *res); +struct ttm_resource * +ttm_lru_first_res_or_null(struct list_head *head); + /** * ttm_resource_manager_for_each_res - iterate over all resources * @man: the resource manager -- cgit v1.2.3 From 9c62fb62c9f0761eeda8f2a9517e007ff2cdbe9a Mon Sep 17 00:00:00 2001 From: Thomas Hellström Date: Fri, 5 Jul 2024 17:32:00 +0200 Subject: drm/ttm: Slightly clean up LRU list iteration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To make the transition to using lru hitches easier, simplify the ttm_resource_manager_next() interface to only take the cursor and reuse ttm_resource_manager_next() functionality from ttm_resource_manager_first(). Cc: Christian König Cc: Somalapuram Amaranath Cc: Matthew Brost Cc: Signed-off-by: Thomas Hellström Reviewed-by: Matthew Brost Reviewed-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20240705153206.68526-3-thomas.hellstrom@linux.intel.com Signed-off-by: Christian König --- drivers/gpu/drm/ttm/ttm_resource.c | 48 +++++++++++++++++--------------------- include/drm/ttm/ttm_resource.h | 10 ++++---- 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index db9a7a3717c4..8bfbddddc0e8 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -496,50 +496,44 @@ struct ttm_resource * ttm_resource_manager_first(struct ttm_resource_manager *man, struct ttm_resource_cursor *cursor) { - struct ttm_lru_item *lru; - lockdep_assert_held(&man->bdev->lru_lock); - for (cursor->priority = 0; cursor->priority < TTM_MAX_BO_PRIORITY; - ++cursor->priority) - list_for_each_entry(lru, &man->lru[cursor->priority], link) { - if (ttm_lru_item_is_res(lru)) - return ttm_lru_item_to_res(lru); - } - - return NULL; + cursor->priority = 0; + cursor->man = man; + cursor->cur = &man->lru[cursor->priority]; + return ttm_resource_manager_next(cursor); } /** * ttm_resource_manager_next * - * @man: resource manager to iterate over * @cursor: cursor to record the position - * @res: the current resource pointer * - * Returns the next resource from the resource manager. + * Return: the next resource from the resource manager. */ struct ttm_resource * -ttm_resource_manager_next(struct ttm_resource_manager *man, - struct ttm_resource_cursor *cursor, - struct ttm_resource *res) +ttm_resource_manager_next(struct ttm_resource_cursor *cursor) { - struct ttm_lru_item *lru = &res->lru; + struct ttm_resource_manager *man = cursor->man; + struct ttm_lru_item *lru; lockdep_assert_held(&man->bdev->lru_lock); - list_for_each_entry_continue(lru, &man->lru[cursor->priority], link) { - if (ttm_lru_item_is_res(lru)) - return ttm_lru_item_to_res(lru); - } - - for (++cursor->priority; cursor->priority < TTM_MAX_BO_PRIORITY; - ++cursor->priority) - list_for_each_entry(lru, &man->lru[cursor->priority], link) { - if (ttm_lru_item_is_res(lru)) - ttm_lru_item_to_res(lru); + for (;;) { + lru = list_entry(cursor->cur, typeof(*lru), link); + list_for_each_entry_continue(lru, &man->lru[cursor->priority], link) { + if (ttm_lru_item_is_res(lru)) { + cursor->cur = &lru->link; + return ttm_lru_item_to_res(lru); + } } + if (++cursor->priority >= TTM_MAX_BO_PRIORITY) + break; + + cursor->cur = &man->lru[cursor->priority]; + } + return NULL; } diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index 1511d91e290d..7d81fd5b5b83 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -272,11 +272,15 @@ ttm_lru_item_to_res(struct ttm_lru_item *item) /** * struct ttm_resource_cursor * + * @man: The resource manager currently being iterated over. + * @cur: The list head the cursor currently points to. * @priority: the current priority * * Cursor to iterate over the resources in a manager. */ struct ttm_resource_cursor { + struct ttm_resource_manager *man; + struct list_head *cur; unsigned int priority; }; @@ -438,9 +442,7 @@ struct ttm_resource * ttm_resource_manager_first(struct ttm_resource_manager *man, struct ttm_resource_cursor *cursor); struct ttm_resource * -ttm_resource_manager_next(struct ttm_resource_manager *man, - struct ttm_resource_cursor *cursor, - struct ttm_resource *res); +ttm_resource_manager_next(struct ttm_resource_cursor *cursor); struct ttm_resource * ttm_lru_first_res_or_null(struct list_head *head); @@ -455,7 +457,7 @@ ttm_lru_first_res_or_null(struct list_head *head); */ #define ttm_resource_manager_for_each_res(man, cursor, res) \ for (res = ttm_resource_manager_first(man, cursor); res; \ - res = ttm_resource_manager_next(man, cursor, res)) + res = ttm_resource_manager_next(cursor)) struct ttm_kmap_iter * ttm_kmap_iter_iomap_init(struct ttm_kmap_iter_iomap *iter_io, -- cgit v1.2.3 From 8e9bf0fb10a79aaed37474600948cd33d14aa606 Mon Sep 17 00:00:00 2001 From: Thomas Hellström Date: Fri, 5 Jul 2024 17:32:01 +0200 Subject: drm/ttm: Use LRU hitches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Have iterators insert themselves into the list they are iterating over using hitch list nodes. Since only the iterator owner can remove these list nodes from the list, it's safe to unlock the list and when continuing, use them as a starting point. Due to the way LRU bumping works in TTM, newly added items will not be missed, and bumped items will be iterated over a second time before reaching the end of the list. The exception is list with bulk move sublists. When bumping a sublist, a hitch that is part of that sublist will also be moved and we might miss items if restarting from it. This will be addressed in a later patch. Changes in previous series: - Updated ttm_resource_cursor_fini() documentation. v2: - Don't reorder ttm_resource_manager_first() and _next(). (Christian König). - Use list_add instead of list_move (Christian König) v3: - Split into two patches, one cleanup, one new functionality (Christian König) - use ttm_resource_cursor_fini_locked() instead of open-coding (Matthew Brost) Cc: Christian König Cc: Somalapuram Amaranath Cc: Matthew Brost Cc: Signed-off-by: Thomas Hellström Reviewed-by: Matthew Brost Reviewed-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20240705153206.68526-4-thomas.hellstrom@linux.intel.com Signed-off-by: Christian König --- drivers/gpu/drm/ttm/ttm_bo.c | 1 + drivers/gpu/drm/ttm/ttm_device.c | 9 ++++-- drivers/gpu/drm/ttm/ttm_resource.c | 56 ++++++++++++++++++++++++++++++++------ include/drm/ttm/ttm_resource.h | 9 ++++-- 4 files changed, 62 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 6396dece0db1..43eda720657f 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -621,6 +621,7 @@ int ttm_mem_evict_first(struct ttm_device *bdev, if (locked) dma_resv_unlock(res->bo->base.resv); } + ttm_resource_cursor_fini_locked(&cursor); if (!bo) { if (busy_bo && !ttm_bo_get_unless_zero(busy_bo)) diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c index 09411978a13a..f9e9b1ec8c8a 100644 --- a/drivers/gpu/drm/ttm/ttm_device.c +++ b/drivers/gpu/drm/ttm/ttm_device.c @@ -170,12 +170,17 @@ int ttm_device_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx, num_pages = PFN_UP(bo->base.size); ret = ttm_bo_swapout(bo, ctx, gfp_flags); /* ttm_bo_swapout has dropped the lru_lock */ - if (!ret) + if (!ret) { + ttm_resource_cursor_fini(&cursor); return num_pages; - if (ret != -EBUSY) + } + if (ret != -EBUSY) { + ttm_resource_cursor_fini(&cursor); return ret; + } } } + ttm_resource_cursor_fini_locked(&cursor); spin_unlock(&bdev->lru_lock); return 0; } diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 8bfbddddc0e8..9c8b6499edfb 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -33,6 +33,37 @@ #include +/** + * ttm_resource_cursor_fini_locked() - Finalize the LRU list cursor usage + * @cursor: The struct ttm_resource_cursor to finalize. + * + * The function pulls the LRU list cursor off any lists it was previusly + * attached to. Needs to be called with the LRU lock held. The function + * can be called multiple times after eachother. + */ +void ttm_resource_cursor_fini_locked(struct ttm_resource_cursor *cursor) +{ + lockdep_assert_held(&cursor->man->bdev->lru_lock); + list_del_init(&cursor->hitch.link); +} + +/** + * ttm_resource_cursor_fini() - Finalize the LRU list cursor usage + * @cursor: The struct ttm_resource_cursor to finalize. + * + * The function pulls the LRU list cursor off any lists it was previusly + * attached to. Needs to be called without the LRU list lock held. The + * function can be called multiple times after eachother. + */ +void ttm_resource_cursor_fini(struct ttm_resource_cursor *cursor) +{ + spinlock_t *lru_lock = &cursor->man->bdev->lru_lock; + + spin_lock(lru_lock); + ttm_resource_cursor_fini_locked(cursor); + spin_unlock(lru_lock); +} + /** * ttm_lru_bulk_move_init - initialize a bulk move structure * @bulk: the structure to init @@ -485,12 +516,15 @@ void ttm_resource_manager_debug(struct ttm_resource_manager *man, EXPORT_SYMBOL(ttm_resource_manager_debug); /** - * ttm_resource_manager_first - * + * ttm_resource_manager_first() - Start iterating over the resources + * of a resource manager * @man: resource manager to iterate over * @cursor: cursor to record the position * - * Returns the first resource from the resource manager. + * Initializes the cursor and starts iterating. When done iterating, + * the caller must explicitly call ttm_resource_cursor_fini(). + * + * Return: The first resource from the resource manager. */ struct ttm_resource * ttm_resource_manager_first(struct ttm_resource_manager *man, @@ -500,13 +534,15 @@ ttm_resource_manager_first(struct ttm_resource_manager *man, cursor->priority = 0; cursor->man = man; - cursor->cur = &man->lru[cursor->priority]; + ttm_lru_item_init(&cursor->hitch, TTM_LRU_HITCH); + list_add(&cursor->hitch.link, &man->lru[cursor->priority]); + return ttm_resource_manager_next(cursor); } /** - * ttm_resource_manager_next - * + * ttm_resource_manager_next() - Continue iterating over the resource manager + * resources * @cursor: cursor to record the position * * Return: the next resource from the resource manager. @@ -520,10 +556,10 @@ ttm_resource_manager_next(struct ttm_resource_cursor *cursor) lockdep_assert_held(&man->bdev->lru_lock); for (;;) { - lru = list_entry(cursor->cur, typeof(*lru), link); + lru = &cursor->hitch; list_for_each_entry_continue(lru, &man->lru[cursor->priority], link) { if (ttm_lru_item_is_res(lru)) { - cursor->cur = &lru->link; + list_move(&cursor->hitch.link, &lru->link); return ttm_lru_item_to_res(lru); } } @@ -531,9 +567,11 @@ ttm_resource_manager_next(struct ttm_resource_cursor *cursor) if (++cursor->priority >= TTM_MAX_BO_PRIORITY) break; - cursor->cur = &man->lru[cursor->priority]; + list_move(&cursor->hitch.link, &man->lru[cursor->priority]); } + ttm_resource_cursor_fini_locked(cursor); + return NULL; } diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index 7d81fd5b5b83..8fac781f641e 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -273,17 +273,22 @@ ttm_lru_item_to_res(struct ttm_lru_item *item) * struct ttm_resource_cursor * * @man: The resource manager currently being iterated over. - * @cur: The list head the cursor currently points to. + * @hitch: A hitch list node inserted before the next resource + * to iterate over. * @priority: the current priority * * Cursor to iterate over the resources in a manager. */ struct ttm_resource_cursor { struct ttm_resource_manager *man; - struct list_head *cur; + struct ttm_lru_item hitch; unsigned int priority; }; +void ttm_resource_cursor_fini_locked(struct ttm_resource_cursor *cursor); + +void ttm_resource_cursor_fini(struct ttm_resource_cursor *cursor); + /** * struct ttm_lru_bulk_move_pos * -- cgit v1.2.3 From 4c44f89c5daee9540cb7428de5d835bd00951350 Mon Sep 17 00:00:00 2001 From: Thomas Hellström Date: Fri, 5 Jul 2024 17:32:02 +0200 Subject: drm/ttm, drm/amdgpu, drm/xe: Consider hitch moves within bulk sublist moves MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To address the problem with hitches moving when bulk move sublists are lru-bumped, register the list cursors with the ttm_lru_bulk_move structure when traversing its list, and when lru-bumping the list, move the cursor hitch to the tail. This also means it's mandatory for drivers to call ttm_lru_bulk_move_init() and ttm_lru_bulk_move_fini() when initializing and finalizing the bulk move structure, so add those calls to the amdgpu- and xe driver. Compared to v1 this is slightly more code but less fragile and hopefully easier to understand. Changes in previous series: - Completely rework the functionality - Avoid a NULL pointer dereference assigning manager->mem_type - Remove some leftover code causing build problems v2: - For hitch bulk tail moves, store the mem_type in the cursor instead of with the manager. v3: - Remove leftover mem_type member from change in v2. v6: - Add some lockdep asserts (Matthew Brost) - Avoid NULL pointer dereference (Matthew Brost) - No need to check bo->resource before dereferencing bo->bulk_move (Matthew Brost) Cc: Christian König Cc: Somalapuram Amaranath Cc: Matthew Brost Cc: Signed-off-by: Thomas Hellström Reviewed-by: Matthew Brost Acked-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20240705153206.68526-5-thomas.hellstrom@linux.intel.com Signed-off-by: Christian König --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 4 ++ drivers/gpu/drm/ttm/ttm_resource.c | 92 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_vm.c | 4 ++ include/drm/ttm/ttm_resource.h | 56 +++++++++++++-------- 4 files changed, 135 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 4e2391c83d7c..6293f3b54b4a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2422,6 +2422,8 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, if (r) return r; + ttm_lru_bulk_move_init(&vm->lru_bulk_move); + vm->is_compute_context = false; vm->use_cpu_for_update = !!(adev->vm_manager.vm_update_mode & @@ -2486,6 +2488,7 @@ error_free_root: error_free_delayed: dma_fence_put(vm->last_tlb_flush); dma_fence_put(vm->last_unlocked); + ttm_lru_bulk_move_fini(&adev->mman.bdev, &vm->lru_bulk_move); amdgpu_vm_fini_entities(vm); return r; @@ -2642,6 +2645,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) } } + ttm_lru_bulk_move_fini(&adev->mman.bdev, &vm->lru_bulk_move); } /** diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 9c8b6499edfb..b6a2daac5518 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -33,6 +33,53 @@ #include +/* Detach the cursor from the bulk move list*/ +static void +ttm_resource_cursor_clear_bulk(struct ttm_resource_cursor *cursor) +{ + lockdep_assert_held(&cursor->man->bdev->lru_lock); + + cursor->bulk = NULL; + list_del_init(&cursor->bulk_link); +} + +/* Move the cursor to the end of the bulk move list it's in */ +static void ttm_resource_cursor_move_bulk_tail(struct ttm_lru_bulk_move *bulk, + struct ttm_resource_cursor *cursor) +{ + struct ttm_lru_bulk_move_pos *pos; + + lockdep_assert_held(&cursor->man->bdev->lru_lock); + + if (WARN_ON_ONCE(bulk != cursor->bulk)) { + list_del_init(&cursor->bulk_link); + return; + } + + pos = &bulk->pos[cursor->mem_type][cursor->priority]; + if (pos->last) + list_move(&cursor->hitch.link, &pos->last->lru.link); + ttm_resource_cursor_clear_bulk(cursor); +} + +/* Move all cursors attached to a bulk move to its end */ +static void ttm_bulk_move_adjust_cursors(struct ttm_lru_bulk_move *bulk) +{ + struct ttm_resource_cursor *cursor, *next; + + list_for_each_entry_safe(cursor, next, &bulk->cursor_list, bulk_link) + ttm_resource_cursor_move_bulk_tail(bulk, cursor); +} + +/* Remove a cursor from an empty bulk move list */ +static void ttm_bulk_move_drop_cursors(struct ttm_lru_bulk_move *bulk) +{ + struct ttm_resource_cursor *cursor, *next; + + list_for_each_entry_safe(cursor, next, &bulk->cursor_list, bulk_link) + ttm_resource_cursor_clear_bulk(cursor); +} + /** * ttm_resource_cursor_fini_locked() - Finalize the LRU list cursor usage * @cursor: The struct ttm_resource_cursor to finalize. @@ -45,6 +92,7 @@ void ttm_resource_cursor_fini_locked(struct ttm_resource_cursor *cursor) { lockdep_assert_held(&cursor->man->bdev->lru_lock); list_del_init(&cursor->hitch.link); + ttm_resource_cursor_clear_bulk(cursor); } /** @@ -73,9 +121,27 @@ void ttm_resource_cursor_fini(struct ttm_resource_cursor *cursor) void ttm_lru_bulk_move_init(struct ttm_lru_bulk_move *bulk) { memset(bulk, 0, sizeof(*bulk)); + INIT_LIST_HEAD(&bulk->cursor_list); } EXPORT_SYMBOL(ttm_lru_bulk_move_init); +/** + * ttm_lru_bulk_move_fini - finalize a bulk move structure + * @bdev: The struct ttm_device + * @bulk: the structure to finalize + * + * Sanity checks that bulk moves don't have any + * resources left and hence no cursors attached. + */ +void ttm_lru_bulk_move_fini(struct ttm_device *bdev, + struct ttm_lru_bulk_move *bulk) +{ + spin_lock(&bdev->lru_lock); + ttm_bulk_move_drop_cursors(bulk); + spin_unlock(&bdev->lru_lock); +} +EXPORT_SYMBOL(ttm_lru_bulk_move_fini); + /** * ttm_lru_bulk_move_tail - bulk move range of resources to the LRU tail. * @@ -88,6 +154,7 @@ void ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move *bulk) { unsigned i, j; + ttm_bulk_move_adjust_cursors(bulk); for (i = 0; i < TTM_NUM_MEM_TYPES; ++i) { for (j = 0; j < TTM_MAX_BO_PRIORITY; ++j) { struct ttm_lru_bulk_move_pos *pos = &bulk->pos[i][j]; @@ -515,6 +582,28 @@ void ttm_resource_manager_debug(struct ttm_resource_manager *man, } EXPORT_SYMBOL(ttm_resource_manager_debug); +static void +ttm_resource_cursor_check_bulk(struct ttm_resource_cursor *cursor, + struct ttm_lru_item *next_lru) +{ + struct ttm_resource *next = ttm_lru_item_to_res(next_lru); + struct ttm_lru_bulk_move *bulk = NULL; + struct ttm_buffer_object *bo = next->bo; + + lockdep_assert_held(&cursor->man->bdev->lru_lock); + bulk = bo->bulk_move; + + if (cursor->bulk != bulk) { + if (bulk) { + list_move_tail(&cursor->bulk_link, &bulk->cursor_list); + cursor->mem_type = next->mem_type; + } else { + list_del_init(&cursor->bulk_link); + } + cursor->bulk = bulk; + } +} + /** * ttm_resource_manager_first() - Start iterating over the resources * of a resource manager @@ -535,6 +624,7 @@ ttm_resource_manager_first(struct ttm_resource_manager *man, cursor->priority = 0; cursor->man = man; ttm_lru_item_init(&cursor->hitch, TTM_LRU_HITCH); + INIT_LIST_HEAD(&cursor->bulk_link); list_add(&cursor->hitch.link, &man->lru[cursor->priority]); return ttm_resource_manager_next(cursor); @@ -559,6 +649,7 @@ ttm_resource_manager_next(struct ttm_resource_cursor *cursor) lru = &cursor->hitch; list_for_each_entry_continue(lru, &man->lru[cursor->priority], link) { if (ttm_lru_item_is_res(lru)) { + ttm_resource_cursor_check_bulk(cursor, lru); list_move(&cursor->hitch.link, &lru->link); return ttm_lru_item_to_res(lru); } @@ -568,6 +659,7 @@ ttm_resource_manager_next(struct ttm_resource_cursor *cursor) break; list_move(&cursor->hitch.link, &man->lru[cursor->priority]); + ttm_resource_cursor_clear_bulk(cursor); } ttm_resource_cursor_fini_locked(cursor); diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 4aa3943e6f29..47b737f10e74 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -1252,6 +1252,8 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) init_rwsem(&vm->userptr.notifier_lock); spin_lock_init(&vm->userptr.invalidated_lock); + ttm_lru_bulk_move_init(&vm->lru_bulk_move); + INIT_LIST_HEAD(&vm->preempt.exec_queues); vm->preempt.min_run_period_ms = 10; /* FIXME: Wire up to uAPI */ @@ -1369,6 +1371,7 @@ err_no_resv: mutex_destroy(&vm->snap_mutex); for_each_tile(tile, xe, id) xe_range_fence_tree_fini(&vm->rftree[id]); + ttm_lru_bulk_move_fini(&xe->ttm, &vm->lru_bulk_move); kfree(vm); if (!(flags & XE_VM_FLAG_MIGRATION)) xe_pm_runtime_put(xe); @@ -1511,6 +1514,7 @@ static void xe_vm_free(struct drm_gpuvm *gpuvm) XE_WARN_ON(vm->pt_root[id]); trace_xe_vm_free(vm); + ttm_lru_bulk_move_fini(&xe->ttm, &vm->lru_bulk_move); kfree(vm); } diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index 8fac781f641e..571abb4861a6 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -269,26 +269,6 @@ ttm_lru_item_to_res(struct ttm_lru_item *item) return container_of(item, struct ttm_resource, lru); } -/** - * struct ttm_resource_cursor - * - * @man: The resource manager currently being iterated over. - * @hitch: A hitch list node inserted before the next resource - * to iterate over. - * @priority: the current priority - * - * Cursor to iterate over the resources in a manager. - */ -struct ttm_resource_cursor { - struct ttm_resource_manager *man; - struct ttm_lru_item hitch; - unsigned int priority; -}; - -void ttm_resource_cursor_fini_locked(struct ttm_resource_cursor *cursor); - -void ttm_resource_cursor_fini(struct ttm_resource_cursor *cursor); - /** * struct ttm_lru_bulk_move_pos * @@ -304,8 +284,9 @@ struct ttm_lru_bulk_move_pos { /** * struct ttm_lru_bulk_move - * * @pos: first/last lru entry for resources in the each domain/priority + * @cursor_list: The list of cursors currently traversing any of + * the sublists of @pos. Protected by the ttm device's lru_lock. * * Container for the current bulk move state. Should be used with * ttm_lru_bulk_move_init() and ttm_bo_set_bulk_move(). @@ -315,8 +296,39 @@ struct ttm_lru_bulk_move_pos { */ struct ttm_lru_bulk_move { struct ttm_lru_bulk_move_pos pos[TTM_NUM_MEM_TYPES][TTM_MAX_BO_PRIORITY]; + struct list_head cursor_list; }; +/** + * struct ttm_resource_cursor + * @man: The resource manager currently being iterated over + * @hitch: A hitch list node inserted before the next resource + * to iterate over. + * @bulk_link: A list link for the list of cursors traversing the + * bulk sublist of @bulk. Protected by the ttm device's lru_lock. + * @bulk: Pointer to struct ttm_lru_bulk_move whose subrange @hitch is + * inserted to. NULL if none. Never dereference this pointer since + * the struct ttm_lru_bulk_move object pointed to might have been + * freed. The pointer is only for comparison. + * @mem_type: The memory type of the LRU list being traversed. + * This field is valid iff @bulk != NULL. + * @priority: the current priority + * + * Cursor to iterate over the resources in a manager. + */ +struct ttm_resource_cursor { + struct ttm_resource_manager *man; + struct ttm_lru_item hitch; + struct list_head bulk_link; + struct ttm_lru_bulk_move *bulk; + unsigned int mem_type; + unsigned int priority; +}; + +void ttm_resource_cursor_fini_locked(struct ttm_resource_cursor *cursor); + +void ttm_resource_cursor_fini(struct ttm_resource_cursor *cursor); + /** * struct ttm_kmap_iter_iomap - Specialization for a struct io_mapping + * struct sg_table backed struct ttm_resource. @@ -405,6 +417,8 @@ ttm_resource_manager_cleanup(struct ttm_resource_manager *man) void ttm_lru_bulk_move_init(struct ttm_lru_bulk_move *bulk); void ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move *bulk); +void ttm_lru_bulk_move_fini(struct ttm_device *bdev, + struct ttm_lru_bulk_move *bulk); void ttm_resource_add_bulk_move(struct ttm_resource *res, struct ttm_buffer_object *bo); -- cgit v1.2.3 From da966b82bf3d16f89a05732c933a589ec798d3f7 Mon Sep 17 00:00:00 2001 From: Thomas Hellström Date: Fri, 5 Jul 2024 17:32:03 +0200 Subject: drm/ttm: Provide a generic LRU walker helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provide a generic LRU walker in TTM, in the spirit of drm_gem_lru_scan() but building on the restartable TTM LRU functionality. The LRU walker optionally supports locking objects as part of a ww mutex locking transaction, to mimic to some extent the current functionality in ttm. However any -EDEADLK return is converted to -ENOSPC and then to -ENOMEM before reaching the driver, so that the driver will need to backoff and possibly retry without being able to keep the ticket. v3: - Move the helper to core ttm. - Remove the drm_exec usage from it for now, it will be reintroduced later in the series. v4: - Handle the -EALREADY case if ticketlocking. v6: - Some cleanup and added code comments (Matthew Brost) - Clarified the ticketlock in the commit message (Matthew Brost) v7: - Use s64 rather than long for the target and progress (Christian König) - Update documentation to not encourage using pages as a progress measure. (Christian König) - Remove cond_resched(). (Christian König) Cc: Christian König Cc: Somalapuram Amaranath Cc: Matthew Brost Cc: Signed-off-by: Thomas Hellström Reviewed-by: Matthew Brost #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20240705153206.68526-6-thomas.hellstrom@linux.intel.com Signed-off-by: Christian König --- drivers/gpu/drm/ttm/ttm_bo_util.c | 151 ++++++++++++++++++++++++++++++++++++++ include/drm/ttm/ttm_bo.h | 35 +++++++++ 2 files changed, 186 insertions(+) diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 0b3f4267130c..c2759add58f5 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -768,3 +768,154 @@ error_destroy_tt: ttm_tt_destroy(bo->bdev, ttm); return ret; } + +static bool ttm_lru_walk_trylock(struct ttm_lru_walk *walk, + struct ttm_buffer_object *bo, + bool *needs_unlock) +{ + struct ttm_operation_ctx *ctx = walk->ctx; + + *needs_unlock = false; + + if (dma_resv_trylock(bo->base.resv)) { + *needs_unlock = true; + return true; + } + + if (bo->base.resv == ctx->resv && ctx->allow_res_evict) { + dma_resv_assert_held(bo->base.resv); + return true; + } + + return false; +} + +static int ttm_lru_walk_ticketlock(struct ttm_lru_walk *walk, + struct ttm_buffer_object *bo, + bool *needs_unlock) +{ + struct dma_resv *resv = bo->base.resv; + int ret; + + if (walk->ctx->interruptible) + ret = dma_resv_lock_interruptible(resv, walk->ticket); + else + ret = dma_resv_lock(resv, walk->ticket); + + if (!ret) { + *needs_unlock = true; + /* + * Only a single ticketlock per loop. Ticketlocks are prone + * to return -EDEADLK causing the eviction to fail, so + * after waiting for the ticketlock, revert back to + * trylocking for this walk. + */ + walk->ticket = NULL; + } else if (ret == -EDEADLK) { + /* Caller needs to exit the ww transaction. */ + ret = -ENOSPC; + } + + return ret; +} + +static void ttm_lru_walk_unlock(struct ttm_buffer_object *bo, bool locked) +{ + if (locked) + dma_resv_unlock(bo->base.resv); +} + +/** + * ttm_lru_walk_for_evict() - Perform a LRU list walk, with actions taken on + * valid items. + * @walk: describe the walks and actions taken + * @bdev: The TTM device. + * @man: The struct ttm_resource manager whose LRU lists we're walking. + * @target: The end condition for the walk. + * + * The LRU lists of @man are walk, and for each struct ttm_resource encountered, + * the corresponding ttm_buffer_object is locked and taken a reference on, and + * the LRU lock is dropped. the LRU lock may be dropped before locking and, in + * that case, it's verified that the item actually remains on the LRU list after + * the lock, and that the buffer object didn't switch resource in between. + * + * With a locked object, the actions indicated by @walk->process_bo are + * performed, and after that, the bo is unlocked, the refcount dropped and the + * next struct ttm_resource is processed. Here, the walker relies on + * TTM's restartable LRU list implementation. + * + * Typically @walk->process_bo() would return the number of pages evicted, + * swapped or shrunken, so that when the total exceeds @target, or when the + * LRU list has been walked in full, iteration is terminated. It's also terminated + * on error. Note that the definition of @target is done by the caller, it + * could have a different meaning than the number of pages. + * + * Note that the way dma_resv individualization is done, locking needs to be done + * either with the LRU lock held (trylocking only) or with a reference on the + * object. + * + * Return: The progress made towards target or negative error code on error. + */ +s64 ttm_lru_walk_for_evict(struct ttm_lru_walk *walk, struct ttm_device *bdev, + struct ttm_resource_manager *man, s64 target) +{ + struct ttm_resource_cursor cursor; + struct ttm_resource *res; + s64 progress = 0; + s64 lret; + + spin_lock(&bdev->lru_lock); + ttm_resource_manager_for_each_res(man, &cursor, res) { + struct ttm_buffer_object *bo = res->bo; + bool bo_needs_unlock = false; + bool bo_locked = false; + int mem_type; + + /* + * Attempt a trylock before taking a reference on the bo, + * since if we do it the other way around, and the trylock fails, + * we need to drop the lru lock to put the bo. + */ + if (ttm_lru_walk_trylock(walk, bo, &bo_needs_unlock)) + bo_locked = true; + else if (!walk->ticket || walk->ctx->no_wait_gpu || + walk->trylock_only) + continue; + + if (!ttm_bo_get_unless_zero(bo)) { + ttm_lru_walk_unlock(bo, bo_needs_unlock); + continue; + } + + mem_type = res->mem_type; + spin_unlock(&bdev->lru_lock); + + lret = 0; + if (!bo_locked) + lret = ttm_lru_walk_ticketlock(walk, bo, &bo_needs_unlock); + + /* + * Note that in between the release of the lru lock and the + * ticketlock, the bo may have switched resource, + * and also memory type, since the resource may have been + * freed and allocated again with a different memory type. + * In that case, just skip it. + */ + if (!lret && bo->resource && bo->resource->mem_type == mem_type) + lret = walk->ops->process_bo(walk, bo); + + ttm_lru_walk_unlock(bo, bo_needs_unlock); + ttm_bo_put(bo); + if (lret == -EBUSY || lret == -EALREADY) + lret = 0; + progress = (lret < 0) ? lret : progress + lret; + + spin_lock(&bdev->lru_lock); + if (progress < 0 || progress >= target) + break; + } + ttm_resource_cursor_fini_locked(&cursor); + spin_unlock(&bdev->lru_lock); + + return progress; +} diff --git a/include/drm/ttm/ttm_bo.h b/include/drm/ttm/ttm_bo.h index ef0f52f56ebc..21fa9d5964ec 100644 --- a/include/drm/ttm/ttm_bo.h +++ b/include/drm/ttm/ttm_bo.h @@ -194,6 +194,41 @@ struct ttm_operation_ctx { uint64_t bytes_moved; }; +struct ttm_lru_walk; + +/** struct ttm_lru_walk_ops - Operations for a LRU walk. */ +struct ttm_lru_walk_ops { + /** + * process_bo - Process this bo. + * @walk: struct ttm_lru_walk describing the walk. + * @bo: A locked and referenced buffer object. + * + * Return: Negative error code on error, User-defined positive value + * (typically, but not always, size of the processed bo) on success. + * On success, the returned values are summed by the walk and the + * walk exits when its target is met. + * 0 also indicates success, -EBUSY means this bo was skipped. + */ + s64 (*process_bo)(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo); +}; + +/** + * struct ttm_lru_walk - Structure describing a LRU walk. + */ +struct ttm_lru_walk { + /** @ops: Pointer to the ops structure. */ + const struct ttm_lru_walk_ops *ops; + /** @ctx: Pointer to the struct ttm_operation_ctx. */ + struct ttm_operation_ctx *ctx; + /** @ticket: The struct ww_acquire_ctx if any. */ + struct ww_acquire_ctx *ticket; + /** @tryock_only: Only use trylock for locking. */ + bool trylock_only; +}; + +s64 ttm_lru_walk_for_evict(struct ttm_lru_walk *walk, struct ttm_device *bdev, + struct ttm_resource_manager *man, s64 target); + /** * ttm_bo_get - reference a struct ttm_buffer_object * -- cgit v1.2.3 From 10efe34dae798c652053d4363871914c478f1475 Mon Sep 17 00:00:00 2001 From: Thomas Hellström Date: Fri, 5 Jul 2024 17:32:04 +0200 Subject: drm/ttm: Use the LRU walker helper for swapping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rework the TTM swapping to use the LRU walker helper. This helps fixing up the ttm_bo_swapout() interface to be consistent about not requiring any locking. For now mimic the current behaviour of using trylock only. We could be using ticket-locks here but defer that until it's deemed necessary. The TTM swapout functionality is a bit weird anyway since it alternates between memory types without exhausting TTM_PL_SYSTEM first. Intentionally keep pages as the unit of progress since changing that to bytes is an unrelated change that can be done later. v6: - Improve on error code translation in the swapout callback (Matthew Brost). v7: - Use s64 rather than long. - Remove ttm_resource_cursor_fini() since it's no longer used. - Rename ttm_resource_cursor_fini_locked() to ttm_resource_cursor_fini(). - Don't swap out pinned bos. Cc: Christian König Cc: Somalapuram Amaranath Cc: Matthew Brost Cc: Signed-off-by: Thomas Hellström Reviewed-by: Matthew Brost #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20240705153206.68526-7-thomas.hellstrom@linux.intel.com Signed-off-by: Christian König --- drivers/gpu/drm/ttm/ttm_bo.c | 116 ++++++++++++++++++++++++------------- drivers/gpu/drm/ttm/ttm_bo_util.c | 2 +- drivers/gpu/drm/ttm/ttm_device.c | 30 ++-------- drivers/gpu/drm/ttm/ttm_resource.c | 23 +------- include/drm/ttm/ttm_bo.h | 5 +- include/drm/ttm/ttm_resource.h | 2 - 6 files changed, 89 insertions(+), 89 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 43eda720657f..f4b2b2bea6cb 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -621,7 +621,7 @@ int ttm_mem_evict_first(struct ttm_device *bdev, if (locked) dma_resv_unlock(res->bo->base.resv); } - ttm_resource_cursor_fini_locked(&cursor); + ttm_resource_cursor_fini(&cursor); if (!bo) { if (busy_bo && !ttm_bo_get_unless_zero(busy_bo)) @@ -1118,12 +1118,24 @@ int ttm_bo_wait_ctx(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx) } EXPORT_SYMBOL(ttm_bo_wait_ctx); -int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, - gfp_t gfp_flags) +/** + * struct ttm_bo_swapout_walk - Parameters for the swapout walk + */ +struct ttm_bo_swapout_walk { + /** @walk: The walk base parameters. */ + struct ttm_lru_walk walk; + /** @gfp_flags: The gfp flags to use for ttm_tt_swapout() */ + gfp_t gfp_flags; +}; + +static s64 +ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo) { - struct ttm_place place; - bool locked; - long ret; + struct ttm_place place = {.mem_type = bo->resource->mem_type}; + struct ttm_bo_swapout_walk *swapout_walk = + container_of(walk, typeof(*swapout_walk), walk); + struct ttm_operation_ctx *ctx = walk->ctx; + s64 ret; /* * While the bo may already reside in SYSTEM placement, set @@ -1131,28 +1143,29 @@ int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, * The driver may use the fact that we're moving from SYSTEM * as an indication that we're about to swap out. */ - memset(&place, 0, sizeof(place)); - place.mem_type = bo->resource->mem_type; - if (!ttm_bo_evict_swapout_allowable(bo, ctx, &place, &locked, NULL)) - return -EBUSY; + if (bo->pin_count || !bo->bdev->funcs->eviction_valuable(bo, &place)) { + ret = -EBUSY; + goto out; + } if (!bo->ttm || !ttm_tt_is_populated(bo->ttm) || bo->ttm->page_flags & TTM_TT_FLAG_EXTERNAL || - bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED || - !ttm_bo_get_unless_zero(bo)) { - if (locked) - dma_resv_unlock(bo->base.resv); - return -EBUSY; + bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED) { + ret = -EBUSY; + goto out; } if (bo->deleted) { - ret = ttm_bo_cleanup_refs(bo, false, false, locked); - ttm_bo_put(bo); - return ret == -EBUSY ? -ENOSPC : ret; - } + pgoff_t num_pages = bo->ttm->num_pages; - /* TODO: Cleanup the locking */ - spin_unlock(&bo->bdev->lru_lock); + ret = ttm_bo_wait_ctx(bo, ctx); + if (ret) + goto out; + + ttm_bo_cleanup_memtype_use(bo); + ret = num_pages; + goto out; + } /* * Move to system cached @@ -1164,12 +1177,13 @@ int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, memset(&hop, 0, sizeof(hop)); place.mem_type = TTM_PL_SYSTEM; ret = ttm_resource_alloc(bo, &place, &evict_mem); - if (unlikely(ret)) + if (ret) goto out; ret = ttm_bo_handle_move_mem(bo, evict_mem, true, ctx, &hop); - if (unlikely(ret != 0)) { - WARN(ret == -EMULTIHOP, "Unexpected multihop in swaput - likely driver bug.\n"); + if (ret) { + WARN(ret == -EMULTIHOP, + "Unexpected multihop in swapout - likely driver bug.\n"); ttm_resource_free(bo, &evict_mem); goto out; } @@ -1179,30 +1193,54 @@ int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, * Make sure BO is idle. */ ret = ttm_bo_wait_ctx(bo, ctx); - if (unlikely(ret != 0)) + if (ret) goto out; ttm_bo_unmap_virtual(bo); - - /* - * Swap out. Buffer will be swapped in again as soon as - * anyone tries to access a ttm page. - */ if (bo->bdev->funcs->swap_notify) bo->bdev->funcs->swap_notify(bo); if (ttm_tt_is_populated(bo->ttm)) - ret = ttm_tt_swapout(bo->bdev, bo->ttm, gfp_flags); + ret = ttm_tt_swapout(bo->bdev, bo->ttm, swapout_walk->gfp_flags); + out: + /* Consider -ENOMEM and -ENOSPC non-fatal. */ + if (ret == -ENOMEM || ret == -ENOSPC) + ret = -EBUSY; - /* - * Unreserve without putting on LRU to avoid swapping out an - * already swapped buffer. - */ - if (locked) - dma_resv_unlock(bo->base.resv); - ttm_bo_put(bo); - return ret == -EBUSY ? -ENOSPC : ret; + return ret; +} + +const struct ttm_lru_walk_ops ttm_swap_ops = { + .process_bo = ttm_bo_swapout_cb, +}; + +/** + * ttm_bo_swapout() - Swap out buffer objects on the LRU list to shmem. + * @bdev: The ttm device. + * @ctx: The ttm_operation_ctx governing the swapout operation. + * @man: The resource manager whose resources / buffer objects are + * goint to be swapped out. + * @gfp_flags: The gfp flags used for shmem page allocations. + * @target: The desired number of bytes to swap out. + * + * Return: The number of bytes actually swapped out, or negative error code + * on error. + */ +s64 ttm_bo_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx, + struct ttm_resource_manager *man, gfp_t gfp_flags, + s64 target) +{ + struct ttm_bo_swapout_walk swapout_walk = { + .walk = { + .ops = &ttm_swap_ops, + .ctx = ctx, + .trylock_only = true, + }, + .gfp_flags = gfp_flags, + }; + + return ttm_lru_walk_for_evict(&swapout_walk.walk, bdev, man, target); } void ttm_bo_tt_destroy(struct ttm_buffer_object *bo) diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index c2759add58f5..3c07f4712d5c 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -914,7 +914,7 @@ s64 ttm_lru_walk_for_evict(struct ttm_lru_walk *walk, struct ttm_device *bdev, if (progress < 0 || progress >= target) break; } - ttm_resource_cursor_fini_locked(&cursor); + ttm_resource_cursor_fini(&cursor); spin_unlock(&bdev->lru_lock); return progress; diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c index f9e9b1ec8c8a..e7cc4954c1bc 100644 --- a/drivers/gpu/drm/ttm/ttm_device.c +++ b/drivers/gpu/drm/ttm/ttm_device.c @@ -148,40 +148,20 @@ int ttm_global_swapout(struct ttm_operation_ctx *ctx, gfp_t gfp_flags) int ttm_device_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx, gfp_t gfp_flags) { - struct ttm_resource_cursor cursor; struct ttm_resource_manager *man; - struct ttm_resource *res; unsigned i; - int ret; + s64 lret; - spin_lock(&bdev->lru_lock); for (i = TTM_PL_SYSTEM; i < TTM_NUM_MEM_TYPES; ++i) { man = ttm_manager_type(bdev, i); if (!man || !man->use_tt) continue; - ttm_resource_manager_for_each_res(man, &cursor, res) { - struct ttm_buffer_object *bo = res->bo; - uint32_t num_pages; - - if (!bo || bo->resource != res) - continue; - - num_pages = PFN_UP(bo->base.size); - ret = ttm_bo_swapout(bo, ctx, gfp_flags); - /* ttm_bo_swapout has dropped the lru_lock */ - if (!ret) { - ttm_resource_cursor_fini(&cursor); - return num_pages; - } - if (ret != -EBUSY) { - ttm_resource_cursor_fini(&cursor); - return ret; - } - } + lret = ttm_bo_swapout(bdev, ctx, man, gfp_flags, 1); + /* Can be both positive (num_pages) and negative (error) */ + if (lret) + return lret; } - ttm_resource_cursor_fini_locked(&cursor); - spin_unlock(&bdev->lru_lock); return 0; } EXPORT_SYMBOL(ttm_device_swapout); diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index b6a2daac5518..b43d04a1dc91 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -81,37 +81,20 @@ static void ttm_bulk_move_drop_cursors(struct ttm_lru_bulk_move *bulk) } /** - * ttm_resource_cursor_fini_locked() - Finalize the LRU list cursor usage + * ttm_resource_cursor_fini() - Finalize the LRU list cursor usage * @cursor: The struct ttm_resource_cursor to finalize. * * The function pulls the LRU list cursor off any lists it was previusly * attached to. Needs to be called with the LRU lock held. The function * can be called multiple times after eachother. */ -void ttm_resource_cursor_fini_locked(struct ttm_resource_cursor *cursor) +void ttm_resource_cursor_fini(struct ttm_resource_cursor *cursor) { lockdep_assert_held(&cursor->man->bdev->lru_lock); list_del_init(&cursor->hitch.link); ttm_resource_cursor_clear_bulk(cursor); } -/** - * ttm_resource_cursor_fini() - Finalize the LRU list cursor usage - * @cursor: The struct ttm_resource_cursor to finalize. - * - * The function pulls the LRU list cursor off any lists it was previusly - * attached to. Needs to be called without the LRU list lock held. The - * function can be called multiple times after eachother. - */ -void ttm_resource_cursor_fini(struct ttm_resource_cursor *cursor) -{ - spinlock_t *lru_lock = &cursor->man->bdev->lru_lock; - - spin_lock(lru_lock); - ttm_resource_cursor_fini_locked(cursor); - spin_unlock(lru_lock); -} - /** * ttm_lru_bulk_move_init - initialize a bulk move structure * @bulk: the structure to init @@ -662,7 +645,7 @@ ttm_resource_manager_next(struct ttm_resource_cursor *cursor) ttm_resource_cursor_clear_bulk(cursor); } - ttm_resource_cursor_fini_locked(cursor); + ttm_resource_cursor_fini(cursor); return NULL; } diff --git a/include/drm/ttm/ttm_bo.h b/include/drm/ttm/ttm_bo.h index 21fa9d5964ec..eb2692de06b8 100644 --- a/include/drm/ttm/ttm_bo.h +++ b/include/drm/ttm/ttm_bo.h @@ -417,8 +417,9 @@ void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map); int ttm_bo_vmap(struct ttm_buffer_object *bo, struct iosys_map *map); void ttm_bo_vunmap(struct ttm_buffer_object *bo, struct iosys_map *map); int ttm_bo_mmap_obj(struct vm_area_struct *vma, struct ttm_buffer_object *bo); -int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, - gfp_t gfp_flags); +s64 ttm_bo_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx, + struct ttm_resource_manager *man, gfp_t gfp_flags, + s64 target); void ttm_bo_pin(struct ttm_buffer_object *bo); void ttm_bo_unpin(struct ttm_buffer_object *bo); int ttm_mem_evict_first(struct ttm_device *bdev, diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index 571abb4861a6..be034be56ba1 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -325,8 +325,6 @@ struct ttm_resource_cursor { unsigned int priority; }; -void ttm_resource_cursor_fini_locked(struct ttm_resource_cursor *cursor); - void ttm_resource_cursor_fini(struct ttm_resource_cursor *cursor); /** -- cgit v1.2.3 From 3756310e9fe1e0182adac89cedaa98c0eea66675 Mon Sep 17 00:00:00 2001 From: Thomas Hellström Date: Fri, 5 Jul 2024 17:32:05 +0200 Subject: drm/ttm: Use the LRU walker for eviction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the LRU walker for eviction. This helps removing a lot of code with weird locking semantics. The functionality is slightly changed so that when trylocked buffer objects are exhausted, we continue to interleave walks with ticket-locks while there is still progress made. The list walks are not restarted in-between evictions. Also provide a separate ttm_bo_evict_first() function for its single user. The context of that user allows sleeping dma_resv locks. v6: - Various cleanups suggested by Matthew Brost. - Fix error return code of ttm_bo_evict_first(). (Matthew Brost) - Fix an error check that was inverted. (Matthew Brost) v7: - Use s64 rather than long (Christian König) - Early ttm_resource_cursor_fini() in ttm_bo_evict_first(). - Simplify check for bo_moved in ttm_bo_evict_first(). (Christian König) - Don't evict pinned bos. Cc: Christian König Cc: Somalapuram Amaranath Cc: Matthew Brost Cc: Signed-off-by: Thomas Hellström Reviewed-by: Matthew Brost #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20240705153206.68526-8-thomas.hellstrom@linux.intel.com Signed-off-by: Christian König --- drivers/gpu/drm/ttm/ttm_bo.c | 345 +++++++++++++++---------------------- drivers/gpu/drm/ttm/ttm_resource.c | 21 +-- include/drm/ttm/ttm_bo.h | 8 +- 3 files changed, 143 insertions(+), 231 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index f4b2b2bea6cb..0131ec802066 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -224,80 +224,6 @@ static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo) dma_resv_iter_end(&cursor); } -/** - * ttm_bo_cleanup_refs - * If bo idle, remove from lru lists, and unref. - * If not idle, block if possible. - * - * Must be called with lru_lock and reservation held, this function - * will drop the lru lock and optionally the reservation lock before returning. - * - * @bo: The buffer object to clean-up - * @interruptible: Any sleeps should occur interruptibly. - * @no_wait_gpu: Never wait for gpu. Return -EBUSY instead. - * @unlock_resv: Unlock the reservation lock as well. - */ - -static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, - bool interruptible, bool no_wait_gpu, - bool unlock_resv) -{ - struct dma_resv *resv = &bo->base._resv; - int ret; - - if (dma_resv_test_signaled(resv, DMA_RESV_USAGE_BOOKKEEP)) - ret = 0; - else - ret = -EBUSY; - - if (ret && !no_wait_gpu) { - long lret; - - if (unlock_resv) - dma_resv_unlock(bo->base.resv); - spin_unlock(&bo->bdev->lru_lock); - - lret = dma_resv_wait_timeout(resv, DMA_RESV_USAGE_BOOKKEEP, - interruptible, - 30 * HZ); - - if (lret < 0) - return lret; - else if (lret == 0) - return -EBUSY; - - spin_lock(&bo->bdev->lru_lock); - if (unlock_resv && !dma_resv_trylock(bo->base.resv)) { - /* - * We raced, and lost, someone else holds the reservation now, - * and is probably busy in ttm_bo_cleanup_memtype_use. - * - * Even if it's not the case, because we finished waiting any - * delayed destruction would succeed, so just return success - * here. - */ - spin_unlock(&bo->bdev->lru_lock); - return 0; - } - ret = 0; - } - - if (ret) { - if (unlock_resv) - dma_resv_unlock(bo->base.resv); - spin_unlock(&bo->bdev->lru_lock); - return ret; - } - - spin_unlock(&bo->bdev->lru_lock); - ttm_bo_cleanup_memtype_use(bo); - - if (unlock_resv) - dma_resv_unlock(bo->base.resv); - - return 0; -} - /* * Block for the dma_resv object to become idle, lock the buffer and clean up * the resource and tt object. @@ -505,151 +431,152 @@ bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, } EXPORT_SYMBOL(ttm_bo_eviction_valuable); -/* - * Check the target bo is allowable to be evicted or swapout, including cases: - * - * a. if share same reservation object with ctx->resv, have assumption - * reservation objects should already be locked, so not lock again and - * return true directly when either the opreation allow_reserved_eviction - * or the target bo already is in delayed free list; +/** + * ttm_bo_evict_first() - Evict the first bo on the manager's LRU list. + * @bdev: The ttm device. + * @man: The manager whose bo to evict. + * @ctx: The TTM operation ctx governing the eviction. * - * b. Otherwise, trylock it. + * Return: 0 if successful or the resource disappeared. Negative error code on error. */ -static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo, - struct ttm_operation_ctx *ctx, - const struct ttm_place *place, - bool *locked, bool *busy) +int ttm_bo_evict_first(struct ttm_device *bdev, struct ttm_resource_manager *man, + struct ttm_operation_ctx *ctx) { - bool ret = false; + struct ttm_resource_cursor cursor; + struct ttm_buffer_object *bo; + struct ttm_resource *res; + unsigned int mem_type; + int ret = 0; - if (bo->pin_count) { - *locked = false; - if (busy) - *busy = false; - return false; + spin_lock(&bdev->lru_lock); + res = ttm_resource_manager_first(man, &cursor); + ttm_resource_cursor_fini(&cursor); + if (!res) { + ret = -ENOENT; + goto out_no_ref; } + bo = res->bo; + if (!ttm_bo_get_unless_zero(bo)) + goto out_no_ref; + mem_type = res->mem_type; + spin_unlock(&bdev->lru_lock); + ret = ttm_bo_reserve(bo, ctx->interruptible, ctx->no_wait_gpu, NULL); + if (ret) + goto out_no_lock; + if (!bo->resource || bo->resource->mem_type != mem_type) + goto out_bo_moved; - if (bo->base.resv == ctx->resv) { - dma_resv_assert_held(bo->base.resv); - if (ctx->allow_res_evict) - ret = true; - *locked = false; - if (busy) - *busy = false; + if (bo->deleted) { + ret = ttm_bo_wait_ctx(bo, ctx); + if (!ret) + ttm_bo_cleanup_memtype_use(bo); } else { - ret = dma_resv_trylock(bo->base.resv); - *locked = ret; - if (busy) - *busy = !ret; - } - - if (ret && place && (bo->resource->mem_type != place->mem_type || - !bo->bdev->funcs->eviction_valuable(bo, place))) { - ret = false; - if (*locked) { - dma_resv_unlock(bo->base.resv); - *locked = false; - } + ret = ttm_bo_evict(bo, ctx); } +out_bo_moved: + dma_resv_unlock(bo->base.resv); +out_no_lock: + ttm_bo_put(bo); + return ret; +out_no_ref: + spin_unlock(&bdev->lru_lock); return ret; } /** - * ttm_mem_evict_wait_busy - wait for a busy BO to become available - * - * @busy_bo: BO which couldn't be locked with trylock - * @ctx: operation context - * @ticket: acquire ticket - * - * Try to lock a busy buffer object to avoid failing eviction. + * struct ttm_bo_evict_walk - Parameters for the evict walk. */ -static int ttm_mem_evict_wait_busy(struct ttm_buffer_object *busy_bo, - struct ttm_operation_ctx *ctx, - struct ww_acquire_ctx *ticket) -{ - int r; - - if (!busy_bo || !ticket) - return -EBUSY; - - if (ctx->interruptible) - r = dma_resv_lock_interruptible(busy_bo->base.resv, - ticket); - else - r = dma_resv_lock(busy_bo->base.resv, ticket); - - /* - * TODO: It would be better to keep the BO locked until allocation is at - * least tried one more time, but that would mean a much larger rework - * of TTM. - */ - if (!r) - dma_resv_unlock(busy_bo->base.resv); - - return r == -EDEADLK ? -EBUSY : r; -} +struct ttm_bo_evict_walk { + /** @walk: The walk base parameters. */ + struct ttm_lru_walk walk; + /** @place: The place passed to the resource allocation. */ + const struct ttm_place *place; + /** @evictor: The buffer object we're trying to make room for. */ + struct ttm_buffer_object *evictor; + /** @res: The allocated resource if any. */ + struct ttm_resource **res; + /** @evicted: Number of successful evictions. */ + unsigned long evicted; +}; -int ttm_mem_evict_first(struct ttm_device *bdev, - struct ttm_resource_manager *man, - const struct ttm_place *place, - struct ttm_operation_ctx *ctx, - struct ww_acquire_ctx *ticket) +static s64 ttm_bo_evict_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo) { - struct ttm_buffer_object *bo = NULL, *busy_bo = NULL; - struct ttm_resource_cursor cursor; - struct ttm_resource *res; - bool locked = false; - int ret; + struct ttm_bo_evict_walk *evict_walk = + container_of(walk, typeof(*evict_walk), walk); + s64 lret; - spin_lock(&bdev->lru_lock); - ttm_resource_manager_for_each_res(man, &cursor, res) { - bool busy; - - if (!ttm_bo_evict_swapout_allowable(res->bo, ctx, place, - &locked, &busy)) { - if (busy && !busy_bo && ticket != - dma_resv_locking_ctx(res->bo->base.resv)) - busy_bo = res->bo; - continue; - } + if (bo->pin_count || !bo->bdev->funcs->eviction_valuable(bo, evict_walk->place)) + return 0; - if (ttm_bo_get_unless_zero(res->bo)) { - bo = res->bo; - break; - } - if (locked) - dma_resv_unlock(res->bo->base.resv); + if (bo->deleted) { + lret = ttm_bo_wait_ctx(bo, walk->ctx); + if (!lret) + ttm_bo_cleanup_memtype_use(bo); + } else { + lret = ttm_bo_evict(bo, walk->ctx); } - ttm_resource_cursor_fini(&cursor); - if (!bo) { - if (busy_bo && !ttm_bo_get_unless_zero(busy_bo)) - busy_bo = NULL; - spin_unlock(&bdev->lru_lock); - ret = ttm_mem_evict_wait_busy(busy_bo, ctx, ticket); - if (busy_bo) - ttm_bo_put(busy_bo); - return ret; - } + if (lret) + goto out; - if (bo->deleted) { - ret = ttm_bo_cleanup_refs(bo, ctx->interruptible, - ctx->no_wait_gpu, locked); - ttm_bo_put(bo); - return ret; - } + evict_walk->evicted++; + if (evict_walk->res) + lret = ttm_resource_alloc(evict_walk->evictor, evict_walk->place, + evict_walk->res); + if (lret == 0) + return 1; +out: + /* Errors that should terminate the walk. */ + if (lret == -ENOSPC) + return -EBUSY; - spin_unlock(&bdev->lru_lock); + return lret; +} - ret = ttm_bo_evict(bo, ctx); - if (locked) - ttm_bo_unreserve(bo); - else - ttm_bo_move_to_lru_tail_unlocked(bo); +static const struct ttm_lru_walk_ops ttm_evict_walk_ops = { + .process_bo = ttm_bo_evict_cb, +}; - ttm_bo_put(bo); - return ret; +static int ttm_bo_evict_alloc(struct ttm_device *bdev, + struct ttm_resource_manager *man, + const struct ttm_place *place, + struct ttm_buffer_object *evictor, + struct ttm_operation_ctx *ctx, + struct ww_acquire_ctx *ticket, + struct ttm_resource **res) +{ + struct ttm_bo_evict_walk evict_walk = { + .walk = { + .ops = &ttm_evict_walk_ops, + .ctx = ctx, + .ticket = ticket, + }, + .place = place, + .evictor = evictor, + .res = res, + }; + s64 lret; + + evict_walk.walk.trylock_only = true; + lret = ttm_lru_walk_for_evict(&evict_walk.walk, bdev, man, 1); + if (lret || !ticket) + goto out; + + /* If ticket-locking, repeat while making progress. */ + evict_walk.walk.trylock_only = false; + do { + /* The walk may clear the evict_walk.walk.ticket field */ + evict_walk.walk.ticket = ticket; + evict_walk.evicted = 0; + lret = ttm_lru_walk_for_evict(&evict_walk.walk, bdev, man, 1); + } while (!lret && evict_walk.evicted); +out: + if (lret < 0) + return lret; + if (lret == 0) + return -EBUSY; + return 0; } /** @@ -760,6 +687,7 @@ static int ttm_bo_alloc_resource(struct ttm_buffer_object *bo, for (i = 0; i < placement->num_placement; ++i) { const struct ttm_place *place = &placement->placement[i]; struct ttm_resource_manager *man; + bool may_evict; man = ttm_manager_type(bdev, place->mem_type); if (!man || !ttm_resource_manager_used(man)) @@ -769,22 +697,21 @@ static int ttm_bo_alloc_resource(struct ttm_buffer_object *bo, TTM_PL_FLAG_FALLBACK)) continue; - do { - ret = ttm_resource_alloc(bo, place, res); - if (unlikely(ret && ret != -ENOSPC)) + may_evict = (force_space && place->mem_type != TTM_PL_SYSTEM); + ret = ttm_resource_alloc(bo, place, res); + if (ret) { + if (ret != -ENOSPC) return ret; - if (likely(!ret) || !force_space) - break; - - ret = ttm_mem_evict_first(bdev, man, place, ctx, - ticket); - if (unlikely(ret == -EBUSY)) - break; - if (unlikely(ret)) + if (!may_evict) + continue; + + ret = ttm_bo_evict_alloc(bdev, man, place, bo, ctx, + ticket, res); + if (ret == -EBUSY) + continue; + if (ret) return ret; - } while (1); - if (ret) - continue; + } ret = ttm_bo_add_move_fence(bo, man, ctx->no_wait_gpu); if (unlikely(ret)) { diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index b43d04a1dc91..6d764ba88aab 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -495,24 +495,11 @@ int ttm_resource_manager_evict_all(struct ttm_device *bdev, }; struct dma_fence *fence; int ret; - unsigned i; - - /* - * Can't use standard list traversal since we're unlocking. - */ - spin_lock(&bdev->lru_lock); - for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { - while (!list_empty(&man->lru[i])) { - spin_unlock(&bdev->lru_lock); - ret = ttm_mem_evict_first(bdev, man, NULL, &ctx, - NULL); - if (ret) - return ret; - spin_lock(&bdev->lru_lock); - } - } - spin_unlock(&bdev->lru_lock); + do { + ret = ttm_bo_evict_first(bdev, man, &ctx); + cond_resched(); + } while (!ret); spin_lock(&man->move_lock); fence = dma_fence_get(man->move); diff --git a/include/drm/ttm/ttm_bo.h b/include/drm/ttm/ttm_bo.h index eb2692de06b8..d1a732d56259 100644 --- a/include/drm/ttm/ttm_bo.h +++ b/include/drm/ttm/ttm_bo.h @@ -422,11 +422,9 @@ s64 ttm_bo_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx, s64 target); void ttm_bo_pin(struct ttm_buffer_object *bo); void ttm_bo_unpin(struct ttm_buffer_object *bo); -int ttm_mem_evict_first(struct ttm_device *bdev, - struct ttm_resource_manager *man, - const struct ttm_place *place, - struct ttm_operation_ctx *ctx, - struct ww_acquire_ctx *ticket); +int ttm_bo_evict_first(struct ttm_device *bdev, + struct ttm_resource_manager *man, + struct ttm_operation_ctx *ctx); vm_fault_t ttm_bo_vm_reserve(struct ttm_buffer_object *bo, struct vm_fault *vmf); vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, -- cgit v1.2.3 From 223c12dd492d67d90d3712ef3d9e042116a47522 Mon Sep 17 00:00:00 2001 From: Manikandan Muralidharan Date: Mon, 1 Jul 2024 14:28:35 +0530 Subject: dt-bindings: display: himax-hx8394: Add Microchip AC40T08A MIPI Display panel Add compatible string for the Microchip's AC40T08A MIPI Display panel.This panel uses a Himax HX8394 display controller. The reset line is not populated and leads to driver probe issues, thus add conditional block to narrow reset-gpio property per variant. Signed-off-by: Manikandan Muralidharan Reviewed-by: Conor Dooley Link: https://lore.kernel.org/r/20240701085837.50855-2-manikandan.m@microchip.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240701085837.50855-2-manikandan.m@microchip.com --- .../devicetree/bindings/display/panel/himax,hx8394.yaml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml b/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml index 644387e4fb6f..75ccabff308b 100644 --- a/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml +++ b/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml @@ -15,14 +15,12 @@ description: such as the HannStar HSD060BHW4 720x1440 TFT LCD panel connected with a MIPI-DSI video interface. -allOf: - - $ref: panel-common.yaml# - properties: compatible: items: - enum: - hannstar,hsd060bhw4 + - microchip,ac40t08a-mipi-panel - powkiddy,x55-panel - const: himax,hx8394 @@ -46,7 +44,6 @@ properties: required: - compatible - reg - - reset-gpios - backlight - port - vcc-supply @@ -54,6 +51,18 @@ required: additionalProperties: false +allOf: + - $ref: panel-common.yaml# + - if: + not: + properties: + compatible: + enum: + - microchip,ac40t08a-mipi-panel + then: + required: + - reset-gpios + examples: - | #include -- cgit v1.2.3 From 1dcfca093be9e013a53e3c9b74b3f60ea9c5160e Mon Sep 17 00:00:00 2001 From: Manikandan Muralidharan Date: Mon, 1 Jul 2024 14:28:36 +0530 Subject: drm/panel: himax-hx8394: switch to devm_gpiod_get_optional() for reset_gpio Switch the driver to use devm_gpiod_get_optional() on reset_gpio to avoid driver probe issues when reset line is not specified. Signed-off-by: Manikandan Muralidharan Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20240701085837.50855-3-manikandan.m@microchip.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240701085837.50855-3-manikandan.m@microchip.com --- drivers/gpu/drm/panel/panel-himax-hx8394.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panel/panel-himax-hx8394.c b/drivers/gpu/drm/panel/panel-himax-hx8394.c index cb9f46e853de..3be461fc5615 100644 --- a/drivers/gpu/drm/panel/panel-himax-hx8394.c +++ b/drivers/gpu/drm/panel/panel-himax-hx8394.c @@ -486,7 +486,7 @@ static int hx8394_probe(struct mipi_dsi_device *dsi) if (!ctx) return -ENOMEM; - ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(ctx->reset_gpio)) return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset gpio\n"); -- cgit v1.2.3 From 014e597d35816b56c7aac1348b77c73657c4066e Mon Sep 17 00:00:00 2001 From: Manikandan Muralidharan Date: Mon, 1 Jul 2024 14:28:37 +0530 Subject: drm/panel: himax-hx8394: Add Support for Microchip AC40T08A MIPI Display Panel Add support for the Microchip AC40T08A MIPI Display panel. This panel uses a Himax HX8394 display controller and requires a vendor provided init sequence. The display resolution is 720x1280@60Hz with width and height of 76mm and 132mm respectively. Signed-off-by: Manikandan Muralidharan Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20240701085837.50855-4-manikandan.m@microchip.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240701085837.50855-4-manikandan.m@microchip.com --- drivers/gpu/drm/panel/panel-himax-hx8394.c | 151 +++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-himax-hx8394.c b/drivers/gpu/drm/panel/panel-himax-hx8394.c index 3be461fc5615..92b03a2f65a3 100644 --- a/drivers/gpu/drm/panel/panel-himax-hx8394.c +++ b/drivers/gpu/drm/panel/panel-himax-hx8394.c @@ -339,6 +339,156 @@ static const struct hx8394_panel_desc powkiddy_x55_desc = { .init_sequence = powkiddy_x55_init_sequence, }; +static int mchp_ac40t08a_init_sequence(struct hx8394 *ctx) +{ + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + + /* DCS commands do not seem to be sent correclty without this delay */ + msleep(20); + + /* 5.19.8 SETEXTC: Set extension command (B9h) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETEXTC, + 0xff, 0x83, 0x94); + + /* 5.19.9 SETMIPI: Set MIPI control (BAh) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETMIPI, + 0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0); + + /* 5.19.2 SETPOWER: Set power (B1h) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER, + 0x48, 0x12, 0x72, 0x09, 0x32, 0x54, + 0x71, 0x71, 0x57, 0x47); + + /* 5.19.3 SETDISP: Set display related register (B2h) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETDISP, + 0x00, 0x80, 0x64, 0x0c, 0x0d, 0x2f); + + /* 5.19.4 SETCYC: Set display waveform cycles (B4h) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETCYC, + 0x73, 0x74, 0x73, 0x74, 0x73, 0x74, + 0x01, 0x0c, 0x86, 0x75, 0x00, 0x3f, + 0x73, 0x74, 0x73, 0x74, 0x73, 0x74, + 0x01, 0x0c, 0x86); + + /* 5.19.5 SETVCOM: Set VCOM voltage (B6h) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETVCOM, + 0x6e, 0x6e); + + /* 5.19.19 SETGIP0: Set GIP Option0 (D3h) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP0, + 0x00, 0x00, 0x07, 0x07, 0x40, 0x07, + 0x0c, 0x00, 0x08, 0x10, 0x08, 0x00, + 0x08, 0x54, 0x15, 0x0a, 0x05, 0x0a, + 0x02, 0x15, 0x06, 0x05, 0x06, 0x47, + 0x44, 0x0a, 0x0a, 0x4b, 0x10, 0x07, + 0x07, 0x0c, 0x40); + + /* 5.19.20 Set GIP Option1 (D5h) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP1, + 0x1c, 0x1c, 0x1d, 0x1d, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x24, 0x25, + 0x18, 0x18, 0x26, 0x27, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x20, 0x21, 0x18, 0x18, + 0x18, 0x18); + + /* 5.19.21 Set GIP Option2 (D6h) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP2, + 0x1c, 0x1c, 0x1d, 0x1d, 0x07, 0x06, + 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x0b, 0x0a, 0x09, 0x08, 0x21, 0x20, + 0x18, 0x18, 0x27, 0x26, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x25, 0x24, 0x18, 0x18, + 0x18, 0x18); + + /* 5.19.25 SETGAMMA: Set gamma curve related setting (E0h) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGAMMA, + 0x00, 0x0a, 0x15, 0x1b, 0x1e, 0x21, + 0x24, 0x22, 0x47, 0x56, 0x65, 0x66, + 0x6e, 0x82, 0x88, 0x8b, 0x9a, 0x9d, + 0x98, 0xa8, 0xb9, 0x5d, 0x5c, 0x61, + 0x66, 0x6a, 0x6f, 0x7f, 0x7f, 0x00, + 0x0a, 0x15, 0x1b, 0x1e, 0x21, 0x24, + 0x22, 0x47, 0x56, 0x65, 0x65, 0x6e, + 0x81, 0x87, 0x8b, 0x98, 0x9d, 0x99, + 0xa8, 0xba, 0x5d, 0x5d, 0x62, 0x67, + 0x6b, 0x72, 0x7f, 0x7f); + + /* Unknown command, not listed in the HX8394-F datasheet (C0H) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN1, + 0x1f, 0x73); + + /* Set CABC control (C9h)*/ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETCABC, + 0x76, 0x00, 0x30); + + /* 5.19.17 SETPANEL (CCh) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPANEL, + 0x0b); + + /* Unknown command, not listed in the HX8394-F datasheet (D4h) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN3, + 0x02); + + /* 5.19.11 Set register bank (BDh) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, + 0x02); + + /* 5.19.11 Set register bank (D8h) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN4, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff); + + /* 5.19.11 Set register bank (BDh) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, + 0x00); + + /* 5.19.11 Set register bank (BDh) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, + 0x01); + + /* 5.19.2 SETPOWER: Set power (B1h) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER, + 0x00); + + /* 5.19.11 Set register bank (BDh) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, + 0x00); + + /* Unknown command, not listed in the HX8394-F datasheet (C6h) */ + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN2, + 0xed); + + return 0; +} + +static const struct drm_display_mode mchp_ac40t08a_mode = { + .hdisplay = 720, + .hsync_start = 720 + 12, + .hsync_end = 720 + 12 + 24, + .htotal = 720 + 12 + 12 + 24, + .vdisplay = 1280, + .vsync_start = 1280 + 13, + .vsync_end = 1280 + 14, + .vtotal = 1280 + 14 + 13, + .clock = 60226, + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, + .width_mm = 76, + .height_mm = 132, +}; + +static const struct hx8394_panel_desc mchp_ac40t08a_desc = { + .mode = &mchp_ac40t08a_mode, + .lanes = 4, + .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST, + .format = MIPI_DSI_FMT_RGB888, + .init_sequence = mchp_ac40t08a_init_sequence, +}; + static int hx8394_enable(struct drm_panel *panel) { struct hx8394 *ctx = panel_to_hx8394(panel); @@ -555,6 +705,7 @@ static void hx8394_remove(struct mipi_dsi_device *dsi) static const struct of_device_id hx8394_of_match[] = { { .compatible = "hannstar,hsd060bhw4", .data = &hsd060bhw4_desc }, { .compatible = "powkiddy,x55-panel", .data = &powkiddy_x55_desc }, + { .compatible = "microchip,ac40t08a-mipi-panel", .data = &mchp_ac40t08a_desc }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, hx8394_of_match); -- cgit v1.2.3 From e7305ad465b50deaa7a9f3a97dde3b22cbd00474 Mon Sep 17 00:00:00 2001 From: Cong Yang Date: Thu, 4 Jul 2024 12:50:15 +0800 Subject: dt-bindings: display: panel: Add compatible for melfas lmfbx101117480 The Melfas lmfbx101117480 is a 10.1" WXGA TFT LCD panel with jadard-jd9365da controller. Hence, we add a new compatible with panel specific config. Signed-off-by: Cong Yang Acked-by: Conor Dooley Link: https://lore.kernel.org/r/20240704045017.2781991-2-yangcong5@huaqin.corp-partner.google.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240704045017.2781991-2-yangcong5@huaqin.corp-partner.google.com --- Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml b/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml index 3d5bede98cf1..b8783eba3ddc 100644 --- a/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml +++ b/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml @@ -18,6 +18,7 @@ properties: - enum: - chongzhou,cz101b4001 - kingdisplay,kd101ne3-40ti + - melfas,lmfbx101117480 - radxa,display-10hd-ad001 - radxa,display-8hd-ad002 - const: jadard,jd9365da-h3 -- cgit v1.2.3 From c4ce398cf18ae2859cc9930a9486b576ce262de9 Mon Sep 17 00:00:00 2001 From: Cong Yang Date: Thu, 4 Jul 2024 12:50:16 +0800 Subject: drm/panel: jd9365da: Support for Melfas lmfbx101117480 MIPI-DSI panel The Melfas lmfbx101117480 is a 10.1" WXGA TFT-LCD panel, use jd9365da controller, which fits in nicely with the existing panel-jadard-jd9365da-h3 driver. Hence, we add a new compatible with panel specific config. Signed-off-by: Cong Yang Acked-by: Linus Walleij Reviewed-by: Douglas Anderson Link: https://lore.kernel.org/r/20240704045017.2781991-3-yangcong5@huaqin.corp-partner.google.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240704045017.2781991-3-yangcong5@huaqin.corp-partner.google.com --- drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c | 246 +++++++++++++++++++++++ 1 file changed, 246 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c index c6b669866fed..5b525a111b90 100644 --- a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c +++ b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c @@ -850,6 +850,248 @@ static const struct jadard_panel_desc kingdisplay_kd101ne3_40ti_desc = { .enter_sleep_to_reset_down_delay_ms = 100, }; +static int melfas_lmfbx101117480_init_cmds(struct jadard *jadard) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi }; + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe1, 0x93); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe2, 0x65); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe3, 0xf8); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x74); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xbf); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0xbf); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x70); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x2d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x2d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x7e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0xfe); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x19); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x28); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x12); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x78); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x7f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x0b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x74); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x8e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x09); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x2e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x1a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x7f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x69); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x59); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x4e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x4c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x45); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x4a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x4a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x68); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x5b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x4e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x24); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x12); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x7f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x69); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x59); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x4e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x4c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x45); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x4a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x4a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x68); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x5b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x4e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x24); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x12); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x52); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x50); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x4e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x4c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x4a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x48); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x46); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x53); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x51); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x4f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x4d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x4b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x47); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x45); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x41); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x26, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x55); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2c, 0x13); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2d, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2e, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2f, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x30, 0x37); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x31, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x32, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0x0d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0x0f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x07); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x09); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x0b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x11); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x12); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x46, 0x37); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x47, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x48, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x49, 0x0c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4a, 0x0e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4b, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4c, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4d, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4e, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4f, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x50, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x52, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x53, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x54, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x6c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x6c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x75); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0xb4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x6c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x6c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x0c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x88); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xbb); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x2a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x23); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x11); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x48); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2e, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe6, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe7, 0x06); + + return dsi_ctx.accum_err; +}; + +static const struct jadard_panel_desc melfas_lmfbx101117480_desc = { + .mode = { + .clock = (800 + 24 + 24 + 24) * (1280 + 30 + 4 + 8) * 60 / 1000, + + .hdisplay = 800, + .hsync_start = 800 + 24, + .hsync_end = 800 + 24 + 24, + .htotal = 800 + 24 + 24 + 24, + + .vdisplay = 1280, + .vsync_start = 1280 + 30, + .vsync_end = 1280 + 30 + 4, + .vtotal = 1280 + 30 + 4 + 8, + + .width_mm = 135, + .height_mm = 216, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, + }, + .lanes = 4, + .format = MIPI_DSI_FMT_RGB888, + .init = melfas_lmfbx101117480_init_cmds, + .lp11_before_reset = true, + .reset_before_power_off_vcioo = true, + .vcioo_to_lp11_delay_ms = 5, + .lp11_to_reset_delay_ms = 10, + .exit_sleep_to_display_on_delay_ms = 120, + .display_on_delay_ms = 20, + .backlight_off_to_display_off_delay_ms = 100, + .display_off_to_enter_sleep_delay_ms = 50, + .enter_sleep_to_reset_down_delay_ms = 100, +}; + static int jadard_dsi_probe(struct mipi_dsi_device *dsi) { struct device *dev = &dsi->dev; @@ -926,6 +1168,10 @@ static const struct of_device_id jadard_of_match[] = { .compatible = "kingdisplay,kd101ne3-40ti", .data = &kingdisplay_kd101ne3_40ti_desc }, + { + .compatible = "melfas,lmfbx101117480", + .data = &melfas_lmfbx101117480_desc + }, { .compatible = "radxa,display-10hd-ad001", .data = &cz101b4001_desc -- cgit v1.2.3 From 533ca79cd9f734aae56814445e3f1e6cc1a50358 Mon Sep 17 00:00:00 2001 From: Cong Yang Date: Thu, 4 Jul 2024 12:50:17 +0800 Subject: drm/panel: jd9365da: Break some CMDS into helper functions These panels have some common cmds (e0h~e3h,80h), let's break them into helper functions. Signed-off-by: Cong Yang Reviewed-by: Linus Walleij Reviewed-by: Douglas Anderson Link: https://lore.kernel.org/r/20240704045017.2781991-4-yangcong5@huaqin.corp-partner.google.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240704045017.2781991-4-yangcong5@huaqin.corp-partner.google.com --- drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c | 89 ++++++++++++++---------- 1 file changed, 53 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c index 5b525a111b90..04d315d96bff 100644 --- a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c +++ b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c @@ -48,6 +48,19 @@ struct jadard { struct gpio_desc *reset; }; +#define JD9365DA_DCS_SWITCH_PAGE 0xe0 + +#define jd9365da_switch_page(dsi_ctx, page) \ + mipi_dsi_dcs_write_seq_multi(dsi_ctx, JD9365DA_DCS_SWITCH_PAGE, (page)) + +static void jadard_enable_standard_cmds(struct mipi_dsi_multi_context *dsi_ctx) +{ + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe1, 0x93); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe2, 0x65); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe3, 0xf8); + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x80, 0x03); +} + static inline struct jadard *panel_to_jadard(struct drm_panel *panel) { return container_of(panel, struct jadard, panel); @@ -198,12 +211,10 @@ static int radxa_display_8hd_ad002_init_cmds(struct jadard *jadard) { struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi }; - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x00); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE1, 0x93); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE2, 0x65); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE3, 0xF8); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x03); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x01); + jd9365da_switch_page(&dsi_ctx, 0x00); + jadard_enable_standard_cmds(&dsi_ctx); + + jd9365da_switch_page(&dsi_ctx, 0x01); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x00); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x7E); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x00); @@ -276,7 +287,8 @@ static int radxa_display_8hd_ad002_init_cmds(struct jadard *jadard) mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x37); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x23); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x10); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x02); + + jd9365da_switch_page(&dsi_ctx, 0x02); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x47); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x47); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x45); @@ -360,13 +372,15 @@ static int radxa_display_8hd_ad002_init_cmds(struct jadard *jadard) mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7C, 0x00); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7D, 0x03); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7E, 0x7B); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x04); + + jd9365da_switch_page(&dsi_ctx, 0x04); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x0E); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0xB3); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x60); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0E, 0x2A); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x59); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x00); + + jd9365da_switch_page(&dsi_ctx, 0x00); return dsi_ctx.accum_err; }; @@ -398,12 +412,10 @@ static int cz101b4001_init_cmds(struct jadard *jadard) { struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi }; - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x00); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE1, 0x93); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE2, 0x65); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE3, 0xF8); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x03); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x01); + jd9365da_switch_page(&dsi_ctx, 0x00); + jadard_enable_standard_cmds(&dsi_ctx); + + jd9365da_switch_page(&dsi_ctx, 0x01); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x00); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x3B); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0C, 0x74); @@ -471,7 +483,8 @@ static int cz101b4001_init_cmds(struct jadard *jadard) mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x20); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x0F); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x00); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x02); + + jd9365da_switch_page(&dsi_ctx, 0x02); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x02); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x02); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x00); @@ -584,12 +597,14 @@ static int cz101b4001_init_cmds(struct jadard *jadard) mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7A, 0x17); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7D, 0x14); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7E, 0x82); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x04); + + jd9365da_switch_page(&dsi_ctx, 0x04); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x0E); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0xB3); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x61); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0E, 0x48); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE0, 0x00); + + jd9365da_switch_page(&dsi_ctx, 0x00); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE6, 0x02); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE7, 0x0C); @@ -623,12 +638,10 @@ static int kingdisplay_kd101ne3_init_cmds(struct jadard *jadard) { struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi }; - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x00); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe1, 0x93); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe2, 0x65); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe3, 0xf8); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x03); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x01); + jd9365da_switch_page(&dsi_ctx, 0x00); + jadard_enable_standard_cmds(&dsi_ctx); + + jd9365da_switch_page(&dsi_ctx, 0x01); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x74); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xc7); @@ -694,7 +707,8 @@ static int kingdisplay_kd101ne3_init_cmds(struct jadard *jadard) mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x26); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x14); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x02); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x02); + + jd9365da_switch_page(&dsi_ctx, 0x02); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x52); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x5f); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x5f); @@ -808,12 +822,14 @@ static int kingdisplay_kd101ne3_init_cmds(struct jadard *jadard) mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x00); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x05); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x2a); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x04); + + jd9365da_switch_page(&dsi_ctx, 0x04); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x0e); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0xb3); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x61); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x48); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x00); + + jd9365da_switch_page(&dsi_ctx, 0x00); return dsi_ctx.accum_err; }; @@ -854,12 +870,10 @@ static int melfas_lmfbx101117480_init_cmds(struct jadard *jadard) { struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi }; - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x00); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe1, 0x93); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe2, 0x65); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe3, 0xf8); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x03); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x01); + jd9365da_switch_page(&dsi_ctx, 0x00); + jadard_enable_standard_cmds(&dsi_ctx); + + jd9365da_switch_page(&dsi_ctx, 0x01); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x74); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xbf); @@ -932,7 +946,8 @@ static int melfas_lmfbx101117480_init_cmds(struct jadard *jadard) mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x24); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x12); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x02); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x02); + + jd9365da_switch_page(&dsi_ctx, 0x02); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x52); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x55); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x55); @@ -1046,14 +1061,16 @@ static int melfas_lmfbx101117480_init_cmds(struct jadard *jadard) mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x00); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x05); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x2a); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x04); + + jd9365da_switch_page(&dsi_ctx, 0x04); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x23); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x11); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x48); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x49); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x08); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2e, 0x03); - mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0x00); + + jd9365da_switch_page(&dsi_ctx, 0x00); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe6, 0x02); mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe7, 0x06); -- cgit v1.2.3 From 56ab6986992ba143aee0bda33e15a764343e271d Mon Sep 17 00:00:00 2001 From: Bommu Krishnaiah Date: Wed, 3 Jul 2024 14:37:54 +0530 Subject: drm/xe/xe2lpg: Extend workaround 14021402888 workaround 14021402888 also applies to Xe2_LPG. Replicate the existing entry to one specific for Xe2_LPG. Signed-off-by: Bommu Krishnaiah Cc: Tejas Upadhyay Cc: Matt Roper Cc: Himal Prasad Ghimiray Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20240703090754.1323647-1-krishnaiah.bommu@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_wa.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c index 6c52d9d02b5f..fd009b2c68fa 100644 --- a/drivers/gpu/drm/xe/xe_wa.c +++ b/drivers/gpu/drm/xe/xe_wa.c @@ -486,6 +486,10 @@ static const struct xe_rtp_entry_sr engine_was[] = { XE_RTP_RULES(GRAPHICS_VERSION(2004), FUNC(xe_rtp_match_first_render_or_compute)), XE_RTP_ACTIONS(SET(TDL_TSL_CHICKEN, SLM_WMTP_RESTORE)) }, + { XE_RTP_NAME("14021402888"), + XE_RTP_RULES(GRAPHICS_VERSION(2004), ENGINE_CLASS(RENDER)), + XE_RTP_ACTIONS(SET(HALF_SLICE_CHICKEN7, CLEAR_OPTIMIZATION_DISABLE)) + }, /* Xe2_HPG */ -- cgit v1.2.3 From 3d122660dc70029d9cccb4e8670125f0affa959e Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Mon, 8 Jul 2024 10:33:01 -0700 Subject: drm/xe/gt: Remove double include The header generated/xe_wa_oob.h is included twice. Remove one. Fixes: 01570b446939 ("drm/xe/bmg: implement Wa_16023588340") Reported-by: kernel test robot Closes: https://lore.kernel.org/r/202407052122.AzuWSPuo-lkp@intel.com/ Reviewed-by: Michal Wajdeczko Link: https://patchwork.freedesktop.org/patch/msgid/20240708173301.1543871-1-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_gt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index ce8994b808fe..b04e47186f5b 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -9,7 +9,6 @@ #include #include -#include #include -- cgit v1.2.3 From 7b5bdae7740eb6a3d09f9cd4e4b07362a15b86b3 Mon Sep 17 00:00:00 2001 From: Umesh Nerlige Ramappa Date: Fri, 28 Jun 2024 17:56:43 -0700 Subject: i915/perf: Remove code to update PWR_CLK_STATE for gen12 PWR_CLK_STATE only needs to be modified up until gen11. For gen12 this code is not applicable. Remove code to update context image with PWR_CLK_STATE for gen12. Fixes: 00a7f0d7155c ("drm/i915/tgl: Add perf support on TGL") Signed-off-by: Umesh Nerlige Ramappa Reviewed-by: Ashutosh Dixit Link: https://patchwork.freedesktop.org/patch/msgid/20240629005643.3050678-1-umesh.nerlige.ramappa@intel.com --- drivers/gpu/drm/i915/i915_perf.c | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 0b1cd4c7a525..025a79fe5920 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -2748,26 +2748,6 @@ oa_configure_all_contexts(struct i915_perf_stream *stream, return 0; } -static int -gen12_configure_all_contexts(struct i915_perf_stream *stream, - const struct i915_oa_config *oa_config, - struct i915_active *active) -{ - struct flex regs[] = { - { - GEN8_R_PWR_CLK_STATE(RENDER_RING_BASE), - CTX_R_PWR_CLK_STATE, - }, - }; - - if (stream->engine->class != RENDER_CLASS) - return 0; - - return oa_configure_all_contexts(stream, - regs, ARRAY_SIZE(regs), - active); -} - static int lrc_configure_all_contexts(struct i915_perf_stream *stream, const struct i915_oa_config *oa_config, @@ -2874,7 +2854,6 @@ gen12_enable_metric_set(struct i915_perf_stream *stream, { struct drm_i915_private *i915 = stream->perf->i915; struct intel_uncore *uncore = stream->uncore; - struct i915_oa_config *oa_config = stream->oa_config; bool periodic = stream->periodic; u32 period_exponent = stream->period_exponent; u32 sqcnt1; @@ -2918,15 +2897,6 @@ gen12_enable_metric_set(struct i915_perf_stream *stream, intel_uncore_rmw(uncore, GEN12_SQCNT1, 0, sqcnt1); - /* - * Update all contexts prior writing the mux configurations as we need - * to make sure all slices/subslices are ON before writing to NOA - * registers. - */ - ret = gen12_configure_all_contexts(stream, oa_config, active); - if (ret) - return ret; - /* * For Gen12, performance counters are context * saved/restored. Only enable it for the context that @@ -2980,9 +2950,6 @@ static void gen12_disable_metric_set(struct i915_perf_stream *stream) _MASKED_BIT_DISABLE(GEN12_DISABLE_DOP_GATING)); } - /* Reset all contexts' slices/subslices configurations. */ - gen12_configure_all_contexts(stream, NULL, NULL); - /* disable the context save/restore or OAR counters */ if (stream->ctx) gen12_configure_oar_context(stream, NULL); -- cgit v1.2.3 From b2013783c4458a1fe8b25c0b249d2e878bcf6999 Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Thu, 4 Jul 2024 13:56:38 +0530 Subject: drm/i915/display: Cache adpative sync caps to use it later Add new member to struct intel_dp to cache support of Adaptive Sync SDP capabilities and use it whenever required to avoid HW access to read capability during each atomic commit. -v2: - Squash both the patches Signed-off-by: Mitul Golani Reviewed-by: Arun R Murthy Link: https://patchwork.freedesktop.org/patch/msgid/20240704082638.2302092-2-mitulkumar.ajitkumar.golani@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_alpm.c | 2 +- drivers/gpu/drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 22 ++++++++++++---------- drivers/gpu/drm/i915/display/intel_dp.h | 1 - drivers/gpu/drm/i915/display/intel_vrr.c | 3 +-- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index 866b3b409c4d..f4f05a859379 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -280,7 +280,7 @@ void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp, if (DISPLAY_VER(i915) < 20) return; - if (!intel_dp_as_sdp_supported(intel_dp)) + if (!intel_dp->as_sdp_supported) return; if (crtc_state->has_psr) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 8713835e2307..a9d2acdc51a4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1806,6 +1806,7 @@ struct intel_dp { /* connector directly attached - won't be use for modeset in mst world */ struct intel_connector *attached_connector; + bool as_sdp_supported; struct drm_dp_tunnel *tunnel; bool tunnel_suspended:1; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 3903f6ead6e6..edfb30857479 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -129,14 +129,6 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp) return dig_port->base.type == INTEL_OUTPUT_EDP; } -bool intel_dp_as_sdp_supported(struct intel_dp *intel_dp) -{ - struct drm_i915_private *i915 = dp_to_i915(intel_dp); - - return HAS_AS_SDP(i915) && - drm_dp_as_sdp_supported(&intel_dp->aux, intel_dp->dpcd); -} - static void intel_dp_unset_edid(struct intel_dp *intel_dp); /* Is link rate UHBR and thus 128b/132b? */ @@ -2625,8 +2617,7 @@ static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - if (!crtc_state->vrr.enable || - !intel_dp_as_sdp_supported(intel_dp)) + if (!crtc_state->vrr.enable || intel_dp->as_sdp_supported) return; crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC); @@ -5900,6 +5891,15 @@ intel_dp_detect_dsc_caps(struct intel_dp *intel_dp, struct intel_connector *conn connector); } +static void +intel_dp_detect_sdp_caps(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + + intel_dp->as_sdp_supported = HAS_AS_SDP(i915) && + drm_dp_as_sdp_supported(&intel_dp->aux, intel_dp->dpcd); +} + static int intel_dp_detect(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx, @@ -5958,6 +5958,8 @@ intel_dp_detect(struct drm_connector *connector, intel_dp_detect_dsc_caps(intel_dp, intel_connector); + intel_dp_detect_sdp_caps(intel_dp); + intel_dp_mst_configure(intel_dp); if (intel_dp->reset_link_params) { diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index a0f990a95ecc..9be539edf817 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -85,7 +85,6 @@ void intel_dp_audio_compute_config(struct intel_encoder *encoder, struct drm_connector_state *conn_state); bool intel_dp_has_hdmi_sink(struct intel_dp *intel_dp); bool intel_dp_is_edp(struct intel_dp *intel_dp); -bool intel_dp_as_sdp_supported(struct intel_dp *intel_dp); bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state); bool intel_dp_has_dsc(const struct intel_connector *connector); int intel_dp_link_symbol_size(int rate); diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 5a0da64c7db3..7e1d9c718214 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -233,8 +233,7 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, crtc_state->mode_flags |= I915_MODE_FLAG_VRR; } - if (intel_dp_as_sdp_supported(intel_dp) && - crtc_state->vrr.enable) { + if (intel_dp->as_sdp_supported && crtc_state->vrr.enable) { crtc_state->vrr.vsync_start = (crtc_state->hw.adjusted_mode.crtc_vtotal - crtc_state->hw.adjusted_mode.vsync_start); -- cgit v1.2.3 From ea74bf9ccba9ae80fc0766c07c4abaef927e9e63 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Mon, 8 Jul 2024 14:29:06 -0700 Subject: drm/xe: Generate oob before compiling anything Instead of keep adding more dependencies as WAs are needed in different places of the driver, just add a rule with all the objects so the code generation happens before anything else. While at it, group lines related to wa_oob in the Makefile. v2: Prefix $(obj) when declaring dependency Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20240708213041.1734028-1-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/Makefile | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 0eb0acc4f198..1ff9602a52f6 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -12,35 +12,15 @@ subdir-ccflags-$(CONFIG_DRM_XE_WERROR) += -Werror subdir-ccflags-y += -I$(obj) -I$(src) # generated sources -hostprogs := xe_gen_wa_oob +hostprogs := xe_gen_wa_oob generated_oob := $(obj)/generated/xe_wa_oob.c $(obj)/generated/xe_wa_oob.h - quiet_cmd_wa_oob = GEN $(notdir $(generated_oob)) cmd_wa_oob = mkdir -p $(@D); $^ $(generated_oob) - $(obj)/generated/%_wa_oob.c $(obj)/generated/%_wa_oob.h: $(obj)/xe_gen_wa_oob \ $(src)/xe_wa_oob.rules $(call cmd,wa_oob) -uses_generated_oob := \ - $(obj)/xe_ggtt.o \ - $(obj)/xe_device.o \ - $(obj)/xe_gsc.o \ - $(obj)/xe_gt.o \ - $(obj)/xe_guc.o \ - $(obj)/xe_guc_ads.o \ - $(obj)/xe_guc_pc.o \ - $(obj)/xe_migrate.o \ - $(obj)/xe_pat.o \ - $(obj)/xe_ring_ops.o \ - $(obj)/xe_vm.o \ - $(obj)/xe_wa.o \ - $(obj)/xe_ttm_stolen_mgr.o \ - $(obj)/display/xe_display_wa.o - -$(uses_generated_oob): $(generated_oob) - # Please keep these build lists sorted! # core driver code @@ -324,3 +304,6 @@ quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@) $(obj)/%.hdrtest: $(src)/%.h FORCE $(call if_changed_dep,hdrtest) + +uses_generated_oob := $(addprefix $(obj)/, $(xe-y)) +$(uses_generated_oob): $(obj)/generated/xe_wa_oob.h -- cgit v1.2.3 From 7fbad577c82c5dd6db7217855c26f51554e53d85 Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Mon, 8 Jul 2024 14:02:46 +0530 Subject: drm/i915/display: WA for Re-initialize dispcnlunitt1 xosc clock The dispcnlunit1_cp_xosc_clk should be de-asserted in display off and only asserted in display on. As part of this workaround, Display driver shall execute set-reset sequence at the end of the initialize sequence to ensure clk does not remain active in display OFF. --v2: - Rebase. --v3: - Correct HSD number in commit message. --v4: - Reformat commit message. - Use intel_de_rmw instead of intel_de_write --v5: - Build Fixes. WA: 15013987218 Signed-off-by: Mitul Golani Reviewed-by: Nemesa Garg Reviewed-by: Suraj Kandpal Signed-off-by: Suraj Kandpal Link: https://patchwork.freedesktop.org/patch/msgid/20240708083247.2611258-1-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/intel_display_power.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index e288a1b21d7e..0af1e34ef2a7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -1704,6 +1704,14 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv, /* Wa_14011503030:xelpd */ if (DISPLAY_VER(dev_priv) == 13) intel_de_write(dev_priv, XELPD_DISPLAY_ERR_FATAL_MASK, ~0); + + /* Wa_15013987218 */ + if (DISPLAY_VER(dev_priv) == 20) { + intel_de_rmw(dev_priv, SOUTH_DSPCLK_GATE_D, + 0, PCH_GMBUSUNIT_CLOCK_GATE_DISABLE); + intel_de_rmw(dev_priv, SOUTH_DSPCLK_GATE_D, + PCH_GMBUSUNIT_CLOCK_GATE_DISABLE, 0); + } } static void icl_display_core_uninit(struct drm_i915_private *dev_priv) -- cgit v1.2.3 From 33891539f9d6f245e93a76e3fb5791338180374f Mon Sep 17 00:00:00 2001 From: Nirmoy Das Date: Mon, 8 Jul 2024 14:59:18 +0200 Subject: drm/xe/display/xe_hdcp_gsc: Free arbiter on driver removal Free arbiter allocated in intel_hdcp_gsc_init(). Fixes: 152f2df954d8 ("drm/xe/hdcp: Enable HDCP for XE") Cc: Suraj Kandpal Cc: Arun R Murthy Cc: Lucas De Marchi Cc: Rodrigo Vivi Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20240708125918.23573-1-nirmoy.das@intel.com Signed-off-by: Nirmoy Das --- drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c index 14b8b4278317..990285aa9b26 100644 --- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c @@ -160,12 +160,16 @@ void intel_hdcp_gsc_fini(struct xe_device *xe) { struct intel_hdcp_gsc_message *hdcp_message = xe->display.hdcp.hdcp_message; + struct i915_hdcp_arbiter *arb = xe->display.hdcp.arbiter; - if (!hdcp_message) - return; + if (hdcp_message) { + xe_bo_unpin_map_no_vm(hdcp_message->hdcp_bo); + kfree(hdcp_message); + xe->display.hdcp.hdcp_message = NULL; + } - xe_bo_unpin_map_no_vm(hdcp_message->hdcp_bo); - kfree(hdcp_message); + kfree(arb); + xe->display.hdcp.arbiter = NULL; } static int xe_gsc_send_sync(struct xe_device *xe, -- cgit v1.2.3 From 24179ff9a2e4524ce83014b8827a73ad03a25c13 Mon Sep 17 00:00:00 2001 From: Zhaoxiong Lv Date: Tue, 9 Jul 2024 21:47:50 +0800 Subject: drm/panel: boe-th101mb31ig002 : Make it compatible with other panel. This driver currently only applies to one panel. Modify it to be compatible with other panels. Signed-off-by: Zhaoxiong Lv Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20240709134754.28013-2-lvzhaoxiong@huaqin.corp-partner.google.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240709134754.28013-2-lvzhaoxiong@huaqin.corp-partner.google.com --- .../gpu/drm/panel/panel-boe-th101mb31ig002-28a.c | 41 ++++++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c b/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c index 763e9f8342d3..8f03920e3503 100644 --- a/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c +++ b/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c @@ -17,11 +17,21 @@ #include #include +struct panel_desc { + const struct drm_display_mode *modes; + unsigned long mode_flags; + enum mipi_dsi_pixel_format format; + int (*init)(struct drm_panel *panel); + unsigned int lanes; +}; + struct boe_th101mb31ig002 { struct drm_panel panel; struct mipi_dsi_device *dsi; + const struct panel_desc *desc; + struct regulator *power; struct gpio_desc *enable; struct gpio_desc *reset; @@ -161,7 +171,10 @@ static int boe_th101mb31ig002_prepare(struct drm_panel *panel) gpiod_set_value_cansleep(ctx->enable, 1); msleep(50); boe_th101mb31ig002_reset(ctx); - boe_th101mb31ig002_enable(panel); + + ret = ctx->desc->init(panel); + if (ret) + return ret; return 0; } @@ -181,6 +194,16 @@ static const struct drm_display_mode boe_th101mb31ig002_default_mode = { .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, }; +static const struct panel_desc boe_th101mb31ig002_desc = { + .modes = &boe_th101mb31ig002_default_mode, + .lanes = 4, + .format = MIPI_DSI_FMT_RGB888, + .mode_flags = MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_NO_EOT_PACKET | + MIPI_DSI_MODE_LPM, + .init = boe_th101mb31ig002_enable, +}; + static int boe_th101mb31ig002_get_modes(struct drm_panel *panel, struct drm_connector *connector) { @@ -237,6 +260,7 @@ static const struct drm_panel_funcs boe_th101mb31ig002_funcs = { static int boe_th101mb31ig002_dsi_probe(struct mipi_dsi_device *dsi) { struct boe_th101mb31ig002 *ctx; + const struct panel_desc *desc; int ret; ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL); @@ -246,11 +270,11 @@ static int boe_th101mb31ig002_dsi_probe(struct mipi_dsi_device *dsi) mipi_dsi_set_drvdata(dsi, ctx); ctx->dsi = dsi; - dsi->lanes = 4; - dsi->format = MIPI_DSI_FMT_RGB888; - dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST | - MIPI_DSI_MODE_NO_EOT_PACKET | - MIPI_DSI_MODE_LPM; + desc = of_device_get_match_data(&dsi->dev); + dsi->lanes = desc->lanes; + dsi->format = desc->format; + dsi->mode_flags = desc->mode_flags; + ctx->desc = desc; ctx->power = devm_regulator_get(&dsi->dev, "power"); if (IS_ERR(ctx->power)) @@ -302,7 +326,10 @@ static void boe_th101mb31ig002_dsi_remove(struct mipi_dsi_device *dsi) } static const struct of_device_id boe_th101mb31ig002_of_match[] = { - { .compatible = "boe,th101mb31ig002-28a", }, + { + .compatible = "boe,th101mb31ig002-28a", + .data = &boe_th101mb31ig002_desc + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, boe_th101mb31ig002_of_match); -- cgit v1.2.3 From 7f58ebaccb67cb22b2936ba79c844f1e446dc73b Mon Sep 17 00:00:00 2001 From: Zhaoxiong Lv Date: Tue, 9 Jul 2024 21:47:51 +0800 Subject: drm/panel: boe-th101mb31ig002: switch to devm_gpiod_get_optional() for reset_gpio Switch the driver to use devm_gpiod_get_optional() on reset_gpio to avoid driver probe issues when reset line is not specified. Signed-off-by: Zhaoxiong Lv Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20240709134754.28013-3-lvzhaoxiong@huaqin.corp-partner.google.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240709134754.28013-3-lvzhaoxiong@huaqin.corp-partner.google.com --- drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c b/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c index 8f03920e3503..b92082bfc932 100644 --- a/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c +++ b/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c @@ -286,7 +286,7 @@ static int boe_th101mb31ig002_dsi_probe(struct mipi_dsi_device *dsi) return dev_err_probe(&dsi->dev, PTR_ERR(ctx->enable), "Failed to get enable GPIO\n"); - ctx->reset = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_HIGH); + ctx->reset = devm_gpiod_get_optional(&dsi->dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(ctx->reset)) return dev_err_probe(&dsi->dev, PTR_ERR(ctx->reset), "Failed to get reset GPIO\n"); -- cgit v1.2.3 From a16b680a2140e6cbda41ac144564696c3ee2815f Mon Sep 17 00:00:00 2001 From: Zhaoxiong Lv Date: Tue, 9 Jul 2024 21:47:52 +0800 Subject: drm/panel: boe-th101mb31ig002: use wrapped MIPI DCS functions Remove conditional code and always use mipi_dsi_dcs_*multi() wrappers to simplify driver's init/enable/exit code. Convert the hex in init_code from UPPERCASE to lowercase. Signed-off-by: Zhaoxiong Lv Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20240709134754.28013-4-lvzhaoxiong@huaqin.corp-partner.google.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240709134754.28013-4-lvzhaoxiong@huaqin.corp-partner.google.com --- .../gpu/drm/panel/panel-boe-th101mb31ig002-28a.c | 143 +++++++++------------ 1 file changed, 63 insertions(+), 80 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c b/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c index b92082bfc932..5993e6c0cc4a 100644 --- a/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c +++ b/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c @@ -17,11 +17,13 @@ #include #include +struct boe_th101mb31ig002; + struct panel_desc { const struct drm_display_mode *modes; unsigned long mode_flags; enum mipi_dsi_pixel_format format; - int (*init)(struct drm_panel *panel); + int (*init)(struct boe_th101mb31ig002 *ctx); unsigned int lanes; }; @@ -49,74 +51,61 @@ static void boe_th101mb31ig002_reset(struct boe_th101mb31ig002 *ctx) usleep_range(5000, 6000); } -static int boe_th101mb31ig002_enable(struct drm_panel *panel) +static int boe_th101mb31ig002_enable(struct boe_th101mb31ig002 *ctx) { - struct boe_th101mb31ig002 *ctx = container_of(panel, - struct boe_th101mb31ig002, - panel); - struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; - - mipi_dsi_dcs_write_seq(dsi, 0xE0, 0xAB, 0xBA); - mipi_dsi_dcs_write_seq(dsi, 0xE1, 0xBA, 0xAB); - mipi_dsi_dcs_write_seq(dsi, 0xB1, 0x10, 0x01, 0x47, 0xFF); - mipi_dsi_dcs_write_seq(dsi, 0xB2, 0x0C, 0x14, 0x04, 0x50, 0x50, 0x14); - mipi_dsi_dcs_write_seq(dsi, 0xB3, 0x56, 0x53, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xB4, 0x33, 0x30, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0xB6, 0xB0, 0x00, 0x00, 0x10, 0x00, 0x10, - 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xB8, 0x05, 0x12, 0x29, 0x49, 0x48, 0x00, - 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xB9, 0x7C, 0x65, 0x55, 0x49, 0x46, 0x36, - 0x3B, 0x24, 0x3D, 0x3C, 0x3D, 0x5C, 0x4C, - 0x55, 0x47, 0x46, 0x39, 0x26, 0x06, 0x7C, - 0x65, 0x55, 0x49, 0x46, 0x36, 0x3B, 0x24, - 0x3D, 0x3C, 0x3D, 0x5C, 0x4C, 0x55, 0x47, - 0x46, 0x39, 0x26, 0x06); - mipi_dsi_dcs_write_seq(dsi, 0x00, 0xFF, 0x87, 0x12, 0x34, 0x44, 0x44, - 0x44, 0x44, 0x98, 0x04, 0x98, 0x04, 0x0F, - 0x00, 0x00, 0xC1); - mipi_dsi_dcs_write_seq(dsi, 0xC1, 0x54, 0x94, 0x02, 0x85, 0x9F, 0x00, - 0x7F, 0x00, 0x54, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xC2, 0x17, 0x09, 0x08, 0x89, 0x08, 0x11, - 0x22, 0x20, 0x44, 0xFF, 0x18, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xC3, 0x86, 0x46, 0x05, 0x05, 0x1C, 0x1C, - 0x1D, 0x1D, 0x02, 0x1F, 0x1F, 0x1E, 0x1E, - 0x0F, 0x0F, 0x0D, 0x0D, 0x13, 0x13, 0x11, - 0x11, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xC4, 0x07, 0x07, 0x04, 0x04, 0x1C, 0x1C, - 0x1D, 0x1D, 0x02, 0x1F, 0x1F, 0x1E, 0x1E, - 0x0E, 0x0E, 0x0C, 0x0C, 0x12, 0x12, 0x10, - 0x10, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xC6, 0x2A, 0x2A); - mipi_dsi_dcs_write_seq(dsi, 0xC8, 0x21, 0x00, 0x31, 0x42, 0x34, 0x16); - mipi_dsi_dcs_write_seq(dsi, 0xCA, 0xCB, 0x43); - mipi_dsi_dcs_write_seq(dsi, 0xCD, 0x0E, 0x4B, 0x4B, 0x20, 0x19, 0x6B, - 0x06, 0xB3); - mipi_dsi_dcs_write_seq(dsi, 0xD2, 0xE3, 0x2B, 0x38, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xD4, 0x00, 0x01, 0x00, 0x0E, 0x04, 0x44, - 0x08, 0x10, 0x00, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xE6, 0x80, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF); - mipi_dsi_dcs_write_seq(dsi, 0xF0, 0x12, 0x03, 0x20, 0x00, 0xFF); - mipi_dsi_dcs_write_seq(dsi, 0xF3, 0x00); - - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } - - msleep(120); - - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set panel on: %d\n", ret); - return ret; - } - - return 0; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0xab, 0xba); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe1, 0xba, 0xab); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, 0x10, 0x01, 0x47, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, 0x0c, 0x14, 0x04, 0x50, 0x50, 0x14); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb3, 0x56, 0x53, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb4, 0x33, 0x30, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, 0xb0, 0x00, 0x00, 0x10, 0x00, 0x10, + 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, 0x05, 0x12, 0x29, 0x49, 0x48, 0x00, + 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb9, 0x7c, 0x65, 0x55, 0x49, 0x46, 0x36, + 0x3b, 0x24, 0x3d, 0x3c, 0x3d, 0x5c, 0x4c, + 0x55, 0x47, 0x46, 0x39, 0x26, 0x06, 0x7c, + 0x65, 0x55, 0x49, 0x46, 0x36, 0x3b, 0x24, + 0x3d, 0x3c, 0x3d, 0x5c, 0x4c, 0x55, 0x47, + 0x46, 0x39, 0x26, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0xff, 0x87, 0x12, 0x34, 0x44, 0x44, + 0x44, 0x44, 0x98, 0x04, 0x98, 0x04, 0x0f, + 0x00, 0x00, 0xc1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc1, 0x54, 0x94, 0x02, 0x85, 0x9f, 0x00, + 0x7f, 0x00, 0x54, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc2, 0x17, 0x09, 0x08, 0x89, 0x08, 0x11, + 0x22, 0x20, 0x44, 0xff, 0x18, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc3, 0x86, 0x46, 0x05, 0x05, 0x1c, 0x1c, + 0x1d, 0x1d, 0x02, 0x1f, 0x1f, 0x1e, 0x1e, + 0x0f, 0x0f, 0x0d, 0x0d, 0x13, 0x13, 0x11, + 0x11, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc4, 0x07, 0x07, 0x04, 0x04, 0x1c, 0x1c, + 0x1d, 0x1d, 0x02, 0x1f, 0x1f, 0x1e, 0x1e, + 0x0e, 0x0e, 0x0c, 0x0c, 0x12, 0x12, 0x10, + 0x10, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc6, 0x2a, 0x2a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc8, 0x21, 0x00, 0x31, 0x42, 0x34, 0x16); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xca, 0xcb, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcd, 0x0e, 0x4b, 0x4b, 0x20, 0x19, 0x6b, + 0x06, 0xb3); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd2, 0xe3, 0x2b, 0x38, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd4, 0x00, 0x01, 0x00, 0x0e, 0x04, 0x44, + 0x08, 0x10, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe6, 0x80, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0x12, 0x03, 0x20, 0x00, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0x00); + + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + + mipi_dsi_msleep(&dsi_ctx, 120); + + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + + return dsi_ctx.accum_err; } static int boe_th101mb31ig002_disable(struct drm_panel *panel) @@ -124,21 +113,15 @@ static int boe_th101mb31ig002_disable(struct drm_panel *panel) struct boe_th101mb31ig002 *ctx = container_of(panel, struct boe_th101mb31ig002, panel); - struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) - dev_err(dev, "Failed to set panel off: %d\n", ret); + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); - msleep(120); + mipi_dsi_msleep(&dsi_ctx, 120); - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); - return 0; + return dsi_ctx.accum_err; } static int boe_th101mb31ig002_unprepare(struct drm_panel *panel) @@ -172,7 +155,7 @@ static int boe_th101mb31ig002_prepare(struct drm_panel *panel) msleep(50); boe_th101mb31ig002_reset(ctx); - ret = ctx->desc->init(panel); + ret = ctx->desc->init(ctx); if (ret) return ret; -- cgit v1.2.3 From 3808a15e3248820c0859d9b8a0f2c7e5c8259044 Mon Sep 17 00:00:00 2001 From: Zhaoxiong Lv Date: Tue, 9 Jul 2024 21:47:53 +0800 Subject: dt-bindings: display: panel: Add compatible for starry-er88577 The starry-er88577 is a 10.1" WXGA TFT-LCD panel, and the init_code of the starry-er88577 panel is very similar to the boe-th101mb31ig002 panel, so We will add a new configuration based on "boe,th101mb31ig002-28a.yaml". Because the panel used reset gpio before but did not add the definition of "reset gpio" in binding, reset gpio was added in binding, but since the starry-er88577 panel did not use "reset gpio", a judgment was added here. Signed-off-by: Zhaoxiong Lv Acked-by: Conor Dooley Link: https://lore.kernel.org/r/20240709134754.28013-5-lvzhaoxiong@huaqin.corp-partner.google.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240709134754.28013-5-lvzhaoxiong@huaqin.corp-partner.google.com --- .../display/panel/boe,th101mb31ig002-28a.yaml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/display/panel/boe,th101mb31ig002-28a.yaml b/Documentation/devicetree/bindings/display/panel/boe,th101mb31ig002-28a.yaml index 5eaccce13c21..6a82bd1ec763 100644 --- a/Documentation/devicetree/bindings/display/panel/boe,th101mb31ig002-28a.yaml +++ b/Documentation/devicetree/bindings/display/panel/boe,th101mb31ig002-28a.yaml @@ -9,20 +9,20 @@ title: BOE TH101MB31IG002-28A WXGA DSI Display Panel maintainers: - Manuel Traut -allOf: - - $ref: panel-common.yaml# - properties: compatible: enum: # BOE TH101MB31IG002-28A 10.1" WXGA TFT LCD panel - boe,th101mb31ig002-28a + # The Starry-er88577 is a 10.1" WXGA TFT-LCD panel + - starry,er88577 reg: maxItems: 1 backlight: true enable-gpios: true + reset-gpios: true power-supply: true port: true rotation: true @@ -33,6 +33,20 @@ required: - enable-gpios - power-supply +allOf: + - $ref: panel-common.yaml# + - if: + properties: + compatible: + # The Starry-er88577 is a 10.1" WXGA TFT-LCD panel + const: starry,er88577 + then: + properties: + reset-gpios: false + else: + required: + - reset-gpios + additionalProperties: false examples: @@ -47,6 +61,7 @@ examples: reg = <0>; backlight = <&backlight_lcd0>; enable-gpios = <&gpio 45 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio 55 GPIO_ACTIVE_LOW>; rotation = <90>; power-supply = <&vcc_3v3>; port { -- cgit v1.2.3 From e4bd1db1c1f771983393bf5574854dff26ca7532 Mon Sep 17 00:00:00 2001 From: Zhaoxiong Lv Date: Tue, 9 Jul 2024 21:47:54 +0800 Subject: drm/panel: boe-th101mb31ig002: Support for starry-er88577 MIPI-DSI panel The init_code of the starry-er88577 panel is very similar to the panel-boe-th101mb31ig002-28a.c driver, so we make it compatible with the panel-boe-th101mb31ig002-28a.c driver Signed-off-by: Zhaoxiong Lv Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20240709134754.28013-6-lvzhaoxiong@huaqin.corp-partner.google.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240709134754.28013-6-lvzhaoxiong@huaqin.corp-partner.google.com --- .../gpu/drm/panel/panel-boe-th101mb31ig002-28a.c | 123 +++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c b/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c index 5993e6c0cc4a..b55cf80c5522 100644 --- a/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c +++ b/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c @@ -25,6 +25,12 @@ struct panel_desc { enum mipi_dsi_pixel_format format; int (*init)(struct boe_th101mb31ig002 *ctx); unsigned int lanes; + bool lp11_before_reset; + unsigned int vcioo_to_lp11_delay_ms; + unsigned int lp11_to_reset_delay_ms; + unsigned int backlight_off_to_display_off_delay_ms; + unsigned int enter_sleep_to_reset_down_delay_ms; + unsigned int power_off_delay_ms; }; struct boe_th101mb31ig002 { @@ -108,6 +114,68 @@ static int boe_th101mb31ig002_enable(struct boe_th101mb31ig002 *ctx) return dsi_ctx.accum_err; } +static int starry_er88577_init_cmd(struct boe_th101mb31ig002 *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + msleep(70); + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe0, 0xab, 0xba); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe1, 0xba, 0xab); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, 0x10, 0x01, 0x47, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, 0x0c, 0x14, 0x04, 0x50, 0x50, 0x14); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb3, 0x56, 0x53, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb4, 0x33, 0x30, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, 0xb0, 0x00, 0x00, 0x10, 0x00, 0x10, + 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, 0x05, 0x12, 0x29, 0x49, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb9, 0x7c, 0x61, 0x4f, 0x42, 0x3e, 0x2d, + 0x31, 0x1a, 0x33, 0x33, 0x33, 0x52, 0x40, + 0x47, 0x38, 0x34, 0x26, 0x0e, 0x06, 0x7c, + 0x61, 0x4f, 0x42, 0x3e, 0x2d, 0x31, 0x1a, + 0x33, 0x33, 0x33, 0x52, 0x40, 0x47, 0x38, + 0x34, 0x26, 0x0e, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc0, 0xcc, 0x76, 0x12, 0x34, 0x44, 0x44, + 0x44, 0x44, 0x98, 0x04, 0x98, 0x04, 0x0f, + 0x00, 0x00, 0xc1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc1, 0x54, 0x94, 0x02, 0x85, 0x9f, 0x00, + 0x6f, 0x00, 0x54, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc2, 0x17, 0x09, 0x08, 0x89, 0x08, 0x11, + 0x22, 0x20, 0x44, 0xff, 0x18, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc3, 0x87, 0x47, 0x05, 0x05, 0x1c, 0x1c, + 0x1d, 0x1d, 0x02, 0x1e, 0x1e, 0x1f, 0x1f, + 0x0f, 0x0f, 0x0d, 0x0d, 0x13, 0x13, 0x11, + 0x11, 0x24); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc4, 0x06, 0x06, 0x04, 0x04, 0x1c, 0x1c, + 0x1d, 0x1d, 0x02, 0x1e, 0x1e, 0x1f, 0x1f, + 0x0e, 0x0e, 0x0c, 0x0c, 0x12, 0x12, 0x10, + 0x10, 0x24); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc8, 0x21, 0x00, 0x31, 0x42, 0x34, 0x16); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xca, 0xcb, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcd, 0x0e, 0x4b, 0x4b, 0x20, 0x19, 0x6b, + 0x06, 0xb3); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd1, 0x40, 0x0d, 0xff, 0x0f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd2, 0xe3, 0x2b, 0x38, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x33, 0x20, 0x3a, 0xd5, 0x86, 0xf3); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd4, 0x00, 0x01, 0x00, 0x0e, 0x04, 0x44, + 0x08, 0x10, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe6, 0x80, 0x09, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0x12, 0x03, 0x20, 0x00, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0x00); + + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + + mipi_dsi_msleep(&dsi_ctx, 120); + + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + + mipi_dsi_msleep(&dsi_ctx, 20); + + return dsi_ctx.accum_err; +} + static int boe_th101mb31ig002_disable(struct drm_panel *panel) { struct boe_th101mb31ig002 *ctx = container_of(panel, @@ -115,12 +183,18 @@ static int boe_th101mb31ig002_disable(struct drm_panel *panel) panel); struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + if (ctx->desc->backlight_off_to_display_off_delay_ms) + mipi_dsi_msleep(&dsi_ctx, ctx->desc->backlight_off_to_display_off_delay_ms); + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); mipi_dsi_msleep(&dsi_ctx, 120); mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + if (ctx->desc->enter_sleep_to_reset_down_delay_ms) + mipi_dsi_msleep(&dsi_ctx, ctx->desc->enter_sleep_to_reset_down_delay_ms); + return dsi_ctx.accum_err; } @@ -134,6 +208,9 @@ static int boe_th101mb31ig002_unprepare(struct drm_panel *panel) gpiod_set_value_cansleep(ctx->enable, 0); regulator_disable(ctx->power); + if (ctx->desc->power_off_delay_ms) + msleep(ctx->desc->power_off_delay_ms); + return 0; } @@ -151,6 +228,18 @@ static int boe_th101mb31ig002_prepare(struct drm_panel *panel) return ret; } + if (ctx->desc->vcioo_to_lp11_delay_ms) + msleep(ctx->desc->vcioo_to_lp11_delay_ms); + + if (ctx->desc->lp11_before_reset) { + ret = mipi_dsi_dcs_nop(ctx->dsi); + if (ret) + return ret; + } + + if (ctx->desc->lp11_to_reset_delay_ms) + msleep(ctx->desc->lp11_to_reset_delay_ms); + gpiod_set_value_cansleep(ctx->enable, 1); msleep(50); boe_th101mb31ig002_reset(ctx); @@ -187,6 +276,36 @@ static const struct panel_desc boe_th101mb31ig002_desc = { .init = boe_th101mb31ig002_enable, }; +static const struct drm_display_mode starry_er88577_default_mode = { + .clock = (800 + 25 + 25 + 25) * (1280 + 20 + 4 + 12) * 60 / 1000, + .hdisplay = 800, + .hsync_start = 800 + 25, + .hsync_end = 800 + 25 + 25, + .htotal = 800 + 25 + 25 + 25, + .vdisplay = 1280, + .vsync_start = 1280 + 20, + .vsync_end = 1280 + 20 + 4, + .vtotal = 1280 + 20 + 4 + 12, + .width_mm = 135, + .height_mm = 216, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +static const struct panel_desc starry_er88577_desc = { + .modes = &starry_er88577_default_mode, + .lanes = 4, + .format = MIPI_DSI_FMT_RGB888, + .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_MODE_LPM, + .init = starry_er88577_init_cmd, + .lp11_before_reset = true, + .vcioo_to_lp11_delay_ms = 5, + .lp11_to_reset_delay_ms = 50, + .backlight_off_to_display_off_delay_ms = 100, + .enter_sleep_to_reset_down_delay_ms = 100, + .power_off_delay_ms = 1000, +}; + static int boe_th101mb31ig002_get_modes(struct drm_panel *panel, struct drm_connector *connector) { @@ -313,6 +432,10 @@ static const struct of_device_id boe_th101mb31ig002_of_match[] = { .compatible = "boe,th101mb31ig002-28a", .data = &boe_th101mb31ig002_desc }, + { + .compatible = "starry,er88577", + .data = &starry_er88577_desc + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, boe_th101mb31ig002_of_match); -- cgit v1.2.3 From 0e7f4e6a20d550252c4f355d5a303b1d9c8ff052 Mon Sep 17 00:00:00 2001 From: Vignesh Raman Date: Thu, 4 Jul 2024 14:52:02 +0530 Subject: drm/ci: uprev IGT Uprev IGT to the latest version, which includes a fix for the writeback tests issue on MSM devices. Enable debugging for igt-runner to log output such as 'Begin test' and 'End test'. This will help identify which test causes system freeze or hangs. Update xfails and add metadata header for each flake test. Signed-off-by: Vignesh Raman Acked-by: Dmitry Baryshkov # msm tests Signed-off-by: Helen Koike Link: https://patchwork.freedesktop.org/patch/msgid/20240704092202.75551-1-vignesh.raman@collabora.com --- drivers/gpu/drm/ci/gitlab-ci.yml | 2 +- drivers/gpu/drm/ci/igt_runner.sh | 1 + drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt | 1 + drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt | 14 +- drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt | 4 +- drivers/gpu/drm/ci/xfails/i915-amly-fails.txt | 12 +- drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt | 41 +++++- drivers/gpu/drm/ci/xfails/i915-amly-skips.txt | 5 +- drivers/gpu/drm/ci/xfails/i915-apl-flakes.txt | 2 +- drivers/gpu/drm/ci/xfails/i915-apl-skips.txt | 4 +- drivers/gpu/drm/ci/xfails/i915-cml-fails.txt | 14 +- drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt | 9 +- drivers/gpu/drm/ci/xfails/i915-cml-skips.txt | 5 +- drivers/gpu/drm/ci/xfails/i915-glk-fails.txt | 24 ++-- drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt | 8 +- drivers/gpu/drm/ci/xfails/i915-glk-skips.txt | 4 +- drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt | 2 + drivers/gpu/drm/ci/xfails/i915-kbl-flakes.txt | 2 +- drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt | 4 +- drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt | 25 ++-- drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt | 4 +- drivers/gpu/drm/ci/xfails/i915-whl-fails.txt | 17 +-- drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt | 2 +- drivers/gpu/drm/ci/xfails/i915-whl-skips.txt | 5 +- .../gpu/drm/ci/xfails/mediatek-mt8173-fails.txt | 9 +- .../gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt | 32 ++++- .../gpu/drm/ci/xfails/mediatek-mt8173-skips.txt | 4 +- .../gpu/drm/ci/xfails/mediatek-mt8183-fails.txt | 2 +- .../gpu/drm/ci/xfails/mediatek-mt8183-skips.txt | 2 +- drivers/gpu/drm/ci/xfails/meson-g12b-fails.txt | 2 +- drivers/gpu/drm/ci/xfails/meson-g12b-skips.txt | 2 +- drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt | 5 +- drivers/gpu/drm/ci/xfails/msm-apq8016-skips.txt | 2 +- drivers/gpu/drm/ci/xfails/msm-apq8096-flakes.txt | 2 +- drivers/gpu/drm/ci/xfails/msm-apq8096-skips.txt | 4 +- .../xfails/msm-sc7180-trogdor-kingoftown-fails.txt | 145 --------------------- .../msm-sc7180-trogdor-kingoftown-flakes.txt | 18 ++- .../xfails/msm-sc7180-trogdor-kingoftown-skips.txt | 5 +- .../msm-sc7180-trogdor-lazor-limozeen-fails.txt | 145 --------------------- .../msm-sc7180-trogdor-lazor-limozeen-flakes.txt | 11 +- .../msm-sc7180-trogdor-lazor-limozeen-skips.txt | 2 +- drivers/gpu/drm/ci/xfails/msm-sdm845-flakes.txt | 105 ++++++++++++++- drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt | 4 +- .../gpu/drm/ci/xfails/rockchip-rk3288-fails.txt | 2 +- .../gpu/drm/ci/xfails/rockchip-rk3288-skips.txt | 2 +- .../gpu/drm/ci/xfails/rockchip-rk3399-fails.txt | 2 +- .../gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt | 4 +- .../gpu/drm/ci/xfails/rockchip-rk3399-skips.txt | 2 +- .../gpu/drm/ci/xfails/virtio_gpu-none-fails.txt | 64 +++++++++ .../gpu/drm/ci/xfails/virtio_gpu-none-skips.txt | 4 +- drivers/gpu/drm/ci/xfails/vkms-none-fails.txt | 4 - drivers/gpu/drm/ci/xfails/vkms-none-flakes.txt | 21 +++ drivers/gpu/drm/ci/xfails/vkms-none-skips.txt | 105 ++++++++++++++- 53 files changed, 527 insertions(+), 395 deletions(-) diff --git a/drivers/gpu/drm/ci/gitlab-ci.yml b/drivers/gpu/drm/ci/gitlab-ci.yml index 80fb0f57ae46..b09976c3d2c2 100644 --- a/drivers/gpu/drm/ci/gitlab-ci.yml +++ b/drivers/gpu/drm/ci/gitlab-ci.yml @@ -5,7 +5,7 @@ variables: UPSTREAM_REPO: git://anongit.freedesktop.org/drm/drm TARGET_BRANCH: drm-next - IGT_VERSION: 0df7b9b97f9da0e364f5ee30fe331004b8c86b56 + IGT_VERSION: f13702b8e4e847c56da3ef6f0969065d686049c5 DEQP_RUNNER_GIT_URL: https://gitlab.freedesktop.org/anholt/deqp-runner.git DEQP_RUNNER_GIT_TAG: v0.15.0 diff --git a/drivers/gpu/drm/ci/igt_runner.sh b/drivers/gpu/drm/ci/igt_runner.sh index 79f41d7da772..37c724dba8cb 100755 --- a/drivers/gpu/drm/ci/igt_runner.sh +++ b/drivers/gpu/drm/ci/igt_runner.sh @@ -80,6 +80,7 @@ igt-runner \ --igt-folder /igt/libexec/igt-gpu-tools \ --caselist $TESTLIST \ --output /results \ + -vvvv \ $IGT_SKIPS \ $IGT_FLAKES \ $IGT_FAILS \ diff --git a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt index e8c2f4044a92..2f74880671ca 100644 --- a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt +++ b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt @@ -30,6 +30,7 @@ kms_cursor_crc@cursor-random-64x64,Fail kms_cursor_crc@cursor-size-change,Fail kms_cursor_crc@cursor-sliding-64x21,Fail kms_cursor_crc@cursor-sliding-64x64,Fail +kms_cursor_edge_walk@64x64-left-edge,Fail kms_flip@flip-vs-modeset-vs-hang,Fail kms_flip@flip-vs-panning-vs-hang,Fail kms_lease@lease-uevent,Fail diff --git a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt index ea512ff8c352..e4faa96fa000 100644 --- a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt @@ -1,8 +1,20 @@ # Board Name: hp-11A-G6-EE-grunt # Bug Report: https://lore.kernel.org/amd-gfx/3542730f-b8d7-404d-a947-b7a5e95d661c@collabora.com/T/#u +# Failure Rate: 50 # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 -# Failure Rate: 50 kms_async_flips@async-flip-with-page-flip-events + +# Board Name: hp-11A-G6-EE-grunt +# Bug Report: https://lore.kernel.org/amd-gfx/3542730f-b8d7-404d-a947-b7a5e95d661c@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_async_flips@crc + +# Board Name: hp-11A-G6-EE-grunt +# Bug Report: https://lore.kernel.org/amd-gfx/3542730f-b8d7-404d-a947-b7a5e95d661c@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_plane@pixel-format-source-clamping diff --git a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt index 3a2ce45d3cb9..931d6d1d0165 100644 --- a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt +++ b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt @@ -2,9 +2,9 @@ .*suspend.* # Skip driver specific tests -msm_.* +^msm.* nouveau_.* -panfrost_.* +^panfrost.* ^v3d.* ^vc4.* ^vmwgfx* diff --git a/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt b/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt index 6641520ac587..9b84f68a5122 100644 --- a/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt @@ -6,11 +6,11 @@ i915_module_load@reload-no-display,Fail i915_module_load@resize-bar,Fail i915_pm_rpm@gem-execbuf-stress,Timeout i915_pm_rpm@module-reload,Fail -kms_async_flips@invalid-async-flip,Timeout -kms_atomic_transition@modeset-transition-fencing,Timeout kms_ccs@crc-primary-rotation-180-yf-tiled-ccs,Timeout +kms_cursor_legacy@short-flip-before-cursor-atomic-transitions,Timeout kms_fb_coherency@memset-crc,Crash -kms_flip@flip-vs-dpms-off-vs-modeset,Timeout +kms_flip@busy-flip,Timeout +kms_flip@single-buffer-flip-vs-dpms-off-vs-modeset-interruptible,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail @@ -33,16 +33,20 @@ kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail +kms_frontbuffer_tracking@fbc-rgb565-draw-mmap-cpu,Timeout kms_lease@lease-uevent,Fail kms_plane_alpha_blend@alpha-basic,Fail kms_plane_alpha_blend@alpha-opaque-fb,Fail kms_plane_alpha_blend@alpha-transparent-fb,Fail kms_plane_alpha_blend@constant-alpha-max,Fail kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation,Timeout -kms_pm_rpm@modeset-lpsp-stress,Timeout +kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-5,Timeout kms_pm_rpm@modeset-stress-extra-wait,Timeout kms_pm_rpm@universal-planes,Timeout kms_pm_rpm@universal-planes-dpms,Timeout +kms_prop_blob@invalid-set-prop,Fail +kms_rotation_crc@primary-rotation-180,Timeout +kms_vblank@query-forked-hang,Timeout perf@i915-ref-count,Fail perf_pmu@module-unload,Fail perf_pmu@rc6,Crash diff --git a/drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt index 0a76547a103d..581f0da4d0f2 100644 --- a/drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt @@ -1,9 +1,48 @@ # Board Name: asus-C433TA-AJ0005-rammus # Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# Failure Rate: 50 # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 -# Failure Rate: 50 i915_hangman@engine-engine-error + +# Board Name: asus-C433TA-AJ0005-rammus +# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 i915_hangman@gt-engine-hang + +# Board Name: asus-C433TA-AJ0005-rammus +# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_async_flips@crc + +# Board Name: asus-C433TA-AJ0005-rammus +# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_universal_plane@cursor-fb-leak + +# Board Name: asus-C433TA-AJ0005-rammus +# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-gf13702b8e +# Linux Version: 6.10.0-rc5 +kms_sysfs_edid_timing + +# Board Name: asus-C433TA-AJ0005-rammus +# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-gf13702b8e +# Linux Version: 6.10.0-rc5 +i915_hangman@engine-engine-hang + +# Board Name: asus-C433TA-AJ0005-rammus +# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-gf13702b8e +# Linux Version: 6.10.0-rc5 +kms_pm_rpm@modeset-lpsp-stress diff --git a/drivers/gpu/drm/ci/xfails/i915-amly-skips.txt b/drivers/gpu/drm/ci/xfails/i915-amly-skips.txt index 5663ed0420a7..5186ba3dbbc6 100644 --- a/drivers/gpu/drm/ci/xfails/i915-amly-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-amly-skips.txt @@ -5,9 +5,9 @@ kms_plane_scaling@invalid-parameters # Skip driver specific tests ^amdgpu.* -msm_.* +^msm.* nouveau_.* -panfrost_.* +^panfrost.* ^v3d.* ^vc4.* ^vmwgfx* @@ -19,6 +19,7 @@ gem_.* i915_pm_rc6_residency.* i915_suspend.* kms_scaling_modes.* +i915_pm_rpm.* # Kernel panic drm_fdinfo.* diff --git a/drivers/gpu/drm/ci/xfails/i915-apl-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-apl-flakes.txt index cb010c153a6a..4663d4d13f35 100644 --- a/drivers/gpu/drm/ci/xfails/i915-apl-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/i915-apl-flakes.txt @@ -1,6 +1,6 @@ # Board Name: asus-C523NA-A20057-coral # Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# Failure Rate: 50 # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 -# Failure Rate: 50 kms_fb_coherency@memset-crc diff --git a/drivers/gpu/drm/ci/xfails/i915-apl-skips.txt b/drivers/gpu/drm/ci/xfails/i915-apl-skips.txt index ab588e7a447c..4f50e0240ff4 100644 --- a/drivers/gpu/drm/ci/xfails/i915-apl-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-apl-skips.txt @@ -7,9 +7,9 @@ kms_3d # Skip driver specific tests ^amdgpu.* -msm_.* +^msm.* nouveau_.* -panfrost_.* +^panfrost.* ^v3d.* ^vc4.* ^vmwgfx* diff --git a/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt b/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt index 26cd62bbf30a..2723e2832797 100644 --- a/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt @@ -9,11 +9,10 @@ i915_pipe_stress@stress-xrgb8888-ytiled,Fail i915_pm_rpm@gem-execbuf-stress,Timeout i915_pm_rpm@module-reload,Fail i915_pm_rpm@system-suspend-execbuf,Timeout -kms_async_flips@invalid-async-flip,Timeout -kms_atomic_transition@modeset-transition-fencing,Timeout kms_ccs@crc-primary-rotation-180-yf-tiled-ccs,Timeout kms_fb_coherency@memset-crc,Crash -kms_flip@flip-vs-dpms-off-vs-modeset,Timeout +kms_flip@busy-flip,Timeout +kms_flip@single-buffer-flip-vs-dpms-off-vs-modeset-interruptible,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail @@ -41,20 +40,25 @@ kms_plane_alpha_blend@alpha-basic,Fail kms_plane_alpha_blend@alpha-opaque-fb,Fail kms_plane_alpha_blend@alpha-transparent-fb,Fail kms_plane_alpha_blend@constant-alpha-max,Fail -kms_plane_alpha_blend@constant-alpha-min,Fail kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation,Timeout +kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-5,Timeout kms_pm_rpm@modeset-stress-extra-wait,Timeout kms_pm_rpm@universal-planes,Timeout kms_pm_rpm@universal-planes-dpms,Timeout +kms_prop_blob@invalid-set-prop,Fail +kms_psr2_sf@cursor-plane-update-sf,Fail kms_psr2_sf@fbc-plane-move-sf-dmg-area,Timeout kms_psr2_sf@overlay-plane-update-continuous-sf,Fail kms_psr2_sf@overlay-plane-update-sf-dmg-area,Fail +kms_psr2_sf@overlay-primary-update-sf-dmg-area,Fail +kms_psr2_sf@plane-move-sf-dmg-area,Fail kms_psr2_sf@primary-plane-update-sf-dmg-area,Fail kms_psr2_sf@primary-plane-update-sf-dmg-area-big-fb,Fail kms_psr2_su@page_flip-NV12,Fail kms_psr2_su@page_flip-P010,Fail -kms_psr@psr-sprite-render,Timeout +kms_rotation_crc@primary-rotation-180,Timeout kms_setmode@basic,Fail +kms_vblank@query-forked-hang,Timeout perf@i915-ref-count,Fail perf_pmu@module-unload,Fail perf_pmu@rc6,Crash diff --git a/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt index bb560ff1e2cd..58a6001abb28 100644 --- a/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt @@ -1,6 +1,13 @@ # Board Name: asus-C436FA-Flip-hatch # Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# Failure Rate: 50 # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 -# Failure Rate: 50 kms_plane_alpha_blend@constant-alpha-min + +# Board Name: asus-C436FA-Flip-hatch +# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-gf13702b8e +# Linux Version: 6.10.0-rc5 +kms_atomic_transition@plane-all-modeset-transition-internal-panels diff --git a/drivers/gpu/drm/ci/xfails/i915-cml-skips.txt b/drivers/gpu/drm/ci/xfails/i915-cml-skips.txt index 93b7736fffbb..9d753d97c9ab 100644 --- a/drivers/gpu/drm/ci/xfails/i915-cml-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-cml-skips.txt @@ -3,9 +3,9 @@ kms_plane_scaling@invalid-parameters # Skip driver specific tests ^amdgpu.* -msm_.* +^msm.* nouveau_.* -panfrost_.* +^panfrost.* ^v3d.* ^vc4.* ^vmwgfx* @@ -19,6 +19,7 @@ i915_suspend.* xe_module_load.* api_intel_allocator.* kms_cursor_legacy.* +i915_pm_rpm.* # Kernel panic drm_fdinfo.* diff --git a/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt b/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt index fca15b487929..4821c9adefd1 100644 --- a/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt @@ -1,20 +1,16 @@ core_setmaster@master-drop-set-user,Fail +core_setmaster_vs_auth,Fail i915_module_load@load,Fail i915_module_load@reload,Fail i915_module_load@reload-no-display,Fail i915_module_load@resize-bar,Fail -kms_async_flips@invalid-async-flip,Timeout -kms_atomic_transition@modeset-transition-fencing,Timeout -kms_big_fb@linear-16bpp-rotate-0,Fail -kms_big_fb@linear-16bpp-rotate-180,Fail -kms_big_fb@linear-32bpp-rotate-0,Fail -kms_big_fb@linear-32bpp-rotate-180,Fail -kms_big_fb@linear-8bpp-rotate-0,Fail -kms_big_fb@linear-8bpp-rotate-180,Fail -kms_big_fb@linear-max-hw-stride-32bpp-rotate-0,Fail +kms_cursor_legacy@short-flip-before-cursor-atomic-transitions,Timeout kms_dirtyfb@default-dirtyfb-ioctl,Fail -kms_draw_crc@draw-method-render,Fail -kms_flip@flip-vs-dpms-off-vs-modeset,Timeout +kms_dirtyfb@drrs-dirtyfb-ioctl,Fail +kms_dirtyfb@fbc-dirtyfb-ioctl,Fail +kms_flip@blocking-wf_vblank,Fail +kms_flip@busy-flip,Timeout +kms_flip@single-buffer-flip-vs-dpms-off-vs-modeset-interruptible,Fail kms_flip@wf_vblank-ts-check,Fail kms_flip@wf_vblank-ts-check-interruptible,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail @@ -26,6 +22,7 @@ kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling,Fail +kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling,Fail @@ -38,19 +35,24 @@ kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail +kms_frontbuffer_tracking@fbc-rgb565-draw-mmap-cpu,Timeout kms_frontbuffer_tracking@fbc-tiling-linear,Fail kms_frontbuffer_tracking@fbcdrrs-tiling-linear,Fail kms_lease@lease-uevent,Fail kms_plane_alpha_blend@alpha-opaque-fb,Fail kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation,Timeout +kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-5,Timeout kms_pm_rpm@legacy-planes,Timeout kms_pm_rpm@legacy-planes-dpms,Timeout kms_pm_rpm@modeset-stress-extra-wait,Timeout kms_pm_rpm@universal-planes,Timeout kms_pm_rpm@universal-planes-dpms,Timeout +kms_prop_blob@invalid-set-prop,Fail kms_rotation_crc@multiplane-rotation,Fail kms_rotation_crc@multiplane-rotation-cropping-bottom,Fail kms_rotation_crc@multiplane-rotation-cropping-top,Fail +kms_rotation_crc@primary-rotation-180,Timeout +kms_vblank@query-forked-hang,Timeout perf@non-zero-reason,Timeout sysfs_heartbeat_interval@long,Timeout sysfs_heartbeat_interval@off,Timeout diff --git a/drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt index 58fc424f8a42..077886b76093 100644 --- a/drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt @@ -1,7 +1,13 @@ # Board Name: hp-x360-12b-ca0010nr-n4020-octopus # Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# Failure Rate: 50 # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 -# Failure Rate: 50 core_hotunplug@unplug-rescan + +# Board Name: hp-x360-12b-ca0010nr-n4020-octopus +# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_fb_coherency@memset-crc diff --git a/drivers/gpu/drm/ci/xfails/i915-glk-skips.txt b/drivers/gpu/drm/ci/xfails/i915-glk-skips.txt index b3226b2d9ba1..9c64146aed90 100644 --- a/drivers/gpu/drm/ci/xfails/i915-glk-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-glk-skips.txt @@ -6,9 +6,9 @@ kms_plane_scaling@invalid-parameters # Skip driver specific tests ^amdgpu.* -msm_.* +^msm.* nouveau_.* -panfrost_.* +^panfrost.* ^v3d.* ^vc4.* ^vmwgfx* diff --git a/drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt index d4fba4f55ec1..1de04a3308c4 100644 --- a/drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt @@ -17,10 +17,12 @@ perf@i915-ref-count,Fail perf_pmu@busy-accuracy-50,Fail perf_pmu@module-unload,Fail perf_pmu@rc6,Crash +prime_busy@after,Fail sysfs_heartbeat_interval@long,Timeout sysfs_heartbeat_interval@off,Timeout sysfs_preempt_timeout@off,Timeout sysfs_timeslice_duration@off,Timeout +testdisplay,Timeout xe_module_load@force-load,Fail xe_module_load@load,Fail xe_module_load@many-reload,Fail diff --git a/drivers/gpu/drm/ci/xfails/i915-kbl-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-kbl-flakes.txt index 6cf1fed2e575..549501e40461 100644 --- a/drivers/gpu/drm/ci/xfails/i915-kbl-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/i915-kbl-flakes.txt @@ -1,6 +1,6 @@ # Board Name: hp-x360-14-G1-sona # Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# Failure Rate: 50 # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 -# Failure Rate: 50 prime_busy@hang diff --git a/drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt b/drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt index f0cf8a6dda25..6ec2f83ffe13 100644 --- a/drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt @@ -6,9 +6,9 @@ kms_plane_scaling@invalid-parameters # Skip driver specific tests ^amdgpu.* -msm_.* +^msm.* nouveau_.* -panfrost_.* +^panfrost.* ^v3d.* ^vc4.* ^vmwgfx* diff --git a/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt index 9a50e894c3e7..e728ccc62326 100644 --- a/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt @@ -1,34 +1,39 @@ -api_intel_bb@blit-noreloc-keep-cache,Timeout +api_intel_allocator@simple-allocator,Timeout +api_intel_bb@object-reloc-keep-cache,Timeout api_intel_bb@offset-control,Timeout -api_intel_bb@render-ccs,Timeout -core_getclient,Timeout -core_hotunplug@hotreplug-lateclose,Timeout -drm_read@short-buffer-block,Timeout +core_auth@getclient-simple,Timeout +core_hotunplug@hotunbind-rebind,Timeout +debugfs_test@read_all_entries_display_on,Timeout +drm_read@invalid-buffer,Timeout drm_read@short-buffer-nonblock,Timeout -dumb_buffer@map-uaf,Timeout gen3_render_tiledx_blits,Timeout gen7_exec_parse@basic-allocation,Timeout gen7_exec_parse@batch-without-end,Timeout gen9_exec_parse@batch-invalid-length,Timeout gen9_exec_parse@bb-secure,Timeout +gen9_exec_parse@secure-batches,Timeout +gen9_exec_parse@shadow-peek,Timeout +gen9_exec_parse@unaligned-jump,Timeout i915_module_load@load,Fail i915_module_load@reload,Fail i915_module_load@reload-no-display,Fail i915_module_load@resize-bar,Fail -i915_pciid,Timeout i915_query@engine-info,Timeout +i915_query@query-topology-kernel-writes,Timeout +i915_query@test-query-geometry-subslices,Timeout kms_lease@lease-uevent,Fail kms_rotation_crc@multiplane-rotation,Fail perf@i915-ref-count,Fail -perf_pmu@busy,Timeout perf_pmu@enable-race,Timeout perf_pmu@event-wait,Timeout perf_pmu@gt-awake,Timeout +perf_pmu@interrupts,Timeout perf_pmu@module-unload,Fail perf_pmu@rc6,Crash prime_mmap@test_map_unmap,Timeout +prime_mmap@test_refcounting,Timeout prime_self_import@basic-with_one_bo,Timeout -syncobj_basic@bad-destroy,Timeout +syncobj_basic@bad-flags-fd-to-handle,Timeout syncobj_eventfd@invalid-bad-pad,Timeout syncobj_wait@invalid-multi-wait-unsubmitted-signaled,Timeout syncobj_wait@invalid-signal-illegal-handle,Timeout @@ -37,7 +42,9 @@ syncobj_wait@multi-wait-all-submitted,Timeout syncobj_wait@multi-wait-for-submit-submitted-signaled,Timeout syncobj_wait@wait-any-complex,Timeout syncobj_wait@wait-delayed-signal,Timeout +template@A,Timeout xe_module_load@force-load,Fail xe_module_load@load,Fail +xe_module_load@many-reload,Fail xe_module_load@reload,Fail xe_module_load@reload-no-display,Fail diff --git a/drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt b/drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt index e600782ef96a..b47df5855e8d 100644 --- a/drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt @@ -12,9 +12,9 @@ kms_plane_scaling@invalid-parameters # Skip driver specific tests ^amdgpu.* -msm_.* +^msm.* nouveau_.* -panfrost_.* +^panfrost.* ^v3d.* ^vc4.* ^vmwgfx* diff --git a/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt index 7582d313dd9b..2adae2175501 100644 --- a/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt @@ -7,18 +7,10 @@ i915_module_load@resize-bar,Fail i915_pm_rpm@gem-execbuf-stress,Timeout i915_pm_rpm@module-reload,Fail i915_pm_rpm@system-suspend-execbuf,Timeout -kms_async_flips@invalid-async-flip,Timeout -kms_atomic_transition@modeset-transition-fencing,Timeout -kms_big_fb@linear-16bpp-rotate-0,Fail -kms_big_fb@linear-16bpp-rotate-180,Fail -kms_big_fb@linear-32bpp-rotate-0,Fail -kms_big_fb@linear-32bpp-rotate-180,Fail -kms_big_fb@linear-8bpp-rotate-0,Fail -kms_big_fb@linear-8bpp-rotate-180,Fail -kms_big_fb@linear-max-hw-stride-32bpp-rotate-0,Fail kms_ccs@crc-primary-rotation-180-yf-tiled-ccs,Timeout +kms_cursor_legacy@short-flip-before-cursor-atomic-transitions,Timeout kms_dirtyfb@default-dirtyfb-ioctl,Fail -kms_draw_crc@draw-method-render,Fail +kms_dirtyfb@fbc-dirtyfb-ioctl,Fail kms_fb_coherency@memset-crc,Crash kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail @@ -40,6 +32,7 @@ kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail +kms_frontbuffer_tracking@fbc-rgb565-draw-mmap-cpu,Timeout kms_frontbuffer_tracking@fbc-tiling-linear,Fail kms_lease@lease-uevent,Fail kms_plane_alpha_blend@alpha-basic,Fail @@ -47,9 +40,13 @@ kms_plane_alpha_blend@alpha-opaque-fb,Fail kms_plane_alpha_blend@alpha-transparent-fb,Fail kms_plane_alpha_blend@constant-alpha-max,Fail kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation,Timeout +kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-5,Timeout kms_pm_rpm@modeset-stress-extra-wait,Timeout kms_pm_rpm@universal-planes,Timeout kms_pm_rpm@universal-planes-dpms,Timeout +kms_prop_blob@invalid-set-prop,Fail +kms_rotation_crc@primary-rotation-180,Timeout +kms_vblank@query-forked-hang,Timeout perf@i915-ref-count,Fail perf_pmu@module-unload,Fail perf_pmu@rc6,Crash diff --git a/drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt index 1167a58c7dd1..60b8d1c64e70 100644 --- a/drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt @@ -1,6 +1,6 @@ # Board Name: dell-latitude-5400-8665U-sarien # Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# Failure Rate: 50 # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 -# Failure Rate: 50 kms_pm_rpm@modeset-lpsp-stress diff --git a/drivers/gpu/drm/ci/xfails/i915-whl-skips.txt b/drivers/gpu/drm/ci/xfails/i915-whl-skips.txt index 20bd91525f45..29bff8922ae1 100644 --- a/drivers/gpu/drm/ci/xfails/i915-whl-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-whl-skips.txt @@ -3,9 +3,9 @@ kms_plane_scaling@invalid-parameters # Skip driver specific tests ^amdgpu.* -msm_.* +^msm.* nouveau_.* -panfrost_.* +^panfrost.* ^v3d.* ^vc4.* ^vmwgfx* @@ -17,6 +17,7 @@ gem_.* i915_pm_rc6_residency.* i915_suspend.* kms_flip.* +i915_pm_rpm.* # Kernel panic drm_fdinfo.* diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt index cc5e9c1c2d57..95aadef2fa2d 100644 --- a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt +++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt @@ -5,8 +5,15 @@ device_reset@unbind-reset-rebind,Fail dumb_buffer@invalid-bpp,Fail fbdev@eof,Fail fbdev@read,Fail -fbdev@unaligned-write,Fail kms_3d,Fail +kms_bw@connected-linear-tiling-1-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-1-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-1-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-1-displays-3840x2160p,Fail +kms_bw@connected-linear-tiling-2-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-2-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-2-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-2-displays-3840x2160p,Fail kms_bw@linear-tiling-1-displays-1920x1080p,Fail kms_bw@linear-tiling-1-displays-2160x1440p,Fail kms_bw@linear-tiling-1-displays-2560x1440p,Fail diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt index 395ac0463404..2e5bf6ae25f2 100644 --- a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt @@ -1,11 +1,41 @@ # Board Name: mt8173-elm-hana # Bug Report: https://lore.kernel.org/linux-mediatek/0b2a1899-15dd-42fa-8f63-ea0ca28dbb17@collabora.com/T/#u +# Failure Rate: 50 # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 -# Failure Rate: 50 core_setmaster_vs_auth + +# Board Name: mt8173-elm-hana +# Bug Report: https://lore.kernel.org/linux-mediatek/0b2a1899-15dd-42fa-8f63-ea0ca28dbb17@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 dumb_buffer@create-clear + +# Board Name: mt8173-elm-hana +# Bug Report: https://lore.kernel.org/linux-mediatek/0b2a1899-15dd-42fa-8f63-ea0ca28dbb17@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 fbdev@unaligned-write + +# Board Name: mt8173-elm-hana +# Bug Report: https://lore.kernel.org/linux-mediatek/0b2a1899-15dd-42fa-8f63-ea0ca28dbb17@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 fbdev@write + +# Board Name: mt8173-elm-hana +# Bug Report: https://lore.kernel.org/linux-mediatek/0b2a1899-15dd-42fa-8f63-ea0ca28dbb17@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_cursor_legacy@cursor-vs-flip-atomic-transitions + +# Board Name: mt8173-elm-hana +# Bug Report: https://lore.kernel.org/linux-mediatek/0b2a1899-15dd-42fa-8f63-ea0ca28dbb17@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_prop_blob@invalid-set-prop diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-skips.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-skips.txt index 0c6108392140..562662eff802 100644 --- a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-skips.txt +++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-skips.txt @@ -1,8 +1,8 @@ # Skip driver specific tests ^amdgpu.* -msm_.* +^msm.* nouveau_.* -panfrost_.* +^panfrost.* ^v3d.* ^vc4.* ^vmwgfx* diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt index 9ef460646d76..5b7d623f404b 100644 --- a/drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt +++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt @@ -4,5 +4,5 @@ dumb_buffer@invalid-bpp,Fail dumb_buffer@map-invalid-size,Fail dumb_buffer@map-uaf,Fail dumb_buffer@map-valid,Fail -panfrost_prime@gem-prime-import,Fail +panfrost/panfrost_prime@gem-prime-import,Fail tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8183-skips.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8183-skips.txt index 715b9a8f4997..03eefa518afa 100644 --- a/drivers/gpu/drm/ci/xfails/mediatek-mt8183-skips.txt +++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8183-skips.txt @@ -1,6 +1,6 @@ # Skip driver specific tests ^amdgpu.* -msm_.* +^msm.* nouveau_.* ^v3d.* ^vc4.* diff --git a/drivers/gpu/drm/ci/xfails/meson-g12b-fails.txt b/drivers/gpu/drm/ci/xfails/meson-g12b-fails.txt index 9ef460646d76..5b7d623f404b 100644 --- a/drivers/gpu/drm/ci/xfails/meson-g12b-fails.txt +++ b/drivers/gpu/drm/ci/xfails/meson-g12b-fails.txt @@ -4,5 +4,5 @@ dumb_buffer@invalid-bpp,Fail dumb_buffer@map-invalid-size,Fail dumb_buffer@map-uaf,Fail dumb_buffer@map-valid,Fail -panfrost_prime@gem-prime-import,Fail +panfrost/panfrost_prime@gem-prime-import,Fail tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/meson-g12b-skips.txt b/drivers/gpu/drm/ci/xfails/meson-g12b-skips.txt index 715b9a8f4997..03eefa518afa 100644 --- a/drivers/gpu/drm/ci/xfails/meson-g12b-skips.txt +++ b/drivers/gpu/drm/ci/xfails/meson-g12b-skips.txt @@ -1,6 +1,6 @@ # Skip driver specific tests ^amdgpu.* -msm_.* +^msm.* nouveau_.* ^v3d.* ^vc4.* diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt b/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt index 6e7fd1ccd1e3..b57884650306 100644 --- a/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt +++ b/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt @@ -4,12 +4,9 @@ device_reset@unbind-cold-reset-rebind,Fail device_reset@unbind-reset-rebind,Fail dumb_buffer@invalid-bpp,Fail kms_3d,Fail -kms_cursor_legacy@forked-move,Fail -kms_cursor_legacy@single-bo,Fail kms_cursor_legacy@torture-bo,Fail -kms_cursor_legacy@torture-move,Fail kms_force_connector_basic@force-edid,Fail kms_hdmi_inject@inject-4k,Fail kms_lease@lease-uevent,Fail -msm_mapping@ring,Fail +msm/msm_mapping@ring,Fail tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8016-skips.txt b/drivers/gpu/drm/ci/xfails/msm-apq8016-skips.txt index ff12202abb6e..ef7697190fff 100644 --- a/drivers/gpu/drm/ci/xfails/msm-apq8016-skips.txt +++ b/drivers/gpu/drm/ci/xfails/msm-apq8016-skips.txt @@ -1,7 +1,7 @@ # Skip driver specific tests ^amdgpu.* nouveau_.* -panfrost_.* +^panfrost.* ^v3d.* ^vc4.* ^vmwgfx* diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8096-flakes.txt b/drivers/gpu/drm/ci/xfails/msm-apq8096-flakes.txt index a275584c8bbb..123d92cb4470 100644 --- a/drivers/gpu/drm/ci/xfails/msm-apq8096-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/msm-apq8096-flakes.txt @@ -1,6 +1,6 @@ # Board Name: apq8096-db820c # Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 -# Failure Rate: 50 dumb_buffer@create-clear diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8096-skips.txt b/drivers/gpu/drm/ci/xfails/msm-apq8096-skips.txt index 1c45fc6c512d..244324d38964 100644 --- a/drivers/gpu/drm/ci/xfails/msm-apq8096-skips.txt +++ b/drivers/gpu/drm/ci/xfails/msm-apq8096-skips.txt @@ -4,7 +4,7 @@ kms_cursor_legacy@all-pipes-torture-move # Skip driver specific tests ^amdgpu.* nouveau_.* -panfrost_.* +^panfrost.* ^v3d.* ^vc4.* ^vmwgfx* @@ -23,4 +23,4 @@ core_hotunplug.* # *** gpu fault: ttbr0=00000001030ea000 iova=0000000001074000 dir=WRITE type=PERMISSION source=1f030000 (0,0,0,0) # msm_mdp 901000.display-controller: RBBM | ME master split | status=0x701000B0 # watchdog: BUG: soft lockup - CPU#0 stuck for 26s! [kworker/u16:3:46] -msm_mapping@shadow +msm/msm_mapping@shadow diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt index eb7a3886d397..8e02392a24cb 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt @@ -3,13 +3,11 @@ device_reset@reset-bound,Fail device_reset@unbind-cold-reset-rebind,Fail device_reset@unbind-reset-rebind,Fail dumb_buffer@invalid-bpp,Fail -kms_atomic_transition@plane-primary-toggle-with-vblank-wait,Fail kms_color@ctm-0-25,Fail kms_color@ctm-0-50,Fail kms_color@ctm-0-75,Fail kms_color@ctm-blue-to-red,Fail kms_color@ctm-green-to-red,Fail -kms_color@ctm-max,Fail kms_color@ctm-negative,Fail kms_color@ctm-red-to-blue,Fail kms_color@ctm-signed,Fail @@ -21,72 +19,6 @@ kms_content_protection@lic-type-1,Crash kms_content_protection@srm,Crash kms_content_protection@type1,Crash kms_content_protection@uevent,Crash -kms_cursor_crc@cursor-alpha-opaque,Fail -kms_cursor_crc@cursor-alpha-transparent,Fail -kms_cursor_crc@cursor-dpms,Fail -kms_cursor_crc@cursor-offscreen-128x128,Fail -kms_cursor_crc@cursor-offscreen-128x42,Fail -kms_cursor_crc@cursor-offscreen-256x256,Fail -kms_cursor_crc@cursor-offscreen-256x85,Fail -kms_cursor_crc@cursor-offscreen-32x10,Fail -kms_cursor_crc@cursor-offscreen-32x32,Fail -kms_cursor_crc@cursor-offscreen-512x170,Fail -kms_cursor_crc@cursor-offscreen-512x512,Fail -kms_cursor_crc@cursor-offscreen-64x21,Fail -kms_cursor_crc@cursor-offscreen-64x64,Fail -kms_cursor_crc@cursor-onscreen-128x128,Fail -kms_cursor_crc@cursor-onscreen-128x42,Fail -kms_cursor_crc@cursor-onscreen-256x256,Fail -kms_cursor_crc@cursor-onscreen-256x85,Fail -kms_cursor_crc@cursor-onscreen-32x10,Fail -kms_cursor_crc@cursor-onscreen-32x32,Fail -kms_cursor_crc@cursor-onscreen-512x170,Fail -kms_cursor_crc@cursor-onscreen-512x512,Fail -kms_cursor_crc@cursor-onscreen-64x21,Fail -kms_cursor_crc@cursor-onscreen-64x64,Fail -kms_cursor_crc@cursor-random-128x128,Fail -kms_cursor_crc@cursor-random-128x42,Fail -kms_cursor_crc@cursor-random-256x256,Fail -kms_cursor_crc@cursor-random-256x85,Fail -kms_cursor_crc@cursor-random-32x10,Fail -kms_cursor_crc@cursor-random-32x32,Fail -kms_cursor_crc@cursor-random-512x170,Fail -kms_cursor_crc@cursor-random-512x512,Fail -kms_cursor_crc@cursor-random-64x21,Fail -kms_cursor_crc@cursor-random-64x64,Fail -kms_cursor_crc@cursor-rapid-movement-128x128,Fail -kms_cursor_crc@cursor-rapid-movement-128x42,Fail -kms_cursor_crc@cursor-rapid-movement-256x256,Fail -kms_cursor_crc@cursor-rapid-movement-256x85,Fail -kms_cursor_crc@cursor-rapid-movement-32x10,Fail -kms_cursor_crc@cursor-rapid-movement-32x32,Fail -kms_cursor_crc@cursor-rapid-movement-512x170,Fail -kms_cursor_crc@cursor-rapid-movement-512x512,Fail -kms_cursor_crc@cursor-rapid-movement-64x21,Fail -kms_cursor_crc@cursor-rapid-movement-64x64,Fail -kms_cursor_crc@cursor-size-change,Fail -kms_cursor_crc@cursor-sliding-128x128,Fail -kms_cursor_crc@cursor-sliding-128x42,Fail -kms_cursor_crc@cursor-sliding-256x256,Fail -kms_cursor_crc@cursor-sliding-256x85,Fail -kms_cursor_crc@cursor-sliding-32x10,Fail -kms_cursor_crc@cursor-sliding-32x32,Fail -kms_cursor_crc@cursor-sliding-512x170,Fail -kms_cursor_crc@cursor-sliding-512x512,Fail -kms_cursor_crc@cursor-sliding-64x21,Fail -kms_cursor_crc@cursor-sliding-64x64,Fail -kms_cursor_edge_walk@128x128-left-edge,Fail -kms_cursor_edge_walk@128x128-right-edge,Fail -kms_cursor_edge_walk@128x128-top-bottom,Fail -kms_cursor_edge_walk@128x128-top-edge,Fail -kms_cursor_edge_walk@256x256-left-edge,Fail -kms_cursor_edge_walk@256x256-right-edge,Fail -kms_cursor_edge_walk@256x256-top-bottom,Fail -kms_cursor_edge_walk@256x256-top-edge,Fail -kms_cursor_edge_walk@64x64-left-edge,Fail -kms_cursor_edge_walk@64x64-right-edge,Fail -kms_cursor_edge_walk@64x64-top-bottom,Fail -kms_cursor_edge_walk@64x64-top-edge,Fail kms_cursor_legacy@2x-cursor-vs-flip-atomic,Fail kms_cursor_legacy@2x-cursor-vs-flip-legacy,Fail kms_cursor_legacy@2x-flip-vs-cursor-atomic,Fail @@ -100,92 +32,15 @@ kms_cursor_legacy@cursor-vs-flip-varying-size,Fail kms_display_modes@extended-mode-basic,Fail kms_flip@2x-flip-vs-modeset-vs-hang,Fail kms_flip@2x-flip-vs-panning-vs-hang,Fail -kms_flip@absolute-wf_vblank,Fail -kms_flip@absolute-wf_vblank-interruptible,Fail -kms_flip@basic-flip-vs-wf_vblank,Fail -kms_flip@basic-plain-flip,Fail -kms_flip@blocking-absolute-wf_vblank,Fail -kms_flip@blocking-absolute-wf_vblank-interruptible,Fail -kms_flip@blocking-wf_vblank,Fail -kms_flip@busy-flip,Fail -kms_flip@dpms-off-confusion,Fail -kms_flip@dpms-off-confusion-interruptible,Fail -kms_flip@dpms-vs-vblank-race,Fail -kms_flip@dpms-vs-vblank-race-interruptible,Fail -kms_flip@flip-vs-absolute-wf_vblank,Fail -kms_flip@flip-vs-absolute-wf_vblank-interruptible,Fail -kms_flip@flip-vs-blocking-wf-vblank,Fail -kms_flip@flip-vs-expired-vblank,Fail -kms_flip@flip-vs-expired-vblank-interruptible,Fail kms_flip@flip-vs-modeset-vs-hang,Fail -kms_flip@flip-vs-panning,Fail -kms_flip@flip-vs-panning-interruptible,Fail kms_flip@flip-vs-panning-vs-hang,Fail -kms_flip@flip-vs-rmfb,Fail -kms_flip@flip-vs-rmfb-interruptible,Fail -kms_flip@flip-vs-wf_vblank-interruptible,Fail -kms_flip@modeset-vs-vblank-race,Fail -kms_flip@modeset-vs-vblank-race-interruptible,Fail -kms_flip@plain-flip-fb-recreate,Fail -kms_flip@plain-flip-fb-recreate-interruptible,Fail -kms_flip@plain-flip-interruptible,Fail -kms_flip@plain-flip-ts-check,Fail -kms_flip@plain-flip-ts-check-interruptible,Fail -kms_flip@wf_vblank-ts-check,Fail -kms_flip@wf_vblank-ts-check-interruptible,Fail -kms_lease@cursor-implicit-plane,Fail kms_lease@lease-uevent,Fail -kms_lease@page-flip-implicit-plane,Fail -kms_lease@setcrtc-implicit-plane,Fail -kms_lease@simple-lease,Fail kms_multipipe_modeset@basic-max-pipe-crc-check,Fail kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail -kms_pipe_crc_basic@compare-crc-sanitycheck-xr24,Fail -kms_pipe_crc_basic@disable-crc-after-crtc,Fail -kms_pipe_crc_basic@nonblocking-crc,Fail -kms_pipe_crc_basic@nonblocking-crc-frame-sequence,Fail -kms_pipe_crc_basic@read-crc,Fail -kms_pipe_crc_basic@read-crc-frame-sequence,Fail -kms_plane@pixel-format,Fail -kms_plane@pixel-format-source-clamping,Fail -kms_plane@plane-panning-bottom-right,Fail -kms_plane@plane-panning-top-left,Fail -kms_plane@plane-position-covered,Fail -kms_plane@plane-position-hole,Fail -kms_plane@plane-position-hole-dpms,Fail kms_plane_alpha_blend@alpha-7efc,Fail -kms_plane_alpha_blend@alpha-basic,Fail -kms_plane_alpha_blend@alpha-opaque-fb,Fail -kms_plane_alpha_blend@alpha-transparent-fb,Fail -kms_plane_alpha_blend@constant-alpha-max,Fail -kms_plane_alpha_blend@constant-alpha-mid,Fail -kms_plane_alpha_blend@constant-alpha-min,Fail kms_plane_alpha_blend@coverage-7efc,Fail kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail -kms_plane_cursor@primary,Fail kms_plane_lowres@tiling-none,Fail -kms_plane_multiple@tiling-none,Fail kms_rmfb@close-fd,Fail -kms_rotation_crc@cursor-rotation-180,Fail -kms_rotation_crc@primary-rotation-180,Fail -kms_sequence@get-busy,Fail -kms_sequence@get-forked,Fail -kms_sequence@get-forked-busy,Fail -kms_sequence@get-idle,Fail -kms_sequence@queue-busy,Fail -kms_sequence@queue-idle,Fail -kms_vblank@accuracy-idle,Fail -kms_vblank@crtc-id,Fail -kms_vblank@query-busy,Fail -kms_vblank@query-forked,Fail -kms_vblank@query-forked-busy,Fail -kms_vblank@query-idle,Fail kms_vblank@ts-continuation-dpms-rpm,Fail -kms_vblank@ts-continuation-idle,Fail -kms_vblank@ts-continuation-modeset,Fail -kms_vblank@ts-continuation-modeset-rpm,Fail -kms_vblank@wait-busy,Fail -kms_vblank@wait-forked,Fail -kms_vblank@wait-forked-busy,Fail -kms_vblank@wait-idle,Fail tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-flakes.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-flakes.txt index 6dec63d48cfb..d74e04405e65 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-flakes.txt @@ -1,8 +1,20 @@ # Board Name: sc7180-trogdor-kingoftown # Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +msm/msm_mapping@shadow + +# Board Name: sc7180-trogdor-kingoftown +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 +msm/msm_shrink@copy-gpu-oom-32 + +# Board Name: sc7180-trogdor-kingoftown +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u # Failure Rate: 50 -msm_mapping@shadow -msm_shrink@copy-gpu-oom-32 -msm_shrink@copy-gpu-oom-8 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +msm/msm_shrink@copy-gpu-oom-8 diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt index 68c96005ba54..bd5a975a1b2f 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt @@ -4,7 +4,7 @@ # Skip driver specific tests ^amdgpu.* nouveau_.* -panfrost_.* +^panfrost.* ^v3d.* ^vc4.* ^vmwgfx* @@ -19,3 +19,6 @@ core_hotunplug.* # Timeout occurs kms_flip@2x-wf_vblank-ts-check + +# Hangs the machine +kms_cursor_crc@cursor-random-max-size diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt index eb7a3886d397..8e02392a24cb 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt @@ -3,13 +3,11 @@ device_reset@reset-bound,Fail device_reset@unbind-cold-reset-rebind,Fail device_reset@unbind-reset-rebind,Fail dumb_buffer@invalid-bpp,Fail -kms_atomic_transition@plane-primary-toggle-with-vblank-wait,Fail kms_color@ctm-0-25,Fail kms_color@ctm-0-50,Fail kms_color@ctm-0-75,Fail kms_color@ctm-blue-to-red,Fail kms_color@ctm-green-to-red,Fail -kms_color@ctm-max,Fail kms_color@ctm-negative,Fail kms_color@ctm-red-to-blue,Fail kms_color@ctm-signed,Fail @@ -21,72 +19,6 @@ kms_content_protection@lic-type-1,Crash kms_content_protection@srm,Crash kms_content_protection@type1,Crash kms_content_protection@uevent,Crash -kms_cursor_crc@cursor-alpha-opaque,Fail -kms_cursor_crc@cursor-alpha-transparent,Fail -kms_cursor_crc@cursor-dpms,Fail -kms_cursor_crc@cursor-offscreen-128x128,Fail -kms_cursor_crc@cursor-offscreen-128x42,Fail -kms_cursor_crc@cursor-offscreen-256x256,Fail -kms_cursor_crc@cursor-offscreen-256x85,Fail -kms_cursor_crc@cursor-offscreen-32x10,Fail -kms_cursor_crc@cursor-offscreen-32x32,Fail -kms_cursor_crc@cursor-offscreen-512x170,Fail -kms_cursor_crc@cursor-offscreen-512x512,Fail -kms_cursor_crc@cursor-offscreen-64x21,Fail -kms_cursor_crc@cursor-offscreen-64x64,Fail -kms_cursor_crc@cursor-onscreen-128x128,Fail -kms_cursor_crc@cursor-onscreen-128x42,Fail -kms_cursor_crc@cursor-onscreen-256x256,Fail -kms_cursor_crc@cursor-onscreen-256x85,Fail -kms_cursor_crc@cursor-onscreen-32x10,Fail -kms_cursor_crc@cursor-onscreen-32x32,Fail -kms_cursor_crc@cursor-onscreen-512x170,Fail -kms_cursor_crc@cursor-onscreen-512x512,Fail -kms_cursor_crc@cursor-onscreen-64x21,Fail -kms_cursor_crc@cursor-onscreen-64x64,Fail -kms_cursor_crc@cursor-random-128x128,Fail -kms_cursor_crc@cursor-random-128x42,Fail -kms_cursor_crc@cursor-random-256x256,Fail -kms_cursor_crc@cursor-random-256x85,Fail -kms_cursor_crc@cursor-random-32x10,Fail -kms_cursor_crc@cursor-random-32x32,Fail -kms_cursor_crc@cursor-random-512x170,Fail -kms_cursor_crc@cursor-random-512x512,Fail -kms_cursor_crc@cursor-random-64x21,Fail -kms_cursor_crc@cursor-random-64x64,Fail -kms_cursor_crc@cursor-rapid-movement-128x128,Fail -kms_cursor_crc@cursor-rapid-movement-128x42,Fail -kms_cursor_crc@cursor-rapid-movement-256x256,Fail -kms_cursor_crc@cursor-rapid-movement-256x85,Fail -kms_cursor_crc@cursor-rapid-movement-32x10,Fail -kms_cursor_crc@cursor-rapid-movement-32x32,Fail -kms_cursor_crc@cursor-rapid-movement-512x170,Fail -kms_cursor_crc@cursor-rapid-movement-512x512,Fail -kms_cursor_crc@cursor-rapid-movement-64x21,Fail -kms_cursor_crc@cursor-rapid-movement-64x64,Fail -kms_cursor_crc@cursor-size-change,Fail -kms_cursor_crc@cursor-sliding-128x128,Fail -kms_cursor_crc@cursor-sliding-128x42,Fail -kms_cursor_crc@cursor-sliding-256x256,Fail -kms_cursor_crc@cursor-sliding-256x85,Fail -kms_cursor_crc@cursor-sliding-32x10,Fail -kms_cursor_crc@cursor-sliding-32x32,Fail -kms_cursor_crc@cursor-sliding-512x170,Fail -kms_cursor_crc@cursor-sliding-512x512,Fail -kms_cursor_crc@cursor-sliding-64x21,Fail -kms_cursor_crc@cursor-sliding-64x64,Fail -kms_cursor_edge_walk@128x128-left-edge,Fail -kms_cursor_edge_walk@128x128-right-edge,Fail -kms_cursor_edge_walk@128x128-top-bottom,Fail -kms_cursor_edge_walk@128x128-top-edge,Fail -kms_cursor_edge_walk@256x256-left-edge,Fail -kms_cursor_edge_walk@256x256-right-edge,Fail -kms_cursor_edge_walk@256x256-top-bottom,Fail -kms_cursor_edge_walk@256x256-top-edge,Fail -kms_cursor_edge_walk@64x64-left-edge,Fail -kms_cursor_edge_walk@64x64-right-edge,Fail -kms_cursor_edge_walk@64x64-top-bottom,Fail -kms_cursor_edge_walk@64x64-top-edge,Fail kms_cursor_legacy@2x-cursor-vs-flip-atomic,Fail kms_cursor_legacy@2x-cursor-vs-flip-legacy,Fail kms_cursor_legacy@2x-flip-vs-cursor-atomic,Fail @@ -100,92 +32,15 @@ kms_cursor_legacy@cursor-vs-flip-varying-size,Fail kms_display_modes@extended-mode-basic,Fail kms_flip@2x-flip-vs-modeset-vs-hang,Fail kms_flip@2x-flip-vs-panning-vs-hang,Fail -kms_flip@absolute-wf_vblank,Fail -kms_flip@absolute-wf_vblank-interruptible,Fail -kms_flip@basic-flip-vs-wf_vblank,Fail -kms_flip@basic-plain-flip,Fail -kms_flip@blocking-absolute-wf_vblank,Fail -kms_flip@blocking-absolute-wf_vblank-interruptible,Fail -kms_flip@blocking-wf_vblank,Fail -kms_flip@busy-flip,Fail -kms_flip@dpms-off-confusion,Fail -kms_flip@dpms-off-confusion-interruptible,Fail -kms_flip@dpms-vs-vblank-race,Fail -kms_flip@dpms-vs-vblank-race-interruptible,Fail -kms_flip@flip-vs-absolute-wf_vblank,Fail -kms_flip@flip-vs-absolute-wf_vblank-interruptible,Fail -kms_flip@flip-vs-blocking-wf-vblank,Fail -kms_flip@flip-vs-expired-vblank,Fail -kms_flip@flip-vs-expired-vblank-interruptible,Fail kms_flip@flip-vs-modeset-vs-hang,Fail -kms_flip@flip-vs-panning,Fail -kms_flip@flip-vs-panning-interruptible,Fail kms_flip@flip-vs-panning-vs-hang,Fail -kms_flip@flip-vs-rmfb,Fail -kms_flip@flip-vs-rmfb-interruptible,Fail -kms_flip@flip-vs-wf_vblank-interruptible,Fail -kms_flip@modeset-vs-vblank-race,Fail -kms_flip@modeset-vs-vblank-race-interruptible,Fail -kms_flip@plain-flip-fb-recreate,Fail -kms_flip@plain-flip-fb-recreate-interruptible,Fail -kms_flip@plain-flip-interruptible,Fail -kms_flip@plain-flip-ts-check,Fail -kms_flip@plain-flip-ts-check-interruptible,Fail -kms_flip@wf_vblank-ts-check,Fail -kms_flip@wf_vblank-ts-check-interruptible,Fail -kms_lease@cursor-implicit-plane,Fail kms_lease@lease-uevent,Fail -kms_lease@page-flip-implicit-plane,Fail -kms_lease@setcrtc-implicit-plane,Fail -kms_lease@simple-lease,Fail kms_multipipe_modeset@basic-max-pipe-crc-check,Fail kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail -kms_pipe_crc_basic@compare-crc-sanitycheck-xr24,Fail -kms_pipe_crc_basic@disable-crc-after-crtc,Fail -kms_pipe_crc_basic@nonblocking-crc,Fail -kms_pipe_crc_basic@nonblocking-crc-frame-sequence,Fail -kms_pipe_crc_basic@read-crc,Fail -kms_pipe_crc_basic@read-crc-frame-sequence,Fail -kms_plane@pixel-format,Fail -kms_plane@pixel-format-source-clamping,Fail -kms_plane@plane-panning-bottom-right,Fail -kms_plane@plane-panning-top-left,Fail -kms_plane@plane-position-covered,Fail -kms_plane@plane-position-hole,Fail -kms_plane@plane-position-hole-dpms,Fail kms_plane_alpha_blend@alpha-7efc,Fail -kms_plane_alpha_blend@alpha-basic,Fail -kms_plane_alpha_blend@alpha-opaque-fb,Fail -kms_plane_alpha_blend@alpha-transparent-fb,Fail -kms_plane_alpha_blend@constant-alpha-max,Fail -kms_plane_alpha_blend@constant-alpha-mid,Fail -kms_plane_alpha_blend@constant-alpha-min,Fail kms_plane_alpha_blend@coverage-7efc,Fail kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail -kms_plane_cursor@primary,Fail kms_plane_lowres@tiling-none,Fail -kms_plane_multiple@tiling-none,Fail kms_rmfb@close-fd,Fail -kms_rotation_crc@cursor-rotation-180,Fail -kms_rotation_crc@primary-rotation-180,Fail -kms_sequence@get-busy,Fail -kms_sequence@get-forked,Fail -kms_sequence@get-forked-busy,Fail -kms_sequence@get-idle,Fail -kms_sequence@queue-busy,Fail -kms_sequence@queue-idle,Fail -kms_vblank@accuracy-idle,Fail -kms_vblank@crtc-id,Fail -kms_vblank@query-busy,Fail -kms_vblank@query-forked,Fail -kms_vblank@query-forked-busy,Fail -kms_vblank@query-idle,Fail kms_vblank@ts-continuation-dpms-rpm,Fail -kms_vblank@ts-continuation-idle,Fail -kms_vblank@ts-continuation-modeset,Fail -kms_vblank@ts-continuation-modeset-rpm,Fail -kms_vblank@wait-busy,Fail -kms_vblank@wait-forked,Fail -kms_vblank@wait-forked-busy,Fail -kms_vblank@wait-idle,Fail tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-flakes.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-flakes.txt index dcb24b835dc3..cd3d3b0befe4 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-flakes.txt @@ -1,6 +1,13 @@ # Board Name: sc7180-trogdor-lazor-limozeen-nots-r5 # Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 -# Failure Rate: 50 -msm_mapping@shadow +msm/msm_mapping@shadow + +# Board Name: sc7180-trogdor-lazor-limozeen-nots-r5 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 100 +# IGT Version: 1.28-gf13702b8e +# Linux Version: 6.10.0-rc5 +kms_lease@page-flip-implicit-plane diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt index 1168c53acd2d..d06c3621300d 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt @@ -4,7 +4,7 @@ # Skip driver specific tests ^amdgpu.* nouveau_.* -panfrost_.* +^panfrost.* ^v3d.* ^vc4.* ^vmwgfx* diff --git a/drivers/gpu/drm/ci/xfails/msm-sdm845-flakes.txt b/drivers/gpu/drm/ci/xfails/msm-sdm845-flakes.txt index 2c5f62b07632..2aa96b1241c3 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sdm845-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sdm845-flakes.txt @@ -1,19 +1,118 @@ # Board Name: sdm845-cheza-r3 # Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 -# Failure Rate: 50 kms_cursor_legacy@basic-flip-after-cursor-atomic + +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_cursor_legacy@basic-flip-after-cursor-legacy + +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_cursor_legacy@basic-flip-after-cursor-varying-size + +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_cursor_legacy@basic-flip-before-cursor-varying-size + +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_cursor_legacy@flip-vs-cursor-atomic-transitions + +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size + +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_cursor_legacy@flip-vs-cursor-varying-size + +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_cursor_legacy@short-flip-after-cursor-atomic-transitions + +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_cursor_legacy@short-flip-after-cursor-atomic-transitions-varying-size + +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_cursor_legacy@short-flip-after-cursor-toggle + +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_cursor_legacy@short-flip-before-cursor-atomic-transitions + +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 kms_cursor_legacy@short-flip-before-cursor-atomic-transitions-varying-size -msm_shrink@copy-gpu-32 -msm_shrink@copy-gpu-oom-32 + +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +msm/msm_shrink@copy-gpu-32 + +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +msm/msm_shrink@copy-gpu-oom-32 + +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-gf13702b8e +# Linux Version: 6.10.0-rc5 +kms_cursor_legacy@short-flip-before-cursor-toggle + +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-gf13702b8e +# Linux Version: 6.10.0-rc5 +kms_cursor_legacy@flip-vs-cursor-toggle + +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-gf13702b8e +# Linux Version: 6.10.0-rc5 +msm/msm_shrink@copy-mmap-oom-8 diff --git a/drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt b/drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt index 5185212c8fb2..041a9637cc3e 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt @@ -4,12 +4,12 @@ kms_bw.* # Failing due to a bootloader/fw issue. The workaround in mesa CI involves these two patches # https://gitlab.freedesktop.org/gfx-ci/linux/-/commit/4b49f902ec6f2bb382cbbf489870573f4b43371e # https://gitlab.freedesktop.org/gfx-ci/linux/-/commit/38cdf4c5559771e2474ae0fecef8469f65147bc1 -msm_mapping@* +msm/msm_mapping@* # Skip driver specific tests ^amdgpu.* nouveau_.* -panfrost_.* +^panfrost.* ^v3d.* ^vc4.* ^vmwgfx* diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt index f9b99bf27105..10689906da3a 100644 --- a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt +++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt @@ -4,5 +4,5 @@ dumb_buffer@invalid-bpp,Crash dumb_buffer@map-invalid-size,Crash dumb_buffer@map-uaf,Crash dumb_buffer@map-valid,Crash -panfrost_prime@gem-prime-import,Crash +panfrost/panfrost_prime@gem-prime-import,Crash tools_test@tools_test,Crash diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-skips.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-skips.txt index 6d3757dca83b..b8cb31842323 100644 --- a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-skips.txt +++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-skips.txt @@ -53,7 +53,7 @@ kms_pipe_crc_basic@disable-crc-after-crtc # Skip driver specific tests ^amdgpu.* -msm_.* +^msm.* nouveau_.* ^v3d.* ^vc4.* diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt index 9ef460646d76..5b7d623f404b 100644 --- a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt +++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt @@ -4,5 +4,5 @@ dumb_buffer@invalid-bpp,Fail dumb_buffer@map-invalid-size,Fail dumb_buffer@map-uaf,Fail dumb_buffer@map-valid,Fail -panfrost_prime@gem-prime-import,Fail +panfrost/panfrost_prime@gem-prime-import,Fail tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt index 742c27d9a598..ac4f8f7244d4 100644 --- a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt @@ -1,6 +1,6 @@ # Board Name: rk3399-gru-kevin # Bug Report: https://lore.kernel.org/dri-devel/5cc34a8b-c1fa-4744-9031-2d33ecf41011@collabora.com/T/#u +# Failure Rate: 50 # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 -# Failure Rate: 50 -panfrost_submit@pan-unhandled-pagefault +panfrost/panfrost_submit@pan-unhandled-pagefault diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt index 5c52b25b4213..743f3eeb2f80 100644 --- a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt +++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt @@ -6,7 +6,7 @@ kms_cursor_legacy.* # Skip driver specific tests ^amdgpu.* -msm_.* +^msm.* nouveau_.* ^v3d.* ^vc4.* diff --git a/drivers/gpu/drm/ci/xfails/virtio_gpu-none-fails.txt b/drivers/gpu/drm/ci/xfails/virtio_gpu-none-fails.txt index fdf09fe11566..248943c2a738 100644 --- a/drivers/gpu/drm/ci/xfails/virtio_gpu-none-fails.txt +++ b/drivers/gpu/drm/ci/xfails/virtio_gpu-none-fails.txt @@ -3,6 +3,70 @@ kms_addfb_basic@bo-too-small,Fail kms_addfb_basic@size-max,Fail kms_addfb_basic@too-high,Fail kms_atomic_transition@plane-primary-toggle-with-vblank-wait,Fail +kms_bw@connected-linear-tiling-1-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-1-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-1-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-1-displays-3840x2160p,Fail +kms_bw@connected-linear-tiling-10-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-10-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-10-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-10-displays-3840x2160p,Fail +kms_bw@connected-linear-tiling-11-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-11-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-11-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-11-displays-3840x2160p,Fail +kms_bw@connected-linear-tiling-12-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-12-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-12-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-12-displays-3840x2160p,Fail +kms_bw@connected-linear-tiling-13-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-13-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-13-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-13-displays-3840x2160p,Fail +kms_bw@connected-linear-tiling-14-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-14-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-14-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-14-displays-3840x2160p,Fail +kms_bw@connected-linear-tiling-15-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-15-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-15-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-15-displays-3840x2160p,Fail +kms_bw@connected-linear-tiling-16-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-16-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-16-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-16-displays-3840x2160p,Fail +kms_bw@connected-linear-tiling-2-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-2-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-2-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-2-displays-3840x2160p,Fail +kms_bw@connected-linear-tiling-3-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-3-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-3-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-3-displays-3840x2160p,Fail +kms_bw@connected-linear-tiling-4-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-4-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-4-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-4-displays-3840x2160p,Fail +kms_bw@connected-linear-tiling-5-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-5-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-5-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-5-displays-3840x2160p,Fail +kms_bw@connected-linear-tiling-6-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-6-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-6-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-6-displays-3840x2160p,Fail +kms_bw@connected-linear-tiling-7-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-7-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-7-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-7-displays-3840x2160p,Fail +kms_bw@connected-linear-tiling-8-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-8-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-8-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-8-displays-3840x2160p,Fail +kms_bw@connected-linear-tiling-9-displays-1920x1080p,Fail +kms_bw@connected-linear-tiling-9-displays-2160x1440p,Fail +kms_bw@connected-linear-tiling-9-displays-2560x1440p,Fail +kms_bw@connected-linear-tiling-9-displays-3840x2160p,Fail kms_bw@linear-tiling-1-displays-1920x1080p,Fail kms_bw@linear-tiling-1-displays-2160x1440p,Fail kms_bw@linear-tiling-1-displays-2560x1440p,Fail diff --git a/drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt b/drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt index e0ca4fadb84f..8198905c5fd4 100644 --- a/drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt +++ b/drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt @@ -7,9 +7,9 @@ kms_flip@flip-vs-suspend.* # Skip driver specific tests ^amdgpu.* -msm_.* +^msm.* nouveau_.* -panfrost_.* +^panfrost.* ^v3d.* ^vc4.* ^vmwgfx* diff --git a/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt b/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt index 691c383b21a0..8385b26073ed 100644 --- a/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt +++ b/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt @@ -41,12 +41,8 @@ kms_cursor_legacy@flip-vs-cursor-crc-legacy,Fail kms_cursor_legacy@flip-vs-cursor-legacy,Fail kms_flip@flip-vs-modeset-vs-hang,Fail kms_flip@flip-vs-panning-vs-hang,Fail -kms_flip@flip-vs-suspend,Timeout -kms_flip@flip-vs-suspend-interruptible,Timeout -kms_flip@plain-flip-fb-recreate,Fail kms_lease@lease-uevent,Fail kms_pipe_crc_basic@nonblocking-crc,Fail -kms_pipe_crc_basic@nonblocking-crc-frame-sequence,Fail kms_writeback@writeback-check-output,Fail kms_writeback@writeback-check-output-XRGB2101010,Fail kms_writeback@writeback-fb-id,Fail diff --git a/drivers/gpu/drm/ci/xfails/vkms-none-flakes.txt b/drivers/gpu/drm/ci/xfails/vkms-none-flakes.txt index eeaa1d5825af..62428f3c8f31 100644 --- a/drivers/gpu/drm/ci/xfails/vkms-none-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/vkms-none-flakes.txt @@ -67,3 +67,24 @@ kms_flip@flip-vs-absolute-wf_vblank-interruptible # IGT Version: 1.28-g0df7b9b97 # Linux Version: 6.9.0-rc7 kms_flip@flip-vs-blocking-wf-vblank + +# Board Name: vkms +# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-gf13702b8e +# Linux Version: 6.10.0-rc5 +kms_cursor_legacy@flip-vs-cursor-varying-size + +# Board Name: vkms +# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-gf13702b8e +# Linux Version: 6.10.0-rc5 +kms_flip@flip-vs-expired-vblank + +# Board Name: vkms +# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-gf13702b8e +# Linux Version: 6.10.0-rc5 +kms_pipe_crc_basic@nonblocking-crc-frame-sequence diff --git a/drivers/gpu/drm/ci/xfails/vkms-none-skips.txt b/drivers/gpu/drm/ci/xfails/vkms-none-skips.txt index fd5d1271115f..6c1f2b2b6e53 100644 --- a/drivers/gpu/drm/ci/xfails/vkms-none-skips.txt +++ b/drivers/gpu/drm/ci/xfails/vkms-none-skips.txt @@ -104,11 +104,112 @@ kms_cursor_crc@cursor-rapid-movement-256x85 # CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 # CR2: 0000000000000078 CR3: 0000000109b38000 CR4: 0000000000350ef0 +kms_cursor_crc@cursor-onscreen-256x256 +# Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI +# CPU: 1 PID: 1913 Comm: kworker/u8:6 Not tainted 6.10.0-rc5-g8a28e73ebead #1 +# Hardware name: ChromiumOS crosvm, BIOS 0 +# Workqueue: vkms_composer vkms_composer_worker [vkms] +# RIP: 0010:compose_active_planes+0x344/0x4e0 [vkms] +# Code: 6a 34 0f 8e 91 fe ff ff 44 89 ea 48 8d 7c 24 48 e8 71 f0 ff ff 4b 8b 04 fc 48 8b 4c 24 50 48 8b 7c 24 40 48 8b 80 48 01 00 00 <48> 63 70 18 8b 40 20 48 89 f2 48 c1 e6 03 29 d0 48 8b 54 24 48 48 +# RSP: 0018:ffffb477409fbd58 EFLAGS: 00010282 +# RAX: 0000000000000000 RBX: 0000000000000002 RCX: ffff8b124a242000 +# RDX: 00000000000000ff RSI: ffff8b124a243ff8 RDI: ffff8b124a244000 +# RBP: 0000000000000002 R08: 0000000000000000 R09: 00000000000003ff +# R10: ffff8b124a244000 R11: 0000000000000000 R12: ffff8b1249282f30 +# R13: 0000000000000002 R14: 0000000000000002 R15: 0000000000000000 +# FS: 0000000000000000(0000) GS:ffff8b126bd00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 0000000000000018 CR3: 0000000107a86000 CR4: 0000000000350ef0 +# Call Trace: +# +# ? __die+0x1e/0x60 +# ? page_fault_oops+0x17b/0x4a0 +# ? exc_page_fault+0x6d/0x230 +# ? asm_exc_page_fault+0x26/0x30 +# ? compose_active_planes+0x344/0x4e0 [vkms] +# ? compose_active_planes+0x32f/0x4e0 [vkms] +# ? srso_return_thunk+0x5/0x5f +# vkms_composer_worker+0x205/0x240 [vkms] +# process_one_work+0x201/0x6c0 +# ? lock_is_held_type+0x9e/0x110 +# worker_thread+0x17e/0x350 +# ? __pfx_worker_thread+0x10/0x10 +# kthread+0xce/0x100 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork+0x2f/0x50 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork_asm+0x1a/0x30 +# +# Modules linked in: vkms +# CR2: 0000000000000018 +# ---[ end trace 0000000000000000 ]--- +# RIP: 0010:compose_active_planes+0x344/0x4e0 [vkms] +# Code: 6a 34 0f 8e 91 fe ff ff 44 89 ea 48 8d 7c 24 48 e8 71 f0 ff ff 4b 8b 04 fc 48 8b 4c 24 50 48 8b 7c 24 40 48 8b 80 48 01 00 00 <48> 63 70 18 8b 40 20 48 89 f2 48 c1 e6 03 29 d0 48 8b 54 24 48 48 +# RSP: 0018:ffffb477409fbd58 EFLAGS: 00010282 +# RAX: 0000000000000000 RBX: 0000000000000002 RCX: ffff8b124a242000 +# RDX: 00000000000000ff RSI: ffff8b124a243ff8 RDI: ffff8b124a244000 +# RBP: 0000000000000002 R08: 0000000000000000 R09: 00000000000003ff +# R10: ffff8b124a244000 R11: 0000000000000000 R12: ffff8b1249282f30 +# R13: 0000000000000002 R14: 0000000000000002 R15: 0000000000000000 +# FS: 0000000000000000(0000) GS:ffff8b126bd00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 0000000000000018 CR3: 0000000107a86000 CR4: 0000000000350ef0 + +kms_cursor_edge_walk@128x128-right-edge +# Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI +# CPU: 0 PID: 1911 Comm: kworker/u8:3 Not tainted 6.10.0-rc5-g5e7a002eefe5 #1 +# Hardware name: ChromiumOS crosvm, BIOS 0 +# Workqueue: vkms_composer vkms_composer_worker [vkms] +# RIP: 0010:compose_active_planes+0x344/0x4e0 [vkms] +# Code: 6a 34 0f 8e 91 fe ff ff 44 89 ea 48 8d 7c 24 48 e8 71 f0 ff ff 4b 8b 04 fc 48 8b 4c 24 50 48 8b 7c 24 40 48 8b 80 48 01 00 00 <48> 63 70 18 8b 40 20 48 89 f2 48 c1 e6 03 29 d0 48 8b 54 24 48 48 +# RSP: 0018:ffffb2f040a43d58 EFLAGS: 00010282 +# RAX: 0000000000000000 RBX: 0000000000000002 RCX: ffffa2c181792000 +# RDX: 0000000000000000 RSI: ffffa2c181793ff8 RDI: ffffa2c181790000 +# RBP: 0000000000000031 R08: 0000000000000000 R09: 00000000000003ff +# R10: ffffa2c181790000 R11: 0000000000000000 R12: ffffa2c1814fa810 +# R13: 0000000000000031 R14: 0000000000000031 R15: 0000000000000000 +# FS: 0000000000000000(0000) GS:ffffa2c1abc00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 0000000000000018 CR3: 0000000106768000 CR4: 0000000000350ef0 +# Call Trace: +# +# ? __die+0x1e/0x60 +# ? page_fault_oops+0x17b/0x4a0 +# ? srso_return_thunk+0x5/0x5f +# ? mark_held_locks+0x49/0x80 +# ? exc_page_fault+0x6d/0x230 +# ? asm_exc_page_fault+0x26/0x30 +# ? compose_active_planes+0x344/0x4e0 [vkms] +# ? compose_active_planes+0x32f/0x4e0 [vkms] +# ? srso_return_thunk+0x5/0x5f +# vkms_composer_worker+0x205/0x240 [vkms] +# process_one_work+0x201/0x6c0 +# ? lock_is_held_type+0x9e/0x110 +# worker_thread+0x17e/0x350 +# ? __pfx_worker_thread+0x10/0x10 +# kthread+0xce/0x100 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork+0x2f/0x50 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork_asm+0x1a/0x30 +# +# Modules linked in: vkms +# CR2: 0000000000000018 +# ---[ end trace 0000000000000000 ]--- +# RIP: 0010:compose_active_planes+0x344/0x4e0 [vkms] +# Code: 6a 34 0f 8e 91 fe ff ff 44 89 ea 48 8d 7c 24 48 e8 71 f0 ff ff 4b 8b 04 fc 48 8b 4c 24 50 48 8b 7c 24 40 48 8b 80 48 01 00 00 <48> 63 70 18 8b 40 20 48 89 f2 48 c1 e6 03 29 d0 48 8b 54 24 48 48 +# RSP: 0018:ffffb2f040a43d58 EFLAGS: 00010282 +# RAX: 0000000000000000 RBX: 0000000000000002 RCX: ffffa2c181792000 +# RDX: 0000000000000000 RSI: ffffa2c181793ff8 RDI: ffffa2c181790000 +# RBP: 0000000000000031 R08: 0000000000000000 R09: 00000000000003ff +# R10: ffffa2c181790000 R11: 0000000000000000 R12: ffffa2c1814fa810 +# R13: 0000000000000031 R14: 0000000000000031 R15: 000000000000 + # Skip driver specific tests ^amdgpu.* -msm_.* +^msm.* nouveau_.* -panfrost_.* +^panfrost.* ^v3d.* ^vc4.* ^vmwgfx* -- cgit v1.2.3 From 76299a557f36d624ca32500173ad7856e1ad93c0 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 3 Jul 2024 00:17:21 -0500 Subject: drm: Introduce 'power saving policy' drm property The `power saving policy` DRM property is an optional property that can be added to a connector by a driver. This property is for compositors to indicate intent of policy of whether a driver can use power saving features that may compromise the experience intended by the compositor. Acked-by: Leo Li Signed-off-by: Mario Limonciello Signed-off-by: Hamza Mahfooz Link: https://patchwork.freedesktop.org/patch/msgid/20240703051722.328-2-mario.limonciello@amd.com --- drivers/gpu/drm/drm_connector.c | 48 +++++++++++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 2 ++ include/drm/drm_mode_config.h | 5 +++++ include/uapi/drm/drm_mode.h | 7 ++++++ 4 files changed, 62 insertions(+) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index b4f4d2f908d1..7c44e3a1d8e0 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1043,6 +1043,11 @@ static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = { { DRM_MODE_SCALE_ASPECT, "Full aspect" }, }; +static const struct drm_prop_enum_list drm_power_saving_policy_enum_list[] = { + { __builtin_ffs(DRM_MODE_REQUIRE_COLOR_ACCURACY) - 1, "Require color accuracy" }, + { __builtin_ffs(DRM_MODE_REQUIRE_LOW_LATENCY) - 1, "Require low latency" }, +}; + static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = { { DRM_MODE_PICTURE_ASPECT_NONE, "Automatic" }, { DRM_MODE_PICTURE_ASPECT_4_3, "4:3" }, @@ -1629,6 +1634,16 @@ EXPORT_SYMBOL(drm_hdmi_connector_get_output_format_name); * * Drivers can set up these properties by calling * drm_mode_create_tv_margin_properties(). + * power saving policy: + * This property is used to set the power saving policy for the connector. + * This property is populated with a bitmask of optional requirements set + * by the drm master for the drm driver to respect: + * - "Require color accuracy": Disable power saving features that will + * affect color fidelity. + * For example: Hardware assisted backlight modulation. + * - "Require low latency": Disable power saving features that will + * affect latency. + * For example: Panel self refresh (PSR) */ int drm_connector_create_standard_properties(struct drm_device *dev) @@ -2131,6 +2146,39 @@ int drm_mode_create_scaling_mode_property(struct drm_device *dev) } EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); +/** + * drm_mode_create_power_saving_policy_property - create power saving policy property + * @dev: DRM device + * @supported_policies: bitmask of supported power saving policies + * + * Called by a driver the first time it's needed, must be attached to desired + * connectors. + * + * Returns: %0 + */ +int drm_mode_create_power_saving_policy_property(struct drm_device *dev, + uint64_t supported_policies) +{ + struct drm_property *power_saving; + + if (dev->mode_config.power_saving_policy) + return 0; + WARN_ON((supported_policies & DRM_MODE_POWER_SAVING_POLICY_ALL) == 0); + + power_saving = + drm_property_create_bitmask(dev, 0, "power saving policy", + drm_power_saving_policy_enum_list, + ARRAY_SIZE(drm_power_saving_policy_enum_list), + supported_policies); + if (!power_saving) + return -ENOMEM; + + dev->mode_config.power_saving_policy = power_saving; + + return 0; +} +EXPORT_SYMBOL(drm_mode_create_power_saving_policy_property); + /** * DOC: Variable refresh properties * diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index e3fa43291f44..5ad735253413 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -2267,6 +2267,8 @@ int drm_mode_create_dp_colorspace_property(struct drm_connector *connector, u32 supported_colorspaces); int drm_mode_create_content_type_property(struct drm_device *dev); int drm_mode_create_suggested_offset_properties(struct drm_device *dev); +int drm_mode_create_power_saving_policy_property(struct drm_device *dev, + uint64_t supported_policies); int drm_connector_set_path_property(struct drm_connector *connector, const char *path); diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index ab0f167474b1..150f9a3b649f 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -969,6 +969,11 @@ struct drm_mode_config { */ struct drm_atomic_state *suspend_state; + /** + * @power_saving_policy: bitmask for power saving policy requests. + */ + struct drm_property *power_saving_policy; + const struct drm_mode_config_helper_funcs *helper_private; }; diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index d390011b89b4..880303c2ad97 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -152,6 +152,13 @@ extern "C" { #define DRM_MODE_SCALE_CENTER 2 /* Centered, no scaling */ #define DRM_MODE_SCALE_ASPECT 3 /* Full screen, preserve aspect */ +/* power saving policy options */ +#define DRM_MODE_REQUIRE_COLOR_ACCURACY BIT(0) /* Compositor requires color accuracy */ +#define DRM_MODE_REQUIRE_LOW_LATENCY BIT(1) /* Compositor requires low latency */ + +#define DRM_MODE_POWER_SAVING_POLICY_ALL (DRM_MODE_REQUIRE_COLOR_ACCURACY |\ + DRM_MODE_REQUIRE_LOW_LATENCY) + /* Dithering mode options */ #define DRM_MODE_DITHERING_OFF 0 #define DRM_MODE_DITHERING_ON 1 -- cgit v1.2.3 From 9d8c094ddab05db88d183ba82e23be807848cad8 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 3 Jul 2024 00:17:22 -0500 Subject: drm/amd: Add power_saving_policy drm property to eDP connectors When the `power_saving_policy` property is set to bit mask "Require color accuracy" ABM should be disabled immediately and any requests by sysfs to update will return an -EBUSY error. When the `power_saving_policy` property is set to bit mask "Require low latency" PSR should be disabled. When the property is restored to an empty bit mask ABM and PSR can be enabled again. Signed-off-by: Mario Limonciello Reviewed-by: Leo Li Signed-off-by: Hamza Mahfooz Link: https://patchwork.freedesktop.org/patch/msgid/20240703051722.328-3-mario.limonciello@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 4 ++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 52 ++++++++++++++++++++--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 + 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 3ecc7ef95172..cfb5220cf182 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -1350,6 +1350,10 @@ int amdgpu_display_modeset_create_props(struct amdgpu_device *adev) "dither", amdgpu_dither_enum_list, sz); + if (adev->dc_enabled) + drm_mode_create_power_saving_policy_property(adev_to_drm(adev), + DRM_MODE_POWER_SAVING_POLICY_ALL); + return 0; } 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 516eb3968e26..07e373deb814 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6436,6 +6436,14 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector, } else if (property == adev->mode_info.underscan_property) { dm_new_state->underscan_enable = val; ret = 0; + } else if (property == dev->mode_config.power_saving_policy) { + dm_new_state->abm_forbidden = val & DRM_MODE_REQUIRE_COLOR_ACCURACY; + dm_new_state->abm_level = (dm_new_state->abm_forbidden || + !dm_old_state->abm_level) ? + ABM_LEVEL_IMMEDIATE_DISABLE : + dm_old_state->abm_level; + dm_new_state->psr_forbidden = val & DRM_MODE_REQUIRE_LOW_LATENCY; + ret = 0; } return ret; @@ -6478,6 +6486,13 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector, } else if (property == adev->mode_info.underscan_property) { *val = dm_state->underscan_enable; ret = 0; + } else if (property == dev->mode_config.power_saving_policy) { + *val = 0; + if (dm_state->psr_forbidden) + *val |= DRM_MODE_REQUIRE_LOW_LATENCY; + if (dm_state->abm_forbidden) + *val |= DRM_MODE_REQUIRE_COLOR_ACCURACY; + ret = 0; } return ret; @@ -6504,9 +6519,12 @@ static ssize_t panel_power_savings_show(struct device *device, u8 val; drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); - val = to_dm_connector_state(connector->state)->abm_level == - ABM_LEVEL_IMMEDIATE_DISABLE ? 0 : - to_dm_connector_state(connector->state)->abm_level; + if (to_dm_connector_state(connector->state)->abm_forbidden) + val = 0; + else + val = to_dm_connector_state(connector->state)->abm_level == + ABM_LEVEL_IMMEDIATE_DISABLE ? 0 : + to_dm_connector_state(connector->state)->abm_level; drm_modeset_unlock(&dev->mode_config.connection_mutex); return sysfs_emit(buf, "%u\n", val); @@ -6530,10 +6548,16 @@ static ssize_t panel_power_savings_store(struct device *device, return -EINVAL; drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); - to_dm_connector_state(connector->state)->abm_level = val ?: - ABM_LEVEL_IMMEDIATE_DISABLE; + if (to_dm_connector_state(connector->state)->abm_forbidden) + ret = -EBUSY; + else + to_dm_connector_state(connector->state)->abm_level = val ?: + ABM_LEVEL_IMMEDIATE_DISABLE; drm_modeset_unlock(&dev->mode_config.connection_mutex); + if (ret) + return ret; + drm_kms_helper_hotplug_event(dev); return count; @@ -7704,6 +7728,14 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, aconnector->base.state->max_bpc = 16; aconnector->base.state->max_requested_bpc = aconnector->base.state->max_bpc; + if (connector_type == DRM_MODE_CONNECTOR_eDP && + (dc_is_dmcu_initialized(adev->dm.dc) || + adev->dm.dc->ctx->dmub_srv)) { + drm_object_attach_property(&aconnector->base.base, + dm->ddev->mode_config.power_saving_policy, + 0); + } + if (connector_type == DRM_MODE_CONNECTOR_HDMIA) { /* Content Type is currently only implemented for HDMI. */ drm_connector_attach_content_type_property(&aconnector->base); @@ -9307,6 +9339,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); struct dc_surface_update *dummy_updates; struct dc_stream_update stream_update; @@ -9360,6 +9393,15 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) stream_update.hdr_static_metadata = &hdr_packet; } + aconnector->disallow_edp_enter_psr = dm_new_con_state->psr_forbidden; + + /* immediately disable PSR if disallowed */ + if (aconnector->disallow_edp_enter_psr) { + mutex_lock(&dm->dc_lock); + amdgpu_dm_psr_disable(dm_new_crtc_state->stream); + mutex_unlock(&dm->dc_lock); + } + status = dc_stream_get_status(dm_new_crtc_state->stream); if (WARN_ON(!status)) 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 09519b7abf67..b246e82f5b0d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -873,6 +873,8 @@ struct dm_connector_state { bool underscan_enable; bool freesync_capable; bool update_hdcp; + bool abm_forbidden; + bool psr_forbidden; uint8_t abm_level; int vcpi_slots; uint64_t pbn; -- cgit v1.2.3 From 71733b8d7f50b61403f940c6c9745fb3a9b98dcb Mon Sep 17 00:00:00 2001 From: Tejas Upadhyay Date: Wed, 10 Jul 2024 10:57:50 +0530 Subject: drm/xe/xe2: Make subsequent L2 flush sequential Issuing the flush on top of an ongoing flush is not desirable. Lets use lock to make it sequential. Reviewed-by: Nirmoy Das Signed-off-by: Tejas Upadhyay Link: https://patchwork.freedesktop.org/patch/msgid/20240710052750.3031586-1-tejas.upadhyay@intel.com Signed-off-by: Nirmoy Das --- drivers/gpu/drm/xe/xe_device.c | 2 ++ drivers/gpu/drm/xe/xe_gt.c | 1 + drivers/gpu/drm/xe/xe_gt_types.h | 6 ++++++ 3 files changed, 9 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 64aea962afd5..06cebaffb451 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -833,10 +833,12 @@ void xe_device_l2_flush(struct xe_device *xe) if (err) return; + spin_lock(>->global_invl_lock); xe_mmio_write32(gt, XE2_GLOBAL_INVAL, 0x1); if (xe_mmio_wait32(gt, XE2_GLOBAL_INVAL, 0x1, 0x0, 150, NULL, true)) xe_gt_err_once(gt, "Global invalidation timeout\n"); + spin_unlock(>->global_invl_lock); xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); } diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index b04e47186f5b..85f974441d50 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -387,6 +387,7 @@ int xe_gt_init_early(struct xe_gt *gt) xe_force_wake_init_gt(gt, gt_to_fw(gt)); xe_pcode_init(gt); + spin_lock_init(>->global_invl_lock); return 0; } diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h index 6b5e0b45efb0..38a0d0e178c8 100644 --- a/drivers/gpu/drm/xe/xe_gt_types.h +++ b/drivers/gpu/drm/xe/xe_gt_types.h @@ -362,6 +362,12 @@ struct xe_gt { */ spinlock_t mcr_lock; + /** + * @global_invl_lock: protects the register for the duration + * of a global invalidation of l2 cache + */ + spinlock_t global_invl_lock; + /** @wa_active: keep track of active workarounds */ struct { /** @wa_active.gt: bitmap with active GT workarounds */ -- cgit v1.2.3 From 993d36ac99efeafeb7b5f12353def6d7d20d6389 Mon Sep 17 00:00:00 2001 From: Hsin-Yi Wang Date: Wed, 10 Jul 2024 12:02:19 -0700 Subject: drm/panel-edp: Add BOE NV140WUM-N41 The raw edid of the panel is: 00 ff ff ff ff ff ff 00 09 e5 e8 0a 00 00 00 00 2a 1f 01 04 a5 1e 13 78 03 fb f5 96 5d 5a 91 29 1e 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 9c 3e 80 c8 70 b0 3c 40 30 20 36 00 2e bc 10 00 00 1a 00 00 00 fd 00 28 3c 4c 4c 10 01 0a 20 20 20 20 20 20 00 00 00 fe 00 42 4f 45 20 43 51 0a 20 20 20 20 20 20 00 00 00 fe 00 4e 56 31 34 30 57 55 4d 2d 4e 34 31 0a 00 26 Signed-off-by: Hsin-Yi Wang Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20240710190235.1095156-1-hsinyi@chromium.org --- drivers/gpu/drm/panel/panel-edp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index 3a574a9b46e7..f85a6404ba58 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1895,6 +1895,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a3e, &delay_200_500_e80, "NV116WHM-N49"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a5d, &delay_200_500_e50, "NV116WHM-N45"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0ac5, &delay_200_500_e50, "NV116WHM-N4C"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x0ae8, &delay_200_500_e50_p2e80, "NV140WUM-N41"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b34, &delay_200_500_e80, "NV122WUM-N41"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b43, &delay_200_500_e200, "NV140FHM-T09"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b56, &delay_200_500_e80, "NT140FHM-N47"), -- cgit v1.2.3 From 0daf44ea9dccfcdb1fe694e9ea85497b6cc3a065 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 8 Jul 2024 22:00:28 +0300 Subject: drm/dp: Add helper to dump an LTTPR PHY descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a helper to dump the DPCD descriptor for an LTTPR PHY. This is based on [1] and [2] moving the helper to DRM core as suggested by Ville. [1] https://lore.kernel.org/all/20240703155937.1674856-5-imre.deak@intel.com [2] https://lore.kernel.org/all/20240703155937.1674856-6-imre.deak@intel.com Cc: dri-devel@lists.freedesktop.org Cc: Ville Syrjälä Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20240708190029.271247-6-imre.deak@intel.com --- drivers/gpu/drm/display/drm_dp_helper.c | 66 ++++++++++++++++++++++++++++----- include/drm/display/drm_dp.h | 4 ++ include/drm/display/drm_dp_helper.h | 2 + 3 files changed, 62 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c index d4c34f364140..6ee51003de3c 100644 --- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -2328,6 +2328,31 @@ drm_dp_get_quirks(const struct drm_dp_dpcd_ident *ident, bool is_branch) #undef DEVICE_ID_ANY #undef DEVICE_ID +static int drm_dp_read_ident(struct drm_dp_aux *aux, unsigned int offset, + struct drm_dp_dpcd_ident *ident) +{ + int ret; + + ret = drm_dp_dpcd_read(aux, offset, ident, sizeof(*ident)); + + return ret < 0 ? ret : 0; +} + +static void drm_dp_dump_desc(struct drm_dp_aux *aux, + const char *device_name, const struct drm_dp_desc *desc) +{ + const struct drm_dp_dpcd_ident *ident = &desc->ident; + + drm_dbg_kms(aux->drm_dev, + "%s: %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d quirks 0x%04x\n", + aux->name, device_name, + (int)sizeof(ident->oui), ident->oui, + (int)strnlen(ident->device_id, sizeof(ident->device_id)), ident->device_id, + ident->hw_rev >> 4, ident->hw_rev & 0xf, + ident->sw_major_rev, ident->sw_minor_rev, + desc->quirks); +} + /** * drm_dp_read_desc - read sink/branch descriptor from DPCD * @aux: DisplayPort AUX channel @@ -2344,27 +2369,48 @@ int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc, { struct drm_dp_dpcd_ident *ident = &desc->ident; unsigned int offset = is_branch ? DP_BRANCH_OUI : DP_SINK_OUI; - int ret, dev_id_len; + int ret; - ret = drm_dp_dpcd_read(aux, offset, ident, sizeof(*ident)); + ret = drm_dp_read_ident(aux, offset, ident); if (ret < 0) return ret; desc->quirks = drm_dp_get_quirks(ident, is_branch); - dev_id_len = strnlen(ident->device_id, sizeof(ident->device_id)); - - drm_dbg_kms(aux->drm_dev, - "%s: DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d quirks 0x%04x\n", - aux->name, is_branch ? "branch" : "sink", - (int)sizeof(ident->oui), ident->oui, dev_id_len, - ident->device_id, ident->hw_rev >> 4, ident->hw_rev & 0xf, - ident->sw_major_rev, ident->sw_minor_rev, desc->quirks); + drm_dp_dump_desc(aux, is_branch ? "DP branch" : "DP sink", desc); return 0; } EXPORT_SYMBOL(drm_dp_read_desc); +/** + * drm_dp_dump_lttpr_desc - read and dump the DPCD descriptor for an LTTPR PHY + * @aux: DisplayPort AUX channel + * @dp_phy: LTTPR PHY instance + * + * Read the DPCD LTTPR PHY descriptor for @dp_phy and print a debug message + * with its details to dmesg. + * + * Returns 0 on success or a negative error code on failure. + */ +int drm_dp_dump_lttpr_desc(struct drm_dp_aux *aux, enum drm_dp_phy dp_phy) +{ + struct drm_dp_desc desc = {}; + int ret; + + if (drm_WARN_ON(aux->drm_dev, dp_phy < DP_PHY_LTTPR1 || dp_phy > DP_MAX_LTTPR_COUNT)) + return -EINVAL; + + ret = drm_dp_read_ident(aux, DP_OUI_PHY_REPEATER(dp_phy), &desc.ident); + if (ret < 0) + return ret; + + drm_dp_dump_desc(aux, drm_dp_phy_name(dp_phy), &desc); + + return 0; +} +EXPORT_SYMBOL(drm_dp_dump_lttpr_desc); + /** * drm_dp_dsc_sink_bpp_incr() - Get bits per pixel increment * @dsc_dpcd: DSC capabilities from DPCD diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h index 0b032faa8cf2..0146ccfe9c2e 100644 --- a/include/drm/display/drm_dp.h +++ b/include/drm/display/drm_dp.h @@ -1523,6 +1523,10 @@ enum drm_dp_phy { #define DP_SYMBOL_ERROR_COUNT_LANE2_PHY_REPEATER1 0xf0039 /* 1.3 */ #define DP_SYMBOL_ERROR_COUNT_LANE3_PHY_REPEATER1 0xf003b /* 1.3 */ +#define DP_OUI_PHY_REPEATER1 0xf003d /* 1.3 */ +#define DP_OUI_PHY_REPEATER(dp_phy) \ + DP_LTTPR_REG(dp_phy, DP_OUI_PHY_REPEATER1) + #define __DP_FEC1_BASE 0xf0290 /* 1.4 */ #define __DP_FEC2_BASE 0xf0298 /* 1.4 */ #define DP_FEC_BASE(dp_phy) \ diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h index 8defcc399f42..f88d78e43443 100644 --- a/include/drm/display/drm_dp_helper.h +++ b/include/drm/display/drm_dp_helper.h @@ -656,6 +656,8 @@ struct drm_dp_desc { int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc, bool is_branch); +int drm_dp_dump_lttpr_desc(struct drm_dp_aux *aux, enum drm_dp_phy dp_phy); + /** * enum drm_dp_quirk - Display Port sink/branch device specific quirks * -- cgit v1.2.3 From a4d5ce61765c08ab364aa4b327f6739b646e6cfa Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 8 Jul 2024 22:00:24 +0300 Subject: drm/i915/dp: Reset intel_dp->link_trained before retraining the link MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regularly retraining a link during an atomic commit happens with the given pipe/link already disabled and hence intel_dp->link_trained being false. Ensure this also for retraining a DP SST link via direct calls to the link training functions (vs. an actual commit as for DP MST). So far nothing depended on this, however the next patch will depend on link_trained==false for changing the LTTPR mode to non-transparent. Cc: # v5.15+ Cc: Ville Syrjälä Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20240708190029.271247-2-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index edfb30857479..d4b1b18453dc 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5305,6 +5305,8 @@ static int intel_dp_retrain_link(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); + intel_dp->link_trained = false; + intel_dp_check_frl_training(intel_dp); intel_dp_pcon_dsc_configure(intel_dp, crtc_state); intel_dp_start_link_train(NULL, intel_dp, crtc_state); -- cgit v1.2.3 From 211ad49cf8ccfdc798a719b4d1e000d0a8a9e588 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 8 Jul 2024 22:00:25 +0300 Subject: drm/i915/dp: Don't switch the LTTPR mode on an active link MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switching to transparent mode leads to a loss of link synchronization, so prevent doing this on an active link. This happened at least on an Intel N100 system / DELL UD22 dock, the LTTPR residing either on the host or the dock. To fix the issue, keep the current mode on an active link, adjusting the LTTPR count accordingly (resetting it to 0 in transparent mode). v2: Adjust code comment during link training about reiniting the LTTPRs. (Ville) Fixes: 7b2a4ab8b0ef ("drm/i915: Switch to LTTPR transparent mode link training") Reported-and-tested-by: Gareth Yu Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10902 Cc: # v5.15+ Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20240708190029.271247-3-imre.deak@intel.com --- .../gpu/drm/i915/display/intel_dp_link_training.c | 55 +++++++++++++++++++--- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index 1bc4ef84ff3b..d044c8e36bb3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -117,10 +117,24 @@ intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable) return drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) == 1; } -static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +static bool intel_dp_lttpr_transparent_mode_enabled(struct intel_dp *intel_dp) +{ + return intel_dp->lttpr_common_caps[DP_PHY_REPEATER_MODE - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV] == + DP_PHY_REPEATER_MODE_TRANSPARENT; +} + +/* + * Read the LTTPR common capabilities and switch the LTTPR PHYs to + * non-transparent mode if this is supported. Preserve the + * transparent/non-transparent mode on an active link. + * + * Return the number of detected LTTPRs in non-transparent mode or 0 if the + * LTTPRs are in transparent mode or the detection failed. + */ +static int intel_dp_init_lttpr_phys(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEIVER_CAP_SIZE]) { int lttpr_count; - int i; if (!intel_dp_read_lttpr_common_caps(intel_dp, dpcd)) return 0; @@ -134,6 +148,19 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEI if (lttpr_count == 0) return 0; + /* + * Don't change the mode on an active link, to prevent a loss of link + * synchronization. See DP Standard v2.0 3.6.7. about the LTTPR + * resetting its internal state when the mode is changed from + * non-transparent to transparent. + */ + if (intel_dp->link_trained) { + if (lttpr_count < 0 || intel_dp_lttpr_transparent_mode_enabled(intel_dp)) + goto out_reset_lttpr_count; + + return lttpr_count; + } + /* * See DP Standard v2.0 3.6.6.1. about the explicit disabling of * non-transparent mode and the disable->enable non-transparent mode @@ -154,11 +181,25 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEI "Switching to LTTPR non-transparent LT mode failed, fall-back to transparent mode\n"); intel_dp_set_lttpr_transparent_mode(intel_dp, true); - intel_dp_reset_lttpr_count(intel_dp); - return 0; + goto out_reset_lttpr_count; } + return lttpr_count; + +out_reset_lttpr_count: + intel_dp_reset_lttpr_count(intel_dp); + + return 0; +} + +static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + int lttpr_count; + int i; + + lttpr_count = intel_dp_init_lttpr_phys(intel_dp, dpcd); + for (i = 0; i < lttpr_count; i++) intel_dp_read_lttpr_phy_caps(intel_dp, dpcd, DP_PHY_LTTPR(i)); @@ -1482,10 +1523,10 @@ void intel_dp_start_link_train(struct intel_atomic_state *state, struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct intel_encoder *encoder = &dig_port->base; bool passed; - /* - * TODO: Reiniting LTTPRs here won't be needed once proper connector - * HW state readout is added. + * Reinit the LTTPRs here to ensure that they are switched to + * non-transparent mode. During an earlier LTTPR detection this + * could've been prevented by an active link. */ int lttpr_count = intel_dp_init_lttpr_and_dprx_caps(intel_dp); -- cgit v1.2.3 From 4613aa66e42ba1b0c896495a207b3b26e94e44d5 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 8 Jul 2024 22:00:26 +0300 Subject: drm/i915/dp: Reset cached LTTPR count if number of LTTPRs is unsupported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After detection the cached LTTPR count can be checked to determine if LTTPRs in non-transparent mode were detected. Reset the cached LTTPR count if the reported number of LTTPRs is invalid to ensure the above checks work as expected. Reviewed-by: Ville Syrjälä Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20240708190029.271247-4-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_link_training.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index d044c8e36bb3..56b9c5cb1254 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -174,7 +174,7 @@ static int intel_dp_init_lttpr_phys(struct intel_dp *intel_dp, const u8 dpcd[DP_ * still taking into account any LTTPR common lane- rate/count limits. */ if (lttpr_count < 0) - return 0; + goto out_reset_lttpr_count; if (!intel_dp_set_lttpr_transparent_mode(intel_dp, false)) { lt_dbg(intel_dp, DP_PHY_DPRX, -- cgit v1.2.3 From 61fe488fc78a3024b8d4cafc90a34158f4562dae Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 8 Jul 2024 22:00:27 +0300 Subject: drm/i915/dp: Keep cached LTTPR mode up-to-date MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nothing depends on the cached LTTPR mode, however for consistency keep it up-to-date with the value programmed to the DPCD register. Reviewed-by: Ville Syrjälä Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20240708190029.271247-5-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_link_training.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index 56b9c5cb1254..af0b71bdf1fc 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -114,7 +114,13 @@ intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable) u8 val = enable ? DP_PHY_REPEATER_MODE_TRANSPARENT : DP_PHY_REPEATER_MODE_NON_TRANSPARENT; - return drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) == 1; + if (drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) != 1) + return false; + + intel_dp->lttpr_common_caps[DP_PHY_REPEATER_MODE - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV] = val; + + return true; } static bool intel_dp_lttpr_transparent_mode_enabled(struct intel_dp *intel_dp) -- cgit v1.2.3 From f6ca930d974e473fd608fc9aa1759fbe731fe44d Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Wed, 10 Jul 2024 14:31:49 -0700 Subject: drm/xe: Add process name and PID to job timedout message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will be very helpful for Mesa CI, where it uses PID to match the exacly test that cause timedout/GPU hang and mark that test as failing. Also printing the process name as it might be relavant for human readers. Cc: Rodrigo Vivi Signed-off-by: José Roberto de Souza Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20240710213149.57662-1-jose.souza@intel.com --- drivers/gpu/drm/xe/xe_guc_submit.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 6392381e8e69..860405527115 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -1060,7 +1060,10 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) struct xe_exec_queue *q = job->q; struct xe_gpu_scheduler *sched = &q->guc->sched; struct xe_guc *guc = exec_queue_to_guc(q); + const char *process_name = "no process"; + struct task_struct *task = NULL; int err = -ETIME; + pid_t pid = -1; int i = 0; bool wedged, skip_timeout_check; @@ -1157,9 +1160,19 @@ trigger_reset: goto sched_enable; } - xe_gt_notice(guc_to_gt(guc), "Timedout job: seqno=%u, lrc_seqno=%u, guc_id=%d, flags=0x%lx", + if (q->vm && q->vm->xef) { + task = get_pid_task(q->vm->xef->drm->pid, PIDTYPE_PID); + if (task) { + process_name = task->comm; + pid = task->pid; + } + } + xe_gt_notice(guc_to_gt(guc), "Timedout job: seqno=%u, lrc_seqno=%u, guc_id=%d, flags=0x%lx in %s [%d]", xe_sched_job_seqno(job), xe_sched_job_lrc_seqno(job), - q->guc->id, q->flags); + q->guc->id, q->flags, process_name, pid); + if (task) + put_task_struct(task); + trace_xe_sched_job_timedout(job); if (!exec_queue_killed(q)) -- cgit v1.2.3 From bd85e00fa489f5374c2bad0eac15842d2ec68045 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 5 Jul 2024 21:10:56 +0200 Subject: drm/xe/kunit: Kill xe_cur_kunit() We shouldn't use custom helper if there is a official one. Signed-off-by: Michal Wajdeczko Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20240705191057.1110-2-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/tests/xe_bo.c | 4 ++-- drivers/gpu/drm/xe/tests/xe_dma_buf.c | 4 ++-- drivers/gpu/drm/xe/tests/xe_migrate.c | 2 +- drivers/gpu/drm/xe/tests/xe_mocs.c | 8 ++++---- drivers/gpu/drm/xe/tests/xe_pci_test.c | 4 ++-- drivers/gpu/drm/xe/tests/xe_test.h | 8 +++----- 6 files changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/xe/tests/xe_bo.c b/drivers/gpu/drm/xe/tests/xe_bo.c index 9f3c02826464..263e0afa8de0 100644 --- a/drivers/gpu/drm/xe/tests/xe_bo.c +++ b/drivers/gpu/drm/xe/tests/xe_bo.c @@ -154,7 +154,7 @@ out_unlock: static int ccs_test_run_device(struct xe_device *xe) { - struct kunit *test = xe_cur_kunit(); + struct kunit *test = kunit_get_current_test(); struct xe_tile *tile; int id; @@ -325,7 +325,7 @@ cleanup_bo: static int evict_test_run_device(struct xe_device *xe) { - struct kunit *test = xe_cur_kunit(); + struct kunit *test = kunit_get_current_test(); struct xe_tile *tile; int id; diff --git a/drivers/gpu/drm/xe/tests/xe_dma_buf.c b/drivers/gpu/drm/xe/tests/xe_dma_buf.c index e7f9b531c465..b56013963911 100644 --- a/drivers/gpu/drm/xe/tests/xe_dma_buf.c +++ b/drivers/gpu/drm/xe/tests/xe_dma_buf.c @@ -107,7 +107,7 @@ static void check_residency(struct kunit *test, struct xe_bo *exported, static void xe_test_dmabuf_import_same_driver(struct xe_device *xe) { - struct kunit *test = xe_cur_kunit(); + struct kunit *test = kunit_get_current_test(); struct dma_buf_test_params *params = to_dma_buf_test_params(test->priv); struct drm_gem_object *import; struct dma_buf *dmabuf; @@ -258,7 +258,7 @@ static const struct dma_buf_test_params test_params[] = { static int dma_buf_run_device(struct xe_device *xe) { const struct dma_buf_test_params *params; - struct kunit *test = xe_cur_kunit(); + struct kunit *test = kunit_get_current_test(); xe_pm_runtime_get(xe); for (params = test_params; params->mem_mask; ++params) { diff --git a/drivers/gpu/drm/xe/tests/xe_migrate.c b/drivers/gpu/drm/xe/tests/xe_migrate.c index 962f6438e219..d277a21ccf91 100644 --- a/drivers/gpu/drm/xe/tests/xe_migrate.c +++ b/drivers/gpu/drm/xe/tests/xe_migrate.c @@ -334,7 +334,7 @@ vunmap: static int migrate_test_run_device(struct xe_device *xe) { - struct kunit *test = xe_cur_kunit(); + struct kunit *test = kunit_get_current_test(); struct xe_tile *tile; int id; diff --git a/drivers/gpu/drm/xe/tests/xe_mocs.c b/drivers/gpu/drm/xe/tests/xe_mocs.c index 67c65e88c384..4fff5de92dea 100644 --- a/drivers/gpu/drm/xe/tests/xe_mocs.c +++ b/drivers/gpu/drm/xe/tests/xe_mocs.c @@ -23,7 +23,7 @@ struct live_mocs { static int live_mocs_init(struct live_mocs *arg, struct xe_gt *gt) { unsigned int flags; - struct kunit *test = xe_cur_kunit(); + struct kunit *test = kunit_get_current_test(); memset(arg, 0, sizeof(*arg)); @@ -41,7 +41,7 @@ static int live_mocs_init(struct live_mocs *arg, struct xe_gt *gt) static void read_l3cc_table(struct xe_gt *gt, const struct xe_mocs_info *info) { - struct kunit *test = xe_cur_kunit(); + struct kunit *test = kunit_get_current_test(); u32 l3cc, l3cc_expected; unsigned int i; u32 reg_val; @@ -78,7 +78,7 @@ static void read_l3cc_table(struct xe_gt *gt, static void read_mocs_table(struct xe_gt *gt, const struct xe_mocs_info *info) { - struct kunit *test = xe_cur_kunit(); + struct kunit *test = kunit_get_current_test(); u32 mocs, mocs_expected; unsigned int i; u32 reg_val; @@ -148,7 +148,7 @@ static int mocs_reset_test_run_device(struct xe_device *xe) struct xe_gt *gt; unsigned int flags; int id; - struct kunit *test = xe_cur_kunit(); + struct kunit *test = kunit_get_current_test(); xe_pm_runtime_get(xe); diff --git a/drivers/gpu/drm/xe/tests/xe_pci_test.c b/drivers/gpu/drm/xe/tests/xe_pci_test.c index a6705a536391..744a37583d2d 100644 --- a/drivers/gpu/drm/xe/tests/xe_pci_test.c +++ b/drivers/gpu/drm/xe/tests/xe_pci_test.c @@ -16,7 +16,7 @@ static void check_graphics_ip(const struct xe_graphics_desc *graphics) { - struct kunit *test = xe_cur_kunit(); + struct kunit *test = kunit_get_current_test(); u64 mask = graphics->hw_engine_mask; /* RCS, CCS, and BCS engines are allowed on the graphics IP */ @@ -30,7 +30,7 @@ static void check_graphics_ip(const struct xe_graphics_desc *graphics) static void check_media_ip(const struct xe_media_desc *media) { - struct kunit *test = xe_cur_kunit(); + struct kunit *test = kunit_get_current_test(); u64 mask = media->hw_engine_mask; /* VCS, VECS and GSCCS engines are allowed on the media IP */ diff --git a/drivers/gpu/drm/xe/tests/xe_test.h b/drivers/gpu/drm/xe/tests/xe_test.h index 7a1ae213e750..55e5b5bedccc 100644 --- a/drivers/gpu/drm/xe/tests/xe_test.h +++ b/drivers/gpu/drm/xe/tests/xe_test.h @@ -9,8 +9,8 @@ #include #if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST) -#include #include +#include /* * Each test that provides a kunit private test structure, place a test id @@ -32,7 +32,6 @@ struct xe_test_priv { #define XE_TEST_DECLARE(x) x #define XE_TEST_ONLY(x) unlikely(x) #define XE_TEST_EXPORT -#define xe_cur_kunit() current->kunit_test /** * xe_cur_kunit_priv - Obtain the struct xe_test_priv pointed to by @@ -48,10 +47,10 @@ xe_cur_kunit_priv(enum xe_test_priv_id id) { struct xe_test_priv *priv; - if (!xe_cur_kunit()) + if (!kunit_get_current_test()) return NULL; - priv = xe_cur_kunit()->priv; + priv = kunit_get_current_test()->priv; return priv->id == id ? priv : NULL; } @@ -60,7 +59,6 @@ xe_cur_kunit_priv(enum xe_test_priv_id id) #define XE_TEST_DECLARE(x) #define XE_TEST_ONLY(x) 0 #define XE_TEST_EXPORT static -#define xe_cur_kunit() NULL #define xe_cur_kunit_priv(_id) NULL #endif -- cgit v1.2.3 From 57c2b3e684ba3e82e9944bc1975e047bd1630537 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 5 Jul 2024 21:10:57 +0200 Subject: drm/xe/kunit: Drop XE_TEST_EXPORT It's unused and can be replaced with VISIBLE_IF_KUNIT if needed. Signed-off-by: Michal Wajdeczko Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20240705191057.1110-3-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/tests/xe_test.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/xe/tests/xe_test.h b/drivers/gpu/drm/xe/tests/xe_test.h index 55e5b5bedccc..9c23ad9dba8d 100644 --- a/drivers/gpu/drm/xe/tests/xe_test.h +++ b/drivers/gpu/drm/xe/tests/xe_test.h @@ -31,7 +31,6 @@ struct xe_test_priv { #define XE_TEST_DECLARE(x) x #define XE_TEST_ONLY(x) unlikely(x) -#define XE_TEST_EXPORT /** * xe_cur_kunit_priv - Obtain the struct xe_test_priv pointed to by @@ -58,7 +57,6 @@ xe_cur_kunit_priv(enum xe_test_priv_id id) #define XE_TEST_DECLARE(x) #define XE_TEST_ONLY(x) 0 -#define XE_TEST_EXPORT static #define xe_cur_kunit_priv(_id) NULL #endif -- cgit v1.2.3 From d6e850acc716d0fad756f09488d198db2077141e Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 8 Jul 2024 13:12:07 +0200 Subject: drm/xe/kunit: Simplify xe_bo live tests code layout The test case logic is implemented by the functions compiled as part of the core Xe driver module and then exported to build and register the test suite in the live test module. But we don't need to export individual test case functions, we may just export the entire test suite. And we don't need to register this test suite in a separate file, it can be done in the main file of the live test module. Signed-off-by: Michal Wajdeczko Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20240708111210.1154-2-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/tests/Makefile | 1 - drivers/gpu/drm/xe/tests/xe_bo.c | 20 +++++++++++++++----- drivers/gpu/drm/xe/tests/xe_bo_test.c | 21 --------------------- drivers/gpu/drm/xe/tests/xe_bo_test.h | 14 -------------- drivers/gpu/drm/xe/tests/xe_live_test_mod.c | 5 +++++ 5 files changed, 20 insertions(+), 41 deletions(-) delete mode 100644 drivers/gpu/drm/xe/tests/xe_bo_test.c delete mode 100644 drivers/gpu/drm/xe/tests/xe_bo_test.h diff --git a/drivers/gpu/drm/xe/tests/Makefile b/drivers/gpu/drm/xe/tests/Makefile index 6e58931fddd4..77331b0a04ad 100644 --- a/drivers/gpu/drm/xe/tests/Makefile +++ b/drivers/gpu/drm/xe/tests/Makefile @@ -3,7 +3,6 @@ # "live" kunit tests obj-$(CONFIG_DRM_XE_KUNIT_TEST) += xe_live_test.o xe_live_test-y = xe_live_test_mod.o \ - xe_bo_test.o \ xe_dma_buf_test.o \ xe_migrate_test.o \ xe_mocs_test.o diff --git a/drivers/gpu/drm/xe/tests/xe_bo.c b/drivers/gpu/drm/xe/tests/xe_bo.c index 263e0afa8de0..692e1b46b9cf 100644 --- a/drivers/gpu/drm/xe/tests/xe_bo.c +++ b/drivers/gpu/drm/xe/tests/xe_bo.c @@ -6,7 +6,6 @@ #include #include -#include "tests/xe_bo_test.h" #include "tests/xe_pci_test.h" #include "tests/xe_test.h" @@ -177,11 +176,10 @@ static int ccs_test_run_device(struct xe_device *xe) return 0; } -void xe_ccs_migrate_kunit(struct kunit *test) +static void xe_ccs_migrate_kunit(struct kunit *test) { xe_call_for_each_device(ccs_test_run_device); } -EXPORT_SYMBOL_IF_KUNIT(xe_ccs_migrate_kunit); static int evict_test_run_tile(struct xe_device *xe, struct xe_tile *tile, struct kunit *test) { @@ -345,8 +343,20 @@ static int evict_test_run_device(struct xe_device *xe) return 0; } -void xe_bo_evict_kunit(struct kunit *test) +static void xe_bo_evict_kunit(struct kunit *test) { xe_call_for_each_device(evict_test_run_device); } -EXPORT_SYMBOL_IF_KUNIT(xe_bo_evict_kunit); + +static struct kunit_case xe_bo_tests[] = { + KUNIT_CASE(xe_ccs_migrate_kunit), + KUNIT_CASE(xe_bo_evict_kunit), + {} +}; + +VISIBLE_IF_KUNIT +struct kunit_suite xe_bo_test_suite = { + .name = "xe_bo", + .test_cases = xe_bo_tests, +}; +EXPORT_SYMBOL_IF_KUNIT(xe_bo_test_suite); diff --git a/drivers/gpu/drm/xe/tests/xe_bo_test.c b/drivers/gpu/drm/xe/tests/xe_bo_test.c deleted file mode 100644 index a324cde77db8..000000000000 --- a/drivers/gpu/drm/xe/tests/xe_bo_test.c +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright © 2022 Intel Corporation - */ - -#include "xe_bo_test.h" - -#include - -static struct kunit_case xe_bo_tests[] = { - KUNIT_CASE(xe_ccs_migrate_kunit), - KUNIT_CASE(xe_bo_evict_kunit), - {} -}; - -static struct kunit_suite xe_bo_test_suite = { - .name = "xe_bo", - .test_cases = xe_bo_tests, -}; - -kunit_test_suite(xe_bo_test_suite); diff --git a/drivers/gpu/drm/xe/tests/xe_bo_test.h b/drivers/gpu/drm/xe/tests/xe_bo_test.h deleted file mode 100644 index 0113ab45066a..000000000000 --- a/drivers/gpu/drm/xe/tests/xe_bo_test.h +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 AND MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#ifndef _XE_BO_TEST_H_ -#define _XE_BO_TEST_H_ - -struct kunit; - -void xe_ccs_migrate_kunit(struct kunit *test); -void xe_bo_evict_kunit(struct kunit *test); - -#endif diff --git a/drivers/gpu/drm/xe/tests/xe_live_test_mod.c b/drivers/gpu/drm/xe/tests/xe_live_test_mod.c index eb1ea99a5a8b..3bffcbd233b2 100644 --- a/drivers/gpu/drm/xe/tests/xe_live_test_mod.c +++ b/drivers/gpu/drm/xe/tests/xe_live_test_mod.c @@ -3,6 +3,11 @@ * Copyright © 2023 Intel Corporation */ #include +#include + +extern struct kunit_suite xe_bo_test_suite; + +kunit_test_suite(xe_bo_test_suite); MODULE_AUTHOR("Intel Corporation"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From ff10c99ab1e644fed578dce13e94e372d2c688c3 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 8 Jul 2024 13:12:08 +0200 Subject: drm/xe/kunit: Simplify xe_dma_buf live tests code layout The test case logic is implemented by the functions compiled as part of the core Xe driver module and then exported to build and register the test suite in the live test module. But we don't need to export individual test case functions, we may just export the entire test suite. And we don't need to register this test suite in a separate file, it can be done in the main file of the live test module. Signed-off-by: Michal Wajdeczko Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20240708111210.1154-3-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/tests/Makefile | 1 - drivers/gpu/drm/xe/tests/xe_dma_buf.c | 16 +++++++++++++--- drivers/gpu/drm/xe/tests/xe_dma_buf_test.c | 20 -------------------- drivers/gpu/drm/xe/tests/xe_dma_buf_test.h | 13 ------------- drivers/gpu/drm/xe/tests/xe_live_test_mod.c | 2 ++ 5 files changed, 15 insertions(+), 37 deletions(-) delete mode 100644 drivers/gpu/drm/xe/tests/xe_dma_buf_test.c delete mode 100644 drivers/gpu/drm/xe/tests/xe_dma_buf_test.h diff --git a/drivers/gpu/drm/xe/tests/Makefile b/drivers/gpu/drm/xe/tests/Makefile index 77331b0a04ad..c77a5882d094 100644 --- a/drivers/gpu/drm/xe/tests/Makefile +++ b/drivers/gpu/drm/xe/tests/Makefile @@ -3,7 +3,6 @@ # "live" kunit tests obj-$(CONFIG_DRM_XE_KUNIT_TEST) += xe_live_test.o xe_live_test-y = xe_live_test_mod.o \ - xe_dma_buf_test.o \ xe_migrate_test.o \ xe_mocs_test.o diff --git a/drivers/gpu/drm/xe/tests/xe_dma_buf.c b/drivers/gpu/drm/xe/tests/xe_dma_buf.c index b56013963911..4f9dc41e13de 100644 --- a/drivers/gpu/drm/xe/tests/xe_dma_buf.c +++ b/drivers/gpu/drm/xe/tests/xe_dma_buf.c @@ -8,7 +8,6 @@ #include #include -#include "tests/xe_dma_buf_test.h" #include "tests/xe_pci_test.h" #include "xe_pci.h" @@ -274,8 +273,19 @@ static int dma_buf_run_device(struct xe_device *xe) return 0; } -void xe_dma_buf_kunit(struct kunit *test) +static void xe_dma_buf_kunit(struct kunit *test) { xe_call_for_each_device(dma_buf_run_device); } -EXPORT_SYMBOL_IF_KUNIT(xe_dma_buf_kunit); + +static struct kunit_case xe_dma_buf_tests[] = { + KUNIT_CASE(xe_dma_buf_kunit), + {} +}; + +VISIBLE_IF_KUNIT +struct kunit_suite xe_dma_buf_test_suite = { + .name = "xe_dma_buf", + .test_cases = xe_dma_buf_tests, +}; +EXPORT_SYMBOL_IF_KUNIT(xe_dma_buf_test_suite); diff --git a/drivers/gpu/drm/xe/tests/xe_dma_buf_test.c b/drivers/gpu/drm/xe/tests/xe_dma_buf_test.c deleted file mode 100644 index 99cdb718b6c6..000000000000 --- a/drivers/gpu/drm/xe/tests/xe_dma_buf_test.c +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright © 2022 Intel Corporation - */ - -#include "xe_dma_buf_test.h" - -#include - -static struct kunit_case xe_dma_buf_tests[] = { - KUNIT_CASE(xe_dma_buf_kunit), - {} -}; - -static struct kunit_suite xe_dma_buf_test_suite = { - .name = "xe_dma_buf", - .test_cases = xe_dma_buf_tests, -}; - -kunit_test_suite(xe_dma_buf_test_suite); diff --git a/drivers/gpu/drm/xe/tests/xe_dma_buf_test.h b/drivers/gpu/drm/xe/tests/xe_dma_buf_test.h deleted file mode 100644 index e6b464ddd526..000000000000 --- a/drivers/gpu/drm/xe/tests/xe_dma_buf_test.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 AND MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#ifndef _XE_DMA_BUF_TEST_H_ -#define _XE_DMA_BUF_TEST_H_ - -struct kunit; - -void xe_dma_buf_kunit(struct kunit *test); - -#endif diff --git a/drivers/gpu/drm/xe/tests/xe_live_test_mod.c b/drivers/gpu/drm/xe/tests/xe_live_test_mod.c index 3bffcbd233b2..d9da15d9fe3f 100644 --- a/drivers/gpu/drm/xe/tests/xe_live_test_mod.c +++ b/drivers/gpu/drm/xe/tests/xe_live_test_mod.c @@ -6,8 +6,10 @@ #include extern struct kunit_suite xe_bo_test_suite; +extern struct kunit_suite xe_dma_buf_test_suite; kunit_test_suite(xe_bo_test_suite); +kunit_test_suite(xe_dma_buf_test_suite); MODULE_AUTHOR("Intel Corporation"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 0237368193e897aadeea9801126c101e33047354 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 8 Jul 2024 13:12:09 +0200 Subject: drm/xe/kunit: Simplify xe_migrate live tests code layout The test case logic is implemented by the functions compiled as part of the core Xe driver module and then exported to build and register the test suite in the live test module. But we don't need to export individual test case functions, we may just export the entire test suite. And we don't need to register this test suite in a separate file, it can be done in the main file of the live test module. Signed-off-by: Michal Wajdeczko Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20240708111210.1154-4-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/tests/Makefile | 1 - drivers/gpu/drm/xe/tests/xe_live_test_mod.c | 2 ++ drivers/gpu/drm/xe/tests/xe_migrate.c | 16 +++++++++++++--- drivers/gpu/drm/xe/tests/xe_migrate_test.c | 20 -------------------- drivers/gpu/drm/xe/tests/xe_migrate_test.h | 13 ------------- 5 files changed, 15 insertions(+), 37 deletions(-) delete mode 100644 drivers/gpu/drm/xe/tests/xe_migrate_test.c delete mode 100644 drivers/gpu/drm/xe/tests/xe_migrate_test.h diff --git a/drivers/gpu/drm/xe/tests/Makefile b/drivers/gpu/drm/xe/tests/Makefile index c77a5882d094..32ce1d6df0fa 100644 --- a/drivers/gpu/drm/xe/tests/Makefile +++ b/drivers/gpu/drm/xe/tests/Makefile @@ -3,7 +3,6 @@ # "live" kunit tests obj-$(CONFIG_DRM_XE_KUNIT_TEST) += xe_live_test.o xe_live_test-y = xe_live_test_mod.o \ - xe_migrate_test.o \ xe_mocs_test.o # Normal kunit tests diff --git a/drivers/gpu/drm/xe/tests/xe_live_test_mod.c b/drivers/gpu/drm/xe/tests/xe_live_test_mod.c index d9da15d9fe3f..4c1e07a0d477 100644 --- a/drivers/gpu/drm/xe/tests/xe_live_test_mod.c +++ b/drivers/gpu/drm/xe/tests/xe_live_test_mod.c @@ -7,9 +7,11 @@ extern struct kunit_suite xe_bo_test_suite; extern struct kunit_suite xe_dma_buf_test_suite; +extern struct kunit_suite xe_migrate_test_suite; kunit_test_suite(xe_bo_test_suite); kunit_test_suite(xe_dma_buf_test_suite); +kunit_test_suite(xe_migrate_test_suite); MODULE_AUTHOR("Intel Corporation"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/xe/tests/xe_migrate.c b/drivers/gpu/drm/xe/tests/xe_migrate.c index d277a21ccf91..0de0e0c66623 100644 --- a/drivers/gpu/drm/xe/tests/xe_migrate.c +++ b/drivers/gpu/drm/xe/tests/xe_migrate.c @@ -6,7 +6,6 @@ #include #include -#include "tests/xe_migrate_test.h" #include "tests/xe_pci_test.h" #include "xe_pci.h" @@ -354,8 +353,19 @@ static int migrate_test_run_device(struct xe_device *xe) return 0; } -void xe_migrate_sanity_kunit(struct kunit *test) +static void xe_migrate_sanity_kunit(struct kunit *test) { xe_call_for_each_device(migrate_test_run_device); } -EXPORT_SYMBOL_IF_KUNIT(xe_migrate_sanity_kunit); + +static struct kunit_case xe_migrate_tests[] = { + KUNIT_CASE(xe_migrate_sanity_kunit), + {} +}; + +VISIBLE_IF_KUNIT +struct kunit_suite xe_migrate_test_suite = { + .name = "xe_migrate", + .test_cases = xe_migrate_tests, +}; +EXPORT_SYMBOL_IF_KUNIT(xe_migrate_test_suite); diff --git a/drivers/gpu/drm/xe/tests/xe_migrate_test.c b/drivers/gpu/drm/xe/tests/xe_migrate_test.c deleted file mode 100644 index eb0d8963419c..000000000000 --- a/drivers/gpu/drm/xe/tests/xe_migrate_test.c +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright © 2022 Intel Corporation - */ - -#include "xe_migrate_test.h" - -#include - -static struct kunit_case xe_migrate_tests[] = { - KUNIT_CASE(xe_migrate_sanity_kunit), - {} -}; - -static struct kunit_suite xe_migrate_test_suite = { - .name = "xe_migrate", - .test_cases = xe_migrate_tests, -}; - -kunit_test_suite(xe_migrate_test_suite); diff --git a/drivers/gpu/drm/xe/tests/xe_migrate_test.h b/drivers/gpu/drm/xe/tests/xe_migrate_test.h deleted file mode 100644 index 7c645c66824f..000000000000 --- a/drivers/gpu/drm/xe/tests/xe_migrate_test.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 AND MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#ifndef _XE_MIGRATE_TEST_H_ -#define _XE_MIGRATE_TEST_H_ - -struct kunit; - -void xe_migrate_sanity_kunit(struct kunit *test); - -#endif -- cgit v1.2.3 From e97701a069612ba2fa1d92b56a720b108049df4e Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 8 Jul 2024 13:12:10 +0200 Subject: drm/xe/kunit: Simplify xe_mocs live tests code layout The test case logic is implemented by the functions compiled as part of the core Xe driver module and then exported to build and register the test suite in the live test module. But we don't need to export individual test case functions, we may just export the entire test suite. And we don't need to register this test suite in a separate file, it can be done in the main file of the live test module. Signed-off-by: Michal Wajdeczko Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20240708111210.1154-5-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/tests/Makefile | 3 +-- drivers/gpu/drm/xe/tests/xe_live_test_mod.c | 2 ++ drivers/gpu/drm/xe/tests/xe_mocs.c | 20 +++++++++++++++----- drivers/gpu/drm/xe/tests/xe_mocs_test.c | 21 --------------------- drivers/gpu/drm/xe/tests/xe_mocs_test.h | 14 -------------- 5 files changed, 18 insertions(+), 42 deletions(-) delete mode 100644 drivers/gpu/drm/xe/tests/xe_mocs_test.c delete mode 100644 drivers/gpu/drm/xe/tests/xe_mocs_test.h diff --git a/drivers/gpu/drm/xe/tests/Makefile b/drivers/gpu/drm/xe/tests/Makefile index 32ce1d6df0fa..0e3408f4952c 100644 --- a/drivers/gpu/drm/xe/tests/Makefile +++ b/drivers/gpu/drm/xe/tests/Makefile @@ -2,8 +2,7 @@ # "live" kunit tests obj-$(CONFIG_DRM_XE_KUNIT_TEST) += xe_live_test.o -xe_live_test-y = xe_live_test_mod.o \ - xe_mocs_test.o +xe_live_test-y = xe_live_test_mod.o # Normal kunit tests obj-$(CONFIG_DRM_XE_KUNIT_TEST) += xe_test.o diff --git a/drivers/gpu/drm/xe/tests/xe_live_test_mod.c b/drivers/gpu/drm/xe/tests/xe_live_test_mod.c index 4c1e07a0d477..5f14737c8210 100644 --- a/drivers/gpu/drm/xe/tests/xe_live_test_mod.c +++ b/drivers/gpu/drm/xe/tests/xe_live_test_mod.c @@ -8,10 +8,12 @@ extern struct kunit_suite xe_bo_test_suite; extern struct kunit_suite xe_dma_buf_test_suite; extern struct kunit_suite xe_migrate_test_suite; +extern struct kunit_suite xe_mocs_test_suite; kunit_test_suite(xe_bo_test_suite); kunit_test_suite(xe_dma_buf_test_suite); kunit_test_suite(xe_migrate_test_suite); +kunit_test_suite(xe_mocs_test_suite); MODULE_AUTHOR("Intel Corporation"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/xe/tests/xe_mocs.c b/drivers/gpu/drm/xe/tests/xe_mocs.c index 4fff5de92dea..febc1d967850 100644 --- a/drivers/gpu/drm/xe/tests/xe_mocs.c +++ b/drivers/gpu/drm/xe/tests/xe_mocs.c @@ -6,7 +6,6 @@ #include #include -#include "tests/xe_mocs_test.h" #include "tests/xe_pci_test.h" #include "tests/xe_test.h" @@ -134,11 +133,10 @@ static int mocs_kernel_test_run_device(struct xe_device *xe) return 0; } -void xe_live_mocs_kernel_kunit(struct kunit *test) +static void xe_live_mocs_kernel_kunit(struct kunit *test) { xe_call_for_each_device(mocs_kernel_test_run_device); } -EXPORT_SYMBOL_IF_KUNIT(xe_live_mocs_kernel_kunit); static int mocs_reset_test_run_device(struct xe_device *xe) { @@ -175,8 +173,20 @@ static int mocs_reset_test_run_device(struct xe_device *xe) return 0; } -void xe_live_mocs_reset_kunit(struct kunit *test) +static void xe_live_mocs_reset_kunit(struct kunit *test) { xe_call_for_each_device(mocs_reset_test_run_device); } -EXPORT_SYMBOL_IF_KUNIT(xe_live_mocs_reset_kunit); + +static struct kunit_case xe_mocs_tests[] = { + KUNIT_CASE(xe_live_mocs_kernel_kunit), + KUNIT_CASE(xe_live_mocs_reset_kunit), + {} +}; + +VISIBLE_IF_KUNIT +struct kunit_suite xe_mocs_test_suite = { + .name = "xe_mocs", + .test_cases = xe_mocs_tests, +}; +EXPORT_SYMBOL_IF_KUNIT(xe_mocs_test_suite); diff --git a/drivers/gpu/drm/xe/tests/xe_mocs_test.c b/drivers/gpu/drm/xe/tests/xe_mocs_test.c deleted file mode 100644 index 6315886b659e..000000000000 --- a/drivers/gpu/drm/xe/tests/xe_mocs_test.c +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright © 2022 Intel Corporation - */ - -#include "xe_mocs_test.h" - -#include - -static struct kunit_case xe_mocs_tests[] = { - KUNIT_CASE(xe_live_mocs_kernel_kunit), - KUNIT_CASE(xe_live_mocs_reset_kunit), - {} -}; - -static struct kunit_suite xe_mocs_test_suite = { - .name = "xe_mocs", - .test_cases = xe_mocs_tests, -}; - -kunit_test_suite(xe_mocs_test_suite); diff --git a/drivers/gpu/drm/xe/tests/xe_mocs_test.h b/drivers/gpu/drm/xe/tests/xe_mocs_test.h deleted file mode 100644 index e7699d495411..000000000000 --- a/drivers/gpu/drm/xe/tests/xe_mocs_test.h +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 AND MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#ifndef _XE_MOCS_TEST_H_ -#define _XE_MOCS_TEST_H_ - -struct kunit; - -void xe_live_mocs_kernel_kunit(struct kunit *test); -void xe_live_mocs_reset_kunit(struct kunit *test); - -#endif -- cgit v1.2.3 From 3b0974d7b74a908d1caa27f05a97551943e1bffe Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 24 Jun 2024 22:10:19 +0300 Subject: drm/i915: Calculate vblank delay more accurately MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calculate the vblank delay in the vblank evasion code correctly for interlaced modes. The current code assumes that we won't be using an interlaced mode. That assumption is actually valid since we've defeatured interlaced scanout in commit f71c9b7bc35f ("drm/i915/display: Prune Interlace modes for Display >=12") for DSB capable platforms. However the feature is still present in the hardware, and if we ever find the need to re-enable it seems better to calculate the vblank delay correctly. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240624191032.27333-2-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_vblank.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c index 5b065e1cd4e4..f183e0d4b2ba 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.c +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -652,7 +652,8 @@ void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state, */ if (intel_color_uses_dsb(new_crtc_state) || new_crtc_state->update_m_n || new_crtc_state->update_lrr) - evade->min -= adjusted_mode->crtc_vblank_start - adjusted_mode->crtc_vdisplay; + evade->min -= intel_mode_vblank_start(adjusted_mode) - + intel_mode_vdisplay(adjusted_mode); } /* must be called with vblank interrupt already enabled! */ -- cgit v1.2.3 From 09af6037128c101c280c95c56d970ce8475506c2 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 24 Jun 2024 22:10:20 +0300 Subject: drm/i915: Make vrr_{enabling,disabling}() usable outside intel_display.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Give vrr_enabling() and vrr_disabling() slightly fancier names, and pass in the whole atomic state so that they'll be easier to use. We'll need to call at least the disabling part from the DSB code soon enough (so that we can do vblank evasions/etc. correctly on the DSB). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240624191032.27333-3-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_display.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c2c388212e2e..01a5faa3fea5 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1014,9 +1014,14 @@ static bool cmrr_params_changed(const struct intel_crtc_state *old_crtc_state, old_crtc_state->cmrr.cmrr_n != new_crtc_state->cmrr.cmrr_n; } -static bool vrr_enabling(const struct intel_crtc_state *old_crtc_state, - const struct intel_crtc_state *new_crtc_state) +static bool intel_crtc_vrr_enabling(struct intel_atomic_state *state, + struct intel_crtc *crtc) { + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + const struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + if (!new_crtc_state->hw.active) return false; @@ -1026,9 +1031,14 @@ static bool vrr_enabling(const struct intel_crtc_state *old_crtc_state, vrr_params_changed(old_crtc_state, new_crtc_state))); } -static bool vrr_disabling(const struct intel_crtc_state *old_crtc_state, - const struct intel_crtc_state *new_crtc_state) +static bool intel_crtc_vrr_disabling(struct intel_atomic_state *state, + struct intel_crtc *crtc) { + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + const struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + if (!old_crtc_state->hw.active) return false; @@ -1181,7 +1191,7 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); enum pipe pipe = crtc->pipe; - if (vrr_disabling(old_crtc_state, new_crtc_state)) { + if (intel_crtc_vrr_disabling(state, crtc)) { intel_vrr_disable(old_crtc_state); intel_crtc_update_active_timings(old_crtc_state, false); } @@ -6830,8 +6840,6 @@ static void commit_pipe_post_planes(struct intel_atomic_state *state, struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); - const struct intel_crtc_state *old_crtc_state = - intel_atomic_get_old_crtc_state(state, crtc); const struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); @@ -6844,7 +6852,7 @@ static void commit_pipe_post_planes(struct intel_atomic_state *state, !intel_crtc_needs_modeset(new_crtc_state)) skl_detach_scalers(new_crtc_state); - if (vrr_enabling(old_crtc_state, new_crtc_state)) + if (intel_crtc_vrr_enabling(state, crtc)) intel_vrr_enable(new_crtc_state); } @@ -6944,7 +6952,7 @@ static void intel_update_crtc(struct intel_atomic_state *state, * * FIXME Should be synchronized with the start of vblank somehow... */ - if (vrr_enabling(old_crtc_state, new_crtc_state) || + if (intel_crtc_vrr_enabling(state, crtc) || new_crtc_state->update_m_n || new_crtc_state->update_lrr) intel_crtc_update_active_timings(new_crtc_state, new_crtc_state->vrr.enable); -- cgit v1.2.3 From bc34d310b578952d37b5200a7fa7475ab2a2bd5e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Jul 2024 17:52:35 +0300 Subject: drm/i915/fbc: Extract intel_fbc_has_fences() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull the "do we have fences?" check into a single helper in the FBC code. Avoids having to call to outside the display code in multiple places for this. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240705145254.3355-2-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_fbc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 67116c9f1464..360b3e6df8fa 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -228,6 +228,11 @@ static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state *plane_s return 0; } +static bool intel_fbc_has_fences(struct drm_i915_private *i915) +{ + return intel_gt_support_legacy_fencing(to_gt(i915)); +} + static u32 i8xx_fbc_ctl(struct intel_fbc *fbc) { const struct intel_fbc_state *fbc_state = &fbc->state; @@ -619,7 +624,7 @@ static void ivb_fbc_activate(struct intel_fbc *fbc) else if (DISPLAY_VER(i915) == 9) skl_fbc_program_cfb_stride(fbc); - if (intel_gt_support_legacy_fencing(to_gt(i915))) + if (intel_fbc_has_fences(i915)) snb_fbc_program_fence(fbc); /* wa_14019417088 Alternative WA*/ @@ -1153,7 +1158,7 @@ static void intel_fbc_update_state(struct intel_atomic_state *state, fbc_state->fence_y_offset = intel_plane_fence_y_offset(plane_state); drm_WARN_ON(&i915->drm, plane_state->flags & PLANE_HAS_FENCE && - !intel_gt_support_legacy_fencing(to_gt(i915))); + !intel_fbc_has_fences(i915)); if (plane_state->flags & PLANE_HAS_FENCE) fbc_state->fence_id = i915_vma_fence_id(plane_state->ggtt_vma); -- cgit v1.2.3 From fd5a9b950ea8ba2c08ce07418b36b296a04d712b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Jul 2024 17:52:36 +0300 Subject: drm/i915/fbc: Convert to intel_display, mostly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch the FBC code over to intel_display from i915, as much as possible. This is the future direction so that the display code can be shared between i915 and xe more cleanly. Some of the platform checks and the stolen mem facing stiff still need i915 around though. v2: Drop some redundant to_i915() casts Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240705145254.3355-3-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi --- .../gpu/drm/i915/display/intel_display_debugfs.c | 4 +- .../gpu/drm/i915/display/intel_display_driver.c | 4 +- drivers/gpu/drm/i915/display/intel_fbc.c | 420 +++++++++++---------- drivers/gpu/drm/i915/display/intel_fbc.h | 13 +- drivers/gpu/drm/i915/display/intel_fifo_underrun.c | 2 +- drivers/gpu/drm/i915/display/intel_modeset_setup.c | 2 +- 6 files changed, 238 insertions(+), 207 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 91757fed9c6d..5cf9b4af9adf 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1008,7 +1008,7 @@ i915_fifo_underrun_reset_write(struct file *filp, return ret; } - intel_fbc_reset_underrun(dev_priv); + intel_fbc_reset_underrun(&dev_priv->display); return cnt; } @@ -1063,7 +1063,7 @@ void intel_display_debugfs_register(struct drm_i915_private *i915) intel_bios_debugfs_register(i915); intel_cdclk_debugfs_register(i915); intel_dmc_debugfs_register(i915); - intel_fbc_debugfs_register(i915); + intel_fbc_debugfs_register(&i915->display); intel_hpd_debugfs_register(i915); intel_opregion_debugfs_register(i915); intel_psr_debugfs_register(i915); diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c index 794b4af38055..13e206ec450f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.c +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c @@ -265,7 +265,7 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915) intel_init_quirks(display); - intel_fbc_init(i915); + intel_fbc_init(display); return 0; @@ -607,7 +607,7 @@ void intel_display_driver_remove_noirq(struct drm_i915_private *i915) destroy_workqueue(i915->display.wq.flip); destroy_workqueue(i915->display.wq.modeset); - intel_fbc_cleanup(i915); + intel_fbc_cleanup(&i915->display); } /* part #3: call after gem init */ diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 360b3e6df8fa..9c51f48b54f6 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -60,13 +60,13 @@ #include "intel_fbc_regs.h" #include "intel_frontbuffer.h" -#define for_each_fbc_id(__dev_priv, __fbc_id) \ +#define for_each_fbc_id(__display, __fbc_id) \ for ((__fbc_id) = INTEL_FBC_A; (__fbc_id) < I915_MAX_FBCS; (__fbc_id)++) \ - for_each_if(DISPLAY_RUNTIME_INFO(__dev_priv)->fbc_mask & BIT(__fbc_id)) + for_each_if(DISPLAY_RUNTIME_INFO(__display)->fbc_mask & BIT(__fbc_id)) -#define for_each_intel_fbc(__dev_priv, __fbc, __fbc_id) \ - for_each_fbc_id((__dev_priv), (__fbc_id)) \ - for_each_if((__fbc) = (__dev_priv)->display.fbc[(__fbc_id)]) +#define for_each_intel_fbc(__display, __fbc, __fbc_id) \ + for_each_fbc_id((__display), (__fbc_id)) \ + for_each_if((__fbc) = (__display)->fbc[(__fbc_id)]) struct intel_fbc_funcs { void (*activate)(struct intel_fbc *fbc); @@ -89,7 +89,7 @@ struct intel_fbc_state { }; struct intel_fbc { - struct drm_i915_private *i915; + struct intel_display *display; const struct intel_fbc_funcs *funcs; /* @@ -150,7 +150,7 @@ static unsigned int _intel_fbc_cfb_stride(const struct intel_plane_state *plane_ /* minimum acceptable cfb stride in bytes, assuming 1:1 compression limit */ static unsigned int skl_fbc_min_cfb_stride(const struct intel_plane_state *plane_state) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); unsigned int limit = 4; /* 1:4 compression limit is the worst case */ unsigned int cpp = 4; /* FBC always 4 bytes per pixel */ unsigned int width = drm_rect_width(&plane_state->uapi.src) >> 16; @@ -164,7 +164,7 @@ static unsigned int skl_fbc_min_cfb_stride(const struct intel_plane_state *plane * Wa_16011863758: icl+ * Avoid some hardware segment address miscalculation. */ - if (DISPLAY_VER(i915) >= 11) + if (DISPLAY_VER(display) >= 11) stride += 64; /* @@ -180,7 +180,7 @@ static unsigned int skl_fbc_min_cfb_stride(const struct intel_plane_state *plane /* properly aligned cfb stride in bytes, assuming 1:1 compression limit */ static unsigned int intel_fbc_cfb_stride(const struct intel_plane_state *plane_state) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); unsigned int stride = _intel_fbc_cfb_stride(plane_state); /* @@ -188,7 +188,7 @@ static unsigned int intel_fbc_cfb_stride(const struct intel_plane_state *plane_s * be 512 byte aligned. Aligning each line to 512 bytes guarantees * that regardless of the compression limit we choose later. */ - if (DISPLAY_VER(i915) >= 9) + if (DISPLAY_VER(display) >= 9) return max(ALIGN(stride, 512), skl_fbc_min_cfb_stride(plane_state)); else return stride; @@ -196,12 +196,12 @@ static unsigned int intel_fbc_cfb_stride(const struct intel_plane_state *plane_s static unsigned int intel_fbc_cfb_size(const struct intel_plane_state *plane_state) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); int lines = drm_rect_height(&plane_state->uapi.src) >> 16; - if (DISPLAY_VER(i915) == 7) + if (DISPLAY_VER(display) == 7) lines = min(lines, 2048); - else if (DISPLAY_VER(i915) >= 8) + else if (DISPLAY_VER(display) >= 8) lines = min(lines, 2560); return lines * intel_fbc_cfb_stride(plane_state); @@ -209,7 +209,7 @@ static unsigned int intel_fbc_cfb_size(const struct intel_plane_state *plane_sta static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state *plane_state) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); unsigned int stride_aligned = intel_fbc_cfb_stride(plane_state); unsigned int stride = _intel_fbc_cfb_stride(plane_state); const struct drm_framebuffer *fb = plane_state->hw.fb; @@ -222,28 +222,31 @@ static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state *plane_s * we always need to use the override there. */ if (stride != stride_aligned || - (DISPLAY_VER(i915) == 9 && fb->modifier == DRM_FORMAT_MOD_LINEAR)) + (DISPLAY_VER(display) == 9 && fb->modifier == DRM_FORMAT_MOD_LINEAR)) return stride_aligned * 4 / 64; return 0; } -static bool intel_fbc_has_fences(struct drm_i915_private *i915) +static bool intel_fbc_has_fences(struct intel_display *display) { + struct drm_i915_private __maybe_unused *i915 = to_i915(display->drm); + return intel_gt_support_legacy_fencing(to_gt(i915)); } static u32 i8xx_fbc_ctl(struct intel_fbc *fbc) { const struct intel_fbc_state *fbc_state = &fbc->state; - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; + struct drm_i915_private *i915 = to_i915(display->drm); unsigned int cfb_stride; u32 fbc_ctl; cfb_stride = fbc_state->cfb_stride / fbc->limit; /* FBC_CTL wants 32B or 64B units */ - if (DISPLAY_VER(i915) == 2) + if (DISPLAY_VER(display) == 2) cfb_stride = (cfb_stride / 32) - 1; else cfb_stride = (cfb_stride / 64) - 1; @@ -277,21 +280,21 @@ static u32 i965_fbc_ctl2(struct intel_fbc *fbc) static void i8xx_fbc_deactivate(struct intel_fbc *fbc) { - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; u32 fbc_ctl; /* Disable compression */ - fbc_ctl = intel_de_read(i915, FBC_CONTROL); + fbc_ctl = intel_de_read(display, FBC_CONTROL); if ((fbc_ctl & FBC_CTL_EN) == 0) return; fbc_ctl &= ~FBC_CTL_EN; - intel_de_write(i915, FBC_CONTROL, fbc_ctl); + intel_de_write(display, FBC_CONTROL, fbc_ctl); /* Wait for compressing bit to clear */ - if (intel_de_wait_for_clear(i915, FBC_STATUS, + if (intel_de_wait_for_clear(display, FBC_STATUS, FBC_STAT_COMPRESSING, 10)) { - drm_dbg_kms(&i915->drm, "FBC idle timed out\n"); + drm_dbg_kms(display->drm, "FBC idle timed out\n"); return; } } @@ -299,32 +302,32 @@ static void i8xx_fbc_deactivate(struct intel_fbc *fbc) static void i8xx_fbc_activate(struct intel_fbc *fbc) { const struct intel_fbc_state *fbc_state = &fbc->state; - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; int i; /* Clear old tags */ for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++) - intel_de_write(i915, FBC_TAG(i), 0); + intel_de_write(display, FBC_TAG(i), 0); - if (DISPLAY_VER(i915) == 4) { - intel_de_write(i915, FBC_CONTROL2, + if (DISPLAY_VER(display) == 4) { + intel_de_write(display, FBC_CONTROL2, i965_fbc_ctl2(fbc)); - intel_de_write(i915, FBC_FENCE_OFF, + intel_de_write(display, FBC_FENCE_OFF, fbc_state->fence_y_offset); } - intel_de_write(i915, FBC_CONTROL, + intel_de_write(display, FBC_CONTROL, FBC_CTL_EN | i8xx_fbc_ctl(fbc)); } static bool i8xx_fbc_is_active(struct intel_fbc *fbc) { - return intel_de_read(fbc->i915, FBC_CONTROL) & FBC_CTL_EN; + return intel_de_read(fbc->display, FBC_CONTROL) & FBC_CTL_EN; } static bool i8xx_fbc_is_compressing(struct intel_fbc *fbc) { - return intel_de_read(fbc->i915, FBC_STATUS) & + return intel_de_read(fbc->display, FBC_STATUS) & (FBC_STAT_COMPRESSING | FBC_STAT_COMPRESSED); } @@ -332,7 +335,7 @@ static void i8xx_fbc_nuke(struct intel_fbc *fbc) { struct intel_fbc_state *fbc_state = &fbc->state; enum i9xx_plane_id i9xx_plane = fbc_state->plane->i9xx_plane; - struct drm_i915_private *dev_priv = fbc->i915; + struct drm_i915_private *dev_priv = to_i915(fbc->display->drm); intel_de_write_fw(dev_priv, DSPADDR(dev_priv, i9xx_plane), intel_de_read_fw(dev_priv, DSPADDR(dev_priv, i9xx_plane))); @@ -340,13 +343,14 @@ static void i8xx_fbc_nuke(struct intel_fbc *fbc) static void i8xx_fbc_program_cfb(struct intel_fbc *fbc) { - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; + struct drm_i915_private *i915 = to_i915(display->drm); - drm_WARN_ON(&i915->drm, + drm_WARN_ON(display->drm, range_overflows_end_t(u64, i915_gem_stolen_area_address(i915), i915_gem_stolen_node_offset(&fbc->compressed_fb), U32_MAX)); - drm_WARN_ON(&i915->drm, + drm_WARN_ON(display->drm, range_overflows_end_t(u64, i915_gem_stolen_area_address(i915), i915_gem_stolen_node_offset(&fbc->compressed_llb), U32_MAX)); @@ -369,7 +373,7 @@ static void i965_fbc_nuke(struct intel_fbc *fbc) { struct intel_fbc_state *fbc_state = &fbc->state; enum i9xx_plane_id i9xx_plane = fbc_state->plane->i9xx_plane; - struct drm_i915_private *dev_priv = fbc->i915; + struct drm_i915_private *dev_priv = to_i915(fbc->display->drm); intel_de_write_fw(dev_priv, DSPSURF(dev_priv, i9xx_plane), intel_de_read_fw(dev_priv, DSPSURF(dev_priv, i9xx_plane))); @@ -402,7 +406,8 @@ static u32 g4x_dpfc_ctl_limit(struct intel_fbc *fbc) static u32 g4x_dpfc_ctl(struct intel_fbc *fbc) { const struct intel_fbc_state *fbc_state = &fbc->state; - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; + struct drm_i915_private *i915 = to_i915(display->drm); u32 dpfc_ctl; dpfc_ctl = g4x_dpfc_ctl_limit(fbc) | @@ -414,7 +419,7 @@ static u32 g4x_dpfc_ctl(struct intel_fbc *fbc) if (fbc_state->fence_id >= 0) { dpfc_ctl |= DPFC_CTL_FENCE_EN_G4X; - if (DISPLAY_VER(i915) < 6) + if (DISPLAY_VER(display) < 6) dpfc_ctl |= DPFC_CTL_FENCENO(fbc_state->fence_id); } @@ -424,43 +429,43 @@ static u32 g4x_dpfc_ctl(struct intel_fbc *fbc) static void g4x_fbc_activate(struct intel_fbc *fbc) { const struct intel_fbc_state *fbc_state = &fbc->state; - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; - intel_de_write(i915, DPFC_FENCE_YOFF, + intel_de_write(display, DPFC_FENCE_YOFF, fbc_state->fence_y_offset); - intel_de_write(i915, DPFC_CONTROL, + intel_de_write(display, DPFC_CONTROL, DPFC_CTL_EN | g4x_dpfc_ctl(fbc)); } static void g4x_fbc_deactivate(struct intel_fbc *fbc) { - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; u32 dpfc_ctl; /* Disable compression */ - dpfc_ctl = intel_de_read(i915, DPFC_CONTROL); + dpfc_ctl = intel_de_read(display, DPFC_CONTROL); if (dpfc_ctl & DPFC_CTL_EN) { dpfc_ctl &= ~DPFC_CTL_EN; - intel_de_write(i915, DPFC_CONTROL, dpfc_ctl); + intel_de_write(display, DPFC_CONTROL, dpfc_ctl); } } static bool g4x_fbc_is_active(struct intel_fbc *fbc) { - return intel_de_read(fbc->i915, DPFC_CONTROL) & DPFC_CTL_EN; + return intel_de_read(fbc->display, DPFC_CONTROL) & DPFC_CTL_EN; } static bool g4x_fbc_is_compressing(struct intel_fbc *fbc) { - return intel_de_read(fbc->i915, DPFC_STATUS) & DPFC_COMP_SEG_MASK; + return intel_de_read(fbc->display, DPFC_STATUS) & DPFC_COMP_SEG_MASK; } static void g4x_fbc_program_cfb(struct intel_fbc *fbc) { - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; - intel_de_write(i915, DPFC_CB_BASE, + intel_de_write(display, DPFC_CB_BASE, i915_gem_stolen_node_offset(&fbc->compressed_fb)); } @@ -476,43 +481,43 @@ static const struct intel_fbc_funcs g4x_fbc_funcs = { static void ilk_fbc_activate(struct intel_fbc *fbc) { struct intel_fbc_state *fbc_state = &fbc->state; - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; - intel_de_write(i915, ILK_DPFC_FENCE_YOFF(fbc->id), + intel_de_write(display, ILK_DPFC_FENCE_YOFF(fbc->id), fbc_state->fence_y_offset); - intel_de_write(i915, ILK_DPFC_CONTROL(fbc->id), + intel_de_write(display, ILK_DPFC_CONTROL(fbc->id), DPFC_CTL_EN | g4x_dpfc_ctl(fbc)); } static void ilk_fbc_deactivate(struct intel_fbc *fbc) { - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; u32 dpfc_ctl; /* Disable compression */ - dpfc_ctl = intel_de_read(i915, ILK_DPFC_CONTROL(fbc->id)); + dpfc_ctl = intel_de_read(display, ILK_DPFC_CONTROL(fbc->id)); if (dpfc_ctl & DPFC_CTL_EN) { dpfc_ctl &= ~DPFC_CTL_EN; - intel_de_write(i915, ILK_DPFC_CONTROL(fbc->id), dpfc_ctl); + intel_de_write(display, ILK_DPFC_CONTROL(fbc->id), dpfc_ctl); } } static bool ilk_fbc_is_active(struct intel_fbc *fbc) { - return intel_de_read(fbc->i915, ILK_DPFC_CONTROL(fbc->id)) & DPFC_CTL_EN; + return intel_de_read(fbc->display, ILK_DPFC_CONTROL(fbc->id)) & DPFC_CTL_EN; } static bool ilk_fbc_is_compressing(struct intel_fbc *fbc) { - return intel_de_read(fbc->i915, ILK_DPFC_STATUS(fbc->id)) & DPFC_COMP_SEG_MASK; + return intel_de_read(fbc->display, ILK_DPFC_STATUS(fbc->id)) & DPFC_COMP_SEG_MASK; } static void ilk_fbc_program_cfb(struct intel_fbc *fbc) { - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; - intel_de_write(i915, ILK_DPFC_CB_BASE(fbc->id), + intel_de_write(display, ILK_DPFC_CB_BASE(fbc->id), i915_gem_stolen_node_offset(&fbc->compressed_fb)); } @@ -528,14 +533,14 @@ static const struct intel_fbc_funcs ilk_fbc_funcs = { static void snb_fbc_program_fence(struct intel_fbc *fbc) { const struct intel_fbc_state *fbc_state = &fbc->state; - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; u32 ctl = 0; if (fbc_state->fence_id >= 0) ctl = SNB_DPFC_FENCE_EN | SNB_DPFC_FENCENO(fbc_state->fence_id); - intel_de_write(i915, SNB_DPFC_CTL_SA, ctl); - intel_de_write(i915, SNB_DPFC_CPU_FENCE_OFFSET, fbc_state->fence_y_offset); + intel_de_write(display, SNB_DPFC_CTL_SA, ctl); + intel_de_write(display, SNB_DPFC_CPU_FENCE_OFFSET, fbc_state->fence_y_offset); } static void snb_fbc_activate(struct intel_fbc *fbc) @@ -547,10 +552,10 @@ static void snb_fbc_activate(struct intel_fbc *fbc) static void snb_fbc_nuke(struct intel_fbc *fbc) { - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; - intel_de_write(i915, MSG_FBC_REND_STATE(fbc->id), FBC_REND_NUKE); - intel_de_posting_read(i915, MSG_FBC_REND_STATE(fbc->id)); + intel_de_write(display, MSG_FBC_REND_STATE(fbc->id), FBC_REND_NUKE); + intel_de_posting_read(display, MSG_FBC_REND_STATE(fbc->id)); } static const struct intel_fbc_funcs snb_fbc_funcs = { @@ -565,20 +570,20 @@ static const struct intel_fbc_funcs snb_fbc_funcs = { static void glk_fbc_program_cfb_stride(struct intel_fbc *fbc) { const struct intel_fbc_state *fbc_state = &fbc->state; - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; u32 val = 0; if (fbc_state->override_cfb_stride) val |= FBC_STRIDE_OVERRIDE | FBC_STRIDE(fbc_state->override_cfb_stride / fbc->limit); - intel_de_write(i915, GLK_FBC_STRIDE(fbc->id), val); + intel_de_write(display, GLK_FBC_STRIDE(fbc->id), val); } static void skl_fbc_program_cfb_stride(struct intel_fbc *fbc) { const struct intel_fbc_state *fbc_state = &fbc->state; - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; u32 val = 0; /* Display WA #0529: skl, kbl, bxt. */ @@ -586,7 +591,7 @@ static void skl_fbc_program_cfb_stride(struct intel_fbc *fbc) val |= CHICKEN_FBC_STRIDE_OVERRIDE | CHICKEN_FBC_STRIDE(fbc_state->override_cfb_stride / fbc->limit); - intel_de_rmw(i915, CHICKEN_MISC_4, + intel_de_rmw(display, CHICKEN_MISC_4, CHICKEN_FBC_STRIDE_OVERRIDE | CHICKEN_FBC_STRIDE_MASK, val); } @@ -594,7 +599,8 @@ static void skl_fbc_program_cfb_stride(struct intel_fbc *fbc) static u32 ivb_dpfc_ctl(struct intel_fbc *fbc) { const struct intel_fbc_state *fbc_state = &fbc->state; - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; + struct drm_i915_private *i915 = to_i915(display->drm); u32 dpfc_ctl; dpfc_ctl = g4x_dpfc_ctl_limit(fbc); @@ -602,7 +608,7 @@ static u32 ivb_dpfc_ctl(struct intel_fbc *fbc) if (IS_IVYBRIDGE(i915)) dpfc_ctl |= DPFC_CTL_PLANE_IVB(fbc_state->plane->i9xx_plane); - if (DISPLAY_VER(i915) >= 20) + if (DISPLAY_VER(display) >= 20) dpfc_ctl |= DPFC_CTL_PLANE_BINDING(fbc_state->plane->id); if (fbc_state->fence_id >= 0) @@ -616,35 +622,35 @@ static u32 ivb_dpfc_ctl(struct intel_fbc *fbc) static void ivb_fbc_activate(struct intel_fbc *fbc) { - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; u32 dpfc_ctl; - if (DISPLAY_VER(i915) >= 10) + if (DISPLAY_VER(display) >= 10) glk_fbc_program_cfb_stride(fbc); - else if (DISPLAY_VER(i915) == 9) + else if (DISPLAY_VER(display) == 9) skl_fbc_program_cfb_stride(fbc); - if (intel_fbc_has_fences(i915)) + if (intel_fbc_has_fences(display)) snb_fbc_program_fence(fbc); /* wa_14019417088 Alternative WA*/ dpfc_ctl = ivb_dpfc_ctl(fbc); - if (DISPLAY_VER(i915) >= 20) - intel_de_write(i915, ILK_DPFC_CONTROL(fbc->id), dpfc_ctl); + if (DISPLAY_VER(display) >= 20) + intel_de_write(display, ILK_DPFC_CONTROL(fbc->id), dpfc_ctl); - intel_de_write(i915, ILK_DPFC_CONTROL(fbc->id), + intel_de_write(display, ILK_DPFC_CONTROL(fbc->id), DPFC_CTL_EN | dpfc_ctl); } static bool ivb_fbc_is_compressing(struct intel_fbc *fbc) { - return intel_de_read(fbc->i915, ILK_DPFC_STATUS2(fbc->id)) & DPFC_COMP_SEG_MASK_IVB; + return intel_de_read(fbc->display, ILK_DPFC_STATUS2(fbc->id)) & DPFC_COMP_SEG_MASK_IVB; } static void ivb_fbc_set_false_color(struct intel_fbc *fbc, bool enable) { - intel_de_rmw(fbc->i915, ILK_DPFC_CONTROL(fbc->id), + intel_de_rmw(fbc->display, ILK_DPFC_CONTROL(fbc->id), DPFC_CTL_FALSE_COLOR, enable ? DPFC_CTL_FALSE_COLOR : 0); } @@ -689,10 +695,10 @@ static bool intel_fbc_is_compressing(struct intel_fbc *fbc) static void intel_fbc_nuke(struct intel_fbc *fbc) { - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; lockdep_assert_held(&fbc->lock); - drm_WARN_ON(&i915->drm, fbc->flip_pending); + drm_WARN_ON(display->drm, fbc->flip_pending); trace_intel_fbc_nuke(fbc->state.plane); @@ -719,16 +725,19 @@ static void intel_fbc_deactivate(struct intel_fbc *fbc, const char *reason) fbc->no_fbc_reason = reason; } -static u64 intel_fbc_cfb_base_max(struct drm_i915_private *i915) +static u64 intel_fbc_cfb_base_max(struct intel_display *display) { - if (DISPLAY_VER(i915) >= 5 || IS_G4X(i915)) + struct drm_i915_private *i915 = to_i915(display->drm); + + if (DISPLAY_VER(display) >= 5 || IS_G4X(i915)) return BIT_ULL(28); else return BIT_ULL(32); } -static u64 intel_fbc_stolen_end(struct drm_i915_private *i915) +static u64 intel_fbc_stolen_end(struct intel_display *display) { + struct drm_i915_private __maybe_unused *i915 = to_i915(display->drm); u64 end; /* The FBC hardware for BDW/SKL doesn't have access to the stolen @@ -736,12 +745,12 @@ static u64 intel_fbc_stolen_end(struct drm_i915_private *i915) * If we enable FBC using a CFB on that memory range we'll get FIFO * underruns, even if that range is not reserved by the BIOS. */ if (IS_BROADWELL(i915) || - (DISPLAY_VER(i915) == 9 && !IS_BROXTON(i915))) + (DISPLAY_VER(display) == 9 && !IS_BROXTON(i915))) end = i915_gem_stolen_area_size(i915) - 8 * 1024 * 1024; else end = U64_MAX; - return min(end, intel_fbc_cfb_base_max(i915)); + return min(end, intel_fbc_cfb_base_max(display)); } static int intel_fbc_min_limit(const struct intel_plane_state *plane_state) @@ -749,8 +758,10 @@ static int intel_fbc_min_limit(const struct intel_plane_state *plane_state) return plane_state->hw.fb->format->cpp[0] == 2 ? 2 : 1; } -static int intel_fbc_max_limit(struct drm_i915_private *i915) +static int intel_fbc_max_limit(struct intel_display *display) { + struct drm_i915_private *i915 = to_i915(display->drm); + /* WaFbcOnly1to1Ratio:ctg */ if (IS_G4X(i915)) return 1; @@ -765,8 +776,9 @@ static int intel_fbc_max_limit(struct drm_i915_private *i915) static int find_compression_limit(struct intel_fbc *fbc, unsigned int size, int min_limit) { - struct drm_i915_private *i915 = fbc->i915; - u64 end = intel_fbc_stolen_end(i915); + struct intel_display *display = fbc->display; + struct drm_i915_private *i915 = to_i915(display->drm); + u64 end = intel_fbc_stolen_end(display); int ret, limit = min_limit; size /= limit; @@ -777,7 +789,7 @@ static int find_compression_limit(struct intel_fbc *fbc, if (ret == 0) return limit; - for (; limit <= intel_fbc_max_limit(i915); limit <<= 1) { + for (; limit <= intel_fbc_max_limit(display); limit <<= 1) { ret = i915_gem_stolen_insert_node_in_range(i915, &fbc->compressed_fb, size >>= 1, 4096, 0, end); if (ret == 0) @@ -790,15 +802,16 @@ static int find_compression_limit(struct intel_fbc *fbc, static int intel_fbc_alloc_cfb(struct intel_fbc *fbc, unsigned int size, int min_limit) { - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; + struct drm_i915_private *i915 = to_i915(display->drm); int ret; - drm_WARN_ON(&i915->drm, + drm_WARN_ON(display->drm, i915_gem_stolen_node_allocated(&fbc->compressed_fb)); - drm_WARN_ON(&i915->drm, + drm_WARN_ON(display->drm, i915_gem_stolen_node_allocated(&fbc->compressed_llb)); - if (DISPLAY_VER(i915) < 5 && !IS_G4X(i915)) { + if (DISPLAY_VER(display) < 5 && !IS_G4X(i915)) { ret = i915_gem_stolen_insert_node(i915, &fbc->compressed_llb, 4096, 4096); if (ret) @@ -809,12 +822,12 @@ static int intel_fbc_alloc_cfb(struct intel_fbc *fbc, if (!ret) goto err_llb; else if (ret > min_limit) - drm_info_once(&i915->drm, + drm_info_once(display->drm, "Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n"); fbc->limit = ret; - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "reserved %llu bytes of contiguous stolen space for FBC, limit: %d\n", i915_gem_stolen_node_size(&fbc->compressed_fb), fbc->limit); return 0; @@ -824,7 +837,8 @@ err_llb: i915_gem_stolen_remove_node(i915, &fbc->compressed_llb); err: if (i915_gem_stolen_initialized(i915)) - drm_info_once(&i915->drm, "not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size); + drm_info_once(display->drm, + "not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size); return -ENOSPC; } @@ -835,14 +849,15 @@ static void intel_fbc_program_cfb(struct intel_fbc *fbc) static void intel_fbc_program_workarounds(struct intel_fbc *fbc) { - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; + struct drm_i915_private *i915 = to_i915(display->drm); if (IS_SKYLAKE(i915) || IS_BROXTON(i915)) { /* * WaFbcHighMemBwCorruptionAvoidance:skl,bxt * Display WA #0883: skl,bxt */ - intel_de_rmw(i915, ILK_DPFC_CHICKEN(fbc->id), + intel_de_rmw(display, ILK_DPFC_CHICKEN(fbc->id), 0, DPFC_DISABLE_DUMMY0); } @@ -852,24 +867,25 @@ static void intel_fbc_program_workarounds(struct intel_fbc *fbc) * WaFbcNukeOnHostModify:skl,kbl,cfl * Display WA #0873: skl,kbl,cfl */ - intel_de_rmw(i915, ILK_DPFC_CHICKEN(fbc->id), + intel_de_rmw(display, ILK_DPFC_CHICKEN(fbc->id), 0, DPFC_NUKE_ON_ANY_MODIFICATION); } /* Wa_1409120013:icl,jsl,tgl,dg1 */ - if (IS_DISPLAY_VER(i915, 11, 12)) - intel_de_rmw(i915, ILK_DPFC_CHICKEN(fbc->id), + if (IS_DISPLAY_VER(display, 11, 12)) + intel_de_rmw(display, ILK_DPFC_CHICKEN(fbc->id), 0, DPFC_CHICKEN_COMP_DUMMY_PIXEL); /* Wa_22014263786:icl,jsl,tgl,dg1,rkl,adls,adlp,mtl */ - if (DISPLAY_VER(i915) >= 11 && !IS_DG2(i915)) - intel_de_rmw(i915, ILK_DPFC_CHICKEN(fbc->id), + if (DISPLAY_VER(display) >= 11 && !IS_DG2(i915)) + intel_de_rmw(display, ILK_DPFC_CHICKEN(fbc->id), 0, DPFC_CHICKEN_FORCE_SLB_INVALIDATION); } static void __intel_fbc_cleanup_cfb(struct intel_fbc *fbc) { - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; + struct drm_i915_private *i915 = to_i915(display->drm); if (WARN_ON(intel_fbc_hw_is_active(fbc))) return; @@ -880,12 +896,12 @@ static void __intel_fbc_cleanup_cfb(struct intel_fbc *fbc) i915_gem_stolen_remove_node(i915, &fbc->compressed_fb); } -void intel_fbc_cleanup(struct drm_i915_private *i915) +void intel_fbc_cleanup(struct intel_display *display) { struct intel_fbc *fbc; enum intel_fbc_id fbc_id; - for_each_intel_fbc(i915, fbc, fbc_id) { + for_each_intel_fbc(display, fbc, fbc_id) { mutex_lock(&fbc->lock); __intel_fbc_cleanup_cfb(fbc); mutex_unlock(&fbc->lock); @@ -937,15 +953,16 @@ static bool icl_fbc_stride_is_valid(const struct intel_plane_state *plane_state) static bool stride_is_valid(const struct intel_plane_state *plane_state) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); + struct drm_i915_private *i915 = to_i915(display->drm); - if (DISPLAY_VER(i915) >= 11) + if (DISPLAY_VER(display) >= 11) return icl_fbc_stride_is_valid(plane_state); - else if (DISPLAY_VER(i915) >= 9) + else if (DISPLAY_VER(display) >= 9) return skl_fbc_stride_is_valid(plane_state); - else if (DISPLAY_VER(i915) >= 5 || IS_G4X(i915)) + else if (DISPLAY_VER(display) >= 5 || IS_G4X(i915)) return g4x_fbc_stride_is_valid(plane_state); - else if (DISPLAY_VER(i915) == 4) + else if (DISPLAY_VER(display) == 4) return i965_fbc_stride_is_valid(plane_state); else return i8xx_fbc_stride_is_valid(plane_state); @@ -953,7 +970,7 @@ static bool stride_is_valid(const struct intel_plane_state *plane_state) static bool i8xx_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_state) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); const struct drm_framebuffer *fb = plane_state->hw.fb; switch (fb->format->format) { @@ -963,7 +980,7 @@ static bool i8xx_fbc_pixel_format_is_valid(const struct intel_plane_state *plane case DRM_FORMAT_XRGB1555: case DRM_FORMAT_RGB565: /* 16bpp not supported on gen2 */ - if (DISPLAY_VER(i915) == 2) + if (DISPLAY_VER(display) == 2) return false; return true; default: @@ -973,7 +990,8 @@ static bool i8xx_fbc_pixel_format_is_valid(const struct intel_plane_state *plane static bool g4x_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_state) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); + struct drm_i915_private *i915 = to_i915(display->drm); const struct drm_framebuffer *fb = plane_state->hw.fb; switch (fb->format->format) { @@ -1008,11 +1026,12 @@ static bool lnl_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_ static bool pixel_format_is_valid(const struct intel_plane_state *plane_state) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); + struct drm_i915_private *i915 = to_i915(display->drm); - if (DISPLAY_VER(i915) >= 20) + if (DISPLAY_VER(display) >= 20) return lnl_fbc_pixel_format_is_valid(plane_state); - else if (DISPLAY_VER(i915) >= 5 || IS_G4X(i915)) + else if (DISPLAY_VER(display) >= 5 || IS_G4X(i915)) return g4x_fbc_pixel_format_is_valid(plane_state); else return i8xx_fbc_pixel_format_is_valid(plane_state); @@ -1042,11 +1061,12 @@ static bool skl_fbc_rotation_is_valid(const struct intel_plane_state *plane_stat static bool rotation_is_valid(const struct intel_plane_state *plane_state) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); + struct drm_i915_private *i915 = to_i915(display->drm); - if (DISPLAY_VER(i915) >= 9) + if (DISPLAY_VER(display) >= 9) return skl_fbc_rotation_is_valid(plane_state); - else if (DISPLAY_VER(i915) >= 5 || IS_G4X(i915)) + else if (DISPLAY_VER(display) >= 5 || IS_G4X(i915)) return g4x_fbc_rotation_is_valid(plane_state); else return i8xx_fbc_rotation_is_valid(plane_state); @@ -1060,19 +1080,20 @@ static bool rotation_is_valid(const struct intel_plane_state *plane_state) */ static bool intel_fbc_hw_tracking_covers_screen(const struct intel_plane_state *plane_state) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); + struct drm_i915_private *i915 = to_i915(display->drm); unsigned int effective_w, effective_h, max_w, max_h; - if (DISPLAY_VER(i915) >= 11) { + if (DISPLAY_VER(display) >= 11) { max_w = 8192; max_h = 4096; - } else if (DISPLAY_VER(i915) >= 10) { + } else if (DISPLAY_VER(display) >= 10) { max_w = 5120; max_h = 4096; - } else if (DISPLAY_VER(i915) >= 7) { + } else if (DISPLAY_VER(display) >= 7) { max_w = 4096; max_h = 4096; - } else if (IS_G4X(i915) || DISPLAY_VER(i915) >= 5) { + } else if (IS_G4X(i915) || DISPLAY_VER(display) >= 5) { max_w = 4096; max_h = 2048; } else { @@ -1090,16 +1111,17 @@ static bool intel_fbc_hw_tracking_covers_screen(const struct intel_plane_state * static bool intel_fbc_plane_size_valid(const struct intel_plane_state *plane_state) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); + struct drm_i915_private *i915 = to_i915(display->drm); unsigned int w, h, max_w, max_h; - if (DISPLAY_VER(i915) >= 10) { + if (DISPLAY_VER(display) >= 10) { max_w = 5120; max_h = 4096; - } else if (DISPLAY_VER(i915) >= 8 || IS_HASWELL(i915)) { + } else if (DISPLAY_VER(display) >= 8 || IS_HASWELL(i915)) { max_w = 4096; max_h = 4096; - } else if (IS_G4X(i915) || DISPLAY_VER(i915) >= 5) { + } else if (IS_G4X(i915) || DISPLAY_VER(display) >= 5) { max_w = 4096; max_h = 2048; } else { @@ -1127,9 +1149,9 @@ static bool skl_fbc_tiling_valid(const struct intel_plane_state *plane_state) static bool tiling_is_valid(const struct intel_plane_state *plane_state) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); - if (DISPLAY_VER(i915) >= 9) + if (DISPLAY_VER(display) >= 9) return skl_fbc_tiling_valid(plane_state); else return i8xx_fbc_tiling_valid(plane_state); @@ -1139,7 +1161,7 @@ static void intel_fbc_update_state(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_plane *plane) { - struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state->base.dev); const struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); const struct intel_plane_state *plane_state = @@ -1157,8 +1179,8 @@ static void intel_fbc_update_state(struct intel_atomic_state *state, fbc_state->fence_y_offset = intel_plane_fence_y_offset(plane_state); - drm_WARN_ON(&i915->drm, plane_state->flags & PLANE_HAS_FENCE && - !intel_fbc_has_fences(i915)); + drm_WARN_ON(display->drm, plane_state->flags & PLANE_HAS_FENCE && + !intel_fbc_has_fences(display)); if (plane_state->flags & PLANE_HAS_FENCE) fbc_state->fence_id = i915_vma_fence_id(plane_state->ggtt_vma); @@ -1172,7 +1194,7 @@ static void intel_fbc_update_state(struct intel_atomic_state *state, static bool intel_fbc_is_fence_ok(const struct intel_plane_state *plane_state) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); /* * The use of a CPU fence is one of two ways to detect writes by the @@ -1186,7 +1208,7 @@ static bool intel_fbc_is_fence_ok(const struct intel_plane_state *plane_state) * so have no fence associated with it) due to aperture constraints * at the time of pinning. */ - return DISPLAY_VER(i915) >= 9 || + return DISPLAY_VER(display) >= 9 || (plane_state->flags & PLANE_HAS_FENCE && i915_vma_fence_id(plane_state->ggtt_vma) != -1); } @@ -1211,7 +1233,8 @@ static bool intel_fbc_is_ok(const struct intel_plane_state *plane_state) static int intel_fbc_check_plane(struct intel_atomic_state *state, struct intel_plane *plane) { - struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state->base.dev); + struct drm_i915_private *i915 = to_i915(display->drm); struct intel_plane_state *plane_state = intel_atomic_get_new_plane_state(state, plane); const struct drm_framebuffer *fb = plane_state->hw.fb; @@ -1232,7 +1255,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, return 0; } - if (!i915->display.params.enable_fbc) { + if (!display->params.enable_fbc) { plane_state->no_fbc_reason = "disabled per module param or by default"; return 0; } @@ -1265,14 +1288,14 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, * Recommendation is to keep this combination disabled * Bspec: 50422 HSD: 14010260002 */ - if (IS_DISPLAY_VER(i915, 12, 14) && crtc_state->has_sel_update && + if (IS_DISPLAY_VER(display, 12, 14) && crtc_state->has_sel_update && !crtc_state->has_panel_replay) { plane_state->no_fbc_reason = "PSR2 enabled"; return 0; } /* Wa_14016291713 */ - if ((IS_DISPLAY_VER(i915, 12, 13) || + if ((IS_DISPLAY_VER(display, 12, 13) || IS_DISPLAY_IP_STEP(i915, IP_VER(14, 0), STEP_A0, STEP_C0)) && crtc_state->has_psr && !crtc_state->has_panel_replay) { plane_state->no_fbc_reason = "PSR1 enabled (Wa_14016291713)"; @@ -1299,7 +1322,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, return 0; } - if (DISPLAY_VER(i915) < 20 && + if (DISPLAY_VER(display) < 20 && plane_state->hw.pixel_blend_mode != DRM_MODE_BLEND_PIXEL_NONE && fb->format->has_alpha) { plane_state->no_fbc_reason = "per-pixel alpha not supported"; @@ -1321,14 +1344,14 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, * having a Y offset that isn't divisible by 4 causes FIFO underrun * and screen flicker. */ - if (DISPLAY_VER(i915) >= 9 && + if (DISPLAY_VER(display) >= 9 && plane_state->view.color_plane[0].y & 3) { plane_state->no_fbc_reason = "plane start Y offset misaligned"; return 0; } /* Wa_22010751166: icl, ehl, tgl, dg1, rkl */ - if (DISPLAY_VER(i915) >= 11 && + if (DISPLAY_VER(display) >= 11 && (plane_state->view.color_plane[0].y + (drm_rect_height(&plane_state->uapi.src) >> 16)) & 3) { plane_state->no_fbc_reason = "plane end Y offset misaligned"; @@ -1404,7 +1427,7 @@ static bool __intel_fbc_pre_update(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_plane *plane) { - struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state->base.dev); struct intel_fbc *fbc = plane->fbc; bool need_vblank_wait = false; @@ -1430,7 +1453,7 @@ static bool __intel_fbc_pre_update(struct intel_atomic_state *state, * and skipping the extra vblank wait before the plane update * if at least one frame has already passed. */ - if (fbc->activated && DISPLAY_VER(i915) >= 10) + if (fbc->activated && DISPLAY_VER(display) >= 10) need_vblank_wait = true; fbc->activated = false; @@ -1464,13 +1487,13 @@ bool intel_fbc_pre_update(struct intel_atomic_state *state, static void __intel_fbc_disable(struct intel_fbc *fbc) { - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; struct intel_plane *plane = fbc->state.plane; lockdep_assert_held(&fbc->lock); - drm_WARN_ON(&i915->drm, fbc->active); + drm_WARN_ON(display->drm, fbc->active); - drm_dbg_kms(&i915->drm, "Disabling FBC on [PLANE:%d:%s]\n", + drm_dbg_kms(display->drm, "Disabling FBC on [PLANE:%d:%s]\n", plane->base.base.id, plane->base.name); __intel_fbc_cleanup_cfb(fbc); @@ -1547,7 +1570,7 @@ void intel_fbc_invalidate(struct drm_i915_private *i915, struct intel_fbc *fbc; enum intel_fbc_id fbc_id; - for_each_intel_fbc(i915, fbc, fbc_id) + for_each_intel_fbc(&i915->display, fbc, fbc_id) __intel_fbc_invalidate(fbc, frontbuffer_bits, origin); } @@ -1586,7 +1609,7 @@ void intel_fbc_flush(struct drm_i915_private *i915, struct intel_fbc *fbc; enum intel_fbc_id fbc_id; - for_each_intel_fbc(i915, fbc, fbc_id) + for_each_intel_fbc(&i915->display, fbc, fbc_id) __intel_fbc_flush(fbc, frontbuffer_bits, origin); } @@ -1611,7 +1634,7 @@ static void __intel_fbc_enable(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_plane *plane) { - struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state->base.dev); const struct intel_plane_state *plane_state = intel_atomic_get_new_plane_state(state, plane); struct intel_fbc *fbc = plane->fbc; @@ -1630,7 +1653,7 @@ static void __intel_fbc_enable(struct intel_atomic_state *state, __intel_fbc_disable(fbc); } - drm_WARN_ON(&i915->drm, fbc->active); + drm_WARN_ON(display->drm, fbc->active); fbc->no_fbc_reason = plane_state->no_fbc_reason; if (fbc->no_fbc_reason) @@ -1652,7 +1675,7 @@ static void __intel_fbc_enable(struct intel_atomic_state *state, return; } - drm_dbg_kms(&i915->drm, "Enabling FBC on [PLANE:%d:%s]\n", + drm_dbg_kms(display->drm, "Enabling FBC on [PLANE:%d:%s]\n", plane->base.base.id, plane->base.name); fbc->no_fbc_reason = "FBC enabled but not active yet\n"; @@ -1670,10 +1693,10 @@ static void __intel_fbc_enable(struct intel_atomic_state *state, */ void intel_fbc_disable(struct intel_crtc *crtc) { - struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_display *display = to_intel_display(crtc->base.dev); struct intel_plane *plane; - for_each_intel_plane(&i915->drm, plane) { + for_each_intel_plane(display->drm, plane) { struct intel_fbc *fbc = plane->fbc; if (!fbc || plane->pipe != crtc->pipe) @@ -1718,7 +1741,8 @@ void intel_fbc_update(struct intel_atomic_state *state, static void intel_fbc_underrun_work_fn(struct work_struct *work) { struct intel_fbc *fbc = container_of(work, typeof(*fbc), underrun_work); - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; + struct drm_i915_private *i915 = to_i915(display->drm); mutex_lock(&fbc->lock); @@ -1726,7 +1750,7 @@ static void intel_fbc_underrun_work_fn(struct work_struct *work) if (fbc->underrun_detected || !fbc->state.plane) goto out; - drm_dbg_kms(&i915->drm, "Disabling FBC due to FIFO underrun.\n"); + drm_dbg_kms(display->drm, "Disabling FBC due to FIFO underrun.\n"); fbc->underrun_detected = true; intel_fbc_deactivate(fbc, "FIFO underrun"); @@ -1739,14 +1763,14 @@ out: static void __intel_fbc_reset_underrun(struct intel_fbc *fbc) { - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; cancel_work_sync(&fbc->underrun_work); mutex_lock(&fbc->lock); if (fbc->underrun_detected) { - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "Re-allowing FBC after fifo underrun\n"); fbc->no_fbc_reason = "FIFO underrun cleared"; } @@ -1757,22 +1781,24 @@ static void __intel_fbc_reset_underrun(struct intel_fbc *fbc) /* * intel_fbc_reset_underrun - reset FBC fifo underrun status. - * @i915: the i915 device + * @display: display * * See intel_fbc_handle_fifo_underrun_irq(). For automated testing we * want to re-enable FBC after an underrun to increase test coverage. */ -void intel_fbc_reset_underrun(struct drm_i915_private *i915) +void intel_fbc_reset_underrun(struct intel_display *display) { struct intel_fbc *fbc; enum intel_fbc_id fbc_id; - for_each_intel_fbc(i915, fbc, fbc_id) + for_each_intel_fbc(display, fbc, fbc_id) __intel_fbc_reset_underrun(fbc); } static void __intel_fbc_handle_fifo_underrun_irq(struct intel_fbc *fbc) { + struct drm_i915_private *i915 = to_i915(fbc->display->drm); + /* * There's no guarantee that underrun_detected won't be set to true * right after this check and before the work is scheduled, but that's @@ -1784,12 +1810,12 @@ static void __intel_fbc_handle_fifo_underrun_irq(struct intel_fbc *fbc) if (READ_ONCE(fbc->underrun_detected)) return; - queue_work(fbc->i915->unordered_wq, &fbc->underrun_work); + queue_work(i915->unordered_wq, &fbc->underrun_work); } /** * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun - * @i915: i915 device + * @display: display * * Without FBC, most underruns are harmless and don't really cause too many * problems, except for an annoying message on dmesg. With FBC, underruns can @@ -1801,12 +1827,12 @@ static void __intel_fbc_handle_fifo_underrun_irq(struct intel_fbc *fbc) * * This function is called from the IRQ handler. */ -void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *i915) +void intel_fbc_handle_fifo_underrun_irq(struct intel_display *display) { struct intel_fbc *fbc; enum intel_fbc_id fbc_id; - for_each_intel_fbc(i915, fbc, fbc_id) + for_each_intel_fbc(display, fbc, fbc_id) __intel_fbc_handle_fifo_underrun_irq(fbc); } @@ -1819,15 +1845,17 @@ void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *i915) * space to change the value during runtime without sanitizing it again. IGT * relies on being able to change i915.enable_fbc at runtime. */ -static int intel_sanitize_fbc_option(struct drm_i915_private *i915) +static int intel_sanitize_fbc_option(struct intel_display *display) { - if (i915->display.params.enable_fbc >= 0) - return !!i915->display.params.enable_fbc; + struct drm_i915_private *i915 = to_i915(display->drm); + + if (display->params.enable_fbc >= 0) + return !!display->params.enable_fbc; - if (!HAS_FBC(i915)) + if (!HAS_FBC(display)) return 0; - if (IS_BROADWELL(i915) || DISPLAY_VER(i915) >= 9) + if (IS_BROADWELL(i915) || DISPLAY_VER(display) >= 9) return 1; return 0; @@ -1838,9 +1866,10 @@ void intel_fbc_add_plane(struct intel_fbc *fbc, struct intel_plane *plane) plane->fbc = fbc; } -static struct intel_fbc *intel_fbc_create(struct drm_i915_private *i915, +static struct intel_fbc *intel_fbc_create(struct intel_display *display, enum intel_fbc_id fbc_id) { + struct drm_i915_private *i915 = to_i915(display->drm); struct intel_fbc *fbc; fbc = kzalloc(sizeof(*fbc), GFP_KERNEL); @@ -1848,19 +1877,19 @@ static struct intel_fbc *intel_fbc_create(struct drm_i915_private *i915, return NULL; fbc->id = fbc_id; - fbc->i915 = i915; + fbc->display = display; INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn); mutex_init(&fbc->lock); - if (DISPLAY_VER(i915) >= 7) + if (DISPLAY_VER(display) >= 7) fbc->funcs = &ivb_fbc_funcs; - else if (DISPLAY_VER(i915) == 6) + else if (DISPLAY_VER(display) == 6) fbc->funcs = &snb_fbc_funcs; - else if (DISPLAY_VER(i915) == 5) + else if (DISPLAY_VER(display) == 5) fbc->funcs = &ilk_fbc_funcs; else if (IS_G4X(i915)) fbc->funcs = &g4x_fbc_funcs; - else if (DISPLAY_VER(i915) == 4) + else if (DISPLAY_VER(display) == 4) fbc->funcs = &i965_fbc_funcs; else fbc->funcs = &i8xx_fbc_funcs; @@ -1870,36 +1899,36 @@ static struct intel_fbc *intel_fbc_create(struct drm_i915_private *i915, /** * intel_fbc_init - Initialize FBC - * @i915: the i915 device + * @display: display * * This function might be called during PM init process. */ -void intel_fbc_init(struct drm_i915_private *i915) +void intel_fbc_init(struct intel_display *display) { enum intel_fbc_id fbc_id; - i915->display.params.enable_fbc = intel_sanitize_fbc_option(i915); - drm_dbg_kms(&i915->drm, "Sanitized enable_fbc value: %d\n", - i915->display.params.enable_fbc); + display->params.enable_fbc = intel_sanitize_fbc_option(display); + drm_dbg_kms(display->drm, "Sanitized enable_fbc value: %d\n", + display->params.enable_fbc); - for_each_fbc_id(i915, fbc_id) - i915->display.fbc[fbc_id] = intel_fbc_create(i915, fbc_id); + for_each_fbc_id(display, fbc_id) + display->fbc[fbc_id] = intel_fbc_create(display, fbc_id); } /** * intel_fbc_sanitize - Sanitize FBC - * @i915: the i915 device + * @display: display * * Make sure FBC is initially disabled since we have no * idea eg. into which parts of stolen it might be scribbling * into. */ -void intel_fbc_sanitize(struct drm_i915_private *i915) +void intel_fbc_sanitize(struct intel_display *display) { struct intel_fbc *fbc; enum intel_fbc_id fbc_id; - for_each_intel_fbc(i915, fbc, fbc_id) { + for_each_intel_fbc(display, fbc, fbc_id) { if (intel_fbc_hw_is_active(fbc)) intel_fbc_hw_deactivate(fbc); } @@ -1908,11 +1937,12 @@ void intel_fbc_sanitize(struct drm_i915_private *i915) static int intel_fbc_debugfs_status_show(struct seq_file *m, void *unused) { struct intel_fbc *fbc = m->private; - struct drm_i915_private *i915 = fbc->i915; + struct intel_display *display = fbc->display; + struct drm_i915_private *i915 = to_i915(display->drm); struct intel_plane *plane; intel_wakeref_t wakeref; - drm_modeset_lock_all(&i915->drm); + drm_modeset_lock_all(display->drm); wakeref = intel_runtime_pm_get(&i915->runtime_pm); mutex_lock(&fbc->lock); @@ -1925,7 +1955,7 @@ static int intel_fbc_debugfs_status_show(struct seq_file *m, void *unused) seq_printf(m, "FBC disabled: %s\n", fbc->no_fbc_reason); } - for_each_intel_plane(&i915->drm, plane) { + for_each_intel_plane(display->drm, plane) { const struct intel_plane_state *plane_state = to_intel_plane_state(plane->base.state); @@ -1941,7 +1971,7 @@ static int intel_fbc_debugfs_status_show(struct seq_file *m, void *unused) mutex_unlock(&fbc->lock); intel_runtime_pm_put(&i915->runtime_pm, wakeref); - drm_modeset_unlock_all(&i915->drm); + drm_modeset_unlock_all(display->drm); return 0; } @@ -1998,12 +2028,12 @@ void intel_fbc_crtc_debugfs_add(struct intel_crtc *crtc) } /* FIXME: remove this once igt is on board with per-crtc stuff */ -void intel_fbc_debugfs_register(struct drm_i915_private *i915) +void intel_fbc_debugfs_register(struct intel_display *display) { - struct drm_minor *minor = i915->drm.primary; + struct drm_minor *minor = display->drm->primary; struct intel_fbc *fbc; - fbc = i915->display.fbc[INTEL_FBC_A]; + fbc = display->fbc[INTEL_FBC_A]; if (fbc) intel_fbc_debugfs_add(fbc, minor->debugfs_root); } diff --git a/drivers/gpu/drm/i915/display/intel_fbc.h b/drivers/gpu/drm/i915/display/intel_fbc.h index 6720ec8ee8a2..ceae55458e14 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.h +++ b/drivers/gpu/drm/i915/display/intel_fbc.h @@ -13,6 +13,7 @@ struct drm_i915_private; struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; +struct intel_display; struct intel_fbc; struct intel_plane; struct intel_plane_state; @@ -31,9 +32,9 @@ bool intel_fbc_pre_update(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_fbc_post_update(struct intel_atomic_state *state, struct intel_crtc *crtc); -void intel_fbc_init(struct drm_i915_private *dev_priv); -void intel_fbc_cleanup(struct drm_i915_private *dev_priv); -void intel_fbc_sanitize(struct drm_i915_private *dev_priv); +void intel_fbc_init(struct intel_display *display); +void intel_fbc_cleanup(struct intel_display *display); +void intel_fbc_sanitize(struct intel_display *display); void intel_fbc_update(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_fbc_disable(struct intel_crtc *crtc); @@ -43,9 +44,9 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv, void intel_fbc_flush(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits, enum fb_op_origin origin); void intel_fbc_add_plane(struct intel_fbc *fbc, struct intel_plane *plane); -void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *i915); -void intel_fbc_reset_underrun(struct drm_i915_private *i915); +void intel_fbc_handle_fifo_underrun_irq(struct intel_display *display); +void intel_fbc_reset_underrun(struct intel_display *display); void intel_fbc_crtc_debugfs_add(struct intel_crtc *crtc); -void intel_fbc_debugfs_register(struct drm_i915_private *i915); +void intel_fbc_debugfs_register(struct intel_display *display); #endif /* __INTEL_FBC_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c index e5e4ca7cc499..8949fbb1cc60 100644 --- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c @@ -440,7 +440,7 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, drm_err(&dev_priv->drm, "CPU pipe %c FIFO underrun\n", pipe_name(pipe)); } - intel_fbc_handle_fifo_underrun_irq(dev_priv); + intel_fbc_handle_fifo_underrun_irq(&dev_priv->display); } /** diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index 7602cb30ebf1..6f85f5352455 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -966,7 +966,7 @@ void intel_modeset_setup_hw_state(struct drm_i915_private *i915, } } - intel_fbc_sanitize(i915); + intel_fbc_sanitize(&i915->display); intel_sanitize_plane_mapping(i915); -- cgit v1.2.3 From 6c9ee258b1f4e7021224c9bf541fe6b17a03ee40 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Jul 2024 17:52:37 +0300 Subject: drm/i915/fbc: s/_intel_fbc_cfb_stride()/intel_fbc_plane_cfb_stride()/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _intel_fbc_cfb_stride() calculates the CFB stride the hardware would automagically generate from the plane's stride. Rename the function to intel_fbc_plane_cfb_stride() to better reflect its purpose. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240705145254.3355-4-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_fbc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 9c51f48b54f6..8b851996cf29 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -140,7 +140,7 @@ static unsigned int intel_fbc_plane_stride(const struct intel_plane_state *plane } /* plane stride based cfb stride in bytes, assuming 1:1 compression limit */ -static unsigned int _intel_fbc_cfb_stride(const struct intel_plane_state *plane_state) +static unsigned int intel_fbc_plane_cfb_stride(const struct intel_plane_state *plane_state) { unsigned int cpp = 4; /* FBC always 4 bytes per pixel */ @@ -181,7 +181,7 @@ static unsigned int skl_fbc_min_cfb_stride(const struct intel_plane_state *plane static unsigned int intel_fbc_cfb_stride(const struct intel_plane_state *plane_state) { struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); - unsigned int stride = _intel_fbc_cfb_stride(plane_state); + unsigned int stride = intel_fbc_plane_cfb_stride(plane_state); /* * At least some of the platforms require each 4 line segment to @@ -211,7 +211,7 @@ static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state *plane_s { struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); unsigned int stride_aligned = intel_fbc_cfb_stride(plane_state); - unsigned int stride = _intel_fbc_cfb_stride(plane_state); + unsigned int stride = intel_fbc_plane_cfb_stride(plane_state); const struct drm_framebuffer *fb = plane_state->hw.fb; /* -- cgit v1.2.3 From a5beee65241d25ad20dd814668c975ba13a42615 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Jul 2024 17:52:38 +0300 Subject: drm/i915/fbc: Extract intel_fbc_max_plane_size() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract intel_fbc_max_plane_size() from intel_fbc_plane_size_valid(). We'll have another use for this soon in determining how much stolen memory we'd like to keep reserved for FBC. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240705145254.3355-5-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_fbc.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 8b851996cf29..05297c5bff09 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1109,25 +1109,32 @@ static bool intel_fbc_hw_tracking_covers_screen(const struct intel_plane_state * return effective_w <= max_w && effective_h <= max_h; } -static bool intel_fbc_plane_size_valid(const struct intel_plane_state *plane_state) +static void intel_fbc_max_plane_size(struct intel_display *display, + unsigned int *w, unsigned int *h) { - struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); struct drm_i915_private *i915 = to_i915(display->drm); - unsigned int w, h, max_w, max_h; if (DISPLAY_VER(display) >= 10) { - max_w = 5120; - max_h = 4096; + *w = 5120; + *h = 4096; } else if (DISPLAY_VER(display) >= 8 || IS_HASWELL(i915)) { - max_w = 4096; - max_h = 4096; + *w = 4096; + *h = 4096; } else if (IS_G4X(i915) || DISPLAY_VER(display) >= 5) { - max_w = 4096; - max_h = 2048; + *w = 4096; + *h = 2048; } else { - max_w = 2048; - max_h = 1536; + *w = 2048; + *h = 1536; } +} + +static bool intel_fbc_plane_size_valid(const struct intel_plane_state *plane_state) +{ + struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); + unsigned int w, h, max_w, max_h; + + intel_fbc_max_plane_size(display, &max_w, &max_h); w = drm_rect_width(&plane_state->uapi.src) >> 16; h = drm_rect_height(&plane_state->uapi.src) >> 16; -- cgit v1.2.3 From da9bbdb97469383a2ac97435a3b09543d14139fe Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Jul 2024 17:52:39 +0300 Subject: drm/i915/fbc: Extract intel_fbc_max_surface_size() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract intel_fbc_max_surface_size() from intel_fbc_hw_tracking_covers_screen(), mainly to mirror the "max plane size" counterparts. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240705145254.3355-6-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_fbc.c | 41 +++++++++++++++++++------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 05297c5bff09..bf655d6dc8ff 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1072,6 +1072,29 @@ static bool rotation_is_valid(const struct intel_plane_state *plane_state) return i8xx_fbc_rotation_is_valid(plane_state); } +static void intel_fbc_max_surface_size(struct intel_display *display, + unsigned int *w, unsigned int *h) +{ + struct drm_i915_private *i915 = to_i915(display->drm); + + if (DISPLAY_VER(display) >= 11) { + *w = 8192; + *h = 4096; + } else if (DISPLAY_VER(display) >= 10) { + *w = 5120; + *h = 4096; + } else if (DISPLAY_VER(display) >= 7) { + *w = 4096; + *h = 4096; + } else if (IS_G4X(i915) || DISPLAY_VER(display) >= 5) { + *w = 4096; + *h = 2048; + } else { + *w = 2048; + *h = 1536; + } +} + /* * For some reason, the hardware tracking starts looking at whatever we * programmed as the display plane base address register. It does not look at @@ -1081,25 +1104,9 @@ static bool rotation_is_valid(const struct intel_plane_state *plane_state) static bool intel_fbc_hw_tracking_covers_screen(const struct intel_plane_state *plane_state) { struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); - struct drm_i915_private *i915 = to_i915(display->drm); unsigned int effective_w, effective_h, max_w, max_h; - if (DISPLAY_VER(display) >= 11) { - max_w = 8192; - max_h = 4096; - } else if (DISPLAY_VER(display) >= 10) { - max_w = 5120; - max_h = 4096; - } else if (DISPLAY_VER(display) >= 7) { - max_w = 4096; - max_h = 4096; - } else if (IS_G4X(i915) || DISPLAY_VER(display) >= 5) { - max_w = 4096; - max_h = 2048; - } else { - max_w = 2048; - max_h = 1536; - } + intel_fbc_max_surface_size(display, &max_w, &max_h); effective_w = plane_state->view.color_plane[0].x + (drm_rect_width(&plane_state->uapi.src) >> 16); -- cgit v1.2.3 From 4c46e34e67587b268abc3916c9613426018561e6 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Jul 2024 17:52:40 +0300 Subject: drm/i915/fbc: s/intel_fbc_hw_tracking_covers_screen()/intel_fbc_surface_size_ok()/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename intel_fbc_hw_tracking_covers_screen() to intel_fbc_surface_size_ok() so that the naming scheme is the same for the surface size vs. plane size checks. "surface size" is what bspec talks about. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240705145254.3355-7-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_fbc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index bf655d6dc8ff..779e96dd3f6f 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1101,7 +1101,7 @@ static void intel_fbc_max_surface_size(struct intel_display *display, * the X and Y offset registers. That's why we include the src x/y offsets * instead of just looking at the plane size. */ -static bool intel_fbc_hw_tracking_covers_screen(const struct intel_plane_state *plane_state) +static bool intel_fbc_surface_size_ok(const struct intel_plane_state *plane_state) { struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); unsigned int effective_w, effective_h, max_w, max_h; @@ -1348,7 +1348,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, return 0; } - if (!intel_fbc_hw_tracking_covers_screen(plane_state)) { + if (!intel_fbc_surface_size_ok(plane_state)) { plane_state->no_fbc_reason = "surface size too big"; return 0; } -- cgit v1.2.3 From 94900000380300b230dc1bed489b598a2a2c55a1 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Jul 2024 17:52:41 +0300 Subject: drm/i915/fbc: Adjust g4x+ platform checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do the "is this ilk+ or g4x" checks in the customary order instead of the reverse order. Easier for the poor brain to parse this when it's always done the same way. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240705145254.3355-8-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_fbc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 779e96dd3f6f..6853573f8486 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1086,7 +1086,7 @@ static void intel_fbc_max_surface_size(struct intel_display *display, } else if (DISPLAY_VER(display) >= 7) { *w = 4096; *h = 4096; - } else if (IS_G4X(i915) || DISPLAY_VER(display) >= 5) { + } else if (DISPLAY_VER(display) >= 5 || IS_G4X(i915)) { *w = 4096; *h = 2048; } else { @@ -1127,7 +1127,7 @@ static void intel_fbc_max_plane_size(struct intel_display *display, } else if (DISPLAY_VER(display) >= 8 || IS_HASWELL(i915)) { *w = 4096; *h = 4096; - } else if (IS_G4X(i915) || DISPLAY_VER(display) >= 5) { + } else if (DISPLAY_VER(display) >= 5 || IS_G4X(i915)) { *w = 4096; *h = 2048; } else { -- cgit v1.2.3 From 6a1738b3fdd92d48e61de438d05dedbc00fc598f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Jul 2024 17:52:42 +0300 Subject: drm/i915/fbc: Extract _intel_fbc_cfb_stride() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull the lower level stuff out from intel_fbc_cfb_stride() into a separate function that doesn't depend on the plane_state. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240705145254.3355-9-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_fbc.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 6853573f8486..e9adb1b8b9a7 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -148,12 +148,11 @@ static unsigned int intel_fbc_plane_cfb_stride(const struct intel_plane_state *p } /* minimum acceptable cfb stride in bytes, assuming 1:1 compression limit */ -static unsigned int skl_fbc_min_cfb_stride(const struct intel_plane_state *plane_state) +static unsigned int skl_fbc_min_cfb_stride(struct intel_display *display, + unsigned int width) { - struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); unsigned int limit = 4; /* 1:4 compression limit is the worst case */ unsigned int cpp = 4; /* FBC always 4 bytes per pixel */ - unsigned int width = drm_rect_width(&plane_state->uapi.src) >> 16; unsigned int height = 4; /* FBC segment is 4 lines */ unsigned int stride; @@ -178,22 +177,29 @@ static unsigned int skl_fbc_min_cfb_stride(const struct intel_plane_state *plane } /* properly aligned cfb stride in bytes, assuming 1:1 compression limit */ -static unsigned int intel_fbc_cfb_stride(const struct intel_plane_state *plane_state) +static unsigned int _intel_fbc_cfb_stride(struct intel_display *display, + unsigned int width, unsigned int stride) { - struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); - unsigned int stride = intel_fbc_plane_cfb_stride(plane_state); - /* * At least some of the platforms require each 4 line segment to * be 512 byte aligned. Aligning each line to 512 bytes guarantees * that regardless of the compression limit we choose later. */ if (DISPLAY_VER(display) >= 9) - return max(ALIGN(stride, 512), skl_fbc_min_cfb_stride(plane_state)); + return max(ALIGN(stride, 512), skl_fbc_min_cfb_stride(display, width)); else return stride; } +static unsigned int intel_fbc_cfb_stride(const struct intel_plane_state *plane_state) +{ + struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); + unsigned int stride = intel_fbc_plane_cfb_stride(plane_state); + unsigned int width = drm_rect_width(&plane_state->uapi.src) >> 16; + + return _intel_fbc_cfb_stride(display, width, stride); +} + static unsigned int intel_fbc_cfb_size(const struct intel_plane_state *plane_state) { struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); -- cgit v1.2.3 From 566ad72ba636b745beb8a440bd4c05e779b95728 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Jul 2024 17:52:43 +0300 Subject: drm/i915/fbc: s/lines/height/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the more customary name 'height' instead of 'lines'. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240705145254.3355-10-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_fbc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index e9adb1b8b9a7..da54cb55906c 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -203,14 +203,14 @@ static unsigned int intel_fbc_cfb_stride(const struct intel_plane_state *plane_s static unsigned int intel_fbc_cfb_size(const struct intel_plane_state *plane_state) { struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); - int lines = drm_rect_height(&plane_state->uapi.src) >> 16; + int height = drm_rect_height(&plane_state->uapi.src) >> 16; if (DISPLAY_VER(display) == 7) - lines = min(lines, 2048); + height = min(height, 2048); else if (DISPLAY_VER(display) >= 8) - lines = min(lines, 2560); + height = min(height, 2560); - return lines * intel_fbc_cfb_stride(plane_state); + return height * intel_fbc_cfb_stride(plane_state); } static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state *plane_state) -- cgit v1.2.3 From 4290eaa8424905dcee4daa0666ec841dc3a0bfb3 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Jul 2024 17:52:44 +0300 Subject: drm/i915/fbc: Reoder CFB max height platform checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rearrange the max CFB max height platform into the more common "new first, old last" order. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240705145254.3355-11-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_fbc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index da54cb55906c..737e3c1e2304 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -205,10 +205,10 @@ static unsigned int intel_fbc_cfb_size(const struct intel_plane_state *plane_sta struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); int height = drm_rect_height(&plane_state->uapi.src) >> 16; - if (DISPLAY_VER(display) == 7) - height = min(height, 2048); - else if (DISPLAY_VER(display) >= 8) + if (DISPLAY_VER(display) >= 8) height = min(height, 2560); + else if (DISPLAY_VER(display) == 7) + height = min(height, 2048); return height * intel_fbc_cfb_stride(plane_state); } -- cgit v1.2.3 From f89d7664c3617836aecd291c56c8ab63fe228fbd Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Jul 2024 17:52:45 +0300 Subject: drm/i915/fbc: Extract intel_fbc_max_cfb_height() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull the code to determine the maximum CFB height into a separate function. To make this work we need to declare an explicit max height for all older platforms as well. But that is actually just the max plane height as pre-HSW hardware supposedly doesn't have the trick of leaving the extra lines uncompressed. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240705145254.3355-12-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_fbc.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 737e3c1e2304..4d83a7e92144 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -200,17 +200,30 @@ static unsigned int intel_fbc_cfb_stride(const struct intel_plane_state *plane_s return _intel_fbc_cfb_stride(display, width, stride); } -static unsigned int intel_fbc_cfb_size(const struct intel_plane_state *plane_state) +/* + * Maximum height the hardware will compress, on HSW+ + * additional lines (up to the actual plane height) will + * remain uncompressed. + */ +static unsigned int intel_fbc_max_cfb_height(struct intel_display *display) { - struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); - int height = drm_rect_height(&plane_state->uapi.src) >> 16; + struct drm_i915_private *i915 = to_i915(display->drm); if (DISPLAY_VER(display) >= 8) - height = min(height, 2560); - else if (DISPLAY_VER(display) == 7) - height = min(height, 2048); + return 2560; + else if (DISPLAY_VER(display) >= 5 || IS_G4X(i915)) + return 2048; + else + return 1536; +} + +static unsigned int intel_fbc_cfb_size(const struct intel_plane_state *plane_state) +{ + struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); + unsigned int height = drm_rect_height(&plane_state->uapi.src) >> 16; - return height * intel_fbc_cfb_stride(plane_state); + return min(height, intel_fbc_max_cfb_height(display)) * + intel_fbc_cfb_stride(plane_state); } static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state *plane_state) -- cgit v1.2.3 From 4d722029930bca7f53d99dbfc300a40dc297dee6 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Jul 2024 17:52:46 +0300 Subject: drm/i915/fbc: Extract _intel_fbc_cfb_size() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull the lower level stuff out from intel_fbc_cfb_size() into a separate function that doesn't depend on the plane_state. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240705145254.3355-13-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_fbc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 4d83a7e92144..bf4240cefe58 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -217,13 +217,18 @@ static unsigned int intel_fbc_max_cfb_height(struct intel_display *display) return 1536; } +static unsigned int _intel_fbc_cfb_size(struct intel_display *display, + unsigned int height, unsigned int stride) +{ + return min(height, intel_fbc_max_cfb_height(display)) * stride; +} + static unsigned int intel_fbc_cfb_size(const struct intel_plane_state *plane_state) { struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); unsigned int height = drm_rect_height(&plane_state->uapi.src) >> 16; - return min(height, intel_fbc_max_cfb_height(display)) * - intel_fbc_cfb_stride(plane_state); + return _intel_fbc_cfb_size(display, height, intel_fbc_cfb_stride(plane_state)); } static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state *plane_state) -- cgit v1.2.3 From d43caea1faf5c31dc02aa1adb8bb1aa1c33bf86f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Jul 2024 17:52:47 +0300 Subject: drm/i915/fbc: Extract intel_fbc_cfb_cpp() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract a helper to determine the CFB bytes per pixel value. Currently this is always 4, but that could change in the future. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240705145254.3355-14-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_fbc.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index bf4240cefe58..4c91a2b69a09 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -139,20 +139,24 @@ static unsigned int intel_fbc_plane_stride(const struct intel_plane_state *plane return stride; } +static unsigned int intel_fbc_cfb_cpp(void) +{ + return 4; /* FBC always 4 bytes per pixel */ +} + /* plane stride based cfb stride in bytes, assuming 1:1 compression limit */ static unsigned int intel_fbc_plane_cfb_stride(const struct intel_plane_state *plane_state) { - unsigned int cpp = 4; /* FBC always 4 bytes per pixel */ + unsigned int cpp = intel_fbc_cfb_cpp(); return intel_fbc_plane_stride(plane_state) * cpp; } /* minimum acceptable cfb stride in bytes, assuming 1:1 compression limit */ static unsigned int skl_fbc_min_cfb_stride(struct intel_display *display, - unsigned int width) + unsigned int cpp, unsigned int width) { unsigned int limit = 4; /* 1:4 compression limit is the worst case */ - unsigned int cpp = 4; /* FBC always 4 bytes per pixel */ unsigned int height = 4; /* FBC segment is 4 lines */ unsigned int stride; @@ -178,7 +182,8 @@ static unsigned int skl_fbc_min_cfb_stride(struct intel_display *display, /* properly aligned cfb stride in bytes, assuming 1:1 compression limit */ static unsigned int _intel_fbc_cfb_stride(struct intel_display *display, - unsigned int width, unsigned int stride) + unsigned int cpp, unsigned int width, + unsigned int stride) { /* * At least some of the platforms require each 4 line segment to @@ -186,7 +191,7 @@ static unsigned int _intel_fbc_cfb_stride(struct intel_display *display, * that regardless of the compression limit we choose later. */ if (DISPLAY_VER(display) >= 9) - return max(ALIGN(stride, 512), skl_fbc_min_cfb_stride(display, width)); + return max(ALIGN(stride, 512), skl_fbc_min_cfb_stride(display, cpp, width)); else return stride; } @@ -196,8 +201,9 @@ static unsigned int intel_fbc_cfb_stride(const struct intel_plane_state *plane_s struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); unsigned int stride = intel_fbc_plane_cfb_stride(plane_state); unsigned int width = drm_rect_width(&plane_state->uapi.src) >> 16; + unsigned int cpp = intel_fbc_cfb_cpp(); - return _intel_fbc_cfb_stride(display, width, stride); + return _intel_fbc_cfb_stride(display, cpp, width, stride); } /* -- cgit v1.2.3 From 43a6faa6d9b5e9139758200a79fe9c8f4aaa0c8d Mon Sep 17 00:00:00 2001 From: Ashutosh Dixit Date: Thu, 11 Jul 2024 14:12:03 -0700 Subject: drm/xe/exec: Fix minor bug related to xe_sync_entry_cleanup Increment num_syncs after xe_sync_entry_parse() is successful to ensure the xe_sync_entry_cleanup() logic under "err_syncs" label works correctly. v2: Use the same pattern as that in xe_vm.c (Matt Brost) Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs") Signed-off-by: Ashutosh Dixit Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20240711211203.3728180-1-ashutosh.dixit@intel.com --- drivers/gpu/drm/xe/xe_exec.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c index 2d72cdec3a0b..f36980aa26e6 100644 --- a/drivers/gpu/drm/xe/xe_exec.c +++ b/drivers/gpu/drm/xe/xe_exec.c @@ -118,7 +118,7 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file) u64 addresses[XE_HW_ENGINE_MAX_INSTANCE]; struct drm_gpuvm_exec vm_exec = {.extra.fn = xe_exec_fn}; struct drm_exec *exec = &vm_exec.exec; - u32 i, num_syncs = 0, num_ufence = 0; + u32 i, num_syncs, num_ufence = 0; struct xe_sched_job *job; struct xe_vm *vm; bool write_locked, skip_retry = false; @@ -156,15 +156,15 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file) vm = q->vm; - for (i = 0; i < args->num_syncs; i++) { - err = xe_sync_entry_parse(xe, xef, &syncs[num_syncs++], - &syncs_user[i], SYNC_PARSE_FLAG_EXEC | + for (num_syncs = 0; num_syncs < args->num_syncs; num_syncs++) { + err = xe_sync_entry_parse(xe, xef, &syncs[num_syncs], + &syncs_user[num_syncs], SYNC_PARSE_FLAG_EXEC | (xe_vm_in_lr_mode(vm) ? SYNC_PARSE_FLAG_LR_MODE : 0)); if (err) goto err_syncs; - if (xe_sync_is_ufence(&syncs[i])) + if (xe_sync_is_ufence(&syncs[num_syncs])) num_ufence++; } @@ -325,8 +325,8 @@ err_unlock_list: if (err == -EAGAIN && !skip_retry) goto retry; err_syncs: - for (i = 0; i < num_syncs; i++) - xe_sync_entry_cleanup(&syncs[i]); + while (num_syncs--) + xe_sync_entry_cleanup(&syncs[num_syncs]); kfree(syncs); err_exec_queue: xe_exec_queue_put(q); -- cgit v1.2.3 From 6f1cacf4eba7a3203f08954a7e00b744e43f741c Mon Sep 17 00:00:00 2001 From: Philipp Stanner Date: Fri, 12 Jul 2024 08:26:18 +0200 Subject: drm/nouveau: Improve variable name in nouveau_sched_init() nouveau_sched_init() uses the function drm_sched_init(). The latter function has parameters called "hang_limit" and "timeout" in its API documentation. nouveau_sched_init(), however, defines a variable called "job_hang_limit" which is passed to drm_sched_init()'s "timeout" parameter. The actual "hang_limit" parameter is directly set to 0. Rename "job_hang_limit" to "timeout". Signed-off-by: Philipp Stanner Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20240712062618.8057-1-pstanner@redhat.com --- drivers/gpu/drm/nouveau/nouveau_sched.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.c b/drivers/gpu/drm/nouveau/nouveau_sched.c index 32fa2e273965..ba4139288a6d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sched.c +++ b/drivers/gpu/drm/nouveau/nouveau_sched.c @@ -404,7 +404,7 @@ nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm, { struct drm_gpu_scheduler *drm_sched = &sched->base; struct drm_sched_entity *entity = &sched->entity; - long job_hang_limit = msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); + const long timeout = msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); int ret; if (!wq) { @@ -418,7 +418,7 @@ nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm, ret = drm_sched_init(drm_sched, &nouveau_sched_ops, wq, NOUVEAU_SCHED_PRIORITY_COUNT, - credit_limit, 0, job_hang_limit, + credit_limit, 0, timeout, NULL, NULL, "nouveau_sched", drm->dev->dev); if (ret) goto fail_wq; -- cgit v1.2.3 From 4c3fe5eae46b92e2fd961b19f7779608352e5368 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 11 Jul 2024 21:23:19 +0200 Subject: drm/xe/pf: Limit fair VF LMEM provisioning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to the current design of the BO and VRAM manager, any object with XE_BO_FLAG_PINNED flag, which the PF driver uses during VF LMEM provisionining, is created with the TTM_PL_FLAG_CONTIGUOUS flag, which may cause VRAM fragmentation that prevents subsequent allocations of larger objects, like fair VF LMEM provisioning. To avoid such failures, round down fair VF LMEM provisioning size to next power of two size, to compensate what xe_ttm_vram_mgr is doing to achieve contiguous allocations. Fixes: ac6598aed1b3 ("drm/xe/pf: Add support to configure SR-IOV VFs") Signed-off-by: Michal Wajdeczko Reviewed-by: Piotr Piórkowski Reviewed-by: Jonathan Cavitt Link: https://patchwork.freedesktop.org/patch/msgid/20240711192320.1198-2-michal.wajdeczko@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index db6c213da847..4699b7836001 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -1543,6 +1543,7 @@ static u64 pf_estimate_fair_lmem(struct xe_gt *gt, unsigned int num_vfs) u64 fair; fair = div_u64(available, num_vfs); + fair = rounddown_pow_of_two(fair); /* XXX: ttm_vram_mgr & drm_buddy limitation */ fair = ALIGN_DOWN(fair, alignment); #ifdef MAX_FAIR_LMEM fair = min_t(u64, MAX_FAIR_LMEM, fair); -- cgit v1.2.3 From 86c5b70a9c0c3f05f7002ef8b789460c96b54e27 Mon Sep 17 00:00:00 2001 From: Tejas Upadhyay Date: Tue, 9 Jul 2024 21:26:06 +0530 Subject: drm/xe/xe2: Add Wa_15015404425 Wa_15015404425 asks us to perform four "dummy" writes to a non-existent register offset before every real register read. Although the specific offset of the writes doesn't directly matter, the workaround suggests offset 0x130030 as a good target so that these writes will be easy to recognize and filter out in debugging traces. V5(MattR): - Avoid negating an equality comparison V4(MattR): - Use writel and remove xe_reg usage V3(MattR): - Define dummy reg local to function - Avoid tracing dummy writes - Update commit message V2: - Add WA to 8/16/32bit reads also - MattR - Corrected dummy reg address - MattR - Use for loop to avoid mental pause - JaniN Reviewed-by: Matt Roper Signed-off-by: Tejas Upadhyay Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20240709155606.2998941-1-tejas.upadhyay@intel.com --- drivers/gpu/drm/xe/xe_mmio.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c index f92faad4b96d..cf622d07e190 100644 --- a/drivers/gpu/drm/xe/xe_mmio.c +++ b/drivers/gpu/drm/xe/xe_mmio.c @@ -121,12 +121,29 @@ int xe_mmio_init(struct xe_device *xe) return devm_add_action_or_reset(xe->drm.dev, mmio_fini, xe); } +static void mmio_flush_pending_writes(struct xe_gt *gt) +{ +#define DUMMY_REG_OFFSET 0x130030 + struct xe_tile *tile = gt_to_tile(gt); + int i; + + if (tile->xe->info.platform != XE_LUNARLAKE) + return; + + /* 4 dummy writes */ + for (i = 0; i < 4; i++) + writel(0, tile->mmio.regs + DUMMY_REG_OFFSET); +} + u8 xe_mmio_read8(struct xe_gt *gt, struct xe_reg reg) { struct xe_tile *tile = gt_to_tile(gt); u32 addr = xe_mmio_adjusted_addr(gt, reg.addr); u8 val; + /* Wa_15015404425 */ + mmio_flush_pending_writes(gt); + val = readb((reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr); trace_xe_reg_rw(gt, false, addr, val, sizeof(val)); @@ -139,6 +156,9 @@ u16 xe_mmio_read16(struct xe_gt *gt, struct xe_reg reg) u32 addr = xe_mmio_adjusted_addr(gt, reg.addr); u16 val; + /* Wa_15015404425 */ + mmio_flush_pending_writes(gt); + val = readw((reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr); trace_xe_reg_rw(gt, false, addr, val, sizeof(val)); @@ -160,6 +180,9 @@ u32 xe_mmio_read32(struct xe_gt *gt, struct xe_reg reg) u32 addr = xe_mmio_adjusted_addr(gt, reg.addr); u32 val; + /* Wa_15015404425 */ + mmio_flush_pending_writes(gt); + if (!reg.vf && IS_SRIOV_VF(gt_to_xe(gt))) val = xe_gt_sriov_vf_read32(gt, reg); else -- cgit v1.2.3 From f32b5128d2c440368b5bf3a7a356823e235caabb Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 11 Jul 2024 14:53:30 +0100 Subject: drm/v3d: Prevent out of bounds access in performance query extensions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check that the number of perfmons userspace is passing in the copy and reset extensions is not greater than the internal kernel storage where the ids will be copied into. Signed-off-by: Tvrtko Ursulin Fixes: bae7cb5d6800 ("drm/v3d: Create a CPU job extension for the reset performance query job") Cc: Maíra Canal Cc: Iago Toral Quiroga Cc: stable@vger.kernel.org # v6.8+ Reviewed-by: Iago Toral Quiroga Reviewed-by: Maíra Canal Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20240711135340.84617-2-tursulin@igalia.com --- drivers/gpu/drm/v3d/v3d_submit.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c index 88f63d526b22..263fefc1d04f 100644 --- a/drivers/gpu/drm/v3d/v3d_submit.c +++ b/drivers/gpu/drm/v3d/v3d_submit.c @@ -637,6 +637,9 @@ v3d_get_cpu_reset_performance_params(struct drm_file *file_priv, if (copy_from_user(&reset, ext, sizeof(reset))) return -EFAULT; + if (reset.nperfmons > V3D_MAX_PERFMONS) + return -EINVAL; + job->job_type = V3D_CPU_JOB_TYPE_RESET_PERFORMANCE_QUERY; job->performance_query.queries = kvmalloc_array(reset.count, @@ -708,6 +711,9 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, if (copy.pad) return -EINVAL; + if (copy.nperfmons > V3D_MAX_PERFMONS) + return -EINVAL; + job->job_type = V3D_CPU_JOB_TYPE_COPY_PERFORMANCE_QUERY; job->performance_query.queries = kvmalloc_array(copy.count, -- cgit v1.2.3 From 753ce4fea62182c77e1691ab4f9022008f25b62e Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 11 Jul 2024 14:53:31 +0100 Subject: drm/v3d: Fix potential memory leak in the timestamp extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If fetching of userspace memory fails during the main loop, all drm sync objs looked up until that point will be leaked because of the missing drm_syncobj_put. Fix it by exporting and using a common cleanup helper. Signed-off-by: Tvrtko Ursulin Fixes: 9ba0ff3e083f ("drm/v3d: Create a CPU job extension for the timestamp query job") Cc: Maíra Canal Cc: Iago Toral Quiroga Cc: stable@vger.kernel.org # v6.8+ Reviewed-by: Maíra Canal Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20240711135340.84617-3-tursulin@igalia.com --- drivers/gpu/drm/v3d/v3d_drv.h | 2 ++ drivers/gpu/drm/v3d/v3d_sched.c | 22 ++++++++++++++------ drivers/gpu/drm/v3d/v3d_submit.c | 43 ++++++++++++++++++++++++++++------------ 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index 099b962bdfde..e208ffdfba32 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -563,6 +563,8 @@ void v3d_mmu_insert_ptes(struct v3d_bo *bo); void v3d_mmu_remove_ptes(struct v3d_bo *bo); /* v3d_sched.c */ +void v3d_timestamp_query_info_free(struct v3d_timestamp_query_info *query_info, + unsigned int count); void v3d_job_update_stats(struct v3d_job *job, enum v3d_queue queue); int v3d_sched_init(struct v3d_dev *v3d); void v3d_sched_fini(struct v3d_dev *v3d); diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index 03df37a3acf5..59dc0287dab9 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -73,18 +73,28 @@ v3d_sched_job_free(struct drm_sched_job *sched_job) v3d_job_cleanup(job); } +void +v3d_timestamp_query_info_free(struct v3d_timestamp_query_info *query_info, + unsigned int count) +{ + if (query_info->queries) { + unsigned int i; + + for (i = 0; i < count; i++) + drm_syncobj_put(query_info->queries[i].syncobj); + + kvfree(query_info->queries); + } +} + static void v3d_cpu_job_free(struct drm_sched_job *sched_job) { struct v3d_cpu_job *job = to_cpu_job(sched_job); - struct v3d_timestamp_query_info *timestamp_query = &job->timestamp_query; struct v3d_performance_query_info *performance_query = &job->performance_query; - if (timestamp_query->queries) { - for (int i = 0; i < timestamp_query->count; i++) - drm_syncobj_put(timestamp_query->queries[i].syncobj); - kvfree(timestamp_query->queries); - } + v3d_timestamp_query_info_free(&job->timestamp_query, + job->timestamp_query.count); if (performance_query->queries) { for (int i = 0; i < performance_query->count; i++) diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c index 263fefc1d04f..121bf1314b80 100644 --- a/drivers/gpu/drm/v3d/v3d_submit.c +++ b/drivers/gpu/drm/v3d/v3d_submit.c @@ -452,6 +452,8 @@ v3d_get_cpu_timestamp_query_params(struct drm_file *file_priv, { u32 __user *offsets, *syncs; struct drm_v3d_timestamp_query timestamp; + unsigned int i; + int err; if (!job) { DRM_DEBUG("CPU job extension was attached to a GPU job.\n"); @@ -480,19 +482,19 @@ v3d_get_cpu_timestamp_query_params(struct drm_file *file_priv, offsets = u64_to_user_ptr(timestamp.offsets); syncs = u64_to_user_ptr(timestamp.syncs); - for (int i = 0; i < timestamp.count; i++) { + for (i = 0; i < timestamp.count; i++) { u32 offset, sync; if (copy_from_user(&offset, offsets++, sizeof(offset))) { - kvfree(job->timestamp_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } job->timestamp_query.queries[i].offset = offset; if (copy_from_user(&sync, syncs++, sizeof(sync))) { - kvfree(job->timestamp_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); @@ -500,6 +502,10 @@ v3d_get_cpu_timestamp_query_params(struct drm_file *file_priv, job->timestamp_query.count = timestamp.count; return 0; + +error: + v3d_timestamp_query_info_free(&job->timestamp_query, i); + return err; } static int @@ -509,6 +515,8 @@ v3d_get_cpu_reset_timestamp_params(struct drm_file *file_priv, { u32 __user *syncs; struct drm_v3d_reset_timestamp_query reset; + unsigned int i; + int err; if (!job) { DRM_DEBUG("CPU job extension was attached to a GPU job.\n"); @@ -533,14 +541,14 @@ v3d_get_cpu_reset_timestamp_params(struct drm_file *file_priv, syncs = u64_to_user_ptr(reset.syncs); - for (int i = 0; i < reset.count; i++) { + for (i = 0; i < reset.count; i++) { u32 sync; job->timestamp_query.queries[i].offset = reset.offset + 8 * i; if (copy_from_user(&sync, syncs++, sizeof(sync))) { - kvfree(job->timestamp_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); @@ -548,6 +556,10 @@ v3d_get_cpu_reset_timestamp_params(struct drm_file *file_priv, job->timestamp_query.count = reset.count; return 0; + +error: + v3d_timestamp_query_info_free(&job->timestamp_query, i); + return err; } /* Get data for the copy timestamp query results job submission. */ @@ -558,7 +570,8 @@ v3d_get_cpu_copy_query_results_params(struct drm_file *file_priv, { u32 __user *offsets, *syncs; struct drm_v3d_copy_timestamp_query copy; - int i; + unsigned int i; + int err; if (!job) { DRM_DEBUG("CPU job extension was attached to a GPU job.\n"); @@ -591,15 +604,15 @@ v3d_get_cpu_copy_query_results_params(struct drm_file *file_priv, u32 offset, sync; if (copy_from_user(&offset, offsets++, sizeof(offset))) { - kvfree(job->timestamp_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } job->timestamp_query.queries[i].offset = offset; if (copy_from_user(&sync, syncs++, sizeof(sync))) { - kvfree(job->timestamp_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); @@ -613,6 +626,10 @@ v3d_get_cpu_copy_query_results_params(struct drm_file *file_priv, job->copy.stride = copy.stride; return 0; + +error: + v3d_timestamp_query_info_free(&job->timestamp_query, i); + return err; } static int -- cgit v1.2.3 From 484de39fa5f5b7bd0c5f2e2c5265167250ef7501 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 11 Jul 2024 14:53:32 +0100 Subject: drm/v3d: Fix potential memory leak in the performance extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If fetching of userspace memory fails during the main loop, all drm sync objs looked up until that point will be leaked because of the missing drm_syncobj_put. Fix it by exporting and using a common cleanup helper. Signed-off-by: Tvrtko Ursulin Fixes: bae7cb5d6800 ("drm/v3d: Create a CPU job extension for the reset performance query job") Cc: Maíra Canal Cc: Iago Toral Quiroga Cc: stable@vger.kernel.org # v6.8+ Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20240711135340.84617-4-tursulin@igalia.com --- drivers/gpu/drm/v3d/v3d_drv.h | 2 ++ drivers/gpu/drm/v3d/v3d_sched.c | 22 ++++++++++++----- drivers/gpu/drm/v3d/v3d_submit.c | 52 ++++++++++++++++++++++++---------------- 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index e208ffdfba32..dd3ead4cb8bd 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -565,6 +565,8 @@ void v3d_mmu_remove_ptes(struct v3d_bo *bo); /* v3d_sched.c */ void v3d_timestamp_query_info_free(struct v3d_timestamp_query_info *query_info, unsigned int count); +void v3d_performance_query_info_free(struct v3d_performance_query_info *query_info, + unsigned int count); void v3d_job_update_stats(struct v3d_job *job, enum v3d_queue queue); int v3d_sched_init(struct v3d_dev *v3d); void v3d_sched_fini(struct v3d_dev *v3d); diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index 59dc0287dab9..5fbbee47c6b7 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -87,20 +87,30 @@ v3d_timestamp_query_info_free(struct v3d_timestamp_query_info *query_info, } } +void +v3d_performance_query_info_free(struct v3d_performance_query_info *query_info, + unsigned int count) +{ + if (query_info->queries) { + unsigned int i; + + for (i = 0; i < count; i++) + drm_syncobj_put(query_info->queries[i].syncobj); + + kvfree(query_info->queries); + } +} + static void v3d_cpu_job_free(struct drm_sched_job *sched_job) { struct v3d_cpu_job *job = to_cpu_job(sched_job); - struct v3d_performance_query_info *performance_query = &job->performance_query; v3d_timestamp_query_info_free(&job->timestamp_query, job->timestamp_query.count); - if (performance_query->queries) { - for (int i = 0; i < performance_query->count; i++) - drm_syncobj_put(performance_query->queries[i].syncobj); - kvfree(performance_query->queries); - } + v3d_performance_query_info_free(&job->performance_query, + job->performance_query.count); v3d_job_cleanup(&job->base); } diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c index 121bf1314b80..50be4e8a7512 100644 --- a/drivers/gpu/drm/v3d/v3d_submit.c +++ b/drivers/gpu/drm/v3d/v3d_submit.c @@ -640,6 +640,8 @@ v3d_get_cpu_reset_performance_params(struct drm_file *file_priv, u32 __user *syncs; u64 __user *kperfmon_ids; struct drm_v3d_reset_performance_query reset; + unsigned int i, j; + int err; if (!job) { DRM_DEBUG("CPU job extension was attached to a GPU job.\n"); @@ -668,39 +670,43 @@ v3d_get_cpu_reset_performance_params(struct drm_file *file_priv, syncs = u64_to_user_ptr(reset.syncs); kperfmon_ids = u64_to_user_ptr(reset.kperfmon_ids); - for (int i = 0; i < reset.count; i++) { + for (i = 0; i < reset.count; i++) { u32 sync; u64 ids; u32 __user *ids_pointer; u32 id; if (copy_from_user(&sync, syncs++, sizeof(sync))) { - kvfree(job->performance_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } - job->performance_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); - if (copy_from_user(&ids, kperfmon_ids++, sizeof(ids))) { - kvfree(job->performance_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } ids_pointer = u64_to_user_ptr(ids); - for (int j = 0; j < reset.nperfmons; j++) { + for (j = 0; j < reset.nperfmons; j++) { if (copy_from_user(&id, ids_pointer++, sizeof(id))) { - kvfree(job->performance_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } job->performance_query.queries[i].kperfmon_ids[j] = id; } + + job->performance_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); } job->performance_query.count = reset.count; job->performance_query.nperfmons = reset.nperfmons; return 0; + +error: + v3d_performance_query_info_free(&job->performance_query, i); + return err; } static int @@ -711,6 +717,8 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, u32 __user *syncs; u64 __user *kperfmon_ids; struct drm_v3d_copy_performance_query copy; + unsigned int i, j; + int err; if (!job) { DRM_DEBUG("CPU job extension was attached to a GPU job.\n"); @@ -742,34 +750,34 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, syncs = u64_to_user_ptr(copy.syncs); kperfmon_ids = u64_to_user_ptr(copy.kperfmon_ids); - for (int i = 0; i < copy.count; i++) { + for (i = 0; i < copy.count; i++) { u32 sync; u64 ids; u32 __user *ids_pointer; u32 id; if (copy_from_user(&sync, syncs++, sizeof(sync))) { - kvfree(job->performance_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } - job->performance_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); - if (copy_from_user(&ids, kperfmon_ids++, sizeof(ids))) { - kvfree(job->performance_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } ids_pointer = u64_to_user_ptr(ids); - for (int j = 0; j < copy.nperfmons; j++) { + for (j = 0; j < copy.nperfmons; j++) { if (copy_from_user(&id, ids_pointer++, sizeof(id))) { - kvfree(job->performance_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } job->performance_query.queries[i].kperfmon_ids[j] = id; } + + job->performance_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); } job->performance_query.count = copy.count; job->performance_query.nperfmons = copy.nperfmons; @@ -782,6 +790,10 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, job->copy.stride = copy.stride; return 0; + +error: + v3d_performance_query_info_free(&job->performance_query, i); + return err; } /* Whenever userspace sets ioctl extensions, v3d_get_extensions parses data -- cgit v1.2.3 From 8d1276d1b8f738c3afe1457d4dff5cc66fc848a3 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 11 Jul 2024 14:53:33 +0100 Subject: drm/v3d: Validate passed in drm syncobj handles in the timestamp extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If userspace provides an unknown or invalid handle anywhere in the handle array the rest of the driver will not handle that well. Fix it by checking handle was looked up successfully or otherwise fail the extension by jumping into the existing unwind. Signed-off-by: Tvrtko Ursulin Fixes: 9ba0ff3e083f ("drm/v3d: Create a CPU job extension for the timestamp query job") Cc: Maíra Canal Cc: Iago Toral Quiroga Cc: stable@vger.kernel.org # v6.8+ Reviewed-by: Maíra Canal Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20240711135340.84617-5-tursulin@igalia.com --- drivers/gpu/drm/v3d/v3d_submit.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c index 50be4e8a7512..9a3e32075ebe 100644 --- a/drivers/gpu/drm/v3d/v3d_submit.c +++ b/drivers/gpu/drm/v3d/v3d_submit.c @@ -498,6 +498,10 @@ v3d_get_cpu_timestamp_query_params(struct drm_file *file_priv, } job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); + if (!job->timestamp_query.queries[i].syncobj) { + err = -ENOENT; + goto error; + } } job->timestamp_query.count = timestamp.count; @@ -552,6 +556,10 @@ v3d_get_cpu_reset_timestamp_params(struct drm_file *file_priv, } job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); + if (!job->timestamp_query.queries[i].syncobj) { + err = -ENOENT; + goto error; + } } job->timestamp_query.count = reset.count; @@ -616,6 +624,10 @@ v3d_get_cpu_copy_query_results_params(struct drm_file *file_priv, } job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); + if (!job->timestamp_query.queries[i].syncobj) { + err = -ENOENT; + goto error; + } } job->timestamp_query.count = copy.count; -- cgit v1.2.3 From a546b7e4d73c23838d7e4d2c92882b3ca902d213 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 11 Jul 2024 14:53:34 +0100 Subject: drm/v3d: Validate passed in drm syncobj handles in the performance extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If userspace provides an unknown or invalid handle anywhere in the handle array the rest of the driver will not handle that well. Fix it by checking handle was looked up successfully or otherwise fail the extension by jumping into the existing unwind. Signed-off-by: Tvrtko Ursulin Fixes: bae7cb5d6800 ("drm/v3d: Create a CPU job extension for the reset performance query job") Cc: Maíra Canal Cc: Iago Toral Quiroga Cc: stable@vger.kernel.org # v6.8+ Reviewed-by: Maíra Canal Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20240711135340.84617-6-tursulin@igalia.com --- drivers/gpu/drm/v3d/v3d_submit.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c index 9a3e32075ebe..4cdfabbf4964 100644 --- a/drivers/gpu/drm/v3d/v3d_submit.c +++ b/drivers/gpu/drm/v3d/v3d_submit.c @@ -710,6 +710,10 @@ v3d_get_cpu_reset_performance_params(struct drm_file *file_priv, } job->performance_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); + if (!job->performance_query.queries[i].syncobj) { + err = -ENOENT; + goto error; + } } job->performance_query.count = reset.count; job->performance_query.nperfmons = reset.nperfmons; @@ -790,6 +794,10 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, } job->performance_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); + if (!job->performance_query.queries[i].syncobj) { + err = -ENOENT; + goto error; + } } job->performance_query.count = copy.count; job->performance_query.nperfmons = copy.nperfmons; -- cgit v1.2.3 From 4bd75a81e61ab691154a83068a694c9af44e2dd6 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 11 Jul 2024 14:53:35 +0100 Subject: drm/v3d: Move part of copying of reset/copy performance extension to a helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The loop which looks up the syncobj and copies the kperfmon ids is identical so lets move it to a helper. The only change is replacing copy_from_user with get_user when copying a scalar. Signed-off-by: Tvrtko Ursulin Reviewed-by: Maíra Canal Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20240711135340.84617-7-tursulin@igalia.com --- drivers/gpu/drm/v3d/v3d_submit.c | 152 ++++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 84 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c index 4cdfabbf4964..ce56e31a027d 100644 --- a/drivers/gpu/drm/v3d/v3d_submit.c +++ b/drivers/gpu/drm/v3d/v3d_submit.c @@ -644,15 +644,64 @@ error: return err; } +static int +v3d_copy_query_info(struct v3d_performance_query_info *query_info, + unsigned int count, + unsigned int nperfmons, + u32 __user *syncs, + u64 __user *kperfmon_ids, + struct drm_file *file_priv) +{ + unsigned int i, j; + int err; + + for (i = 0; i < count; i++) { + struct v3d_performance_query *query = &query_info->queries[i]; + u32 __user *ids_pointer; + u32 sync, id; + u64 ids; + + if (get_user(sync, syncs++)) { + err = -EFAULT; + goto error; + } + + if (get_user(ids, kperfmon_ids++)) { + err = -EFAULT; + goto error; + } + + ids_pointer = u64_to_user_ptr(ids); + + for (j = 0; j < nperfmons; j++) { + if (get_user(id, ids_pointer++)) { + err = -EFAULT; + goto error; + } + + query->kperfmon_ids[j] = id; + } + + query->syncobj = drm_syncobj_find(file_priv, sync); + if (!query->syncobj) { + err = -ENOENT; + goto error; + } + } + + return 0; + +error: + v3d_performance_query_info_free(query_info, i); + return err; +} + static int v3d_get_cpu_reset_performance_params(struct drm_file *file_priv, struct drm_v3d_extension __user *ext, struct v3d_cpu_job *job) { - u32 __user *syncs; - u64 __user *kperfmon_ids; struct drm_v3d_reset_performance_query reset; - unsigned int i, j; int err; if (!job) { @@ -679,50 +728,19 @@ v3d_get_cpu_reset_performance_params(struct drm_file *file_priv, if (!job->performance_query.queries) return -ENOMEM; - syncs = u64_to_user_ptr(reset.syncs); - kperfmon_ids = u64_to_user_ptr(reset.kperfmon_ids); - - for (i = 0; i < reset.count; i++) { - u32 sync; - u64 ids; - u32 __user *ids_pointer; - u32 id; + err = v3d_copy_query_info(&job->performance_query, + reset.count, + reset.nperfmons, + u64_to_user_ptr(reset.syncs), + u64_to_user_ptr(reset.kperfmon_ids), + file_priv); + if (err) + return err; - if (copy_from_user(&sync, syncs++, sizeof(sync))) { - err = -EFAULT; - goto error; - } - - if (copy_from_user(&ids, kperfmon_ids++, sizeof(ids))) { - err = -EFAULT; - goto error; - } - - ids_pointer = u64_to_user_ptr(ids); - - for (j = 0; j < reset.nperfmons; j++) { - if (copy_from_user(&id, ids_pointer++, sizeof(id))) { - err = -EFAULT; - goto error; - } - - job->performance_query.queries[i].kperfmon_ids[j] = id; - } - - job->performance_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); - if (!job->performance_query.queries[i].syncobj) { - err = -ENOENT; - goto error; - } - } job->performance_query.count = reset.count; job->performance_query.nperfmons = reset.nperfmons; return 0; - -error: - v3d_performance_query_info_free(&job->performance_query, i); - return err; } static int @@ -730,10 +748,7 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, struct drm_v3d_extension __user *ext, struct v3d_cpu_job *job) { - u32 __user *syncs; - u64 __user *kperfmon_ids; struct drm_v3d_copy_performance_query copy; - unsigned int i, j; int err; if (!job) { @@ -763,42 +778,15 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, if (!job->performance_query.queries) return -ENOMEM; - syncs = u64_to_user_ptr(copy.syncs); - kperfmon_ids = u64_to_user_ptr(copy.kperfmon_ids); - - for (i = 0; i < copy.count; i++) { - u32 sync; - u64 ids; - u32 __user *ids_pointer; - u32 id; - - if (copy_from_user(&sync, syncs++, sizeof(sync))) { - err = -EFAULT; - goto error; - } + err = v3d_copy_query_info(&job->performance_query, + copy.count, + copy.nperfmons, + u64_to_user_ptr(copy.syncs), + u64_to_user_ptr(copy.kperfmon_ids), + file_priv); + if (err) + return err; - if (copy_from_user(&ids, kperfmon_ids++, sizeof(ids))) { - err = -EFAULT; - goto error; - } - - ids_pointer = u64_to_user_ptr(ids); - - for (j = 0; j < copy.nperfmons; j++) { - if (copy_from_user(&id, ids_pointer++, sizeof(id))) { - err = -EFAULT; - goto error; - } - - job->performance_query.queries[i].kperfmon_ids[j] = id; - } - - job->performance_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); - if (!job->performance_query.queries[i].syncobj) { - err = -ENOENT; - goto error; - } - } job->performance_query.count = copy.count; job->performance_query.nperfmons = copy.nperfmons; job->performance_query.ncounters = copy.ncounters; @@ -810,10 +798,6 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, job->copy.stride = copy.stride; return 0; - -error: - v3d_performance_query_info_free(&job->performance_query, i); - return err; } /* Whenever userspace sets ioctl extensions, v3d_get_extensions parses data -- cgit v1.2.3 From c9d6630f7c67a5c6cc2ba90f1abbd0dff7d8eca9 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 11 Jul 2024 14:53:36 +0100 Subject: drm/v3d: Size the kperfmon_ids array at runtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of statically reserving pessimistic space for the kperfmon_ids array, make the userspace extension code allocate the exactly required amount of space. Apart from saving some memory at runtime, this also removes the need for the V3D_MAX_PERFMONS macro whose removal will benefit further driver cleanup. Signed-off-by: Tvrtko Ursulin Reviewed-by: Maíra Canal Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20240711135340.84617-8-tursulin@igalia.com --- drivers/gpu/drm/v3d/v3d_drv.h | 6 +----- drivers/gpu/drm/v3d/v3d_sched.c | 4 +++- drivers/gpu/drm/v3d/v3d_submit.c | 17 +++++++++++------ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index dd3ead4cb8bd..b1dfec49ba7d 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -351,13 +351,9 @@ struct v3d_timestamp_query { struct drm_syncobj *syncobj; }; -/* Number of perfmons required to handle all supported performance counters */ -#define V3D_MAX_PERFMONS DIV_ROUND_UP(V3D_MAX_COUNTERS, \ - DRM_V3D_MAX_PERF_COUNTERS) - struct v3d_performance_query { /* Performance monitor IDs for this query */ - u32 kperfmon_ids[V3D_MAX_PERFMONS]; + u32 *kperfmon_ids; /* Syncobj that indicates the query availability */ struct drm_syncobj *syncobj; diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index 5fbbee47c6b7..7b2195ba4248 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -94,8 +94,10 @@ v3d_performance_query_info_free(struct v3d_performance_query_info *query_info, if (query_info->queries) { unsigned int i; - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { drm_syncobj_put(query_info->queries[i].syncobj); + kvfree(query_info->queries[i].kperfmon_ids); + } kvfree(query_info->queries); } diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c index ce56e31a027d..d1060e60aafa 100644 --- a/drivers/gpu/drm/v3d/v3d_submit.c +++ b/drivers/gpu/drm/v3d/v3d_submit.c @@ -671,10 +671,20 @@ v3d_copy_query_info(struct v3d_performance_query_info *query_info, goto error; } + query->kperfmon_ids = + kvmalloc_array(nperfmons, + sizeof(struct v3d_performance_query *), + GFP_KERNEL); + if (!query->kperfmon_ids) { + err = -ENOMEM; + goto error; + } + ids_pointer = u64_to_user_ptr(ids); for (j = 0; j < nperfmons; j++) { if (get_user(id, ids_pointer++)) { + kvfree(query->kperfmon_ids); err = -EFAULT; goto error; } @@ -684,6 +694,7 @@ v3d_copy_query_info(struct v3d_performance_query_info *query_info, query->syncobj = drm_syncobj_find(file_priv, sync); if (!query->syncobj) { + kvfree(query->kperfmon_ids); err = -ENOENT; goto error; } @@ -717,9 +728,6 @@ v3d_get_cpu_reset_performance_params(struct drm_file *file_priv, if (copy_from_user(&reset, ext, sizeof(reset))) return -EFAULT; - if (reset.nperfmons > V3D_MAX_PERFMONS) - return -EINVAL; - job->job_type = V3D_CPU_JOB_TYPE_RESET_PERFORMANCE_QUERY; job->performance_query.queries = kvmalloc_array(reset.count, @@ -767,9 +775,6 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, if (copy.pad) return -EINVAL; - if (copy.nperfmons > V3D_MAX_PERFMONS) - return -EINVAL; - job->job_type = V3D_CPU_JOB_TYPE_COPY_PERFORMANCE_QUERY; job->performance_query.queries = kvmalloc_array(copy.count, -- cgit v1.2.3 From 1be825c5c060b6239f7c8ef45880f885f9dba056 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 11 Jul 2024 14:53:37 +0100 Subject: drm/v3d: Do not use intermediate storage when copying performance query results MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removing the intermediate buffer removes the last use of the V3D_MAX_COUNTERS define, which will enable further driver cleanup. While at it pull the 32 vs 64 bit copying decision outside the loop in order to reduce the number of conditional instructions. Signed-off-by: Tvrtko Ursulin Reviewed-by: Iago Toral Quiroga Reviewed-by: Maíra Canal Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20240711135340.84617-9-tursulin@igalia.com --- drivers/gpu/drm/v3d/v3d_sched.c | 57 ++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index 7b2195ba4248..d193072703f3 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -421,18 +421,23 @@ v3d_reset_timestamp_queries(struct v3d_cpu_job *job) v3d_put_bo_vaddr(bo); } -static void -write_to_buffer(void *dst, u32 idx, bool do_64bit, u64 value) +static void write_to_buffer_32(u32 *dst, unsigned int idx, u32 value) { - if (do_64bit) { - u64 *dst64 = (u64 *)dst; + dst[idx] = value; +} - dst64[idx] = value; - } else { - u32 *dst32 = (u32 *)dst; +static void write_to_buffer_64(u64 *dst, unsigned int idx, u64 value) +{ + dst[idx] = value; +} - dst32[idx] = (u32)value; - } +static void +write_to_buffer(void *dst, unsigned int idx, bool do_64bit, u64 value) +{ + if (do_64bit) + write_to_buffer_64(dst, idx, value); + else + write_to_buffer_32(dst, idx, value); } static void @@ -505,18 +510,24 @@ v3d_reset_performance_queries(struct v3d_cpu_job *job) } static void -v3d_write_performance_query_result(struct v3d_cpu_job *job, void *data, u32 query) +v3d_write_performance_query_result(struct v3d_cpu_job *job, void *data, + unsigned int query) { - struct v3d_performance_query_info *performance_query = &job->performance_query; - struct v3d_copy_query_results_info *copy = &job->copy; + struct v3d_performance_query_info *performance_query = + &job->performance_query; struct v3d_file_priv *v3d_priv = job->base.file->driver_priv; + struct v3d_performance_query *perf_query = + &performance_query->queries[query]; struct v3d_dev *v3d = job->base.v3d; - struct v3d_perfmon *perfmon; - u64 counter_values[V3D_MAX_COUNTERS]; + unsigned int i, j, offset; + + for (i = 0, offset = 0; + i < performance_query->nperfmons; + i++, offset += DRM_V3D_MAX_PERF_COUNTERS) { + struct v3d_perfmon *perfmon; - for (int i = 0; i < performance_query->nperfmons; i++) { perfmon = v3d_perfmon_find(v3d_priv, - performance_query->queries[query].kperfmon_ids[i]); + perf_query->kperfmon_ids[i]); if (!perfmon) { DRM_DEBUG("Failed to find perfmon."); continue; @@ -524,14 +535,18 @@ v3d_write_performance_query_result(struct v3d_cpu_job *job, void *data, u32 quer v3d_perfmon_stop(v3d, perfmon, true); - memcpy(&counter_values[i * DRM_V3D_MAX_PERF_COUNTERS], perfmon->values, - perfmon->ncounters * sizeof(u64)); + if (job->copy.do_64bit) { + for (j = 0; j < perfmon->ncounters; j++) + write_to_buffer_64(data, offset + j, + perfmon->values[j]); + } else { + for (j = 0; j < perfmon->ncounters; j++) + write_to_buffer_32(data, offset + j, + perfmon->values[j]); + } v3d_perfmon_put(perfmon); } - - for (int i = 0; i < performance_query->ncounters; i++) - write_to_buffer(data, i, copy->do_64bit, counter_values[i]); } static void -- cgit v1.2.3 From 3ef80d4ed6ff8441195a90a7897db3b67f38cd95 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 11 Jul 2024 14:53:38 +0100 Subject: drm/v3d: Move perfmon init completely into own unit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the build time dependencies on various array sizes have been removed, we can move the perfmon init completely into its own compilation unit and remove the hardcoded defines. This improves on the temporary fix quickly delivered in commit 9c3951ec27b9 ("drm/v3d: Fix perfmon build error/warning"). Signed-off-by: Tvrtko Ursulin References: 9c3951ec27b9 ("drm/v3d: Fix perfmon build error/warning") Reviewed-by: Maíra Canal Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20240711135340.84617-10-tursulin@igalia.com --- drivers/gpu/drm/v3d/v3d_drv.c | 9 ++---- drivers/gpu/drm/v3d/v3d_drv.h | 6 ++-- drivers/gpu/drm/v3d/v3d_perfmon.c | 40 +++++++++++++++----------- drivers/gpu/drm/v3d/v3d_performance_counters.h | 16 +++++++---- 4 files changed, 38 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c index a47f00b443d3..491c638a4d74 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.c +++ b/drivers/gpu/drm/v3d/v3d_drv.c @@ -95,7 +95,7 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data, args->value = 1; return 0; case DRM_V3D_PARAM_MAX_PERF_COUNTERS: - args->value = v3d->max_counters; + args->value = v3d->perfmon_info.max_counters; return 0; default: DRM_DEBUG("Unknown parameter %d\n", args->param); @@ -298,12 +298,7 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) v3d->cores = V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_NCORES); WARN_ON(v3d->cores > 1); /* multicore not yet implemented */ - if (v3d->ver >= 71) - v3d->max_counters = V3D_V71_NUM_PERFCOUNTERS; - else if (v3d->ver >= 42) - v3d->max_counters = V3D_V42_NUM_PERFCOUNTERS; - else - v3d->max_counters = 0; + v3d_perfmon_init(v3d); v3d->reset = devm_reset_control_get_exclusive(dev, NULL); if (IS_ERR(v3d->reset)) { diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index b1dfec49ba7d..8524761bc62d 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -104,10 +104,7 @@ struct v3d_dev { int ver; bool single_irq_line; - /* Different revisions of V3D have different total number of performance - * counters - */ - unsigned int max_counters; + struct v3d_perfmon_info perfmon_info; void __iomem *hub_regs; void __iomem *core_regs[3]; @@ -568,6 +565,7 @@ int v3d_sched_init(struct v3d_dev *v3d); void v3d_sched_fini(struct v3d_dev *v3d); /* v3d_perfmon.c */ +void v3d_perfmon_init(struct v3d_dev *v3d); void v3d_perfmon_get(struct v3d_perfmon *perfmon); void v3d_perfmon_put(struct v3d_perfmon *perfmon); void v3d_perfmon_start(struct v3d_dev *v3d, struct v3d_perfmon *perfmon); diff --git a/drivers/gpu/drm/v3d/v3d_perfmon.c b/drivers/gpu/drm/v3d/v3d_perfmon.c index b7d0b02e1a95..cd7f1eedf17f 100644 --- a/drivers/gpu/drm/v3d/v3d_perfmon.c +++ b/drivers/gpu/drm/v3d/v3d_perfmon.c @@ -195,6 +195,23 @@ static const struct v3d_perf_counter_desc v3d_v71_performance_counters[] = { {"QPU", "QPU-stalls-other", "[QPU] Stalled qcycles waiting for any other reason (vary/W/Z)"}, }; +void v3d_perfmon_init(struct v3d_dev *v3d) +{ + const struct v3d_perf_counter_desc *counters = NULL; + unsigned int max = 0; + + if (v3d->ver >= 71) { + counters = v3d_v71_performance_counters; + max = ARRAY_SIZE(v3d_v71_performance_counters); + } else if (v3d->ver >= 42) { + counters = v3d_v42_performance_counters; + max = ARRAY_SIZE(v3d_v42_performance_counters); + } + + v3d->perfmon_info.max_counters = max; + v3d->perfmon_info.counters = counters; +} + void v3d_perfmon_get(struct v3d_perfmon *perfmon) { if (perfmon) @@ -321,7 +338,7 @@ int v3d_perfmon_create_ioctl(struct drm_device *dev, void *data, /* Make sure all counters are valid. */ for (i = 0; i < req->ncounters; i++) { - if (req->counters[i] >= v3d->max_counters) + if (req->counters[i] >= v3d->perfmon_info.max_counters) return -EINVAL; } @@ -416,25 +433,14 @@ int v3d_perfmon_get_counter_ioctl(struct drm_device *dev, void *data, return -EINVAL; } + if (!v3d->perfmon_info.max_counters) + return -EOPNOTSUPP; + /* Make sure that the counter ID is valid */ - if (req->counter >= v3d->max_counters) + if (req->counter >= v3d->perfmon_info.max_counters) return -EINVAL; - BUILD_BUG_ON(ARRAY_SIZE(v3d_v42_performance_counters) != - V3D_V42_NUM_PERFCOUNTERS); - BUILD_BUG_ON(ARRAY_SIZE(v3d_v71_performance_counters) != - V3D_V71_NUM_PERFCOUNTERS); - BUILD_BUG_ON(V3D_MAX_COUNTERS < V3D_V42_NUM_PERFCOUNTERS); - BUILD_BUG_ON(V3D_MAX_COUNTERS < V3D_V71_NUM_PERFCOUNTERS); - BUILD_BUG_ON((V3D_MAX_COUNTERS != V3D_V42_NUM_PERFCOUNTERS) && - (V3D_MAX_COUNTERS != V3D_V71_NUM_PERFCOUNTERS)); - - if (v3d->ver >= 71) - counter = &v3d_v71_performance_counters[req->counter]; - else if (v3d->ver >= 42) - counter = &v3d_v42_performance_counters[req->counter]; - else - return -EOPNOTSUPP; + counter = &v3d->perfmon_info.counters[req->counter]; strscpy(req->name, counter->name, sizeof(req->name)); strscpy(req->category, counter->category, sizeof(req->category)); diff --git a/drivers/gpu/drm/v3d/v3d_performance_counters.h b/drivers/gpu/drm/v3d/v3d_performance_counters.h index 131b2909522a..d919a2fc9449 100644 --- a/drivers/gpu/drm/v3d/v3d_performance_counters.h +++ b/drivers/gpu/drm/v3d/v3d_performance_counters.h @@ -19,11 +19,17 @@ struct v3d_perf_counter_desc { char description[256]; }; +struct v3d_perfmon_info { + /* + * Different revisions of V3D have different total number of + * performance counters. + */ + unsigned int max_counters; -#define V3D_V42_NUM_PERFCOUNTERS (87) -#define V3D_V71_NUM_PERFCOUNTERS (93) - -/* Maximum number of performance counters supported by any version of V3D */ -#define V3D_MAX_COUNTERS (93) + /* + * Array of counters valid for the platform. + */ + const struct v3d_perf_counter_desc *counters; +}; #endif -- cgit v1.2.3 From 96bc9049ba41f99178f31658082891ff9850e522 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 11 Jul 2024 14:53:39 +0100 Subject: drm/v3d: Prefer get_user for scalar types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It makes it just a tiny bit more obvious what is going on. Signed-off-by: Tvrtko Ursulin Reviewed-by: Maíra Canal Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20240711135340.84617-11-tursulin@igalia.com --- drivers/gpu/drm/v3d/v3d_submit.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c index d1060e60aafa..b282d12571b5 100644 --- a/drivers/gpu/drm/v3d/v3d_submit.c +++ b/drivers/gpu/drm/v3d/v3d_submit.c @@ -485,14 +485,14 @@ v3d_get_cpu_timestamp_query_params(struct drm_file *file_priv, for (i = 0; i < timestamp.count; i++) { u32 offset, sync; - if (copy_from_user(&offset, offsets++, sizeof(offset))) { + if (get_user(offset, offsets++)) { err = -EFAULT; goto error; } job->timestamp_query.queries[i].offset = offset; - if (copy_from_user(&sync, syncs++, sizeof(sync))) { + if (get_user(sync, syncs++)) { err = -EFAULT; goto error; } @@ -550,7 +550,7 @@ v3d_get_cpu_reset_timestamp_params(struct drm_file *file_priv, job->timestamp_query.queries[i].offset = reset.offset + 8 * i; - if (copy_from_user(&sync, syncs++, sizeof(sync))) { + if (get_user(sync, syncs++)) { err = -EFAULT; goto error; } @@ -611,14 +611,14 @@ v3d_get_cpu_copy_query_results_params(struct drm_file *file_priv, for (i = 0; i < copy.count; i++) { u32 offset, sync; - if (copy_from_user(&offset, offsets++, sizeof(offset))) { + if (get_user(offset, offsets++)) { err = -EFAULT; goto error; } job->timestamp_query.queries[i].offset = offset; - if (copy_from_user(&sync, syncs++, sizeof(sync))) { + if (get_user(sync, syncs++)) { err = -EFAULT; goto error; } -- cgit v1.2.3 From c48abf099d5126fb93a941685df56e064d716175 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 11 Jul 2024 14:53:40 +0100 Subject: drm/v3d: Add some local variables in queries/extensions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add some local variables to make the code a bit less verbose, with the main benefit being pulling some lines to under 80 columns wide. Signed-off-by: Tvrtko Ursulin Reviewed-by: Maíra Canal Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20240711135340.84617-12-tursulin@igalia.com --- drivers/gpu/drm/v3d/v3d_submit.c | 88 ++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c index b282d12571b5..d607aa9c4ec2 100644 --- a/drivers/gpu/drm/v3d/v3d_submit.c +++ b/drivers/gpu/drm/v3d/v3d_submit.c @@ -452,6 +452,7 @@ v3d_get_cpu_timestamp_query_params(struct drm_file *file_priv, { u32 __user *offsets, *syncs; struct drm_v3d_timestamp_query timestamp; + struct v3d_timestamp_query_info *query_info = &job->timestamp_query; unsigned int i; int err; @@ -473,10 +474,10 @@ v3d_get_cpu_timestamp_query_params(struct drm_file *file_priv, job->job_type = V3D_CPU_JOB_TYPE_TIMESTAMP_QUERY; - job->timestamp_query.queries = kvmalloc_array(timestamp.count, - sizeof(struct v3d_timestamp_query), - GFP_KERNEL); - if (!job->timestamp_query.queries) + query_info->queries = kvmalloc_array(timestamp.count, + sizeof(struct v3d_timestamp_query), + GFP_KERNEL); + if (!query_info->queries) return -ENOMEM; offsets = u64_to_user_ptr(timestamp.offsets); @@ -490,20 +491,21 @@ v3d_get_cpu_timestamp_query_params(struct drm_file *file_priv, goto error; } - job->timestamp_query.queries[i].offset = offset; + query_info->queries[i].offset = offset; if (get_user(sync, syncs++)) { err = -EFAULT; goto error; } - job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); - if (!job->timestamp_query.queries[i].syncobj) { + query_info->queries[i].syncobj = drm_syncobj_find(file_priv, + sync); + if (!query_info->queries[i].syncobj) { err = -ENOENT; goto error; } } - job->timestamp_query.count = timestamp.count; + query_info->count = timestamp.count; return 0; @@ -519,6 +521,7 @@ v3d_get_cpu_reset_timestamp_params(struct drm_file *file_priv, { u32 __user *syncs; struct drm_v3d_reset_timestamp_query reset; + struct v3d_timestamp_query_info *query_info = &job->timestamp_query; unsigned int i; int err; @@ -537,10 +540,10 @@ v3d_get_cpu_reset_timestamp_params(struct drm_file *file_priv, job->job_type = V3D_CPU_JOB_TYPE_RESET_TIMESTAMP_QUERY; - job->timestamp_query.queries = kvmalloc_array(reset.count, - sizeof(struct v3d_timestamp_query), - GFP_KERNEL); - if (!job->timestamp_query.queries) + query_info->queries = kvmalloc_array(reset.count, + sizeof(struct v3d_timestamp_query), + GFP_KERNEL); + if (!query_info->queries) return -ENOMEM; syncs = u64_to_user_ptr(reset.syncs); @@ -548,20 +551,21 @@ v3d_get_cpu_reset_timestamp_params(struct drm_file *file_priv, for (i = 0; i < reset.count; i++) { u32 sync; - job->timestamp_query.queries[i].offset = reset.offset + 8 * i; + query_info->queries[i].offset = reset.offset + 8 * i; if (get_user(sync, syncs++)) { err = -EFAULT; goto error; } - job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); - if (!job->timestamp_query.queries[i].syncobj) { + query_info->queries[i].syncobj = drm_syncobj_find(file_priv, + sync); + if (!query_info->queries[i].syncobj) { err = -ENOENT; goto error; } } - job->timestamp_query.count = reset.count; + query_info->count = reset.count; return 0; @@ -578,6 +582,7 @@ v3d_get_cpu_copy_query_results_params(struct drm_file *file_priv, { u32 __user *offsets, *syncs; struct drm_v3d_copy_timestamp_query copy; + struct v3d_timestamp_query_info *query_info = &job->timestamp_query; unsigned int i; int err; @@ -599,10 +604,10 @@ v3d_get_cpu_copy_query_results_params(struct drm_file *file_priv, job->job_type = V3D_CPU_JOB_TYPE_COPY_TIMESTAMP_QUERY; - job->timestamp_query.queries = kvmalloc_array(copy.count, - sizeof(struct v3d_timestamp_query), - GFP_KERNEL); - if (!job->timestamp_query.queries) + query_info->queries = kvmalloc_array(copy.count, + sizeof(struct v3d_timestamp_query), + GFP_KERNEL); + if (!query_info->queries) return -ENOMEM; offsets = u64_to_user_ptr(copy.offsets); @@ -616,20 +621,21 @@ v3d_get_cpu_copy_query_results_params(struct drm_file *file_priv, goto error; } - job->timestamp_query.queries[i].offset = offset; + query_info->queries[i].offset = offset; if (get_user(sync, syncs++)) { err = -EFAULT; goto error; } - job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); - if (!job->timestamp_query.queries[i].syncobj) { + query_info->queries[i].syncobj = drm_syncobj_find(file_priv, + sync); + if (!query_info->queries[i].syncobj) { err = -ENOENT; goto error; } } - job->timestamp_query.count = copy.count; + query_info->count = copy.count; job->copy.do_64bit = copy.do_64bit; job->copy.do_partial = copy.do_partial; @@ -712,6 +718,7 @@ v3d_get_cpu_reset_performance_params(struct drm_file *file_priv, struct drm_v3d_extension __user *ext, struct v3d_cpu_job *job) { + struct v3d_performance_query_info *query_info = &job->performance_query; struct drm_v3d_reset_performance_query reset; int err; @@ -730,13 +737,14 @@ v3d_get_cpu_reset_performance_params(struct drm_file *file_priv, job->job_type = V3D_CPU_JOB_TYPE_RESET_PERFORMANCE_QUERY; - job->performance_query.queries = kvmalloc_array(reset.count, - sizeof(struct v3d_performance_query), - GFP_KERNEL); - if (!job->performance_query.queries) + query_info->queries = + kvmalloc_array(reset.count, + sizeof(struct v3d_performance_query), + GFP_KERNEL); + if (!query_info->queries) return -ENOMEM; - err = v3d_copy_query_info(&job->performance_query, + err = v3d_copy_query_info(query_info, reset.count, reset.nperfmons, u64_to_user_ptr(reset.syncs), @@ -745,8 +753,8 @@ v3d_get_cpu_reset_performance_params(struct drm_file *file_priv, if (err) return err; - job->performance_query.count = reset.count; - job->performance_query.nperfmons = reset.nperfmons; + query_info->count = reset.count; + query_info->nperfmons = reset.nperfmons; return 0; } @@ -756,6 +764,7 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, struct drm_v3d_extension __user *ext, struct v3d_cpu_job *job) { + struct v3d_performance_query_info *query_info = &job->performance_query; struct drm_v3d_copy_performance_query copy; int err; @@ -777,13 +786,14 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, job->job_type = V3D_CPU_JOB_TYPE_COPY_PERFORMANCE_QUERY; - job->performance_query.queries = kvmalloc_array(copy.count, - sizeof(struct v3d_performance_query), - GFP_KERNEL); - if (!job->performance_query.queries) + query_info->queries = + kvmalloc_array(copy.count, + sizeof(struct v3d_performance_query), + GFP_KERNEL); + if (!query_info->queries) return -ENOMEM; - err = v3d_copy_query_info(&job->performance_query, + err = v3d_copy_query_info(query_info, copy.count, copy.nperfmons, u64_to_user_ptr(copy.syncs), @@ -792,9 +802,9 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, if (err) return err; - job->performance_query.count = copy.count; - job->performance_query.nperfmons = copy.nperfmons; - job->performance_query.ncounters = copy.ncounters; + query_info->count = copy.count; + query_info->nperfmons = copy.nperfmons; + query_info->ncounters = copy.ncounters; job->copy.do_64bit = copy.do_64bit; job->copy.do_partial = copy.do_partial; -- cgit v1.2.3 From 0b91c6dacae24a1393f99f8154037c56454c277c Mon Sep 17 00:00:00 2001 From: Maíra Canal Date: Thu, 11 Jul 2024 11:25:24 -0300 Subject: drm/v3d: Expose memory stats through fdinfo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the common DRM function `drm_show_memory_stats()` to expose standard fdinfo memory stats. V3D exposes global GPU memory stats through debugfs. Those stats will be preserved while the DRM subsystem doesn't have a standard solution to expose global GPU stats. Signed-off-by: Maíra Canal Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20240711142736.783816-1-mcanal@igalia.com --- drivers/gpu/drm/v3d/v3d_bo.c | 12 ++++++++++++ drivers/gpu/drm/v3d/v3d_drv.c | 2 ++ 2 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/v3d/v3d_bo.c b/drivers/gpu/drm/v3d/v3d_bo.c index a165cbcdd27b..ecb80fd75b1a 100644 --- a/drivers/gpu/drm/v3d/v3d_bo.c +++ b/drivers/gpu/drm/v3d/v3d_bo.c @@ -26,6 +26,17 @@ #include "v3d_drv.h" #include "uapi/drm/v3d_drm.h" +static enum drm_gem_object_status v3d_gem_status(struct drm_gem_object *obj) +{ + struct v3d_bo *bo = to_v3d_bo(obj); + enum drm_gem_object_status res = 0; + + if (bo->base.pages) + res |= DRM_GEM_OBJECT_RESIDENT; + + return res; +} + /* Called DRM core on the last userspace/kernel unreference of the * BO. */ @@ -63,6 +74,7 @@ static const struct drm_gem_object_funcs v3d_gem_funcs = { .vmap = drm_gem_shmem_object_vmap, .vunmap = drm_gem_shmem_object_vunmap, .mmap = drm_gem_shmem_object_mmap, + .status = v3d_gem_status, .vm_ops = &drm_gem_shmem_vm_ops, }; diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c index 491c638a4d74..d38628e4fc2f 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.c +++ b/drivers/gpu/drm/v3d/v3d_drv.c @@ -184,6 +184,8 @@ static void v3d_show_fdinfo(struct drm_printer *p, struct drm_file *file) drm_printf(p, "v3d-jobs-%s: \t%llu jobs\n", v3d_queue_to_string(queue), jobs_completed); } + + drm_show_memory_stats(p, file); } static const struct file_operations v3d_drm_fops = { -- cgit v1.2.3 From cd3a2e8b0a0367c636cd82efaf7802cf85ae5dad Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 11 Jul 2024 09:23:04 +0200 Subject: drm/mgag200: Only set VIDRST bits in CRTC modesetting The VRSTEN and HRSTEN bits control whether a CRTC synchronizes its display signal with an external source on the VIDRST pin. The G200WB and G200EW3 models synchronize with a BMC chip, but different external video encoders, such as the Matrox Maven, can also be attached to the pin. Only set VRSTEN and HRSTEN bits in the CRTC mode-setting code, so the bits are independent from the BMC. Add the field set_vidrst to the CRTC state for this purpose. Off by default, control the CRTC VIDRST setting from the CRTC's atomic_check helper. v3: - don't clear bits unnecessary (Jocelyn) v2: - keep logic entirely in CRTC (Jocelyn) Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20240711072415.11831-2-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_bmc.c | 5 ----- drivers/gpu/drm/mgag200/mgag200_drv.h | 5 ++++- drivers/gpu/drm/mgag200/mgag200_g200er.c | 2 +- drivers/gpu/drm/mgag200/mgag200_g200ev.c | 2 +- drivers/gpu/drm/mgag200/mgag200_g200se.c | 2 +- drivers/gpu/drm/mgag200/mgag200_mode.c | 12 ++++++++---- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_bmc.c b/drivers/gpu/drm/mgag200/mgag200_bmc.c index 23ef85aa7e37..1c7aa4f36787 100644 --- a/drivers/gpu/drm/mgag200/mgag200_bmc.c +++ b/drivers/gpu/drm/mgag200/mgag200_bmc.c @@ -77,11 +77,6 @@ void mgag200_bmc_enable_vidrst(struct mga_device *mdev) { u8 tmp; - /* Ensure that the vrsten and hrsten are set */ - WREG8(MGAREG_CRTCEXT_INDEX, 1); - tmp = RREG8(MGAREG_CRTCEXT_DATA); - WREG8(MGAREG_CRTCEXT_DATA, tmp | 0x88); - /* Assert rstlvl2 */ WREG8(DAC_INDEX, MGA1064_REMHEADCTL2); tmp = RREG8(DAC_DATA); diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 7f7dfbd0f013..4b75613de882 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -179,6 +179,8 @@ struct mgag200_crtc_state { const struct drm_format_info *format; struct mgag200_pll_values pixpllc; + + bool set_vidrst; }; static inline struct mgag200_crtc_state *to_mgag200_crtc_state(struct drm_crtc_state *base) @@ -430,7 +432,8 @@ void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_st .atomic_duplicate_state = mgag200_crtc_atomic_duplicate_state, \ .atomic_destroy_state = mgag200_crtc_atomic_destroy_state -void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mode *mode); +void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mode *mode, + bool set_vidrst); void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_format_info *format); void mgag200_enable_display(struct mga_device *mdev); void mgag200_init_registers(struct mga_device *mdev); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c index 4e8a1756138d..abfbed6ec390 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200er.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c @@ -195,7 +195,7 @@ static void mgag200_g200er_crtc_helper_atomic_enable(struct drm_crtc *crtc, funcs->disable_vidrst(mdev); mgag200_set_format_regs(mdev, format); - mgag200_set_mode_regs(mdev, adjusted_mode); + mgag200_set_mode_regs(mdev, adjusted_mode, mgag200_crtc_state->set_vidrst); if (funcs->pixpllc_atomic_update) funcs->pixpllc_atomic_update(crtc, old_state); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c index d884f3cb0ec7..acc99999e2b5 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c @@ -196,7 +196,7 @@ static void mgag200_g200ev_crtc_helper_atomic_enable(struct drm_crtc *crtc, funcs->disable_vidrst(mdev); mgag200_set_format_regs(mdev, format); - mgag200_set_mode_regs(mdev, adjusted_mode); + mgag200_set_mode_regs(mdev, adjusted_mode, mgag200_crtc_state->set_vidrst); if (funcs->pixpllc_atomic_update) funcs->pixpllc_atomic_update(crtc, old_state); diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c index a824bb8ad579..be4e124102c6 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200se.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c @@ -327,7 +327,7 @@ static void mgag200_g200se_crtc_helper_atomic_enable(struct drm_crtc *crtc, funcs->disable_vidrst(mdev); mgag200_set_format_regs(mdev, format); - mgag200_set_mode_regs(mdev, adjusted_mode); + mgag200_set_mode_regs(mdev, adjusted_mode, mgag200_crtc_state->set_vidrst); if (funcs->pixpllc_atomic_update) funcs->pixpllc_atomic_update(crtc, old_state); diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index d4550e4b3b01..6ecb7c334f2b 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -201,9 +201,9 @@ void mgag200_init_registers(struct mga_device *mdev) WREG8(MGA_MISC_OUT, misc); } -void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mode *mode) +void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mode *mode, + bool set_vidrst) { - const struct mgag200_device_info *info = mdev->info; unsigned int hdisplay, hsyncstart, hsyncend, htotal; unsigned int vdisplay, vsyncstart, vsyncend, vtotal; u8 misc, crtcext1, crtcext2, crtcext5; @@ -238,7 +238,7 @@ void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mod ((hdisplay & 0x100) >> 7) | ((hsyncstart & 0x100) >> 6) | (htotal & 0x40); - if (info->has_vidrst) + if (set_vidrst) crtcext1 |= MGAREG_CRTCEXT1_VRSTEN | MGAREG_CRTCEXT1_HRSTEN; @@ -597,6 +597,7 @@ int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_st struct mga_device *mdev = to_mga_device(dev); const struct mgag200_device_funcs *funcs = mdev->funcs; struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); struct drm_property_blob *new_gamma_lut = new_crtc_state->gamma_lut; int ret; @@ -607,6 +608,8 @@ int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_st if (ret) return ret; + new_mgag200_crtc_state->set_vidrst = mdev->info->has_vidrst; + if (new_crtc_state->mode_changed) { if (funcs->pixpllc_atomic_check) { ret = funcs->pixpllc_atomic_check(crtc, new_state); @@ -656,7 +659,7 @@ void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_ funcs->disable_vidrst(mdev); mgag200_set_format_regs(mdev, format); - mgag200_set_mode_regs(mdev, adjusted_mode); + mgag200_set_mode_regs(mdev, adjusted_mode, mgag200_crtc_state->set_vidrst); if (funcs->pixpllc_atomic_update) funcs->pixpllc_atomic_update(crtc, old_state); @@ -717,6 +720,7 @@ struct drm_crtc_state *mgag200_crtc_atomic_duplicate_state(struct drm_crtc *crtc new_mgag200_crtc_state->format = mgag200_crtc_state->format; memcpy(&new_mgag200_crtc_state->pixpllc, &mgag200_crtc_state->pixpllc, sizeof(new_mgag200_crtc_state->pixpllc)); + new_mgag200_crtc_state->set_vidrst = mgag200_crtc_state->set_vidrst; return &new_mgag200_crtc_state->base; } -- cgit v1.2.3 From 7bb97cf915884956311352eae3f444eaaae48cea Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 11 Jul 2024 09:23:05 +0200 Subject: drm/mgag200: Remove vidrst callbacks from struct mgag200_device_funcs The callbacks disable_vidrst and enable_vidrst are obsolete. Remove the fields from struct mgag200_device_funcs. Instead call their implementations directly of the field 'has_vidrst' has been set in struct mgag200_device_info. Also change the logic slightly. The BMC used to start and stop scanout during the CRTC's atomic_enable and atomic_disable. Plane updates were done while the BMC scanned out the display. Now only stop once in atomic_disable at the beginning of a modeset and then restart the scanout at the end of a modeset in atomic_enable. While the modeset takes place, the BMC does not scanout at all. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20240711072415.11831-3-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_drv.h | 12 ------------ drivers/gpu/drm/mgag200/mgag200_g200er.c | 7 ++----- drivers/gpu/drm/mgag200/mgag200_g200ev.c | 7 ++----- drivers/gpu/drm/mgag200/mgag200_g200ew3.c | 2 -- drivers/gpu/drm/mgag200/mgag200_g200se.c | 7 ++----- drivers/gpu/drm/mgag200/mgag200_g200wb.c | 2 -- drivers/gpu/drm/mgag200/mgag200_mode.c | 15 ++++----------- 7 files changed, 10 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 4b75613de882..4a46c8c006c8 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -247,18 +247,6 @@ struct mgag200_device_info { } struct mgag200_device_funcs { - /* - * Disables an external reset source (i.e., BMC) before programming - * a new display mode. - */ - void (*disable_vidrst)(struct mga_device *mdev); - - /* - * Enables an external reset source (i.e., BMC) after programming - * a new display mode. - */ - void (*enable_vidrst)(struct mga_device *mdev); - /* * Validate that the given state can be programmed into PIXPLLC. On * success, the calculated parameters should be stored in the CRTC's diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c index abfbed6ec390..b3bb3e9fb0d1 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200er.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c @@ -191,9 +191,6 @@ static void mgag200_g200er_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); const struct drm_format_info *format = mgag200_crtc_state->format; - if (funcs->disable_vidrst) - funcs->disable_vidrst(mdev); - mgag200_set_format_regs(mdev, format); mgag200_set_mode_regs(mdev, adjusted_mode, mgag200_crtc_state->set_vidrst); @@ -209,8 +206,8 @@ static void mgag200_g200er_crtc_helper_atomic_enable(struct drm_crtc *crtc, mgag200_enable_display(mdev); - if (funcs->enable_vidrst) - funcs->enable_vidrst(mdev); + if (mdev->info->has_vidrst) + mgag200_bmc_enable_vidrst(mdev); } static const struct drm_crtc_helper_funcs mgag200_g200er_crtc_helper_funcs = { diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c index acc99999e2b5..3ac0a508e2c5 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c @@ -192,9 +192,6 @@ static void mgag200_g200ev_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); const struct drm_format_info *format = mgag200_crtc_state->format; - if (funcs->disable_vidrst) - funcs->disable_vidrst(mdev); - mgag200_set_format_regs(mdev, format); mgag200_set_mode_regs(mdev, adjusted_mode, mgag200_crtc_state->set_vidrst); @@ -210,8 +207,8 @@ static void mgag200_g200ev_crtc_helper_atomic_enable(struct drm_crtc *crtc, mgag200_enable_display(mdev); - if (funcs->enable_vidrst) - funcs->enable_vidrst(mdev); + if (mdev->info->has_vidrst) + mgag200_bmc_enable_vidrst(mdev); } static const struct drm_crtc_helper_funcs mgag200_g200ev_crtc_helper_funcs = { diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c index 839401e8b465..265f3e95830a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c @@ -146,8 +146,6 @@ static const struct mgag200_device_info mgag200_g200ew3_device_info = MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, true, 0, 1, false); static const struct mgag200_device_funcs mgag200_g200ew3_device_funcs = { - .disable_vidrst = mgag200_bmc_disable_vidrst, - .enable_vidrst = mgag200_bmc_enable_vidrst, .pixpllc_atomic_check = mgag200_g200ew3_pixpllc_atomic_check, .pixpllc_atomic_update = mgag200_g200wb_pixpllc_atomic_update, // same as G200WB }; diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c index be4e124102c6..7a8099eb100c 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200se.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c @@ -323,9 +323,6 @@ static void mgag200_g200se_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); const struct drm_format_info *format = mgag200_crtc_state->format; - if (funcs->disable_vidrst) - funcs->disable_vidrst(mdev); - mgag200_set_format_regs(mdev, format); mgag200_set_mode_regs(mdev, adjusted_mode, mgag200_crtc_state->set_vidrst); @@ -341,8 +338,8 @@ static void mgag200_g200se_crtc_helper_atomic_enable(struct drm_crtc *crtc, mgag200_enable_display(mdev); - if (funcs->enable_vidrst) - funcs->enable_vidrst(mdev); + if (mdev->info->has_vidrst) + mgag200_bmc_enable_vidrst(mdev); } static const struct drm_crtc_helper_funcs mgag200_g200se_crtc_helper_funcs = { diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c index 835df0f4fc13..e25477347c3e 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c @@ -280,8 +280,6 @@ static const struct mgag200_device_info mgag200_g200wb_device_info = MGAG200_DEVICE_INFO_INIT(1280, 1024, 31877, true, 0, 1, false); static const struct mgag200_device_funcs mgag200_g200wb_device_funcs = { - .disable_vidrst = mgag200_bmc_disable_vidrst, - .enable_vidrst = mgag200_bmc_enable_vidrst, .pixpllc_atomic_check = mgag200_g200wb_pixpllc_atomic_check, .pixpllc_atomic_update = mgag200_g200wb_pixpllc_atomic_update, }; diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 6ecb7c334f2b..276d5d61fe14 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -655,9 +655,6 @@ void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_ struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); const struct drm_format_info *format = mgag200_crtc_state->format; - if (funcs->disable_vidrst) - funcs->disable_vidrst(mdev); - mgag200_set_format_regs(mdev, format); mgag200_set_mode_regs(mdev, adjusted_mode, mgag200_crtc_state->set_vidrst); @@ -671,22 +668,18 @@ void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_ mgag200_enable_display(mdev); - if (funcs->enable_vidrst) - funcs->enable_vidrst(mdev); + if (mdev->info->has_vidrst) + mgag200_bmc_enable_vidrst(mdev); } void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *old_state) { struct mga_device *mdev = to_mga_device(crtc->dev); - const struct mgag200_device_funcs *funcs = mdev->funcs; - if (funcs->disable_vidrst) - funcs->disable_vidrst(mdev); + if (mdev->info->has_vidrst) + mgag200_bmc_disable_vidrst(mdev); mgag200_disable_display(mdev); - - if (funcs->enable_vidrst) - funcs->enable_vidrst(mdev); } void mgag200_crtc_reset(struct drm_crtc *crtc) -- cgit v1.2.3 From 3ac9384061b250ee40eda5facff10b85e2d5d3d8 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 11 Jul 2024 09:23:06 +0200 Subject: drm/mgag200: Rename BMC vidrst names The BMC's scanout synchronization is only indirectly related to the VIDRST functionality. Do some renaming. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20240711072415.11831-4-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_bmc.c | 4 ++-- drivers/gpu/drm/mgag200/mgag200_drv.h | 14 +++++++------- drivers/gpu/drm/mgag200/mgag200_g200er.c | 4 ++-- drivers/gpu/drm/mgag200/mgag200_g200ev.c | 4 ++-- drivers/gpu/drm/mgag200/mgag200_g200se.c | 4 ++-- drivers/gpu/drm/mgag200/mgag200_mode.c | 10 +++++----- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_bmc.c b/drivers/gpu/drm/mgag200/mgag200_bmc.c index 1c7aa4f36787..45e35dffb3ea 100644 --- a/drivers/gpu/drm/mgag200/mgag200_bmc.c +++ b/drivers/gpu/drm/mgag200/mgag200_bmc.c @@ -14,7 +14,7 @@ static struct mgag200_bmc_connector *to_mgag200_bmc_connector(struct drm_connect return container_of(connector, struct mgag200_bmc_connector, base); } -void mgag200_bmc_disable_vidrst(struct mga_device *mdev) +void mgag200_bmc_stop_scanout(struct mga_device *mdev) { u8 tmp; int iter_max; @@ -73,7 +73,7 @@ void mgag200_bmc_disable_vidrst(struct mga_device *mdev) } } -void mgag200_bmc_enable_vidrst(struct mga_device *mdev) +void mgag200_bmc_start_scanout(struct mga_device *mdev) { u8 tmp; diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 4a46c8c006c8..f97eaa49b089 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -216,8 +216,8 @@ struct mgag200_device_info { */ unsigned long max_mem_bandwidth; - /* HW has external source (e.g., BMC) to synchronize with */ - bool has_vidrst:1; + /* Synchronize scanout with BMC */ + bool sync_bmc:1; struct { unsigned data_bit:3; @@ -232,13 +232,13 @@ struct mgag200_device_info { }; #define MGAG200_DEVICE_INFO_INIT(_max_hdisplay, _max_vdisplay, _max_mem_bandwidth, \ - _has_vidrst, _i2c_data_bit, _i2c_clock_bit, \ + _sync_bmc, _i2c_data_bit, _i2c_clock_bit, \ _bug_no_startadd) \ { \ .max_hdisplay = (_max_hdisplay), \ .max_vdisplay = (_max_vdisplay), \ .max_mem_bandwidth = (_max_mem_bandwidth), \ - .has_vidrst = (_has_vidrst), \ + .sync_bmc = (_sync_bmc), \ .i2c = { \ .data_bit = (_i2c_data_bit), \ .clock_bit = (_i2c_clock_bit), \ @@ -430,9 +430,9 @@ int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_avail /* mgag200_vga.c */ int mgag200_vga_output_init(struct mga_device *mdev); - /* mgag200_bmc.c */ -void mgag200_bmc_disable_vidrst(struct mga_device *mdev); -void mgag200_bmc_enable_vidrst(struct mga_device *mdev); +/* mgag200_bmc.c */ +void mgag200_bmc_stop_scanout(struct mga_device *mdev); +void mgag200_bmc_start_scanout(struct mga_device *mdev); int mgag200_bmc_output_init(struct mga_device *mdev, struct drm_connector *physical_connector); #endif /* __MGAG200_DRV_H__ */ diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c index b3bb3e9fb0d1..737a48aa9160 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200er.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c @@ -206,8 +206,8 @@ static void mgag200_g200er_crtc_helper_atomic_enable(struct drm_crtc *crtc, mgag200_enable_display(mdev); - if (mdev->info->has_vidrst) - mgag200_bmc_enable_vidrst(mdev); + if (mdev->info->sync_bmc) + mgag200_bmc_start_scanout(mdev); } static const struct drm_crtc_helper_funcs mgag200_g200er_crtc_helper_funcs = { diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c index 3ac0a508e2c5..8d1ccc2ad94a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c @@ -207,8 +207,8 @@ static void mgag200_g200ev_crtc_helper_atomic_enable(struct drm_crtc *crtc, mgag200_enable_display(mdev); - if (mdev->info->has_vidrst) - mgag200_bmc_enable_vidrst(mdev); + if (mdev->info->sync_bmc) + mgag200_bmc_start_scanout(mdev); } static const struct drm_crtc_helper_funcs mgag200_g200ev_crtc_helper_funcs = { diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c index 7a8099eb100c..cf7f6897838f 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200se.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c @@ -338,8 +338,8 @@ static void mgag200_g200se_crtc_helper_atomic_enable(struct drm_crtc *crtc, mgag200_enable_display(mdev); - if (mdev->info->has_vidrst) - mgag200_bmc_enable_vidrst(mdev); + if (mdev->info->sync_bmc) + mgag200_bmc_start_scanout(mdev); } static const struct drm_crtc_helper_funcs mgag200_g200se_crtc_helper_funcs = { diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 276d5d61fe14..ec6f5e9e2d8f 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -608,7 +608,7 @@ int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_st if (ret) return ret; - new_mgag200_crtc_state->set_vidrst = mdev->info->has_vidrst; + new_mgag200_crtc_state->set_vidrst = mdev->info->sync_bmc; if (new_crtc_state->mode_changed) { if (funcs->pixpllc_atomic_check) { @@ -668,16 +668,16 @@ void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_ mgag200_enable_display(mdev); - if (mdev->info->has_vidrst) - mgag200_bmc_enable_vidrst(mdev); + if (mdev->info->sync_bmc) + mgag200_bmc_start_scanout(mdev); } void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *old_state) { struct mga_device *mdev = to_mga_device(crtc->dev); - if (mdev->info->has_vidrst) - mgag200_bmc_disable_vidrst(mdev); + if (mdev->info->sync_bmc) + mgag200_bmc_stop_scanout(mdev); mgag200_disable_display(mdev); } -- cgit v1.2.3 From fd39730c58890cd7f0a594231e19bb357f28877c Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 31 May 2023 10:28:54 +0300 Subject: drm/stm: ltdc: check memory returned by devm_kzalloc() devm_kzalloc() can fail and return NULL pointer. Check its return status. Identified with Coccinelle (kmerr.cocci script). Fixes: 484e72d3146b ("drm/stm: ltdc: add support of ycbcr pixel formats") Signed-off-by: Claudiu Beznea Acked-by: Raphael Gallais-Pou Link: https://patchwork.freedesktop.org/patch/msgid/20230531072854.142629-1-claudiu.beznea@microchip.com Signed-off-by: Raphael Gallais-Pou --- drivers/gpu/drm/stm/ltdc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 5576fdae4962..5aec1e58c968 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -1580,6 +1580,8 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev, ARRAY_SIZE(ltdc_drm_fmt_ycbcr_sp) + ARRAY_SIZE(ltdc_drm_fmt_ycbcr_fp)) * sizeof(*formats), GFP_KERNEL); + if (!formats) + return NULL; for (i = 0; i < ldev->caps.pix_fmt_nb; i++) { drm_fmt = ldev->caps.pix_fmt_drm[i]; -- cgit v1.2.3 From 19dd9780b7ac673be95bf6fd6892a184c9db611f Mon Sep 17 00:00:00 2001 From: Katya Orlova Date: Fri, 16 Feb 2024 15:50:40 +0300 Subject: drm/stm: Avoid use-after-free issues with crtc and plane MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ltdc_load() calls functions drm_crtc_init_with_planes(), drm_universal_plane_init() and drm_encoder_init(). These functions should not be called with parameters allocated with devm_kzalloc() to avoid use-after-free issues [1]. Use allocations managed by the DRM framework. Found by Linux Verification Center (linuxtesting.org). [1] https://lore.kernel.org/lkml/u366i76e3qhh3ra5oxrtngjtm2u5lterkekcz6y2jkndhuxzli@diujon4h7qwb/ Signed-off-by: Katya Orlova Acked-by: Raphaël Gallais-Pou Link: https://patchwork.freedesktop.org/patch/msgid/20240216125040.8968-1-e.orlova@ispras.ru Signed-off-by: Raphael Gallais-Pou --- drivers/gpu/drm/stm/drv.c | 3 +- drivers/gpu/drm/stm/ltdc.c | 73 ++++++++++++---------------------------------- 2 files changed, 20 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c index 4d2db079ad4f..e1232f74dfa5 100644 --- a/drivers/gpu/drm/stm/drv.c +++ b/drivers/gpu/drm/stm/drv.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "ltdc.h" @@ -75,7 +76,7 @@ static int drv_load(struct drm_device *ddev) DRM_DEBUG("%s\n", __func__); - ldev = devm_kzalloc(ddev->dev, sizeof(*ldev), GFP_KERNEL); + ldev = drmm_kzalloc(ddev, sizeof(*ldev), GFP_KERNEL); if (!ldev) return -ENOMEM; diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 5aec1e58c968..056642d12265 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -36,6 +36,7 @@ #include #include #include +#include #include