[PATCH] drm/v3d: fix wait for TMU write combiner flush
The hardware sets the TMUWCF bit back to 0 when the TMU write combiner flush completes so we should be checking for that instead of the L2TFLS bit. Fixes spurious Vulkan CTS failures in: dEQP-VK.binding_model.descriptorset_random.* --- drivers/gpu/drm/v3d/v3d_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index a3529809d547..5159f544bc16 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -197,7 +197,7 @@ v3d_clean_caches(struct v3d_dev *v3d) V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF); if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) & - V3D_L2TCACTL_L2TFLS), 100)) { + V3D_L2TCACTL_TMUWCF), 100)) { DRM_ERROR("Timeout waiting for L1T write combiner flush\n"); } -- 2.25.1
[PATCH 2/4] drm/i915/guc: Do error capture asynchronously
An error capture allocates memory, memory allocations depend on resets, and resets need to flush the G2H handlers to seal several races. If the error capture is done from the G2H handler this creates a circular dependency. To work around this, do a error capture in a work queue asynchronously from the G2H handler. This should be fine as (eventually) all register state is put into a buffer by the GuC so it is safe to restart the context before the error capture is complete. Example of lockdep splat below: [ 154.625989] == [ 154.632195] WARNING: possible circular locking dependency detected [ 154.638393] 5.14.0-rc5-guc+ #50 Tainted: G U [ 154.643991] -- [ 154.650196] i915_selftest/1673 is trying to acquire lock: [ 154.655621] 8881079cb918 ((work_completion)(>requests.worker)){+.+.}-{0:0}, at: __flush_work+0x350/0x4d0 [ 154.665826] but task is already holding lock: [ 154.671682] 8881079cbfb8 (>reset.mutex){+.+.}-{3:3}, at: intel_gt_reset+0xf0/0x300 [i915] [ 154.680659] which lock already depends on the new lock. [ 154.688857] the existing dependency chain (in reverse order) is: [ 154.696365] -> #2 (>reset.mutex){+.+.}-{3:3}: [ 154.702571]lock_acquire+0xd2/0x300 [ 154.706695]i915_gem_shrinker_taints_mutex+0x2d/0x50 [i915] [ 154.712959]intel_gt_init_reset+0x61/0x80 [i915] [ 154.718258]intel_gt_init_early+0xe6/0x120 [i915] [ 154.723648]i915_driver_probe+0x592/0xdc0 [i915] [ 154.728942]i915_pci_probe+0x43/0x1c0 [i915] [ 154.733891]pci_device_probe+0x9b/0x110 [ 154.738362]really_probe+0x1a6/0x3a0 [ 154.742568]__driver_probe_device+0xf9/0x170 [ 154.747468]driver_probe_device+0x19/0x90 [ 154.752114]__driver_attach+0x99/0x170 [ 154.756492]bus_for_each_dev+0x73/0xc0 [ 154.760870]bus_add_driver+0x14b/0x1f0 [ 154.765248]driver_register+0x67/0xb0 [ 154.769542]i915_init+0x18/0x8c [i915] [ 154.773964]do_one_initcall+0x53/0x2e0 [ 154.778343]do_init_module+0x56/0x210 [ 154.782639]load_module+0x25fc/0x29f0 [ 154.786934]__do_sys_finit_module+0xae/0x110 [ 154.791835]do_syscall_64+0x38/0xc0 [ 154.795958]entry_SYSCALL_64_after_hwframe+0x44/0xae [ 154.801558] -> #1 (fs_reclaim){+.+.}-{0:0}: [ 154.807241]lock_acquire+0xd2/0x300 [ 154.811361]fs_reclaim_acquire+0x9e/0xd0 [ 154.815914]kmem_cache_alloc_trace+0x30/0x790 [ 154.820899]i915_gpu_coredump_alloc+0x53/0x1a0 [i915] [ 154.826649]i915_gpu_coredump+0x39/0x560 [i915] [ 154.831866]i915_capture_error_state+0xa/0x70 [i915] [ 154.837513]intel_guc_context_reset_process_msg+0x174/0x1f0 [i915] [ 154.844383]ct_incoming_request_worker_func+0x130/0x1b0 [i915] [ 154.850898]process_one_work+0x264/0x590 [ 154.855451]worker_thread+0x4b/0x3a0 [ 154.859655]kthread+0x147/0x170 [ 154.863428]ret_from_fork+0x1f/0x30 [ 154.867548] -> #0 ((work_completion)(>requests.worker)){+.+.}-{0:0}: [ 154.875747]check_prev_add+0x90/0xc30 [ 154.880042]__lock_acquire+0x1643/0x2110 [ 154.884595]lock_acquire+0xd2/0x300 [ 154.888715]__flush_work+0x373/0x4d0 [ 154.892920]intel_guc_submission_reset_prepare+0xf3/0x340 [i915] [ 154.899606]intel_uc_reset_prepare+0x40/0x50 [i915] [ 154.905166]reset_prepare+0x55/0x60 [i915] [ 154.909946]intel_gt_reset+0x11c/0x300 [i915] [ 154.914984]do_device_reset+0x13/0x20 [i915] [ 154.919936]check_whitelist_across_reset+0x166/0x250 [i915] [ 154.926212]live_reset_whitelist.cold+0x6a/0x7a [i915] [ 154.932037]__i915_subtests.cold+0x20/0x74 [i915] [ 154.937428]__run_selftests.cold+0x96/0xee [i915] [ 154.942816]i915_live_selftests+0x2c/0x60 [i915] [ 154.948125]i915_pci_probe+0x93/0x1c0 [i915] [ 154.953076]pci_device_probe+0x9b/0x110 [ 154.957545]really_probe+0x1a6/0x3a0 [ 154.961749]__driver_probe_device+0xf9/0x170 [ 154.966653]driver_probe_device+0x19/0x90 [ 154.971290]__driver_attach+0x99/0x170 [ 154.975671]bus_for_each_dev+0x73/0xc0 [ 154.980053]bus_add_driver+0x14b/0x1f0 [ 154.984431]driver_register+0x67/0xb0 [ 154.988725]i915_init+0x18/0x8c [i915] [ 154.993149]do_one_initcall+0x53/0x2e0 [ 154.997527]do_init_module+0x56/0x210 [ 155.001822]load_module+0x25fc/0x29f0 [ 155.006118]__do_sys_finit_module+0xae/0x110 [ 155.011019]do_syscall_64+0x38/0xc0 [ 155.015139]entry_SYSCALL_64_after_hwframe+0x44/0xae [ 155.020729] other info that might help us debug this: [ 155.028752] Chain exists of:
[PATCH 3/4] drm/i915/guc: Flush G2H work queue during reset
It isn't safe to scrub for missing G2H or continue with the reset until all G2H processing is complete. Flush the G2H work queue during reset to ensure it is done running. No need to call the IRQ handler directly either as the scrubbing code can deal with any missing G2H. Signed-off-by: Matthew Brost Reviewed-by: Daniele Ceraolo Spurio --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 18 +- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index ba6838a35a69..1986a57b52cc 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -800,8 +800,6 @@ static void guc_flush_submissions(struct intel_guc *guc) void intel_guc_submission_reset_prepare(struct intel_guc *guc) { - int i; - if (unlikely(!guc_submission_initialized(guc))) { /* Reset called during driver load? GuC not yet initialised! */ return; @@ -816,21 +814,7 @@ void intel_guc_submission_reset_prepare(struct intel_guc *guc) spin_unlock_irq(_to_gt(guc)->irq_lock); guc_flush_submissions(guc); - - /* -* Handle any outstanding G2Hs before reset. Call IRQ handler directly -* each pass as interrupt have been disabled. We always scrub for -* outstanding G2H as it is possible for outstanding_submission_g2h to -* be incremented after the context state update. -*/ - for (i = 0; i < 4 && atomic_read(>outstanding_submission_g2h); ++i) { - intel_guc_to_host_event_handler(guc); -#define wait_for_reset(guc, wait_var) \ - intel_guc_wait_for_pending_msg(guc, wait_var, false, (HZ / 20)) - do { - wait_for_reset(guc, >outstanding_submission_g2h); - } while (!list_empty(>ct.requests.incoming)); - } + flush_work(>ct.requests.worker); scrub_guc_desc_for_outstanding_g2h(guc); } -- 2.32.0
[PATCH 1/4] drm/i915/guc: Move guc_ids under submission_state sub-structure
Move guc_ids under submission_state sub-structure as a future patch will use contexts_lock (global GuC submission lock) to protect more data. Introducing the sub-structure makes ownership of the locking / fields clear. v2: (Docs) - Fix Docs warning by adding comment to submission_state structure Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/gt/intel_context_types.h | 9 ++-- drivers/gpu/drm/i915/gt/uc/intel_guc.h| 26 +++ .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 44 ++- 3 files changed, 45 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 930569a1a01f..af43b3c83339 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -189,18 +189,19 @@ struct intel_context { struct { /** * @id: handle which is used to uniquely identify this context -* with the GuC, protected by guc->contexts_lock +* with the GuC, protected by guc->submission_state.lock */ u16 id; /** * @ref: the number of references to the guc_id, when * transitioning in and out of zero protected by -* guc->contexts_lock +* guc->submission_state.lock */ atomic_t ref; /** -* @link: in guc->guc_id_list when the guc_id has no refs but is -* still valid, protected by guc->contexts_lock +* @link: in guc->submission_state.guc_id_list when the guc_id +* has no refs but is still valid, protected by +* guc->submission_state.lock */ struct list_head link; } guc_id; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 5dd174babf7a..0e28f490c12d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -71,16 +71,24 @@ struct intel_guc { } interrupts; /** -* @contexts_lock: protects guc_ids, guc_id_list, ce->guc_id.id, and -* ce->guc_id.ref when transitioning in and out of zero +* @submission_state: all state related to GuC submission that needs to +* be protected by a common lock */ - spinlock_t contexts_lock; - /** @guc_ids: used to allocate unique ce->guc_id.id values */ - struct ida guc_ids; - /** -* @guc_id_list: list of intel_context with valid guc_ids but no refs -*/ - struct list_head guc_id_list; + struct { + /** +* @lock: protects everything in submission_state and ce->guc_id +*/ + spinlock_t lock; + /** +* @guc_ids: used to allocate new guc_ids +*/ + struct ida guc_ids; + /** +* @guc_id_list: list of intel_context with valid guc_ids but no +* refs +*/ + struct list_head guc_id_list; + } submission_state; /** * @submission_supported: tracks whether we support GuC submission on diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index c7a41802b448..678da915eb9d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -89,7 +89,7 @@ * sched_engine can be submitting at a time. Currently only one sched_engine is * used for all of GuC submission but that could change in the future. * - * guc->contexts_lock + * guc->submission_state.lock * Protects guc_id allocation for the given GuC, i.e. only one context can be * doing guc_id allocation operations at a time for each GuC in the system. * @@ -103,7 +103,7 @@ * * Lock ordering rules: * sched_engine->lock -> ce->guc_state.lock - * guc->contexts_lock -> ce->guc_state.lock + * guc->submission_state.lock -> ce->guc_state.lock * * Reset races: * When a full GT reset is triggered it is assumed that some G2H responses to @@ -1148,9 +1148,9 @@ int intel_guc_submission_init(struct intel_guc *guc) xa_init_flags(>context_lookup, XA_FLAGS_LOCK_IRQ); - spin_lock_init(>contexts_lock); - INIT_LIST_HEAD(>guc_id_list); - ida_init(>guc_ids); + spin_lock_init(>submission_state.lock); + INIT_LIST_HEAD(>submission_state.guc_id_list); + ida_init(>submission_state.guc_ids); return 0; } @@ -1215,7 +1215,7 @@ static void guc_submit_request(struct i915_request *rq) static int new_guc_id(struct intel_guc *guc) { - return ida_simple_get(>guc_ids, 0, + return ida_simple_get(>submission_state.guc_ids, 0,
[PATCH 4/4] drm/i915/guc: Refcount context during error capture
From: John Harrison When i915 receives a context reset notification from GuC, it triggers an error capture before resetting any outstanding requsts of that context. Unfortunately, the error capture is not a time bound operation. In certain situations it can take a long time, particularly when multiple large LMEM buffers must be read back and eoncoded. If this delay is longer than other timeouts (heartbeat, test recovery, etc.) then a full GT reset can be triggered in the middle. That can result in the context being reset by GuC actually being destroyed before the error capture completes and the GuC submission code resumes. Thus, the GuC side can start dereferencing stale pointers and Bad Things ensue. So add a refcount get of the context during the entire reset operation. That way, the context can't be destroyed part way through no matter what other resets or user interactions occur. v2: (Matthew Brost) - Update patch to work with async error capture Signed-off-by: John Harrison Signed-off-by: Matthew Brost --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 24 +-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 1986a57b52cc..02917fc4d4a8 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -2888,6 +2888,8 @@ static void capture_worker_func(struct work_struct *w) intel_engine_set_hung_context(engine, ce); with_intel_runtime_pm(>runtime_pm, wakeref) i915_capture_error_state(gt, ce->engine->mask); + + intel_context_put(ce); } static void capture_error_state(struct intel_guc *guc, @@ -2924,7 +2926,7 @@ static void guc_context_replay(struct intel_context *ce) tasklet_hi_schedule(_engine->tasklet); } -static void guc_handle_context_reset(struct intel_guc *guc, +static bool guc_handle_context_reset(struct intel_guc *guc, struct intel_context *ce) { trace_intel_context_reset(ce); @@ -2937,7 +2939,11 @@ static void guc_handle_context_reset(struct intel_guc *guc, !context_blocked(ce))) { capture_error_state(guc, ce); guc_context_replay(ce); + + return false; } + + return true; } int intel_guc_context_reset_process_msg(struct intel_guc *guc, @@ -2945,6 +2951,7 @@ int intel_guc_context_reset_process_msg(struct intel_guc *guc, { struct intel_context *ce; int desc_idx; + unsigned long flags; if (unlikely(len != 1)) { drm_err(_to_gt(guc)->i915->drm, "Invalid length %u", len); @@ -2952,11 +2959,24 @@ int intel_guc_context_reset_process_msg(struct intel_guc *guc, } desc_idx = msg[0]; + + /* +* The context lookup uses the xarray but lookups only require an RCU lock +* not the full spinlock. So take the lock explicitly and keep it until the +* context has been reference count locked to ensure it can't be destroyed +* asynchronously until the reset is done. +*/ + xa_lock_irqsave(>context_lookup, flags); ce = g2h_context_lookup(guc, desc_idx); + if (ce) + intel_context_get(ce); + xa_unlock_irqrestore(>context_lookup, flags); + if (unlikely(!ce)) return -EPROTO; - guc_handle_context_reset(guc, ce); + if (guc_handle_context_reset(guc, ce)) + intel_context_put(ce); return 0; } -- 2.32.0
[PATCH 0/4] Do error capture async, flush G2H processing on reset
Rather allocating an error capture in nowait context to break a lockdep splat [1], do the error capture async compared to the G2H processing. v2: Fix Docs warning Signed-off-by: Matthew Brost [1] https://patchwork.freedesktop.org/patch/451415/?series=93704=5 John Harrison (1): drm/i915/guc: Refcount context during error capture Matthew Brost (3): drm/i915/guc: Move guc_ids under submission_state sub-structure drm/i915/guc: Do error capture asynchronously drm/i915/guc: Flush G2H work queue during reset drivers/gpu/drm/i915/gt/intel_context.c | 2 + drivers/gpu/drm/i915/gt/intel_context_types.h | 16 ++- drivers/gpu/drm/i915/gt/uc/intel_guc.h| 36 +++-- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 133 -- 4 files changed, 130 insertions(+), 57 deletions(-) -- 2.32.0
Re: [Intel-gfx] [PATCH 07/27] drm/i915/guc: Don't call switch_to_kernel_context with GuC submission
On Mon, Sep 13, 2021 at 03:38:44PM -0700, John Harrison wrote: > On 9/13/2021 09:54, Matthew Brost wrote: > > On Thu, Sep 09, 2021 at 03:51:27PM -0700, John Harrison wrote: > > On 8/20/2021 15:44, Matthew Brost wrote: > > Calling switch_to_kernel_context isn't needed if the engine PM > reference > is taken while all contexts are pinned. By not calling > switch_to_kernel_context we save on issuing a request to the > engine. > > I thought the intention of the switch_to_kernel was to ensure that > the GPU > is not touching any user context and is basically idle. That is not a > valid > assumption with an external scheduler such as GuC. So why is the > description > above only mentioning PM references? What is the connection between > the PM > ref and the switch_to_kernel? > > Also, the comment in the code does not mention anything about PM > references, > it just says 'not necessary with GuC' but no explanation at all. > > > Yea, this need to be explained better. How about this? > > Calling switch_to_kernel_context isn't needed if the engine PM reference > is take while all user contexts have scheduling enabled. Once scheduling > is disabled on all user contexts the GuC is guaranteed to not touch any > user context state which is effectively the same pointing to a kernel > context. > > Matt > > I'm still not seeing how the PM reference is involved? > We shouldn't trap into the GT PM park code while a user context has scheduling enabled as the GT PM park code may have side affects we don't to execute if a user context still has scheduling enabled. I guess that isn't explained very well. > Also, IMHO the focus is wrong in the above text. The fundamental requirement > is > the ensure the hardware is idle. Execlist achieves this by switching to a safe > context. GuC achieves it by disabling scheduling. Indeed, switching to a > 'safe' > context really has no effect with GuC submission. So 'effectively the same as > pointing to a kernel context' is an incorrect description. I would go with > something like: > > "This is execlist specific behaviour intended to ensure the GPU is idle by > switching to a known 'safe' context. With GuC submission, the same idle > guarantee is achieved by other means (disabling scheduling). Further, > switching to a 'safe' context has no effect with GuC submission as the > scheduler can just switch back again. > FIXME: Move this backend scheduler specific behaviour into the scheduler > backend." > That is worded better. Will pull into the next rev. Matt > > John. > > > > > > v2: > (Daniel Vetter) >- Add FIXME comment about pushing switch_to_kernel_context to > backend > > Signed-off-by: Matthew Brost > Reviewed-by: Daniel Vetter > --- > drivers/gpu/drm/i915/gt/intel_engine_pm.c | 9 + > 1 file changed, 9 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c > b/drivers/gpu/drm/i915/gt/intel_engine_pm.c > index 1f07ac4e0672..11fee66daf60 100644 > --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c > +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c > @@ -162,6 +162,15 @@ static bool switch_to_kernel_context(struct > intel_engine_cs *engine) > unsigned long flags; > bool result = true; > + /* > +* No need to switch_to_kernel_context if GuC submission > +* > +* FIXME: This execlists specific backend behavior in > generic code, this > > "This execlists" -> "This is execlist" > > "this should be" -> "it should be" > > John. > > > +* should be pushed to the backend. > +*/ > + if (intel_engine_uses_guc(engine)) > + return true; > + > /* GPU is pointing to the void, as good as in the kernel > context. */ > if (intel_gt_is_wedged(engine->gt)) > return true; > > > SECURITY NOTE: file ~/.netrc must not be accessible by others
Re: [PATCH 1/5] drm/i915: Do not define vma on stack
On Tue, 14 Sept 2021 at 14:55, Matthew Brost wrote: > > From: Venkata Sandeep Dhanalakota > > Defining vma on stack can cause stack overflow, if > vma gets populated with new fields. Is there some higher level locking stopping that from getting trashed? or a guarantee that uc_fw_bind_ggtt is only entered by one thread at a time? Dave. > > Cc: Daniele Ceraolo Spurio > Cc: Tvrtko Ursulin > Signed-off-by: Venkata Sandeep Dhanalakota > Signed-off-by: Matthew Brost > Reviewed-by: Matthew Brost > --- > drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 18 +- > drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h | 2 ++ > 2 files changed, 11 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c > b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c > index 3a16d08608a5..f632dbd32b42 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c > @@ -413,20 +413,20 @@ static void uc_fw_bind_ggtt(struct intel_uc_fw *uc_fw) > { > struct drm_i915_gem_object *obj = uc_fw->obj; > struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt; > - struct i915_vma dummy = { > - .node.start = uc_fw_ggtt_offset(uc_fw), > - .node.size = obj->base.size, > - .pages = obj->mm.pages, > - .vm = >vm, > - }; > + struct i915_vma *dummy = _fw->dummy; > + > + dummy->node.start = uc_fw_ggtt_offset(uc_fw); > + dummy->node.size = obj->base.size; > + dummy->pages = obj->mm.pages; > + dummy->vm = >vm; > > GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); > - GEM_BUG_ON(dummy.node.size > ggtt->uc_fw.size); > + GEM_BUG_ON(dummy->node.size > ggtt->uc_fw.size); > > /* uc_fw->obj cache domains were not controlled across suspend */ > - drm_clflush_sg(dummy.pages); > + drm_clflush_sg(dummy->pages); > > - ggtt->vm.insert_entries(>vm, , I915_CACHE_NONE, 0); > + ggtt->vm.insert_entries(>vm, dummy, I915_CACHE_NONE, 0); > } > > static void uc_fw_unbind_ggtt(struct intel_uc_fw *uc_fw) > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h > b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h > index 99bb1fe1af66..693cc0ebcd63 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h > @@ -10,6 +10,7 @@ > #include "intel_uc_fw_abi.h" > #include "intel_device_info.h" > #include "i915_gem.h" > +#include "i915_vma.h" > > struct drm_printer; > struct drm_i915_private; > @@ -75,6 +76,7 @@ struct intel_uc_fw { > bool user_overridden; > size_t size; > struct drm_i915_gem_object *obj; > + struct i915_vma dummy; > > /* > * The firmware build process will generate a version header file > with major and > -- > 2.32.0 >
[PATCH 1/5] drm/i915: Do not define vma on stack
From: Venkata Sandeep Dhanalakota Defining vma on stack can cause stack overflow, if vma gets populated with new fields. Cc: Daniele Ceraolo Spurio Cc: Tvrtko Ursulin Signed-off-by: Venkata Sandeep Dhanalakota Signed-off-by: Matthew Brost Reviewed-by: Matthew Brost --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 18 +- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h | 2 ++ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 3a16d08608a5..f632dbd32b42 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -413,20 +413,20 @@ static void uc_fw_bind_ggtt(struct intel_uc_fw *uc_fw) { struct drm_i915_gem_object *obj = uc_fw->obj; struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt; - struct i915_vma dummy = { - .node.start = uc_fw_ggtt_offset(uc_fw), - .node.size = obj->base.size, - .pages = obj->mm.pages, - .vm = >vm, - }; + struct i915_vma *dummy = _fw->dummy; + + dummy->node.start = uc_fw_ggtt_offset(uc_fw); + dummy->node.size = obj->base.size; + dummy->pages = obj->mm.pages; + dummy->vm = >vm; GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); - GEM_BUG_ON(dummy.node.size > ggtt->uc_fw.size); + GEM_BUG_ON(dummy->node.size > ggtt->uc_fw.size); /* uc_fw->obj cache domains were not controlled across suspend */ - drm_clflush_sg(dummy.pages); + drm_clflush_sg(dummy->pages); - ggtt->vm.insert_entries(>vm, , I915_CACHE_NONE, 0); + ggtt->vm.insert_entries(>vm, dummy, I915_CACHE_NONE, 0); } static void uc_fw_unbind_ggtt(struct intel_uc_fw *uc_fw) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h index 99bb1fe1af66..693cc0ebcd63 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h @@ -10,6 +10,7 @@ #include "intel_uc_fw_abi.h" #include "intel_device_info.h" #include "i915_gem.h" +#include "i915_vma.h" struct drm_printer; struct drm_i915_private; @@ -75,6 +76,7 @@ struct intel_uc_fw { bool user_overridden; size_t size; struct drm_i915_gem_object *obj; + struct i915_vma dummy; /* * The firmware build process will generate a version header file with major and -- 2.32.0
[PATCH 5/5] drm/i915/guc: Use i915_gem_object_is_lmem in i915_gem_object_is_lmem
The GuC objects are perma-pinned and need to be dumped during an error capture. Use the macro i915_gem_object_is_lmem rather than __i915_gem_object_is_lmem to avoid a lockdep splat as the former is the correct call if the object is perma-pinned. Signed-off-by: Matthew Brost Cc: Thomas Hellstrom --- drivers/gpu/drm/i915/i915_gpu_error.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index b9f66dbd46bb..a61e23deeb00 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1068,7 +1068,7 @@ i915_vma_coredump_create(const struct intel_gt *gt, if (ret) break; } - } else if (__i915_gem_object_is_lmem(vma->obj)) { + } else if (i915_gem_object_is_lmem(vma->obj)) { struct intel_memory_region *mem = vma->obj->mm.region; dma_addr_t dma; -- 2.32.0
[PATCH 2/5] drm/i915/guc: put all guc objects in lmem when available
From: Daniele Ceraolo Spurio The firmware binary has to be loaded from lmem and the recommendation is to put all other objects in there as well. Note that we don't fall back to system memory if the allocation in lmem fails because all objects are allocated during driver load and if we have issues with lmem at that point something is seriously wrong with the system, so no point in trying to handle it. Cc: Matthew Auld Cc: Abdiel Janulgue Cc: Michal Wajdeczko Cc: Vinay Belgaumkar Cc: Radoslaw Szwichtenberg Signed-off-by: Daniele Ceraolo Spurio Signed-off-by: Matthew Brost Reviewed-by: Matthew Brost --- drivers/gpu/drm/i915/gem/i915_gem_lmem.c | 26 drivers/gpu/drm/i915/gem/i915_gem_lmem.h | 4 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.c| 9 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 13 ++-- drivers/gpu/drm/i915/gt/uc/intel_huc.c| 14 - drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 75 +-- 6 files changed, 128 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c index eb345305dc52..034226c5d4d0 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c @@ -103,6 +103,32 @@ __i915_gem_object_create_lmem_with_ps(struct drm_i915_private *i915, size, page_size, flags); } +struct drm_i915_gem_object * +i915_gem_object_create_lmem_from_data(struct drm_i915_private *i915, + const void *data, size_t size) +{ + struct drm_i915_gem_object *obj; + void *map; + + obj = i915_gem_object_create_lmem(i915, + round_up(size, PAGE_SIZE), + I915_BO_ALLOC_CONTIGUOUS); + if (IS_ERR(obj)) + return obj; + + map = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WC); + if (IS_ERR(map)) { + i915_gem_object_put(obj); + return map; + } + + memcpy(map, data, size); + + i915_gem_object_unpin_map(obj); + + return obj; +} + struct drm_i915_gem_object * i915_gem_object_create_lmem(struct drm_i915_private *i915, resource_size_t size, diff --git a/drivers/gpu/drm/i915/gem/i915_gem_lmem.h b/drivers/gpu/drm/i915/gem/i915_gem_lmem.h index 4ee81fc66302..1b88ea13435c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_lmem.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_lmem.h @@ -23,6 +23,10 @@ bool i915_gem_object_is_lmem(struct drm_i915_gem_object *obj); bool __i915_gem_object_is_lmem(struct drm_i915_gem_object *obj); +struct drm_i915_gem_object * +i915_gem_object_create_lmem_from_data(struct drm_i915_private *i915, + const void *data, size_t size); + struct drm_i915_gem_object * __i915_gem_object_create_lmem_with_ps(struct drm_i915_private *i915, resource_size_t size, diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index fbfcae727d7f..8ffb689066f6 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -3,6 +3,7 @@ * Copyright © 2014-2019 Intel Corporation */ +#include "gem/i915_gem_lmem.h" #include "gt/intel_gt.h" #include "gt/intel_gt_irq.h" #include "gt/intel_gt_pm_irq.h" @@ -647,7 +648,13 @@ struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size) u64 flags; int ret; - obj = i915_gem_object_create_shmem(gt->i915, size); + if (HAS_LMEM(gt->i915)) + obj = i915_gem_object_create_lmem(gt->i915, size, + I915_BO_ALLOC_CPU_CLEAR | + I915_BO_ALLOC_CONTIGUOUS); + else + obj = i915_gem_object_create_shmem(gt->i915, size); + if (IS_ERR(obj)) return ERR_CAST(obj); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c index 76fe766ad1bc..196424be0998 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c @@ -41,18 +41,21 @@ static void guc_prepare_xfer(struct intel_uncore *uncore) } /* Copy RSA signature from the fw image to HW for verification */ -static void guc_xfer_rsa(struct intel_uc_fw *guc_fw, -struct intel_uncore *uncore) +static int guc_xfer_rsa(struct intel_uc_fw *guc_fw, + struct intel_uncore *uncore) { u32 rsa[UOS_RSA_SCRATCH_COUNT]; size_t copied; int i; copied = intel_uc_fw_copy_rsa(guc_fw, rsa, sizeof(rsa)); - GEM_BUG_ON(copied < sizeof(rsa)); + if (copied < sizeof(rsa)) + return -ENOMEM; for (i = 0; i < UOS_RSA_SCRATCH_COUNT; i++) intel_uncore_write(uncore, UOS_RSA_SCRATCH(i),
[PATCH 4/5] drm/i915/guc: Enable GuC submission by default on DG1
Enable GuC submission by default on DG1 Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/gt/uc/intel_uc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index 86c318516e14..2fef3b0bbe95 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -35,7 +35,7 @@ static void uc_expand_default_options(struct intel_uc *uc) } /* Intermediate platforms are HuC authentication only */ - if (IS_DG1(i915) || IS_ALDERLAKE_S(i915)) { + if (IS_ALDERLAKE_S(i915)) { i915->params.enable_guc = ENABLE_GUC_LOAD_HUC; return; } -- 2.32.0
[PATCH 3/5] drm/i915/guc: Add DG1 GuC / HuC firmware defs
From: Daniele Ceraolo Spurio Add DG1 GuC / HuC firmware defs Signed-off-by: Matthew Brost Signed-off-by: Daniele Ceraolo Spurio Reviewed-by: Matthew Brost --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index f8cb00ffb506..a685d563df72 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -51,6 +51,7 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, #define INTEL_UC_FIRMWARE_DEFS(fw_def, guc_def, huc_def) \ fw_def(ALDERLAKE_P, 0, guc_def(adlp, 62, 0, 3), huc_def(tgl, 7, 9, 3)) \ fw_def(ALDERLAKE_S, 0, guc_def(tgl, 62, 0, 0), huc_def(tgl, 7, 9, 3)) \ + fw_def(DG1, 0, guc_def(dg1, 62, 0, 0), huc_def(dg1, 7, 9, 3)) \ fw_def(ROCKETLAKE, 0, guc_def(tgl, 62, 0, 0), huc_def(tgl, 7, 9, 3)) \ fw_def(TIGERLAKE, 0, guc_def(tgl, 62, 0, 0), huc_def(tgl, 7, 9, 3)) \ fw_def(JASPERLAKE, 0, guc_def(ehl, 62, 0, 0), huc_def(ehl, 9, 0, 0)) \ -- 2.32.0
[PATCH 0/5] Enable GuC submission by default on DG1
Minimum set of patches to enable GuC submission on DG1 and enable it by default. A little difficult to test as IGTs do not work with DG1 due to a bunch of uAPI features being disabled (e.g. relocations, caching memory options, etc...) and CI for DG1 isn't all that useful yet. Tested quite thoroughly locally though. Signed-off-by: Matthew Brost Daniele Ceraolo Spurio (2): drm/i915/guc: put all guc objects in lmem when available drm/i915/guc: Add DG1 GuC / HuC firmware defs Matthew Brost (2): drm/i915/guc: Enable GuC submission by default on DG1 drm/i915/guc: Use i915_gem_object_is_lmem in i915_gem_object_is_lmem Venkata Sandeep Dhanalakota (1): drm/i915: Do not define vma on stack drivers/gpu/drm/i915/gem/i915_gem_lmem.c | 26 +++ drivers/gpu/drm/i915/gem/i915_gem_lmem.h | 4 + drivers/gpu/drm/i915/gt/uc/intel_guc.c| 9 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 13 +++- drivers/gpu/drm/i915/gt/uc/intel_huc.c| 14 +++- drivers/gpu/drm/i915/gt/uc/intel_uc.c | 2 +- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 90 --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h | 2 + drivers/gpu/drm/i915/i915_gpu_error.c | 2 +- 9 files changed, 140 insertions(+), 22 deletions(-) -- 2.32.0
[PATCH 1/4] drm/i915/guc: Move guc_ids under submission_state sub-structure
Move guc_ids under submission_state sub-structure as a future patch will use contexts_lock (global GuC submission lock) to protect more data. Introducing the sub-structure makes ownership of the locking / fields clear. Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/gt/intel_context_types.h | 9 ++-- drivers/gpu/drm/i915/gt/uc/intel_guc.h| 26 ++- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 44 ++- 3 files changed, 43 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 930569a1a01f..af43b3c83339 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -189,18 +189,19 @@ struct intel_context { struct { /** * @id: handle which is used to uniquely identify this context -* with the GuC, protected by guc->contexts_lock +* with the GuC, protected by guc->submission_state.lock */ u16 id; /** * @ref: the number of references to the guc_id, when * transitioning in and out of zero protected by -* guc->contexts_lock +* guc->submission_state.lock */ atomic_t ref; /** -* @link: in guc->guc_id_list when the guc_id has no refs but is -* still valid, protected by guc->contexts_lock +* @link: in guc->submission_state.guc_id_list when the guc_id +* has no refs but is still valid, protected by +* guc->submission_state.lock */ struct list_head link; } guc_id; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 5dd174babf7a..c0292a94f4c3 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -70,17 +70,21 @@ struct intel_guc { void (*disable)(struct intel_guc *guc); } interrupts; - /** -* @contexts_lock: protects guc_ids, guc_id_list, ce->guc_id.id, and -* ce->guc_id.ref when transitioning in and out of zero -*/ - spinlock_t contexts_lock; - /** @guc_ids: used to allocate unique ce->guc_id.id values */ - struct ida guc_ids; - /** -* @guc_id_list: list of intel_context with valid guc_ids but no refs -*/ - struct list_head guc_id_list; + struct { + /** +* @lock: protects everything in submission_state and ce->guc_id +*/ + spinlock_t lock; + /** +* @guc_ids: used to allocate new guc_ids +*/ + struct ida guc_ids; + /** +* @guc_id_list: list of intel_context with valid guc_ids but no +* refs +*/ + struct list_head guc_id_list; + } submission_state; /** * @submission_supported: tracks whether we support GuC submission on diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index c7a41802b448..678da915eb9d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -89,7 +89,7 @@ * sched_engine can be submitting at a time. Currently only one sched_engine is * used for all of GuC submission but that could change in the future. * - * guc->contexts_lock + * guc->submission_state.lock * Protects guc_id allocation for the given GuC, i.e. only one context can be * doing guc_id allocation operations at a time for each GuC in the system. * @@ -103,7 +103,7 @@ * * Lock ordering rules: * sched_engine->lock -> ce->guc_state.lock - * guc->contexts_lock -> ce->guc_state.lock + * guc->submission_state.lock -> ce->guc_state.lock * * Reset races: * When a full GT reset is triggered it is assumed that some G2H responses to @@ -1148,9 +1148,9 @@ int intel_guc_submission_init(struct intel_guc *guc) xa_init_flags(>context_lookup, XA_FLAGS_LOCK_IRQ); - spin_lock_init(>contexts_lock); - INIT_LIST_HEAD(>guc_id_list); - ida_init(>guc_ids); + spin_lock_init(>submission_state.lock); + INIT_LIST_HEAD(>submission_state.guc_id_list); + ida_init(>submission_state.guc_ids); return 0; } @@ -1215,7 +1215,7 @@ static void guc_submit_request(struct i915_request *rq) static int new_guc_id(struct intel_guc *guc) { - return ida_simple_get(>guc_ids, 0, + return ida_simple_get(>submission_state.guc_ids, 0, GUC_MAX_LRC_DESCRIPTORS, GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN); } @@ -1223,7 +1223,8 @@ static int new_guc_id(struct
[PATCH 3/4] drm/i915/guc: Flush G2H work queue during reset
It isn't safe to scrub for missing G2H or continue with the reset until all G2H processing is complete. Flush the G2H work queue during reset to ensure it is done running. No need to call the IRQ handler directly either as the scrubbing code can deal with any missing G2H. Signed-off-by: Matthew Brost Reviewed-by: Daniele Ceraolo Spurio --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 18 +- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index ba6838a35a69..1986a57b52cc 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -800,8 +800,6 @@ static void guc_flush_submissions(struct intel_guc *guc) void intel_guc_submission_reset_prepare(struct intel_guc *guc) { - int i; - if (unlikely(!guc_submission_initialized(guc))) { /* Reset called during driver load? GuC not yet initialised! */ return; @@ -816,21 +814,7 @@ void intel_guc_submission_reset_prepare(struct intel_guc *guc) spin_unlock_irq(_to_gt(guc)->irq_lock); guc_flush_submissions(guc); - - /* -* Handle any outstanding G2Hs before reset. Call IRQ handler directly -* each pass as interrupt have been disabled. We always scrub for -* outstanding G2H as it is possible for outstanding_submission_g2h to -* be incremented after the context state update. -*/ - for (i = 0; i < 4 && atomic_read(>outstanding_submission_g2h); ++i) { - intel_guc_to_host_event_handler(guc); -#define wait_for_reset(guc, wait_var) \ - intel_guc_wait_for_pending_msg(guc, wait_var, false, (HZ / 20)) - do { - wait_for_reset(guc, >outstanding_submission_g2h); - } while (!list_empty(>ct.requests.incoming)); - } + flush_work(>ct.requests.worker); scrub_guc_desc_for_outstanding_g2h(guc); } -- 2.32.0
[PATCH 0/4] Do error capture async, flush G2H processing on reset
Rather allocating an error capture in nowait context to break a lockdep splat [1], do the error capture async compared to the G2H processing. Signed-off-by: Matthew Brost [1] https://patchwork.freedesktop.org/patch/451415/?series=93704=5 John Harrison (1): drm/i915/guc: Refcount context during error capture Matthew Brost (3): drm/i915/guc: Move guc_ids under submission_state sub-structure drm/i915/guc: Do error capture asynchronously drm/i915/guc: Flush G2H work queue during reset drivers/gpu/drm/i915/gt/intel_context.c | 2 + drivers/gpu/drm/i915/gt/intel_context_types.h | 16 ++- drivers/gpu/drm/i915/gt/uc/intel_guc.h| 36 +++-- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 133 -- 4 files changed, 128 insertions(+), 59 deletions(-) -- 2.32.0
[PATCH 4/4] drm/i915/guc: Refcount context during error capture
From: John Harrison When i915 receives a context reset notification from GuC, it triggers an error capture before resetting any outstanding requsts of that context. Unfortunately, the error capture is not a time bound operation. In certain situations it can take a long time, particularly when multiple large LMEM buffers must be read back and eoncoded. If this delay is longer than other timeouts (heartbeat, test recovery, etc.) then a full GT reset can be triggered in the middle. That can result in the context being reset by GuC actually being destroyed before the error capture completes and the GuC submission code resumes. Thus, the GuC side can start dereferencing stale pointers and Bad Things ensue. So add a refcount get of the context during the entire reset operation. That way, the context can't be destroyed part way through no matter what other resets or user interactions occur. v2: (Matthew Brost) - Update patch to work with async error capture Signed-off-by: John Harrison Signed-off-by: Matthew Brost --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 24 +-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 1986a57b52cc..02917fc4d4a8 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -2888,6 +2888,8 @@ static void capture_worker_func(struct work_struct *w) intel_engine_set_hung_context(engine, ce); with_intel_runtime_pm(>runtime_pm, wakeref) i915_capture_error_state(gt, ce->engine->mask); + + intel_context_put(ce); } static void capture_error_state(struct intel_guc *guc, @@ -2924,7 +2926,7 @@ static void guc_context_replay(struct intel_context *ce) tasklet_hi_schedule(_engine->tasklet); } -static void guc_handle_context_reset(struct intel_guc *guc, +static bool guc_handle_context_reset(struct intel_guc *guc, struct intel_context *ce) { trace_intel_context_reset(ce); @@ -2937,7 +2939,11 @@ static void guc_handle_context_reset(struct intel_guc *guc, !context_blocked(ce))) { capture_error_state(guc, ce); guc_context_replay(ce); + + return false; } + + return true; } int intel_guc_context_reset_process_msg(struct intel_guc *guc, @@ -2945,6 +2951,7 @@ int intel_guc_context_reset_process_msg(struct intel_guc *guc, { struct intel_context *ce; int desc_idx; + unsigned long flags; if (unlikely(len != 1)) { drm_err(_to_gt(guc)->i915->drm, "Invalid length %u", len); @@ -2952,11 +2959,24 @@ int intel_guc_context_reset_process_msg(struct intel_guc *guc, } desc_idx = msg[0]; + + /* +* The context lookup uses the xarray but lookups only require an RCU lock +* not the full spinlock. So take the lock explicitly and keep it until the +* context has been reference count locked to ensure it can't be destroyed +* asynchronously until the reset is done. +*/ + xa_lock_irqsave(>context_lookup, flags); ce = g2h_context_lookup(guc, desc_idx); + if (ce) + intel_context_get(ce); + xa_unlock_irqrestore(>context_lookup, flags); + if (unlikely(!ce)) return -EPROTO; - guc_handle_context_reset(guc, ce); + if (guc_handle_context_reset(guc, ce)) + intel_context_put(ce); return 0; } -- 2.32.0
[PATCH 2/4] drm/i915/guc: Do error capture asynchronously
An error capture allocates memory, memory allocations depend on resets, and resets need to flush the G2H handlers to seal several races. If the error capture is done from the G2H handler this creates a circular dependency. To work around this, do a error capture in a work queue asynchronously from the G2H handler. This should be fine as (eventually) all register state is put into a buffer by the GuC so it is safe to restart the context before the error capture is complete. Example of lockdep splat below: [ 154.625989] == [ 154.632195] WARNING: possible circular locking dependency detected [ 154.638393] 5.14.0-rc5-guc+ #50 Tainted: G U [ 154.643991] -- [ 154.650196] i915_selftest/1673 is trying to acquire lock: [ 154.655621] 8881079cb918 ((work_completion)(>requests.worker)){+.+.}-{0:0}, at: __flush_work+0x350/0x4d0 [ 154.665826] but task is already holding lock: [ 154.671682] 8881079cbfb8 (>reset.mutex){+.+.}-{3:3}, at: intel_gt_reset+0xf0/0x300 [i915] [ 154.680659] which lock already depends on the new lock. [ 154.688857] the existing dependency chain (in reverse order) is: [ 154.696365] -> #2 (>reset.mutex){+.+.}-{3:3}: [ 154.702571]lock_acquire+0xd2/0x300 [ 154.706695]i915_gem_shrinker_taints_mutex+0x2d/0x50 [i915] [ 154.712959]intel_gt_init_reset+0x61/0x80 [i915] [ 154.718258]intel_gt_init_early+0xe6/0x120 [i915] [ 154.723648]i915_driver_probe+0x592/0xdc0 [i915] [ 154.728942]i915_pci_probe+0x43/0x1c0 [i915] [ 154.733891]pci_device_probe+0x9b/0x110 [ 154.738362]really_probe+0x1a6/0x3a0 [ 154.742568]__driver_probe_device+0xf9/0x170 [ 154.747468]driver_probe_device+0x19/0x90 [ 154.752114]__driver_attach+0x99/0x170 [ 154.756492]bus_for_each_dev+0x73/0xc0 [ 154.760870]bus_add_driver+0x14b/0x1f0 [ 154.765248]driver_register+0x67/0xb0 [ 154.769542]i915_init+0x18/0x8c [i915] [ 154.773964]do_one_initcall+0x53/0x2e0 [ 154.778343]do_init_module+0x56/0x210 [ 154.782639]load_module+0x25fc/0x29f0 [ 154.786934]__do_sys_finit_module+0xae/0x110 [ 154.791835]do_syscall_64+0x38/0xc0 [ 154.795958]entry_SYSCALL_64_after_hwframe+0x44/0xae [ 154.801558] -> #1 (fs_reclaim){+.+.}-{0:0}: [ 154.807241]lock_acquire+0xd2/0x300 [ 154.811361]fs_reclaim_acquire+0x9e/0xd0 [ 154.815914]kmem_cache_alloc_trace+0x30/0x790 [ 154.820899]i915_gpu_coredump_alloc+0x53/0x1a0 [i915] [ 154.826649]i915_gpu_coredump+0x39/0x560 [i915] [ 154.831866]i915_capture_error_state+0xa/0x70 [i915] [ 154.837513]intel_guc_context_reset_process_msg+0x174/0x1f0 [i915] [ 154.844383]ct_incoming_request_worker_func+0x130/0x1b0 [i915] [ 154.850898]process_one_work+0x264/0x590 [ 154.855451]worker_thread+0x4b/0x3a0 [ 154.859655]kthread+0x147/0x170 [ 154.863428]ret_from_fork+0x1f/0x30 [ 154.867548] -> #0 ((work_completion)(>requests.worker)){+.+.}-{0:0}: [ 154.875747]check_prev_add+0x90/0xc30 [ 154.880042]__lock_acquire+0x1643/0x2110 [ 154.884595]lock_acquire+0xd2/0x300 [ 154.888715]__flush_work+0x373/0x4d0 [ 154.892920]intel_guc_submission_reset_prepare+0xf3/0x340 [i915] [ 154.899606]intel_uc_reset_prepare+0x40/0x50 [i915] [ 154.905166]reset_prepare+0x55/0x60 [i915] [ 154.909946]intel_gt_reset+0x11c/0x300 [i915] [ 154.914984]do_device_reset+0x13/0x20 [i915] [ 154.919936]check_whitelist_across_reset+0x166/0x250 [i915] [ 154.926212]live_reset_whitelist.cold+0x6a/0x7a [i915] [ 154.932037]__i915_subtests.cold+0x20/0x74 [i915] [ 154.937428]__run_selftests.cold+0x96/0xee [i915] [ 154.942816]i915_live_selftests+0x2c/0x60 [i915] [ 154.948125]i915_pci_probe+0x93/0x1c0 [i915] [ 154.953076]pci_device_probe+0x9b/0x110 [ 154.957545]really_probe+0x1a6/0x3a0 [ 154.961749]__driver_probe_device+0xf9/0x170 [ 154.966653]driver_probe_device+0x19/0x90 [ 154.971290]__driver_attach+0x99/0x170 [ 154.975671]bus_for_each_dev+0x73/0xc0 [ 154.980053]bus_add_driver+0x14b/0x1f0 [ 154.984431]driver_register+0x67/0xb0 [ 154.988725]i915_init+0x18/0x8c [i915] [ 154.993149]do_one_initcall+0x53/0x2e0 [ 154.997527]do_init_module+0x56/0x210 [ 155.001822]load_module+0x25fc/0x29f0 [ 155.006118]__do_sys_finit_module+0xae/0x110 [ 155.011019]do_syscall_64+0x38/0xc0 [ 155.015139]entry_SYSCALL_64_after_hwframe+0x44/0xae [ 155.020729] other info that might help us debug this: [ 155.028752] Chain exists of:
Re: [PATCH 1/1] lib, stackdepot: Add helper to print stack entries into buffer.
On 13/9/21 6:51 pm, Vlastimil Babka wrote: On 9/10/21 16:10, Imran Khan wrote: To print stack entries into a buffer, users of stackdepot, first get a list of stack entries using stack_depot_fetch and then print this list into a buffer using stack_trace_snprint. Provide a helper in stackdepot for this purpose. Also change above mentioned users to use this helper. Signed-off-by: Imran Khan Suggested-by: Vlastimil Babka Acked-by: Vlastimil Babka Thanks for the review. A comment below: --- a/lib/stackdepot.c +++ b/lib/stackdepot.c @@ -214,6 +214,29 @@ static inline struct stack_record *find_stack(struct stack_record *bucket, return NULL; } [...] + */ +int stack_depot_snprint(depot_stack_handle_t handle, char *buf, size_t size, + int spaces) +{ + unsigned long *entries; + unsigned int nr_entries; + + nr_entries = stack_depot_fetch(handle, ); + return stack_trace_snprint(buf, size, entries, nr_entries, 0); stack_trace_snprint() has a WARN_ON(!entries). So maybe we should not call it if nr_entries is 0 (because e.g. handle was 0) as the warnings are not useful in that case. Agree. I have addressed this feedback in v2 of patch. Thanks -- Imran
[PATCH v2 0/1] lib, stackdepot: Add helper to print stack entries into buffer.
Changes in v2: - Addressed review comment. - Added Acked from Vlastimil. - Fixed one mistake, due to which stack_trace_snprint was always getting invoked with 0 as space value. Changed it to make use of space argument, because users that are printing stack entries into buffer, may intend to specify indentation as well. I also observed build error reported at [4]. This is happening due to failure in cherry-picking this patch and this happens because the earlier patches (mentioned in original cover lette), are not there in the tree. Please let me know, if it would be better if I send earlier patches with this change as well. I can resend those patches keeping the Acked-by and Reviewed-by tags, obtained in those patches. [4] https://urldefense.com/v3/__https://patchwork.freedesktop.org/series/94553/__;!!ACWV5N9M2RV99hQ!f4tVsbn8O3mxUrGV-8udpN7kFqqQ84bFeSgkqV0aOmatwAJStZV0dkai1xkpsOSDpQ$ Original cover letter -- This change is in response to discussion at [1]. The patch has been created on top of my earlier changes [2] and [3]. If needed I can resend all of these patches together, though my earlier patches have been Acked. [1] https://lore.kernel.org/lkml/e6f6fb85-1d83-425b-9e36-b5784cc9e...@suse.cz/ [2] https://lore.kernel.org/lkml/fe94ffd8-d235-87d8-9c3d-80f7f73e0...@suse.cz/ [3] https://lore.kernel.org/lkml/85f4f073-0b5a-9052-0ba9-74d450608...@suse.cz/ Imran Khan (1): lib, stackdepot: Add helper to print stack entries into buffer. drivers/gpu/drm/drm_dp_mst_topology.c | 5 + drivers/gpu/drm/drm_mm.c| 5 + drivers/gpu/drm/i915/i915_vma.c | 5 + drivers/gpu/drm/i915/intel_runtime_pm.c | 20 +--- include/linux/stackdepot.h | 3 +++ lib/stackdepot.c| 24 mm/page_owner.c | 5 + 7 files changed, 36 insertions(+), 31 deletions(-) -- 2.30.2
[PATCH v2 1/1] lib, stackdepot: Add helper to print stack entries into buffer.
To print stack entries into a buffer, users of stackdepot, first get a list of stack entries using stack_depot_fetch and then print this list into a buffer using stack_trace_snprint. Provide a helper in stackdepot for this purpose. Also change above mentioned users to use this helper. Signed-off-by: Imran Khan Suggested-by: Vlastimil Babka Acked-by: Vlastimil Babka --- drivers/gpu/drm/drm_dp_mst_topology.c | 5 + drivers/gpu/drm/drm_mm.c| 5 + drivers/gpu/drm/i915/i915_vma.c | 5 + drivers/gpu/drm/i915/intel_runtime_pm.c | 20 +--- include/linux/stackdepot.h | 3 +++ lib/stackdepot.c| 24 mm/page_owner.c | 5 + 7 files changed, 36 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 86d13d6bc463..2d1adab9e360 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1668,13 +1668,10 @@ __dump_topology_ref_history(struct drm_dp_mst_topology_ref_history *history, for (i = 0; i < history->len; i++) { const struct drm_dp_mst_topology_ref_entry *entry = >entries[i]; - ulong *entries; - uint nr_entries; u64 ts_nsec = entry->ts_nsec; u32 rem_nsec = do_div(ts_nsec, 10); - nr_entries = stack_depot_fetch(entry->backtrace, ); - stack_trace_snprint(buf, PAGE_SIZE, entries, nr_entries, 4); + stack_depot_snprint(entry->backtrace, buf, PAGE_SIZE, 4); drm_printf(, " %d %ss (last at %5llu.%06u):\n%s", entry->count, diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 93d48a6f04ab..ca04d7f6f7b5 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -118,8 +118,6 @@ static noinline void save_stack(struct drm_mm_node *node) static void show_leaks(struct drm_mm *mm) { struct drm_mm_node *node; - unsigned long *entries; - unsigned int nr_entries; char *buf; buf = kmalloc(BUFSZ, GFP_KERNEL); @@ -133,8 +131,7 @@ static void show_leaks(struct drm_mm *mm) continue; } - nr_entries = stack_depot_fetch(node->stack, ); - stack_trace_snprint(buf, BUFSZ, entries, nr_entries, 0); + stack_depot_snprint(node->stack, buf, BUFSZ); DRM_ERROR("node [%08llx + %08llx]: inserted at\n%s", node->start, node->size, buf); } diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 4b7fc4647e46..f2d9ed375109 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -56,8 +56,6 @@ void i915_vma_free(struct i915_vma *vma) static void vma_print_allocator(struct i915_vma *vma, const char *reason) { - unsigned long *entries; - unsigned int nr_entries; char buf[512]; if (!vma->node.stack) { @@ -66,8 +64,7 @@ static void vma_print_allocator(struct i915_vma *vma, const char *reason) return; } - nr_entries = stack_depot_fetch(vma->node.stack, ); - stack_trace_snprint(buf, sizeof(buf), entries, nr_entries, 0); + stack_depot_snprint(vma->node.stack, buf, sizeof(buf), 0); DRM_DEBUG_DRIVER("vma.node [%08llx + %08llx] %s: inserted at %s\n", vma->node.start, vma->node.size, reason, buf); } diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index eaf7688f517d..cc312f0a05eb 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -65,16 +65,6 @@ static noinline depot_stack_handle_t __save_depot_stack(void) return stack_depot_save(entries, n, GFP_NOWAIT | __GFP_NOWARN); } -static void __print_depot_stack(depot_stack_handle_t stack, - char *buf, int sz, int indent) -{ - unsigned long *entries; - unsigned int nr_entries; - - nr_entries = stack_depot_fetch(stack, ); - stack_trace_snprint(buf, sz, entries, nr_entries, indent); -} - static void init_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm) { spin_lock_init(>debug.lock); @@ -146,12 +136,12 @@ static void untrack_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm, if (!buf) return; - __print_depot_stack(stack, buf, PAGE_SIZE, 2); + stack_depot_snprint(stack, buf, PAGE_SIZE, 2); DRM_DEBUG_DRIVER("wakeref %x from\n%s", stack, buf); stack = READ_ONCE(rpm->debug.last_release); if (stack) { - __print_depot_stack(stack, buf, PAGE_SIZE, 2); +
Re: [PATCH] drm/rockchip: cdn-dp-core: Fix cdn_dp_resume unused warning
On 1/14/21 11:40 PM, Palmer Dabbelt wrote: From: Palmer Dabbelt cdn_dp_resume is only used under PM_SLEEP, and now that it's static an unused function warning is triggered undner !PM_SLEEP. This conditionally enables the function to avoid the warning. Fixes: 7c49abb4c2f8 ("drm/rockchip: cdn-dp-core: Make cdn_dp_core_suspend/resume static") Signed-off-by: Palmer Dabbelt --- drivers/gpu/drm/rockchip/cdn-dp-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index a4a45daf93f2..063a60d213ba 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -1121,6 +1121,7 @@ static int cdn_dp_suspend(struct device *dev) return ret; } +#ifdef CONFIG_PM_SLEEP static int cdn_dp_resume(struct device *dev) { struct cdn_dp_device *dp = dev_get_drvdata(dev); @@ -1133,6 +1134,7 @@ static int cdn_dp_resume(struct device *dev) return 0; } +#endif static int cdn_dp_probe(struct platform_device *pdev) { Acked-by: Randy Dunlap # build-tested Is someone going to merge this patch from January? thanks. -- ~Randy
Re: [PATCH v1 1/2] drm/msm/dp: Add support for SC7280 eDP
Quoting Sankeerth Billakanti (2021-08-11 17:08:01) > The eDP controller on SC7280 is similar to the eDP/DP controllers > supported by the current driver implementation. > > SC7280 supports one EDP and one DP controller which can operate > concurrently. > > The following are some required changes for the sc7280 sink: > 1. Additional gpio configuration for backlight and pwm via pmic. > 2. ASSR support programming on the sink. > 3. SSC support programming on the sink. > > Signed-off-by: Sankeerth Billakanti > --- > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 4 ++-- > drivers/gpu/drm/msm/dp/dp_ctrl.c | 19 +++ > drivers/gpu/drm/msm/dp/dp_display.c| 32 > -- > drivers/gpu/drm/msm/dp/dp_parser.c | 31 + > drivers/gpu/drm/msm/dp/dp_parser.h | 5 > 5 files changed, 87 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c > b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c > index b131fd37..1096c44 100644 > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c > @@ -856,9 +856,9 @@ static const struct dpu_intf_cfg sm8150_intf[] = { > }; > > static const struct dpu_intf_cfg sc7280_intf[] = { > - INTF_BLK("intf_0", INTF_0, 0x34000, INTF_DP, 0, 24, INTF_SC7280_MASK, > MDP_SSPP_TOP0_INTR, 24, 25), > + INTF_BLK("intf_0", INTF_0, 0x34000, INTF_DP, 1, 24, INTF_SC7280_MASK, > MDP_SSPP_TOP0_INTR, 24, 25), > INTF_BLK("intf_1", INTF_1, 0x35000, INTF_DSI, 0, 24, > INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 26, 27), > - INTF_BLK("intf_5", INTF_5, 0x39000, INTF_EDP, 0, 24, > INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 22, 23), > + INTF_BLK("intf_5", INTF_5, 0x39000, INTF_DP, 0, 24, INTF_SC7280_MASK, > MDP_SSPP_TOP0_INTR, 22, 23), Why is this INTF_5? Instead of INTF_2? I noticed that if I changed it to INTF_2 that I could get external DP to work but not the internal eDP. Then changing it back to INTF_5 got eDP interface working but not DP. I also noticed that we changed it from INTF_EDP to INTF_DP for the eDP hardware. Can you please explain this struct? I looked at it and I still don't understand what's going on. The index (fifth element above) seems to need to match the index that is set for the address in sc7280_edp_cfg[]. If the two don't match things don't seem to work either. But then I also tried flipping that and still things didn't work. Does that index matter? Or can the first INTF_DP be 0 still?
Re: [PATCH] kernel/locking: Add context to ww_mutex_trylock.
Hi Maarten, I love your patch! Perhaps something to improve: [auto build test WARNING on regulator/for-next] [also build test WARNING on tegra-drm/drm/tegra/for-next v5.14] [cannot apply to tip/locking/core linus/master next-20210909] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Maarten-Lankhorst/kernel-locking-Add-context-to-ww_mutex_trylock/20210907-212220 base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next :: branch date: 2 days ago :: commit date: 2 days ago config: x86_64-randconfig-c007-20210908 (attached as .config) compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 9c476172b93367d2cb88d7d3f4b1b5b456fa6020) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/1e66afa09b0aa7d6db3122f0312e10d36f6fa217 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Maarten-Lankhorst/kernel-locking-Add-context-to-ww_mutex_trylock/20210907-212220 git checkout 1e66afa09b0aa7d6db3122f0312e10d36f6fa217 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 clang-analyzer If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot clang-analyzer warnings: (new ones prefixed by >>) >> kernel/locking/test-ww_mutex.c:172:2: warning: Undefined or garbage value returned to caller [clang-analyzer-core.uninitialized.UndefReturn] return ret; ^ kernel/locking/test-ww_mutex.c:639:8: note: Calling 'test_aa' ret = test_aa(true); ^ kernel/locking/test-ww_mutex.c:125:2: note: 'ret' declared without an initial value int ret; ^~~ kernel/locking/test-ww_mutex.c:126:21: note: 'trylock' is true const char *from = trylock ? "trylock" : "lock"; ^~~ kernel/locking/test-ww_mutex.c:126:21: note: '?' condition is true kernel/locking/test-ww_mutex.c:131:7: note: 'trylock' is true if (!trylock) { ^~~ kernel/locking/test-ww_mutex.c:131:2: note: Taking false branch if (!trylock) { ^ kernel/locking/test-ww_mutex.c:138:7: note: Assuming the condition is true if (!ww_mutex_trylock(, )) { ^~~ kernel/locking/test-ww_mutex.c:138:3: note: Taking true branch if (!ww_mutex_trylock(, )) { ^ kernel/locking/test-ww_mutex.c:140:4: note: Control jumps to line 171 goto out; ^ kernel/locking/test-ww_mutex.c:172:2: note: Undefined or garbage value returned to caller return ret; ^ ~~~ vim +172 kernel/locking/test-ww_mutex.c f2a5fec17395f2 Chris Wilson 2016-12-01 120 1e66afa09b0aa7 Maarten Lankhorst 2021-09-07 121 static int test_aa(bool trylock) c22fb3807fd0a3 Chris Wilson 2016-12-01 122 { c22fb3807fd0a3 Chris Wilson 2016-12-01 123struct ww_mutex mutex; c22fb3807fd0a3 Chris Wilson 2016-12-01 124struct ww_acquire_ctx ctx; c22fb3807fd0a3 Chris Wilson 2016-12-01 125int ret; 1e66afa09b0aa7 Maarten Lankhorst 2021-09-07 126const char *from = trylock ? "trylock" : "lock"; c22fb3807fd0a3 Chris Wilson 2016-12-01 127 c22fb3807fd0a3 Chris Wilson 2016-12-01 128ww_mutex_init(, _class); c22fb3807fd0a3 Chris Wilson 2016-12-01 129ww_acquire_init(, _class); c22fb3807fd0a3 Chris Wilson 2016-12-01 130 1e66afa09b0aa7 Maarten Lankhorst 2021-09-07 131if (!trylock) { 1e66afa09b0aa7 Maarten Lankhorst 2021-09-07 132ret = ww_mutex_lock(, ); 1e66afa09b0aa7 Maarten Lankhorst 2021-09-07 133if (ret) { 1e66afa09b0aa7 Maarten Lankhorst 2021-09-07 134pr_err("%s: initial lock failed!\n", __func__); 1e66afa09b0aa7 Maarten Lankhorst 2021-09-07 135goto out; 1e66afa09b0aa7 Maarten Lankhorst 2021-09-07 136} 1e66afa09b0aa7 Maarten Lankhorst 2021-09-07 137} else { 1e66afa09b0aa7 Maarten Lankhorst 2021-09-07 138if (!ww_mutex_trylock(, )) { 1e66afa09b0aa7 Maarten Lankhorst 2021-09-07 139pr_err("%s: initial trylock failed!\n", __func__); 1e66afa09b0aa7 Maarten Lankhorst 2021-09-07 140goto out; 1e66afa09b0aa7 Maarten Lankhorst 2021-09-07 141} 1e66afa09b0aa7 Maarten Lankhorst 2021-09-07
Re: [PATCH 1/8] drm/i915/gem: Break out some shmem backend utils
Hi Matthew, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on drm-tip/drm-tip] [also build test WARNING on drm-exynos/exynos-drm-next linus/master v5.15-rc1 next-20210913] [cannot apply to drm-intel/for-linux-next tegra-drm/drm/tegra/for-next drm/drm-next] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Matthew-Auld/drm-i915-gem-Break-out-some-shmem-backend-utils/20210914-021041 base: git://anongit.freedesktop.org/drm/drm-tip drm-tip config: x86_64-randconfig-a015-20210913 (attached as .config) compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 261cbe98c38f8c1ee1a482fe7650e790f58a) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/94ccd9fd87e302b0435e60b7fe7747c0d0599133 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Matthew-Auld/drm-i915-gem-Break-out-some-shmem-backend-utils/20210914-021041 git checkout 94ccd9fd87e302b0435e60b7fe7747c0d0599133 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All warnings (new ones prefixed by >>): >> drivers/gpu/drm/i915/gem/i915_gem_shmem.c:273:20: warning: variable >> 'mapping' is uninitialized when used here [-Wuninitialized] shmem_free_st(st, mapping, false, false); ^~~ drivers/gpu/drm/i915/gem/i915_gem_shmem.c:201:31: note: initialize the variable 'mapping' to silence this warning struct address_space *mapping; ^ = NULL 1 warning generated. vim +/mapping +273 drivers/gpu/drm/i915/gem/i915_gem_shmem.c 195 196 static int shmem_get_pages(struct drm_i915_gem_object *obj) 197 { 198 struct drm_i915_private *i915 = to_i915(obj->base.dev); 199 struct intel_memory_region *mem = obj->mm.region; 200 const unsigned long page_count = obj->base.size / PAGE_SIZE; 201 struct address_space *mapping; 202 struct sg_table *st; 203 struct sgt_iter sgt_iter; 204 struct page *page; 205 unsigned int max_segment = i915_sg_segment_size(); 206 int ret; 207 208 /* 209 * Assert that the object is not currently in any GPU domain. As it 210 * wasn't in the GTT, there shouldn't be any way it could have been in 211 * a GPU cache 212 */ 213 GEM_BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS); 214 GEM_BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS); 215 216 rebuild_st: 217 st = shmem_alloc_st(i915, obj->base.size, mem, 218 obj->base.filp->f_mapping, max_segment); 219 if (IS_ERR(st)) { 220 ret = PTR_ERR(st); 221 goto err_st; 222 } 223 224 ret = i915_gem_gtt_prepare_pages(obj, st); 225 if (ret) { 226 /* 227 * DMA remapping failed? One possible cause is that 228 * it could not reserve enough large entries, asking 229 * for PAGE_SIZE chunks instead may be helpful. 230 */ 231 if (max_segment > PAGE_SIZE) { 232 for_each_sgt_page(page, sgt_iter, st) 233 put_page(page); 234 sg_free_table(st); 235 kfree(st); 236 237 max_segment = PAGE_SIZE; 238 goto rebuild_st; 239 } else { 240 dev_warn(i915->drm.dev, 241 "Failed to DMA remap %lu pages\n", 242 page_count); 243 goto err_pages; 244 } 245 } 246 247 if (i915_gem_object_needs_bit17_swizzle(obj)) 248 i915_gem_object_do_bit_17_swizzle(obj, st); 249 250 /* 251 * EHL and JSL add the 'Bypass LLC' MOCS entry, which should make it 252 * possible for userspace to bypass the GTT caching bits set by the 253 * kernel, as per the given object cache_level. This is
RE: [RFC][PATCH] drm/amdgpu/powerplay/smu10: Add custom profile
[AMD Official Use Only] Driver can exchange the custom profiling settings with SMU FW using the table below: TABLE_CUSTOM_DPM And the related data structure is CustomDpmSettings_t. BR Evan > -Original Message- > From: Alex Deucher > Sent: Monday, September 13, 2021 11:11 PM > To: Daniel Gomez ; Huang, Ray ; > Quan, Evan ; Zhu, Changfeng > > Cc: amd-gfx list ; Maling list - DRI > developers ; Daniel Gomez > ; Deucher, Alexander > ; Koenig, Christian > ; Pan, Xinhui > Subject: Re: [RFC][PATCH] drm/amdgpu/powerplay/smu10: Add custom > profile > > On Wed, Sep 8, 2021 at 3:23 AM Daniel Gomez wrote: > > > > On Tue, 7 Sept 2021 at 19:23, Alex Deucher > wrote: > > > > > > On Tue, Sep 7, 2021 at 4:53 AM Daniel Gomez wrote: > > > > > > > > Add custom power profile mode support on smu10. > > > > Update workload bit list. > > > > --- > > > > > > > > Hi, > > > > > > > > I'm trying to add custom profile for the Raven Ridge but not sure > > > > if I'd need a different parameter than PPSMC_MSG_SetCustomPolicy > > > > to configure the custom values. The code seemed to support CUSTOM > > > > for workload types but it didn't show up in the menu or accept any > > > > user input parameter. So far, I've added that part but a bit > > > > confusing to me what is the policy I need for setting these > > > > parameters or if it's maybe not possible at all. > > > > > > > > After applying the changes I'd configure the CUSTOM mode as follows: > > > > > > > > echo manual > > > > > > /sys/class/drm/card0/device/hwmon/hwmon1/device/power_dpm_force_ > pe > > > > rformance_level echo "6 70 90 0 0" > > > > > > /sys/class/drm/card0/device/hwmon/hwmon1/device/pp_power_profile_ > m > > > > ode > > > > > > > > Then, using Darren Powell script for testing modes I get the > > > > following > > > > output: > > > > > > > > 05:00.0 VGA compatible controller [0300]: Advanced Micro Devices, > > > > Inc. [AMD/ATI] Raven Ridge [Radeon Vega Series / Radeon Vega > > > > Mobile Series] [1002:15dd] (rev 83) === pp_dpm_sclk === > > > > 0: 200Mhz > > > > 1: 400Mhz * > > > > 2: 1100Mhz > > > > === pp_dpm_mclk === > > > > 0: 400Mhz > > > > 1: 933Mhz * > > > > 2: 1067Mhz > > > > 3: 1200Mhz > > > > === pp_power_profile_mode === > > > > NUMMODE_NAME BUSY_SET_POINT FPS USE_RLC_BUSY > MIN_ACTIVE_LEVEL > > > > 0 BOOTUP_DEFAULT : 70 60 0 0 > > > > 1 3D_FULL_SCREEN : 70 60 1 3 > > > > 2 POWER_SAVING : 90 60 0 0 > > > > 3 VIDEO : 70 60 0 0 > > > > 4 VR : 70 90 0 0 > > > > 5COMPUTE : 30 60 0 6 > > > > 6 CUSTOM*: 70 90 0 0 > > > > > > > > As you can also see in my changes, I've also updated the workload > > > > bit table but I'm not completely sure about that change. With the > > > > tests I've done, using bit 5 for the WORKLOAD_PPLIB_CUSTOM_BIT > > > > makes the gpu sclk locked around ~36%. So, maybe I'm missing a > > > > clock limit configuraton table somewhere. Would you give me some > > > > hints to proceed with this? > > > > > > I don't think APUs support customizing the workloads the same way > > > dGPUs do. I think they just support predefined profiles. > > > > > > Alex > > > > > > Thanks Alex for the quick response. Would it make sense then to remove > > the custom workload code (PP_SMC_POWER_PROFILE_CUSTOM) from the > smu10? > > That workload was added in this commit: > > f6f75ebdc06c04d3cfcd100f1b10256a9cdca407 [1] and not use at all in the > > code as it's limited to PP_SMC_POWER_PROFILE_COMPUTE index. The > > smu10.h also includes the custom workload bit definition and that was > > a bit confusing for me to understand if it was half-supported or not > > possible to use at all as I understood from your comment. > > > > Perhaps could also be mentioned (if that's kind of standard) in the > > documentation[2] so, the custom pp_power_profile_mode is only > > supported in dGPUs. > > > > I can send the patches if it makes sense. > > I guess I was thinking of another asic. @Huang Rui, @changzhu, @Quan, > Evan can any of you comment on what is required for custom profiles on > APUs? > > Alex > > > > > > [1]: > > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit. > > > kernel.org%2Fpub%2Fscm%2Flinux%2Fkernel%2Fgit%2Ftorvalds%2Flinux.git > %2 > > > Fcommit%2Fdrivers%2Fgpu%2Fdrm%2Famd%2Fpm%2Fpowerplay%2Fhwmg > r%2Fsmu10_h > > > wmgr.c%3Fid%3Df6f75ebdc06c04d3cfcd100f1b10256a9cdca407data=0 > 4%7C0 > > > 1%7CEvan.Quan%40amd.com%7Cfdb9fc6f03f84cb69dc608d976c8b517%7C3d > d8961fe > > > 4884e608e11a82d994e183d%7C0%7C0%7C637671426675410633%7CUnknown > %7CTWFpb > > > GZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI > 6Mn0 > > %3D%7C1000sdata=Nsmj%2BgJpv9QZj%2FKF57E9n7LJfcOc9Jg51jy0h > eOPTRI%3 > > Dreserved=0 > > [2]:
Re: [Intel-gfx] [PATCH 07/14] drm/i915/hdcp: Use HDCP helpers for i915
Hi Sean, I love your patch! Yet something to improve: [auto build test ERROR on drm-tip/drm-tip] [cannot apply to drm-intel/for-linux-next drm-exynos/exynos-drm-next tegra-drm/drm/tegra/for-next linus/master drm/drm-next v5.15-rc1 next-20210913] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Sean-Paul/drm-hdcp-Pull-HDCP-auth-exchange-check-into/20210914-020004 base: git://anongit.freedesktop.org/drm/drm-tip drm-tip config: x86_64-allyesconfig (attached as .config) compiler: gcc-9 (Debian 9.3.0-22) 9.3.0 reproduce (this is a W=1 build): # https://github.com/0day-ci/linux/commit/995396b306d5f83dea2943ecc2718f344a80d46e git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Sean-Paul/drm-hdcp-Pull-HDCP-auth-exchange-check-into/20210914-020004 git checkout 995396b306d5f83dea2943ecc2718f344a80d46e # save the attached .config to linux build tree make W=1 ARCH=x86_64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All errors (new ones prefixed by >>): >> drivers/gpu/drm/i915/display/intel_dp_hdcp.c:658:43: error: >> 'intel_dp_mst_hdcp_helper_funcs' defined but not used >> [-Werror=unused-const-variable=] 658 | static const struct drm_hdcp_helper_funcs intel_dp_mst_hdcp_helper_funcs = { | ^~ cc1: all warnings being treated as errors vim +/intel_dp_mst_hdcp_helper_funcs +658 drivers/gpu/drm/i915/display/intel_dp_hdcp.c 657 > 658 static const struct drm_hdcp_helper_funcs > intel_dp_mst_hdcp_helper_funcs = { 659 .setup = intel_hdcp_setup, 660 .load_keys = intel_hdcp_load_keys, 661 .hdcp2_capable = intel_dp_hdcp2_capable, 662 .hdcp2_enable = intel_hdcp2_enable, 663 .hdcp2_check_link = intel_hdcp2_check_link, 664 .hdcp2_disable = intel_hdcp2_disable, 665 .hdcp1_send_an_aksv = intel_dp_hdcp1_send_an_aksv, 666 .hdcp1_store_receiver_info = intel_hdcp1_store_receiver_info, 667 .hdcp1_enable_encryption = intel_hdcp1_enable_encryption, 668 .hdcp1_wait_for_r0 = intel_hdcp1_wait_for_r0, 669 .hdcp1_match_ri = intel_hdcp1_match_ri, 670 .hdcp1_post_encryption = intel_dp_mst_hdcp1_post_encryption, 671 .hdcp1_store_ksv_fifo = intel_hdcp1_store_ksv_fifo, 672 .hdcp1_disable = intel_dp_mst_hdcp1_disable, 673 }; 674 675 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org .config.gz Description: application/gzip
Re: [virtio-dev] [PATCH v1 09/12] drm/virtio: implement context init: allocate an array of fence contexts
On Mon, Sep 13, 2021 at 11:52 AM Chia-I Wu wrote: > . > > On Mon, Sep 13, 2021 at 10:48 AM Gurchetan Singh > wrote: > > > > > > > > On Fri, Sep 10, 2021 at 12:33 PM Chia-I Wu wrote: > >> > >> On Wed, Sep 8, 2021 at 6:37 PM Gurchetan Singh > >> wrote: > >> > > >> > We don't want fences from different 3D contexts (virgl, gfxstream, > >> > venus) to be on the same timeline. With explicit context creation, > >> > we can specify the number of ring each context wants. > >> > > >> > Execbuffer can specify which ring to use. > >> > > >> > Signed-off-by: Gurchetan Singh > >> > Acked-by: Lingfeng Yang > >> > --- > >> > drivers/gpu/drm/virtio/virtgpu_drv.h | 3 +++ > >> > drivers/gpu/drm/virtio/virtgpu_ioctl.c | 34 > -- > >> > 2 files changed, 35 insertions(+), 2 deletions(-) > >> > > >> > diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h > b/drivers/gpu/drm/virtio/virtgpu_drv.h > >> > index a5142d60c2fa..cca9ab505deb 100644 > >> > --- a/drivers/gpu/drm/virtio/virtgpu_drv.h > >> > +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h > >> > @@ -56,6 +56,7 @@ > >> > #define STATE_ERR 2 > >> > > >> > #define MAX_CAPSET_ID 63 > >> > +#define MAX_RINGS 64 > >> > > >> > struct virtio_gpu_object_params { > >> > unsigned long size; > >> > @@ -263,6 +264,8 @@ struct virtio_gpu_fpriv { > >> > uint32_t ctx_id; > >> > uint32_t context_init; > >> > bool context_created; > >> > + uint32_t num_rings; > >> > + uint64_t base_fence_ctx; > >> > struct mutex context_lock; > >> > }; > >> > > >> > diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c > b/drivers/gpu/drm/virtio/virtgpu_ioctl.c > >> > index f51f3393a194..262f79210283 100644 > >> > --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c > >> > +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c > >> > @@ -99,6 +99,11 @@ static int virtio_gpu_execbuffer_ioctl(struct > drm_device *dev, void *data, > >> > int in_fence_fd = exbuf->fence_fd; > >> > int out_fence_fd = -1; > >> > void *buf; > >> > + uint64_t fence_ctx; > >> > + uint32_t ring_idx; > >> > + > >> > + fence_ctx = vgdev->fence_drv.context; > >> > + ring_idx = 0; > >> > > >> > if (vgdev->has_virgl_3d == false) > >> > return -ENOSYS; > >> > @@ -106,6 +111,17 @@ static int virtio_gpu_execbuffer_ioctl(struct > drm_device *dev, void *data, > >> > if ((exbuf->flags & ~VIRTGPU_EXECBUF_FLAGS)) > >> > return -EINVAL; > >> > > >> > + if ((exbuf->flags & VIRTGPU_EXECBUF_RING_IDX)) { > >> > + if (exbuf->ring_idx >= vfpriv->num_rings) > >> > + return -EINVAL; > >> > + > >> > + if (!vfpriv->base_fence_ctx) > >> > + return -EINVAL; > >> > + > >> > + fence_ctx = vfpriv->base_fence_ctx; > >> > + ring_idx = exbuf->ring_idx; > >> > + } > >> > + > >> > exbuf->fence_fd = -1; > >> > > >> > virtio_gpu_create_context(dev, file); > >> > @@ -173,7 +189,7 @@ static int virtio_gpu_execbuffer_ioctl(struct > drm_device *dev, void *data, > >> > goto out_memdup; > >> > } > >> > > >> > - out_fence = virtio_gpu_fence_alloc(vgdev, > vgdev->fence_drv.context, 0); > >> > + out_fence = virtio_gpu_fence_alloc(vgdev, fence_ctx, > ring_idx); > >> > if(!out_fence) { > >> > ret = -ENOMEM; > >> > goto out_unresv; > >> > @@ -691,7 +707,7 @@ static int virtio_gpu_context_init_ioctl(struct > drm_device *dev, > >> > return -EINVAL; > >> > > >> > /* Number of unique parameters supported at this time. */ > >> > - if (num_params > 1) > >> > + if (num_params > 2) > >> > return -EINVAL; > >> > > >> > ctx_set_params = > memdup_user(u64_to_user_ptr(args->ctx_set_params), > >> > @@ -731,6 +747,20 @@ static int virtio_gpu_context_init_ioctl(struct > drm_device *dev, > >> > > >> > vfpriv->context_init |= value; > >> > break; > >> > + case VIRTGPU_CONTEXT_PARAM_NUM_RINGS: > >> > + if (vfpriv->base_fence_ctx) { > >> > + ret = -EINVAL; > >> > + goto out_unlock; > >> > + } > >> > + > >> > + if (value > MAX_RINGS) { > >> > + ret = -EINVAL; > >> > + goto out_unlock; > >> > + } > >> > + > >> > + vfpriv->base_fence_ctx = > dma_fence_context_alloc(value); > >> With multiple fence contexts, we should do something about implicit > fencing. > >> > >> The classic example is Mesa and X server. When both use virgl and the > >> global fence context, no dma_fence_wait is fine. But when Mesa uses > >> venus and the ring fence context, dma_fence_wait should be inserted. > > > > > >
Re: [PATCH 13/14] drm/msm: Add hdcp register ranges to sc7180 device tree
Quoting Sean Paul (2021-09-13 10:57:44) > From: Sean Paul > > This patch adds the register ranges required for HDCP to the sc7180 > device tree. These registers will be used to inject HDCP key as well as > toggle HDCP on and off. It doesn't look to do any of that? > > Signed-off-by: Sean Paul > --- > drivers/gpu/drm/msm/dp/dp_parser.c | 30 +++--- > drivers/gpu/drm/msm/dp/dp_parser.h | 4 > 2 files changed, 31 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c > b/drivers/gpu/drm/msm/dp/dp_parser.c > index 0519dd3ac3c3..4bbe2485ce3c 100644 > --- a/drivers/gpu/drm/msm/dp/dp_parser.c > +++ b/drivers/gpu/drm/msm/dp/dp_parser.c > @@ -20,11 +20,19 @@ static const struct dp_regulator_cfg sdm845_dp_reg_cfg = { > }; > > static int msm_dss_ioremap(struct platform_device *pdev, > - struct dss_io_data *io_data) > + struct dss_io_data *io_data, const char *name, > + int fallback_idx) > { > struct resource *res = NULL; > > - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); > + > + /* Support dts which do not have named resources */ Please no. Just use index and know that 0 is the dp hardware, 1 is the hdcp key and 2 is the tz interaction zone. There is some backwards compat logic to maintain for when it was split out but I hope we can drop that soon. Alternatively we could make a new compatible and then not care about future conflicts. > + if (!res) { > + if (fallback_idx >= 0) > + res = platform_get_resource(pdev, IORESOURCE_MEM, > + fallback_idx); > + } > if (!res) { > DRM_ERROR("%pS->%s: msm_dss_get_res failed\n", > __builtin_return_address(0), __func__); > @@ -55,6 +63,8 @@ static void dp_parser_unmap_io_resources(struct dp_parser > *parser) > { > struct dp_io *io = >io; > > + msm_dss_iounmap(>hdcp_tz); > + msm_dss_iounmap(>hdcp_key); > msm_dss_iounmap(>dp_controller); > } > > @@ -64,12 +74,26 @@ static int dp_parser_ctrl_res(struct dp_parser *parser) > struct platform_device *pdev = parser->pdev; > struct dp_io *io = >io; > > - rc = msm_dss_ioremap(pdev, >dp_controller); > + rc = msm_dss_ioremap(pdev, >dp_controller, "dp_controller", 0); > if (rc) { > DRM_ERROR("unable to remap dp io resources, rc=%d\n", rc); > goto err; > } > > + rc = msm_dss_ioremap(pdev, >hdcp_key, "hdcp_key", -1); > + if (rc) { > + DRM_INFO("unable to remap dp hdcp resources, rc=%d\n", rc); > + io->hdcp_key.base = NULL; > + io->hdcp_key.len = 0; > + } > + > + rc = msm_dss_ioremap(pdev, >hdcp_tz, "hdcp_tz", -1); > + if (rc) { > + DRM_INFO("unable to remap dp hdcp resources, rc=%d\n", rc); These shouldn't be info messages. Also, the ioremap wrapper already prints the message that it failed so these are redundant. > + io->hdcp_tz.base = NULL; > + io->hdcp_tz.len = 0; > + } > + > io->phy = devm_phy_get(>dev, "dp"); > if (IS_ERR(io->phy)) { > rc = PTR_ERR(io->phy);
Re: [Intel-gfx] [PATCH 10/27] drm/i915/guc: Introduce context parent-child relationship
On Mon, Sep 13, 2021 at 04:19:00PM -0700, John Harrison wrote: > On 8/20/2021 15:44, Matthew Brost wrote: > > Introduce context parent-child relationship. Once this relationship is > > created all pinning / unpinning operations are directed to the parent > > context. The parent context is responsible for pinning all of its' > > children and itself. > > > > This is a precursor to the full GuC multi-lrc implementation but aligns > > to how GuC mutli-lrc interface is defined - a single H2G is used > > register / deregister all of the contexts simultaneously. > > > > Subsequent patches in the series will implement the pinning / unpinning > > operations for parent / child contexts. > > > > v2: > > (Daniel Vetter) > >- Add kernel doc, add wrapper to access parent to ensure safety > > > > Signed-off-by: Matthew Brost > > --- > > drivers/gpu/drm/i915/gt/intel_context.c | 29 ++ > > drivers/gpu/drm/i915/gt/intel_context.h | 39 +++ > > drivers/gpu/drm/i915/gt/intel_context_types.h | 23 +++ > > 3 files changed, 91 insertions(+) > > > > diff --git a/drivers/gpu/drm/i915/gt/intel_context.c > > b/drivers/gpu/drm/i915/gt/intel_context.c > > index 508cfe5770c0..00d1aee6d199 100644 > > --- a/drivers/gpu/drm/i915/gt/intel_context.c > > +++ b/drivers/gpu/drm/i915/gt/intel_context.c > > @@ -404,6 +404,8 @@ intel_context_init(struct intel_context *ce, struct > > intel_engine_cs *engine) > > INIT_LIST_HEAD(>destroyed_link); > No need for this blank line? > I guess but typically I try to put blank lines between each different set of variables (e.g. a lock and list would next to each other if the lock protects the list, two different lists would have a blank line like this case here). > > + INIT_LIST_HEAD(>guc_child_list); > > + > > /* > > * Initialize fence to be complete as this is expected to be complete > > * unless there is a pending schedule disable outstanding. > > @@ -418,10 +420,17 @@ intel_context_init(struct intel_context *ce, struct > > intel_engine_cs *engine) > > void intel_context_fini(struct intel_context *ce) > > { > > + struct intel_context *child, *next; > > + > > if (ce->timeline) > > intel_timeline_put(ce->timeline); > > i915_vm_put(ce->vm); > > + /* Need to put the creation ref for the children */ > > + if (intel_context_is_parent(ce)) > > + for_each_child_safe(ce, child, next) > > + intel_context_put(child); > > + > > mutex_destroy(>pin_mutex); > > i915_active_fini(>active); > > } > > @@ -537,6 +546,26 @@ struct i915_request > > *intel_context_find_active_request(struct intel_context *ce) > > return active; > > } > > +void intel_context_bind_parent_child(struct intel_context *parent, > > +struct intel_context *child) > > +{ > > + /* > > +* Callers responsibility to validate that this function is used > > +* correctly but we use GEM_BUG_ON here ensure that they do. > > +*/ > > + GEM_BUG_ON(!intel_engine_uses_guc(parent->engine)); > > + GEM_BUG_ON(intel_context_is_pinned(parent)); > > + GEM_BUG_ON(intel_context_is_child(parent)); > > + GEM_BUG_ON(intel_context_is_pinned(child)); > > + GEM_BUG_ON(intel_context_is_child(child)); > > + GEM_BUG_ON(intel_context_is_parent(child)); > > + > > + parent->guc_number_children++; > > + list_add_tail(>guc_child_link, > > + >guc_child_list); > > + child->parent = parent; > > +} > > + > > #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) > > #include "selftest_context.c" > > #endif > > diff --git a/drivers/gpu/drm/i915/gt/intel_context.h > > b/drivers/gpu/drm/i915/gt/intel_context.h > > index c41098950746..c2985822ab74 100644 > > --- a/drivers/gpu/drm/i915/gt/intel_context.h > > +++ b/drivers/gpu/drm/i915/gt/intel_context.h > > @@ -44,6 +44,45 @@ void intel_context_free(struct intel_context *ce); > > int intel_context_reconfigure_sseu(struct intel_context *ce, > >const struct intel_sseu sseu); > > +static inline bool intel_context_is_child(struct intel_context *ce) > > +{ > > + return !!ce->parent; > > +} > > + > > +static inline bool intel_context_is_parent(struct intel_context *ce) > > +{ > > + return !!ce->guc_number_children; > > +} > > + > > +static inline bool intel_context_is_pinned(struct intel_context *ce); > No point declaring 'static inline' if there is no function body? > Forward delc for the below function. > > + > > +static inline struct intel_context * > > +intel_context_to_parent(struct intel_context *ce) > > +{ > > +if (intel_context_is_child(ce)) { > > + /* > > +* The parent holds ref count to the child so it is always safe > > +* for the parent to access the child, but the child has pointer > has pointer -> has a pointer > Yep. > > +* to the parent without a ref. To ensure this is safe the child > > +*
Re: [PATCH 12/14] dt-bindings: msm/dp: Add bindings for HDCP registers
Quoting Sean Paul (2021-09-13 10:57:43) > diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml > b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml > index 64d8d9e5e47a..984301442653 100644 > --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml > +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml > @@ -21,6 +21,11 @@ properties: >reg: > maxItems: 1 > > + reg-names: > +const: dp_controller > +const: hdcp_key > +const: hdcp_tz Perhaps we should drop reg-names and assume index 1 is hdcp_key and index 2 is hdcp_tz? And then make them optional by having minItems: 1 on the reg property. > + >interrupts: > maxItems: 1 >
Re: [Intel-gfx] [PATCH 06/27] drm/i915/guc: Take engine PM when a context is pinned with GuC submission
On Mon, Sep 13, 2021 at 03:26:29PM -0700, John Harrison wrote: > On 9/9/2021 17:41, Matthew Brost wrote: > > On Thu, Sep 09, 2021 at 03:46:43PM -0700, John Harrison wrote: > > > On 8/20/2021 15:44, Matthew Brost wrote: > > > > Taking a PM reference to prevent intel_gt_wait_for_idle from short > > > > circuiting while a scheduling of user context could be enabled. > > > As with earlier PM patch, needs more explanation of what the problem is > > > and > > > why it is only now a problem. > > > > > > > > Same explaination, will add here. > > > > > > v2: > > > >(Daniel Vetter) > > > > - Add might_lock annotations to pin / unpin function > > > > > > > > Signed-off-by: Matthew Brost > > > > --- > > > >drivers/gpu/drm/i915/gt/intel_context.c | 3 ++ > > > >drivers/gpu/drm/i915/gt/intel_engine_pm.h | 15 > > > >drivers/gpu/drm/i915/gt/intel_gt_pm.h | 10 ++ > > > >.../gpu/drm/i915/gt/uc/intel_guc_submission.c | 36 > > > > +-- > > > >drivers/gpu/drm/i915/intel_wakeref.h | 12 +++ > > > >5 files changed, 73 insertions(+), 3 deletions(-) > > > > > > > > diff --git a/drivers/gpu/drm/i915/gt/intel_context.c > > > > b/drivers/gpu/drm/i915/gt/intel_context.c > > > > index c8595da64ad8..508cfe5770c0 100644 > > > > --- a/drivers/gpu/drm/i915/gt/intel_context.c > > > > +++ b/drivers/gpu/drm/i915/gt/intel_context.c > > > > @@ -240,6 +240,8 @@ int __intel_context_do_pin_ww(struct intel_context > > > > *ce, > > > > if (err) > > > > goto err_post_unpin; > > > > + intel_engine_pm_might_get(ce->engine); > > > > + > > > > if (unlikely(intel_context_is_closed(ce))) { > > > > err = -ENOENT; > > > > goto err_unlock; > > > > @@ -313,6 +315,7 @@ void __intel_context_do_unpin(struct intel_context > > > > *ce, int sub) > > > > return; > > > > CE_TRACE(ce, "unpin\n"); > > > > + intel_engine_pm_might_put(ce->engine); > > > > ce->ops->unpin(ce); > > > > ce->ops->post_unpin(ce); > > > > diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.h > > > > b/drivers/gpu/drm/i915/gt/intel_engine_pm.h > > > > index 17a5028ea177..3fe2ae1bcc26 100644 > > > > --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.h > > > > +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.h > > > > @@ -9,6 +9,7 @@ > > > >#include "i915_request.h" > > > >#include "intel_engine_types.h" > > > >#include "intel_wakeref.h" > > > > +#include "intel_gt_pm.h" > > > >static inline bool > > > >intel_engine_pm_is_awake(const struct intel_engine_cs *engine) > > > > @@ -31,6 +32,13 @@ static inline bool > > > > intel_engine_pm_get_if_awake(struct intel_engine_cs *engine) > > > > return intel_wakeref_get_if_active(>wakeref); > > > >} > > > > +static inline void intel_engine_pm_might_get(struct intel_engine_cs > > > > *engine) > > > > +{ > > > > + if (!intel_engine_is_virtual(engine)) > > > > + intel_wakeref_might_get(>wakeref); > > > Why doesn't this need to iterate through the physical engines of the > > > virtual > > > engine? > > > > > Yea, technically it should. This is just an annotation though to check > > if we do something horribly wrong in our code. If we use any physical > > engine in our stack this annotation should pop and we can fix it. I just > > don't see what making this 100% correct for virtual engines buys us. If > > you want I can fix this but thinking the more complex we make this > > annotation the less likely it just gets compiled out with lockdep off > > which is what we are aiming for. > But if the annotation is missing a fundamental lock then it is surely not > actually going to do any good? Not sure if you need to iterate over all > child engines + parent but it seems like you should be calling might_lock() > on at least one engine's mutex to feed the lockdep annotation. > These are all inline functions so the compiler to be able to compile this out if lockdep is disabled. I'll fix this in the next rev. Matt > John. > > > Matt > > > > > John. > > > > > > > + intel_gt_pm_might_get(engine->gt); > > > > +} > > > > + > > > >static inline void intel_engine_pm_put(struct intel_engine_cs > > > > *engine) > > > >{ > > > > intel_wakeref_put(>wakeref); > > > > @@ -52,6 +60,13 @@ static inline void intel_engine_pm_flush(struct > > > > intel_engine_cs *engine) > > > > intel_wakeref_unlock_wait(>wakeref); > > > >} > > > > +static inline void intel_engine_pm_might_put(struct intel_engine_cs > > > > *engine) > > > > +{ > > > > + if (!intel_engine_is_virtual(engine)) > > > > + intel_wakeref_might_put(>wakeref); > > > > + intel_gt_pm_might_put(engine->gt); > > > > +} > > > > + > > > >static inline struct i915_request * > > > >intel_engine_create_kernel_request(struct intel_engine_cs *engine) > > > >{ > > > > diff --git
Re: [Intel-gfx] [PATCH 09/27] drm/i915: Expose logical engine instance to user
On Mon, Sep 13, 2021 at 04:06:33PM -0700, John Harrison wrote: > On 8/20/2021 15:44, Matthew Brost wrote: > > Expose logical engine instance to user via query engine info IOCTL. This > > is required for split-frame workloads as these needs to be placed on > > engines in a logically contiguous order. The logical mapping can change > > based on fusing. Rather than having user have knowledge of the fusing we > > simply just expose the logical mapping with the existing query engine > > info IOCTL. > > > > IGT: https://patchwork.freedesktop.org/patch/445637/?series=92854=1 > > media UMD: link coming soon > > > > v2: > > (Daniel Vetter) > >- Add IGT link, placeholder for media UMD > > > > Cc: Tvrtko Ursulin > > Signed-off-by: Matthew Brost > > --- > > drivers/gpu/drm/i915/i915_query.c | 2 ++ > > include/uapi/drm/i915_drm.h | 8 +++- > > 2 files changed, 9 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/i915/i915_query.c > > b/drivers/gpu/drm/i915/i915_query.c > > index e49da36c62fb..8a72923fbdba 100644 > > --- a/drivers/gpu/drm/i915/i915_query.c > > +++ b/drivers/gpu/drm/i915/i915_query.c > > @@ -124,7 +124,9 @@ query_engine_info(struct drm_i915_private *i915, > > for_each_uabi_engine(engine, i915) { > > info.engine.engine_class = engine->uabi_class; > > info.engine.engine_instance = engine->uabi_instance; > > + info.flags = I915_ENGINE_INFO_HAS_LOGICAL_INSTANCE; > > info.capabilities = engine->uabi_capabilities; > > + info.logical_instance = ilog2(engine->logical_mask); > > if (copy_to_user(info_ptr, , sizeof(info))) > > return -EFAULT; > > diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h > > index bde5860b3686..b1248a67b4f8 100644 > > --- a/include/uapi/drm/i915_drm.h > > +++ b/include/uapi/drm/i915_drm.h > > @@ -2726,14 +2726,20 @@ struct drm_i915_engine_info { > > /** @flags: Engine flags. */ > > __u64 flags; > > +#define I915_ENGINE_INFO_HAS_LOGICAL_INSTANCE (1 << 0) > > /** @capabilities: Capabilities of this engine. */ > > __u64 capabilities; > > #define I915_VIDEO_CLASS_CAPABILITY_HEVC (1 << 0) > > #define I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC (1 << 1) > > + /** @logical_instance: Logical instance of engine */ > > + __u16 logical_instance; > > + > > /** @rsvd1: Reserved fields. */ > > - __u64 rsvd1[4]; > > + __u16 rsvd1[3]; > > + /** @rsvd2: Reserved fields. */ > > + __u64 rsvd2[3]; > > }; > > /** > Any idea why the padding? Would be useful if the comment said 'this > structure must be at least/exactly X bytes in size / a multiple of X bytes > in size because ...' or whatever. > I think this is pretty standard in UABI interface - add a bunch of padding bits in case you need them in the future (i.e. this patch is an example of that). Matt > However, not really anything to do with this patch as such, so either way: > Reviewed-by: John Harrison >
Re: [RFC PATCH v2 1/2] drm/bridge: parade-ps8640: Use regmap APIs
Hi, On Mon, Sep 13, 2021 at 2:33 PM Philip Chen wrote: > > diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c > b/drivers/gpu/drm/bridge/parade-ps8640.c > index 685e9c38b2db..1b2414601538 100644 > --- a/drivers/gpu/drm/bridge/parade-ps8640.c > +++ b/drivers/gpu/drm/bridge/parade-ps8640.c > @@ -9,6 +9,7 @@ > #include > #include > #include > +#include > #include > > #include > @@ -31,6 +32,11 @@ > > #define NUM_MIPI_LANES 4 > > +#define COMMON_PS8640_REGMAP_CONFIG \ > + .reg_bits = 8, \ > + .val_bits = 8, \ > + .cache_type = REGCACHE_NONE At some point we should see if we get any speed gains by actually caching, but that could be done later and isn't terribly high priority. > + > /* > * PS8640 uses multiple addresses: > * page[0]: for DP control > @@ -64,12 +70,48 @@ struct ps8640 { > struct drm_bridge *panel_bridge; > struct mipi_dsi_device *dsi; > struct i2c_client *page[MAX_DEVS]; > + struct regmap *regmap[MAX_DEVS]; > struct regulator_bulk_data supplies[2]; > struct gpio_desc *gpio_reset; > struct gpio_desc *gpio_powerdown; > bool powered; > }; > > +static const struct regmap_config ps8640_regmap_config[] = { > + [PAGE0_DP_CNTL] = { > + COMMON_PS8640_REGMAP_CONFIG, > + .max_register = 0xbf > + }, > + [PAGE1_VDO_BDG] = { > + COMMON_PS8640_REGMAP_CONFIG, > + .max_register = 0xff > + }, > + [PAGE2_TOP_CNTL] = { > + COMMON_PS8640_REGMAP_CONFIG, > + .max_register = 0xff > + }, > + [PAGE3_DSI_CNTL1] = { > + COMMON_PS8640_REGMAP_CONFIG, > + .max_register = 0xff > + }, > + [PAGE4_MIPI_PHY] = { > + COMMON_PS8640_REGMAP_CONFIG, > + .max_register = 0xff > + }, > + [PAGE5_VPLL] = { > + COMMON_PS8640_REGMAP_CONFIG, > + .max_register = 0x7f > + }, > + [PAGE6_DSI_CNTL2] = { > + COMMON_PS8640_REGMAP_CONFIG, > + .max_register = 0xff > + }, > + [PAGE7_SPI_CNTL] = { > + COMMON_PS8640_REGMAP_CONFIG, > + .max_register = 0xff > + } nit: stylistically it's nice to add a "," after the last brace too. It's not technically needed but it makes diffs cleaner if another config is later added. > @@ -362,6 +390,10 @@ static int ps8640_probe(struct i2c_client *client) > > ps_bridge->page[PAGE0_DP_CNTL] = client; > > + ps_bridge->regmap[PAGE0_DP_CNTL] = devm_regmap_init_i2c(client, > ps8640_regmap_config); > + if (IS_ERR(ps_bridge->regmap[PAGE0_DP_CNTL])) > + return PTR_ERR(ps_bridge->regmap[PAGE0_DP_CNTL]); I'm a huge fan of dev_err_probe(). I wonder if it makes sense to use it here? Untested: if (IS_ERR(ps_bridge->regmap[PAGE0_DP_CNTL])) return dev_err_probe(dev, PTR_ERR(ps_bridge->regmap[PAGE0_DP_CNTL]), "Error initting page 0 regmap\n"); All of that is just nits, so: Reviewed-by: Douglas Anderson
[RFC v1 3/6] drm: Add a capability flag to support additional flip completion signalling
If a driver supports this capability, it means that there would be an additional signalling mechanism for a page flip completion in addition to out_fence or DRM_MODE_PAGE_FLIP_EVENT. This capability may only be relevant for Virtual KMS drivers and is currently used only by virtio-gpu. Also, it can provide a potential solution for: https://gitlab.freedesktop.org/wayland/weston/-/issues/514 Signed-off-by: Vivek Kasireddy --- drivers/gpu/drm/drm_ioctl.c | 3 +++ include/drm/drm_mode_config.h | 8 include/uapi/drm/drm.h| 1 + 3 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 8b8744dcf691..8a420844f8bc 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -302,6 +302,9 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_ case DRM_CAP_CRTC_IN_VBLANK_EVENT: req->value = 1; break; + case DRM_CAP_RELEASE_FENCE: + req->value = dev->mode_config.release_fence; + break; default: return -EINVAL; } diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index 12b964540069..944bebf359d7 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -935,6 +935,14 @@ struct drm_mode_config { */ bool normalize_zpos; + /** +* @release_fence: +* +* If this option is set, it means there would be an additional signalling +* mechanism for a page flip completion. +*/ + bool release_fence; + /** * @modifiers_property: Plane property to list support modifier/format * combination. diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 3b810b53ba8b..8b8985f65581 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -767,6 +767,7 @@ struct drm_gem_open { * Documentation/gpu/drm-mm.rst, section "DRM Sync Objects". */ #define DRM_CAP_SYNCOBJ_TIMELINE 0x14 +#define DRM_CAP_RELEASE_FENCE 0x15 /* DRM_IOCTL_GET_CAP ioctl argument type */ struct drm_get_cap { -- 2.30.2
[RFC v1 6/6] drm/virtio: Add a fence to set_scanout_blob
Cc: Gerd Hoffmann Signed-off-by: Vivek Kasireddy --- drivers/gpu/drm/virtio/virtgpu_plane.c | 63 +++--- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index a49fd9480381..ab39254c19e5 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "virtgpu_drv.h" @@ -163,6 +164,60 @@ static void virtio_gpu_resource_flush(struct drm_plane *plane, } } +static void virtio_gpu_set_scanout_blob(struct drm_plane *plane, + struct virtio_gpu_output *output) +{ + struct drm_device *dev = plane->dev; + struct virtio_gpu_device *vgdev = dev->dev_private; + struct virtio_gpu_framebuffer *vgfb; + struct virtio_gpu_object *bo; + + vgfb = to_virtio_gpu_framebuffer(plane->state->fb); + bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]); + if (bo->guest_blob && vgdev->ddev->mode_config.release_fence) { + struct drm_crtc_state *crtc_state; + struct drm_pending_event *e; + struct virtio_gpu_object_array *objs; + struct virtio_gpu_fence *fence; + + crtc_state = output->crtc.state; + if (!crtc_state || !crtc_state->event) + return; + + e = _state->event->base; + if (!e->release_fence) + return; + + fence = virtio_gpu_fence_alloc(vgdev); + if (!fence) + return; + + objs = virtio_gpu_array_alloc(1); + if (!objs) + return; + + fence->release_fence = e->release_fence; + virtio_gpu_array_add_obj(objs, vgfb->base.obj[0]); + virtio_gpu_array_lock_resv(objs); + virtio_gpu_cmd_set_scanout_blob(vgdev, output->index, bo, + plane->state->fb, + plane->state->src_w >> 16, + plane->state->src_h >> 16, + plane->state->src_x >> 16, + plane->state->src_y >> 16, + objs, fence); + } else { + virtio_gpu_cmd_set_scanout_blob(vgdev, output->index, bo, + plane->state->fb, + plane->state->src_w >> 16, + plane->state->src_h >> 16, + plane->state->src_x >> 16, + plane->state->src_y >> 16, + NULL, NULL); + } +} + + static void virtio_gpu_primary_plane_update(struct drm_plane *plane, struct drm_atomic_state *state) { @@ -215,13 +270,7 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane, plane->state->src_y >> 16); if (bo->host3d_blob || bo->guest_blob) { - virtio_gpu_cmd_set_scanout_blob - (vgdev, output->index, bo, -plane->state->fb, -plane->state->src_w >> 16, -plane->state->src_h >> 16, -plane->state->src_x >> 16, -plane->state->src_y >> 16); + virtio_gpu_set_scanout_blob(plane, output); } else { virtio_gpu_cmd_set_scanout(vgdev, output->index, bo->hw_res_handle, -- 2.30.2
[RFC v1 2/6] drm/atomic: Add support for release_fence and its associated property
Release_fence is very similar if not the same as out_fence; it is an additional signalling mechanism for a page flip completion. Signed-off-by: Vivek Kasireddy --- drivers/gpu/drm/drm_atomic_uapi.c | 43 +-- drivers/gpu/drm/drm_crtc.c| 2 ++ drivers/gpu/drm/drm_mode_config.c | 6 + include/drm/drm_atomic.h | 1 + include/drm/drm_file.h| 9 +++ include/drm/drm_mode_config.h | 7 + 6 files changed, 66 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 6436677fa2f8..5d0bf3e525b3 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -367,6 +367,23 @@ static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state, return fence_ptr; } +static void set_release_fence_for_crtc(struct drm_atomic_state *state, + struct drm_crtc *crtc, s32 __user *fence_ptr) +{ + state->crtcs[drm_crtc_index(crtc)].release_fence_ptr = fence_ptr; +} + +static s32 __user *get_release_fence_for_crtc(struct drm_atomic_state *state, + struct drm_crtc *crtc) +{ + s32 __user *fence_ptr; + + fence_ptr = state->crtcs[drm_crtc_index(crtc)].release_fence_ptr; + state->crtcs[drm_crtc_index(crtc)].release_fence_ptr = NULL; + + return fence_ptr; +} + static int set_out_fence_for_connector(struct drm_atomic_state *state, struct drm_connector *connector, s32 __user *fence_ptr) @@ -482,6 +499,16 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc, return -EFAULT; set_out_fence_for_crtc(state->state, crtc, fence_ptr); + } else if (property == config->prop_release_fence_ptr) { + s32 __user *fence_ptr = u64_to_user_ptr(val); + + if (!fence_ptr) + return 0; + + if (put_user(-1, fence_ptr)) + return -EFAULT; + + set_release_fence_for_crtc(state->state, crtc, fence_ptr); } else if (property == crtc->scaling_filter_property) { state->scaling_filter = val; } else if (crtc->funcs->atomic_set_property) { @@ -519,6 +546,8 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc, *val = (state->gamma_lut) ? state->gamma_lut->base.id : 0; else if (property == config->prop_out_fence_ptr) *val = 0; + else if (property == config->prop_release_fence_ptr) + *val = 0; else if (property == crtc->scaling_filter_property) *val = state->scaling_filter; else if (crtc->funcs->atomic_get_property) @@ -1185,7 +1214,7 @@ static int prepare_signaling(struct drm_device *dev, for_each_new_crtc_in_state(state, crtc, crtc_state, i) { struct dma_fence *fence; - s32 __user *fence_ptr; + s32 __user *fence_ptr, *rel_fence_ptr; fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc); @@ -1220,9 +1249,19 @@ static int prepare_signaling(struct drm_device *dev, if (IS_ERR(fence)) return PTR_ERR(fence); + crtc_state->event->base.fence = fence; + } + rel_fence_ptr = get_release_fence_for_crtc(crtc_state->state, + crtc); + if (rel_fence_ptr) { + fence = crtc_create_out_fence(crtc, fence_state, + rel_fence_ptr, + num_fences); + if (IS_ERR(fence)) + return PTR_ERR(fence); - crtc_state->event->base.fence = fence; + crtc_state->event->base.release_fence = fence; } c++; diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 26a77a735905..e682ac04f873 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -312,6 +312,8 @@ static int __drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc * drm_object_attach_property(>base, config->prop_mode_id, 0); drm_object_attach_property(>base, config->prop_out_fence_ptr, 0); + drm_object_attach_property(>base, + config->prop_release_fence_ptr, 0); drm_object_attach_property(>base, config->prop_vrr_enabled, 0); } diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index 37b4b9f0e468..fc1f5a8d2991 100644 ---
[RFC v1 5/6] drm/virtio: Prepare set_scanout_blob to accept a fence
Signed-off-by: Vivek Kasireddy --- drivers/gpu/drm/virtio/virtgpu_drv.h | 4 +++- drivers/gpu/drm/virtio/virtgpu_vq.c | 7 +-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 9126bca47c6d..c219ebde27c3 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -406,7 +406,9 @@ virtio_gpu_cmd_set_scanout_blob(struct virtio_gpu_device *vgdev, struct virtio_gpu_object *bo, struct drm_framebuffer *fb, uint32_t width, uint32_t height, - uint32_t x, uint32_t y); + uint32_t x, uint32_t y, + struct virtio_gpu_object_array *objs, + struct virtio_gpu_fence *fence); /* virtgpu_display.c */ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev); diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 2e71e91278b4..760e8b8eefb6 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -1280,7 +1280,9 @@ void virtio_gpu_cmd_set_scanout_blob(struct virtio_gpu_device *vgdev, struct virtio_gpu_object *bo, struct drm_framebuffer *fb, uint32_t width, uint32_t height, -uint32_t x, uint32_t y) +uint32_t x, uint32_t y, +struct virtio_gpu_object_array *objs, +struct virtio_gpu_fence *fence) { uint32_t i; struct virtio_gpu_set_scanout_blob *cmd_p; @@ -1289,6 +1291,7 @@ void virtio_gpu_cmd_set_scanout_blob(struct virtio_gpu_device *vgdev, cmd_p = virtio_gpu_alloc_cmd(vgdev, , sizeof(*cmd_p)); memset(cmd_p, 0, sizeof(*cmd_p)); + vbuf->objs = objs; cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_SET_SCANOUT_BLOB); cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle); @@ -1308,5 +1311,5 @@ void virtio_gpu_cmd_set_scanout_blob(struct virtio_gpu_device *vgdev, cmd_p->r.x = cpu_to_le32(x); cmd_p->r.y = cpu_to_le32(y); - virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); + virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, fence); } -- 2.30.2
[RFC v1 4/6] drm/virtio: Probe and implement VIRTIO_GPU_F_RELEASE_FENCE feature
Cc: Gerd Hoffmann Signed-off-by: Vivek Kasireddy --- drivers/gpu/drm/virtio/virtgpu_debugfs.c | 1 + drivers/gpu/drm/virtio/virtgpu_drv.c | 1 + drivers/gpu/drm/virtio/virtgpu_drv.h | 1 + drivers/gpu/drm/virtio/virtgpu_fence.c | 9 + drivers/gpu/drm/virtio/virtgpu_kms.c | 9 +++-- include/uapi/linux/virtio_gpu.h | 2 ++ 6 files changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_debugfs.c b/drivers/gpu/drm/virtio/virtgpu_debugfs.c index c2b20e0ee030..15d2cb89ff18 100644 --- a/drivers/gpu/drm/virtio/virtgpu_debugfs.c +++ b/drivers/gpu/drm/virtio/virtgpu_debugfs.c @@ -52,6 +52,7 @@ static int virtio_gpu_features(struct seq_file *m, void *data) vgdev->has_resource_assign_uuid); virtio_gpu_add_bool(m, "blob resources", vgdev->has_resource_blob); + virtio_gpu_add_bool(m, "release fence", vgdev->ddev->mode_config.release_fence); virtio_gpu_add_int(m, "cap sets", vgdev->num_capsets); virtio_gpu_add_int(m, "scanouts", vgdev->num_scanouts); if (vgdev->host_visible_region.len) { diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index ed85a7863256..29cb2c355587 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -172,6 +172,7 @@ static unsigned int features[] = { VIRTIO_GPU_F_EDID, VIRTIO_GPU_F_RESOURCE_UUID, VIRTIO_GPU_F_RESOURCE_BLOB, + VIRTIO_GPU_F_RELEASE_FENCE, }; static struct virtio_driver virtio_gpu_driver = { .feature_table = features, diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 0c4810982530..9126bca47c6d 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -140,6 +140,7 @@ struct virtio_gpu_fence { uint64_t fence_id; struct virtio_gpu_fence_driver *drv; struct list_head node; + struct dma_fence *release_fence; }; struct virtio_gpu_vbuffer { diff --git a/drivers/gpu/drm/virtio/virtgpu_fence.c b/drivers/gpu/drm/virtio/virtgpu_fence.c index d28e25e8409b..d1c36b5fa8ef 100644 --- a/drivers/gpu/drm/virtio/virtgpu_fence.c +++ b/drivers/gpu/drm/virtio/virtgpu_fence.c @@ -134,6 +134,9 @@ void virtio_gpu_fence_event_process(struct virtio_gpu_device *vgdev, if (signaled->f.context != curr->f.context) continue; + if (curr->release_fence) + continue; + if (!dma_fence_is_later(>f, >f)) continue; @@ -142,6 +145,12 @@ void virtio_gpu_fence_event_process(struct virtio_gpu_device *vgdev, dma_fence_put(>f); } + if (signaled->release_fence) { + dma_fence_signal(signaled->release_fence); + dma_fence_put(signaled->release_fence); + signaled->release_fence = NULL; + } + dma_fence_signal_locked(>f); list_del(>node); dma_fence_put(>f); diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index f3379059f324..5706703eb676 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -156,6 +156,9 @@ int virtio_gpu_init(struct drm_device *dev) if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_RESOURCE_BLOB)) { vgdev->has_resource_blob = true; } + if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_RELEASE_FENCE)) { + vgdev->ddev->mode_config.release_fence = true; + } if (virtio_get_shm_region(vgdev->vdev, >host_visible_region, VIRTIO_GPU_SHM_ID_HOST_VISIBLE)) { if (!devm_request_mem_region(>vdev->dev, @@ -176,11 +179,13 @@ int virtio_gpu_init(struct drm_device *dev) (unsigned long)vgdev->host_visible_region.len); } - DRM_INFO("features: %cvirgl %cedid %cresource_blob %chost_visible\n", + DRM_INFO("features: %cvirgl %cedid %cresource_blob %chost_visible \ +%crelease_fence\n", vgdev->has_virgl_3d? '+' : '-', vgdev->has_edid? '+' : '-', vgdev->has_resource_blob ? '+' : '-', -vgdev->has_host_visible ? '+' : '-'); +vgdev->has_host_visible ? '+' : '-', +vgdev->ddev->mode_config.release_fence ? '+' : '-'); ret = virtio_find_vqs(vgdev->vdev, 2, vqs, callbacks, names, NULL); if (ret) { diff --git a/include/uapi/linux/virtio_gpu.h b/include/uapi/linux/virtio_gpu.h index 97523a95781d..9468e17a3c13 100644 --- a/include/uapi/linux/virtio_gpu.h +++ b/include/uapi/linux/virtio_gpu.h @@ -60,6 +60,8 @@ */ #define VIRTIO_GPU_F_RESOURCE_BLOB
[RFC v1 0/6] drm: Add support for DRM_CAP_RELEASE_FENCE capability
The main idea behind DRM_CAP_RELEASE_FENCE is to add an additional signaling mechanism for a pageflip completion in addition to out_fence or DRM_EVENT_FLIP_COMPLETE event. This allows a compositor to start a new repaint cycle with a new buffer instead of waiting for the old buffer to be free. Why? So, an atomic pageflip completion indicates two things to a compositor: - that it can repaint again and - that the old fb is free and can be reused (that was submitted in the previous repaint cycle) Essentially, DRM_CAP_RELEASE_FENCE is about separating out the above two assumptions. DRM_EVENT_FLIP_COMPLETE event or out_fence would serve as a signal to repaint and newly added release_fence would provide a way to determine when old fbs can be re-used again. This separation is really needed when the fb(s) associated with a pageflip are shared outside of the OS -- which is indeed the case with Virtio-gpu, a Virtual KMS driver. The Virtio-gpu driver runs in a Virtual Machine and can share the fb with the Host -- via Wayland UI -- in a zero-copy way. And, in this particular environment where the Host and Guest/VM are running Wayland based compositors, it would be desirable to have the Guest compositor's scanout fb be placed directly on a hardware plane on the Host -- to improve performance when there are multiple Guests running. To ensure 60 FPS and to prevent Guest and Host compositors from using an fb at the same time, the signaling of Guest's release_fence is tied to Host's wl_buffer_release event and DRM_EVENT_FLIP_COMPLETE/ out_fence signaling is tied to Host compositor's frame callback event. Implementation: Since release_fence is almost identical to out_fence, it is implemented by making use of the existing out_fence machinery. And, although, the drm core creates the release_fence, the Virtio-gpu driver takes care of signaling it when it gets notified by the Host that the fb is free. This work is based on the idea/suggestion from Simon and Pekka. And, this patch series provides a solution for this Weston issue: https://gitlab.freedesktop.org/wayland/weston/-/issues/514 Tested with: Weston MR: https://gitlab.freedesktop.org/wayland/weston/-/merge_requests/668 and Qemu patches: https://lists.nongnu.org/archive/html/qemu-devel/2021-09/msg03463.html Earlier version/discussion of this patch series can be found at: https://lists.freedesktop.org/archives/dri-devel/2021-July/317672.html Cc: Daniel Vetter Cc: Gerd Hoffmann Cc: Pekka Paalanen Cc: Simon Ser Cc: Michel Dänzer Cc: Tina Zhang Cc: Dongwon Kim Cc: Satyeshwar Singh Vivek Kasireddy (6): drm/atomic: Move out_fence creation/setup into a separate function drm/atomic: Add support for release_fence and its associated property drm: Add a capability flag to support additional flip completion signalling drm/virtio: Probe and implement VIRTIO_GPU_F_RELEASE_FENCE feature drm/virtio: Prepare set_scanout_blob to accept a fence drm/virtio: Add a fence to set_scanout_blob drivers/gpu/drm/drm_atomic_uapi.c| 100 ++- drivers/gpu/drm/drm_crtc.c | 2 + drivers/gpu/drm/drm_ioctl.c | 3 + drivers/gpu/drm/drm_mode_config.c| 6 ++ drivers/gpu/drm/virtio/virtgpu_debugfs.c | 1 + drivers/gpu/drm/virtio/virtgpu_drv.c | 1 + drivers/gpu/drm/virtio/virtgpu_drv.h | 5 +- drivers/gpu/drm/virtio/virtgpu_fence.c | 9 ++ drivers/gpu/drm/virtio/virtgpu_kms.c | 9 +- drivers/gpu/drm/virtio/virtgpu_plane.c | 63 -- drivers/gpu/drm/virtio/virtgpu_vq.c | 7 +- include/drm/drm_atomic.h | 1 + include/drm/drm_file.h | 9 ++ include/drm/drm_mode_config.h| 15 include/uapi/drm/drm.h | 1 + include/uapi/linux/virtio_gpu.h | 2 + 16 files changed, 200 insertions(+), 34 deletions(-) -- 2.30.2
[RFC v1 1/6] drm/atomic: Move out_fence creation/setup into a separate function
This is needed to leverage the out_fence machinery for similar but additional singalling mechanisms. Signed-off-by: Vivek Kasireddy --- drivers/gpu/drm/drm_atomic_uapi.c | 57 --- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 909f31833181..6436677fa2f8 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -1135,6 +1135,38 @@ static int setup_out_fence(struct drm_out_fence_state *fence_state, return 0; } +static struct dma_fence *crtc_create_out_fence(struct drm_crtc *crtc, + struct drm_out_fence_state **fence_state, + s32 __user *fence_ptr, + unsigned int *num_fences) +{ + struct dma_fence *fence; + struct drm_out_fence_state *f; + int ret; + + f = krealloc(*fence_state, sizeof(**fence_state) * +(*num_fences + 1), GFP_KERNEL); + if (!f) + return ERR_PTR(-ENOMEM); + + memset([*num_fences], 0, sizeof(*f)); + + f[*num_fences].out_fence_ptr = fence_ptr; + *fence_state = f; + + fence = drm_crtc_create_fence(crtc); + if (!fence) + return ERR_PTR(-ENOMEM); + + ret = setup_out_fence([(*num_fences)++], fence); + if (ret) { + dma_fence_put(fence); + return ERR_PTR(ret); + } + + return fence; +} + static int prepare_signaling(struct drm_device *dev, struct drm_atomic_state *state, struct drm_mode_atomic *arg, @@ -1152,6 +1184,7 @@ static int prepare_signaling(struct drm_device *dev, return 0; for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + struct dma_fence *fence; s32 __user *fence_ptr; fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc); @@ -1182,28 +1215,12 @@ static int prepare_signaling(struct drm_device *dev, } if (fence_ptr) { - struct dma_fence *fence; - struct drm_out_fence_state *f; - - f = krealloc(*fence_state, sizeof(**fence_state) * -(*num_fences + 1), GFP_KERNEL); - if (!f) - return -ENOMEM; - - memset([*num_fences], 0, sizeof(*f)); + fence = crtc_create_out_fence(crtc, fence_state, + fence_ptr, num_fences); + if (IS_ERR(fence)) + return PTR_ERR(fence); - f[*num_fences].out_fence_ptr = fence_ptr; - *fence_state = f; - fence = drm_crtc_create_fence(crtc); - if (!fence) - return -ENOMEM; - - ret = setup_out_fence([(*num_fences)++], fence); - if (ret) { - dma_fence_put(fence); - return ret; - } crtc_state->event->base.fence = fence; } -- 2.30.2
Re: [RFC PATCH v2 2/2] drm/bridge: parade-ps8640: Add support for AUX channel
Hi, On Mon, Sep 13, 2021 at 2:33 PM Philip Chen wrote: > > Implement the first version of AUX support, which will be useful as > we expand the driver to support varied use cases. > > WARNING: This patch is not fully verified by hardware. But as AUX CH > is not implemented for ps8640 driver until now, the patch shouldn't > cause any functional regression in practice. Thanks for the heads up. NOTE: having this patch posted to do early code review is fine, but fair warning that I don't think there'd be much benefit in landing until the patch is verified more. > Signed-off-by: Philip Chen > --- > > Changes in v2: > - Handle the case where an AUX transaction has no payload > - Add a reg polling for p0.0x83 to confirm AUX cmd is issued and > read data is returned > - Replace regmap_noinc_read/write with looped regmap_read/write, > as regmap_noinc_read/write doesn't read one byte at a time unless > max_raw_read/write is set to 1. What about if you set val_bytes? I think you just need to set that to "1" and it'll work? > - Register/Unregister the AUX device explicitly when the bridge is > attached/detached > - Remove the use of runtime PM I suspect runtime PM will need to be added back in at some point since AUX channel needs to be functional even if the bridge hasn't been "pre_enable"ed. > - Program AUX addr/cmd/len in a single regmap_bulk_write() > - Add newlines for DRM_ERROR mesages > > drivers/gpu/drm/bridge/parade-ps8640.c | 156 - > 1 file changed, 153 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c > b/drivers/gpu/drm/bridge/parade-ps8640.c > index 1b2414601538..3b28e992bb3e 100644 > --- a/drivers/gpu/drm/bridge/parade-ps8640.c > +++ b/drivers/gpu/drm/bridge/parade-ps8640.c > @@ -13,11 +13,32 @@ > #include > > #include > +#include > #include > #include > #include > #include > > +#define PAGE0_AUXCH_CFG3 0x76 > +#define AUXCH_CFG3_RESET 0xff > +#define PAGE0_AUX_ADDR_7_0 0x7d > +#define PAGE0_AUX_ADDR_15_80x7e > +#define PAGE0_AUX_ADDR_23_16 0x7f nit: my manual calls the above "SWAUX_ADDR". Can you add the "SW"? I know it doesn't look pretty, but matching the manual is really nice. Similar with other commands below. > +#define AUX_ADDR_19_16_MASK GENMASK(3, 0) > +#define AUX_CMD_MASK GENMASK(7, 4) > +#define PAGE0_AUX_LENGTH 0x80 > +#define AUX_LENGTH_MASK GENMASK(3, 0) > +#define AUX_NO_PAYLOADBIT(7) > +#define PAGE0_AUX_WDATA0x81 > +#define PAGE0_AUX_RDATA0x82 > +#define PAGE0_AUX_CTRL 0x83 > +#define AUX_SEND BIT(0) > +#define PAGE0_AUX_STATUS 0x84 > +#define AUX_STATUS_MASK GENMASK(7, 5) > +#define AUX_STATUS_TIMEOUT(0x7 << 5) > +#define AUX_STATUS_DEFER (0x2 << 5) > +#define AUX_STATUS_NACK (0x1 << 5) > + > #define PAGE2_GPIO_H 0xa7 > #define PS_GPIO9 BIT(1) > #define PAGE2_I2C_BYPASS 0xea > @@ -68,6 +89,7 @@ enum ps8640_vdo_control { > struct ps8640 { > struct drm_bridge bridge; > struct drm_bridge *panel_bridge; > + struct drm_dp_aux aux; > struct mipi_dsi_device *dsi; > struct i2c_client *page[MAX_DEVS]; > struct regmap *regmap[MAX_DEVS]; > @@ -117,6 +139,114 @@ static inline struct ps8640 *bridge_to_ps8640(struct > drm_bridge *e) > return container_of(e, struct ps8640, bridge); > } > > +static inline struct ps8640 *aux_to_ps8640(struct drm_dp_aux *aux) > +{ > + return container_of(aux, struct ps8640, aux); > +} > + > +static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, > + struct drm_dp_aux_msg *msg) > +{ > + struct ps8640 *ps_bridge = aux_to_ps8640(aux); > + struct regmap *map = ps_bridge->regmap[PAGE0_DP_CNTL]; > + unsigned int len = msg->size; > + unsigned int data; > + int ret; > + u8 request = msg->request & > +~(DP_AUX_I2C_MOT | DP_AUX_I2C_WRITE_STATUS_UPDATE); > + u8 *buf = msg->buffer; > + u8 addr_len[PAGE0_AUX_LENGTH + 1 - PAGE0_AUX_ADDR_7_0]; > + u8 i; > + bool is_native_aux = false; > + > + if (len > DP_AUX_MAX_PAYLOAD_BYTES) > + return -EINVAL; > + > + switch (request) { > + case DP_AUX_NATIVE_WRITE: > + case DP_AUX_NATIVE_READ: > + is_native_aux = true; I think you need a "fallthrough;" here. > + case DP_AUX_I2C_WRITE: > + case DP_AUX_I2C_READ: > + ret = regmap_write(map, PAGE0_AUXCH_CFG3, AUXCH_CFG3_RESET); Why not move the regmap_write() out of the switch statement? Also: you store the "ret" but you never check it. You should handle the error. > + break; > + default: > + ret = -EINVAL; > + goto exit; > + } > + > + /* Assume it's good */ > + msg->reply = 0; > + > +
Re: [PATCH v1 6/6] drm/mediatek: Add mt8195 DisplayPort driver
Hi, Markus: Markus Schneider-Pargmann 於 2021年9月10日 週五 下午1:36寫道: > > Hi Chun-Kuang, > > On Fri, Sep 10, 2021 at 07:37:50AM +0800, Chun-Kuang Hu wrote: > > Hi, Markus: > > > > Markus Schneider-Pargmann 於 2021年9月7日 週二 上午3:37寫道: > > > > > > This patch adds a DisplayPort driver for the Mediatek mt8195 SoC. > > > > > > It supports both functional units on the mt8195, the embedded > > > DisplayPort as well as the external DisplayPort units. It offers > > > hot-plug-detection, audio up to 8 channels, and DisplayPort 1.4 with up > > > to 4 lanes. > > > > > > This driver is based on an initial version by > > > Jason-JH.Lin . > > > > > > Signed-off-by: Markus Schneider-Pargmann > > > --- > > > > > > Notes: > > > Changes RFC -> v1: > > > - Removed unused register definitions. > > > - Replaced workqueue with threaded irq. > > > - Removed connector code. > > > - Move to atomic_* drm functions. > > > - General cleanups of the code. > > > - Remove unused select GENERIC_PHY. > > > > > > drivers/gpu/drm/mediatek/Kconfig |6 + > > > drivers/gpu/drm/mediatek/Makefile |2 + > > > drivers/gpu/drm/mediatek/mtk_dp.c | 2881 + > > > drivers/gpu/drm/mediatek/mtk_dp_reg.h | 580 + > > > 4 files changed, 3469 insertions(+) > > > create mode 100644 drivers/gpu/drm/mediatek/mtk_dp.c > > > create mode 100644 drivers/gpu/drm/mediatek/mtk_dp_reg.h > > > > > ... > > > > +#define TOP_OFFSET 0x2000 > > > +#define ENC0_OFFSET0x3000 > > > +#define ENC1_OFFSET0x3200 > > > +#define TRANS_OFFSET 0x3400 > > > +#define AUX_OFFSET 0x3600 > > > +#define SEC_OFFSET 0x4000 > > ... > > > > + > > > +#define DP_PHY_DIG_PLL_CTL_1 0x1014 > > > +# define TPLL_SSC_EN BIT(3) > > > > It seems that register 0x1000 ~ 0x1fff is to control phy and 0x2000 ~ > > 0x4fff is to control non-phy part. For mipi and hdmi, the phy part is > > an independent device [1] and the phy driver is independent [2] , so I > > would like this phy to be an independent device. > > > > [1] > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/mediatek/mt8173.dtsi?h=v5.14 > > [2] > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/phy/mediatek?h=v5.14 > > Thanks for your feedback. I looked into both mipi and hdmi phy drivers > that you referenced. It looks like both are really separate units in > their SoCs having their own registerspaces located at a completely > different range than the units using the phy. > > For this displayport driver, the phy registers are listed as part of the > (e)DP_TX unit in the datasheet. Next to the phy registers all the other > parts are listed as well in the same overall register ranges (see > above), e.g. TOP_OFFSET, ENC_OFFSET or SEC_OFFSET. Also I would like to > avoid splitting it up into a separate unit in the devicetree as the > datasheet handles it as a single unit (including the phy registers). OK, according to the datasheet, let it to be a single device. > > From a practical perspective there is also not much to these PHY > registers. The only things that would be done in the driver are: > - initializing the lane driving parameters with static values > - setup the bitrate > - enable/disable SSC > - do a reset > Exporting these four used functions over a driver boundary wouldn't help > clarity I think and the code probably can't be reused by any other > component anyways. Use mmsys device [1] as an example. mmsys has both clock control function and other function including routing function. The main driver [2] is placed in soc folder, and the clock control part [3] is separated to clk folder but the clock control part just simply control clock gating. [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/mediatek/mt8173.dtsi?h=v5.15-rc1#n992 [2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/soc/mediatek/mtk-mmsys.c?h=v5.15-rc1 [3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clk/mediatek/clk-mt8173-mm.c?h=v5.15-rc1 I think many phy driver could be used only by single device driver, so we don't need to consider the reusability. Regards, Chun-Kuang. > > So I personally would prefer keeping it as part of the whole driver > because of the above mentioned reasons. What do you think? > > Thanks, > Markus > > > > > Regards, > > Chun-Kuang. > > > > > + > > > +#define DP_PHY_DIG_BIT_RATE0x103C > > > +# define BIT_RATE_RBR 0 > > > +# define BIT_RATE_HBR 1 > > > +# define BIT_RATE_HBR2 2 > > > +# define BIT_RATE_HBR3 3 > > > + > > > +#define
Re: [Intel-gfx] [PATCH 10/27] drm/i915/guc: Introduce context parent-child relationship
On 8/20/2021 15:44, Matthew Brost wrote: Introduce context parent-child relationship. Once this relationship is created all pinning / unpinning operations are directed to the parent context. The parent context is responsible for pinning all of its' children and itself. This is a precursor to the full GuC multi-lrc implementation but aligns to how GuC mutli-lrc interface is defined - a single H2G is used register / deregister all of the contexts simultaneously. Subsequent patches in the series will implement the pinning / unpinning operations for parent / child contexts. v2: (Daniel Vetter) - Add kernel doc, add wrapper to access parent to ensure safety Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/gt/intel_context.c | 29 ++ drivers/gpu/drm/i915/gt/intel_context.h | 39 +++ drivers/gpu/drm/i915/gt/intel_context_types.h | 23 +++ 3 files changed, 91 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index 508cfe5770c0..00d1aee6d199 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -404,6 +404,8 @@ intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine) INIT_LIST_HEAD(>destroyed_link); No need for this blank line? + INIT_LIST_HEAD(>guc_child_list); + /* * Initialize fence to be complete as this is expected to be complete * unless there is a pending schedule disable outstanding. @@ -418,10 +420,17 @@ intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine) void intel_context_fini(struct intel_context *ce) { + struct intel_context *child, *next; + if (ce->timeline) intel_timeline_put(ce->timeline); i915_vm_put(ce->vm); + /* Need to put the creation ref for the children */ + if (intel_context_is_parent(ce)) + for_each_child_safe(ce, child, next) + intel_context_put(child); + mutex_destroy(>pin_mutex); i915_active_fini(>active); } @@ -537,6 +546,26 @@ struct i915_request *intel_context_find_active_request(struct intel_context *ce) return active; } +void intel_context_bind_parent_child(struct intel_context *parent, +struct intel_context *child) +{ + /* +* Callers responsibility to validate that this function is used +* correctly but we use GEM_BUG_ON here ensure that they do. +*/ + GEM_BUG_ON(!intel_engine_uses_guc(parent->engine)); + GEM_BUG_ON(intel_context_is_pinned(parent)); + GEM_BUG_ON(intel_context_is_child(parent)); + GEM_BUG_ON(intel_context_is_pinned(child)); + GEM_BUG_ON(intel_context_is_child(child)); + GEM_BUG_ON(intel_context_is_parent(child)); + + parent->guc_number_children++; + list_add_tail(>guc_child_link, + >guc_child_list); + child->parent = parent; +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftest_context.c" #endif diff --git a/drivers/gpu/drm/i915/gt/intel_context.h b/drivers/gpu/drm/i915/gt/intel_context.h index c41098950746..c2985822ab74 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.h +++ b/drivers/gpu/drm/i915/gt/intel_context.h @@ -44,6 +44,45 @@ void intel_context_free(struct intel_context *ce); int intel_context_reconfigure_sseu(struct intel_context *ce, const struct intel_sseu sseu); +static inline bool intel_context_is_child(struct intel_context *ce) +{ + return !!ce->parent; +} + +static inline bool intel_context_is_parent(struct intel_context *ce) +{ + return !!ce->guc_number_children; +} + +static inline bool intel_context_is_pinned(struct intel_context *ce); No point declaring 'static inline' if there is no function body? + +static inline struct intel_context * +intel_context_to_parent(struct intel_context *ce) +{ +if (intel_context_is_child(ce)) { + /* +* The parent holds ref count to the child so it is always safe +* for the parent to access the child, but the child has pointer has pointer -> has a pointer +* to the parent without a ref. To ensure this is safe the child +* should only access the parent pointer while the parent is +* pinned. +*/ +GEM_BUG_ON(!intel_context_is_pinned(ce->parent)); + +return ce->parent; +} else { +return ce; +} +} + +void intel_context_bind_parent_child(struct intel_context *parent, +struct intel_context *child); + +#define for_each_child(parent, ce)\ + list_for_each_entry(ce, &(parent)->guc_child_list, guc_child_link) +#define for_each_child_safe(parent, ce, cn)\ + list_for_each_entry_safe(ce, cn,
Re: [Intel-gfx] [PATCH 09/27] drm/i915: Expose logical engine instance to user
On 8/20/2021 15:44, Matthew Brost wrote: Expose logical engine instance to user via query engine info IOCTL. This is required for split-frame workloads as these needs to be placed on engines in a logically contiguous order. The logical mapping can change based on fusing. Rather than having user have knowledge of the fusing we simply just expose the logical mapping with the existing query engine info IOCTL. IGT: https://patchwork.freedesktop.org/patch/445637/?series=92854=1 media UMD: link coming soon v2: (Daniel Vetter) - Add IGT link, placeholder for media UMD Cc: Tvrtko Ursulin Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/i915_query.c | 2 ++ include/uapi/drm/i915_drm.h | 8 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c index e49da36c62fb..8a72923fbdba 100644 --- a/drivers/gpu/drm/i915/i915_query.c +++ b/drivers/gpu/drm/i915/i915_query.c @@ -124,7 +124,9 @@ query_engine_info(struct drm_i915_private *i915, for_each_uabi_engine(engine, i915) { info.engine.engine_class = engine->uabi_class; info.engine.engine_instance = engine->uabi_instance; + info.flags = I915_ENGINE_INFO_HAS_LOGICAL_INSTANCE; info.capabilities = engine->uabi_capabilities; + info.logical_instance = ilog2(engine->logical_mask); if (copy_to_user(info_ptr, , sizeof(info))) return -EFAULT; diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index bde5860b3686..b1248a67b4f8 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -2726,14 +2726,20 @@ struct drm_i915_engine_info { /** @flags: Engine flags. */ __u64 flags; +#define I915_ENGINE_INFO_HAS_LOGICAL_INSTANCE (1 << 0) /** @capabilities: Capabilities of this engine. */ __u64 capabilities; #define I915_VIDEO_CLASS_CAPABILITY_HEVC (1 << 0) #define I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC (1 << 1) + /** @logical_instance: Logical instance of engine */ + __u16 logical_instance; + /** @rsvd1: Reserved fields. */ - __u64 rsvd1[4]; + __u16 rsvd1[3]; + /** @rsvd2: Reserved fields. */ + __u64 rsvd2[3]; }; /** Any idea why the padding? Would be useful if the comment said 'this structure must be at least/exactly X bytes in size / a multiple of X bytes in size because ...' or whatever. However, not really anything to do with this patch as such, so either way: Reviewed-by: John Harrison
Re: [Intel-gfx] [PATCH 07/27] drm/i915/guc: Don't call switch_to_kernel_context with GuC submission
On 9/13/2021 09:54, Matthew Brost wrote: On Thu, Sep 09, 2021 at 03:51:27PM -0700, John Harrison wrote: On 8/20/2021 15:44, Matthew Brost wrote: Calling switch_to_kernel_context isn't needed if the engine PM reference is taken while all contexts are pinned. By not calling switch_to_kernel_context we save on issuing a request to the engine. I thought the intention of the switch_to_kernel was to ensure that the GPU is not touching any user context and is basically idle. That is not a valid assumption with an external scheduler such as GuC. So why is the description above only mentioning PM references? What is the connection between the PM ref and the switch_to_kernel? Also, the comment in the code does not mention anything about PM references, it just says 'not necessary with GuC' but no explanation at all. Yea, this need to be explained better. How about this? Calling switch_to_kernel_context isn't needed if the engine PM reference is take while all user contexts have scheduling enabled. Once scheduling is disabled on all user contexts the GuC is guaranteed to not touch any user context state which is effectively the same pointing to a kernel context. Matt I'm still not seeing how the PM reference is involved? Also, IMHO the focus is wrong in the above text. The fundamental requirement is the ensure the hardware is idle. Execlist achieves this by switching to a safe context. GuC achieves it by disabling scheduling. Indeed, switching to a 'safe' context really has no effect with GuC submission. So 'effectively the same as pointing to a kernel context' is an incorrect description. I would go with something like: "This is execlist specific behaviour intended to ensure the GPU is idle by switching to a known 'safe' context. With GuC submission, the same idle guarantee is achieved by other means (disabling scheduling). Further, switching to a 'safe' context has no effect with GuC submission as the scheduler can just switch back again. FIXME: Move this backend scheduler specific behaviour into the scheduler backend." John. v2: (Daniel Vetter) - Add FIXME comment about pushing switch_to_kernel_context to backend Signed-off-by: Matthew Brost Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/gt/intel_engine_pm.c | 9 + 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index 1f07ac4e0672..11fee66daf60 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -162,6 +162,15 @@ static bool switch_to_kernel_context(struct intel_engine_cs *engine) unsigned long flags; bool result = true; + /* +* No need to switch_to_kernel_context if GuC submission +* +* FIXME: This execlists specific backend behavior in generic code, this "This execlists" -> "This is execlist" "this should be" -> "it should be" John. +* should be pushed to the backend. +*/ + if (intel_engine_uses_guc(engine)) + return true; + /* GPU is pointing to the void, as good as in the kernel context. */ if (intel_gt_is_wedged(engine->gt)) return true;
Re: [Intel-gfx] [PATCH 06/27] drm/i915/guc: Take engine PM when a context is pinned with GuC submission
On 9/9/2021 17:41, Matthew Brost wrote: On Thu, Sep 09, 2021 at 03:46:43PM -0700, John Harrison wrote: On 8/20/2021 15:44, Matthew Brost wrote: Taking a PM reference to prevent intel_gt_wait_for_idle from short circuiting while a scheduling of user context could be enabled. As with earlier PM patch, needs more explanation of what the problem is and why it is only now a problem. Same explaination, will add here. v2: (Daniel Vetter) - Add might_lock annotations to pin / unpin function Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/gt/intel_context.c | 3 ++ drivers/gpu/drm/i915/gt/intel_engine_pm.h | 15 drivers/gpu/drm/i915/gt/intel_gt_pm.h | 10 ++ .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 36 +-- drivers/gpu/drm/i915/intel_wakeref.h | 12 +++ 5 files changed, 73 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index c8595da64ad8..508cfe5770c0 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -240,6 +240,8 @@ int __intel_context_do_pin_ww(struct intel_context *ce, if (err) goto err_post_unpin; + intel_engine_pm_might_get(ce->engine); + if (unlikely(intel_context_is_closed(ce))) { err = -ENOENT; goto err_unlock; @@ -313,6 +315,7 @@ void __intel_context_do_unpin(struct intel_context *ce, int sub) return; CE_TRACE(ce, "unpin\n"); + intel_engine_pm_might_put(ce->engine); ce->ops->unpin(ce); ce->ops->post_unpin(ce); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.h b/drivers/gpu/drm/i915/gt/intel_engine_pm.h index 17a5028ea177..3fe2ae1bcc26 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.h @@ -9,6 +9,7 @@ #include "i915_request.h" #include "intel_engine_types.h" #include "intel_wakeref.h" +#include "intel_gt_pm.h" static inline bool intel_engine_pm_is_awake(const struct intel_engine_cs *engine) @@ -31,6 +32,13 @@ static inline bool intel_engine_pm_get_if_awake(struct intel_engine_cs *engine) return intel_wakeref_get_if_active(>wakeref); } +static inline void intel_engine_pm_might_get(struct intel_engine_cs *engine) +{ + if (!intel_engine_is_virtual(engine)) + intel_wakeref_might_get(>wakeref); Why doesn't this need to iterate through the physical engines of the virtual engine? Yea, technically it should. This is just an annotation though to check if we do something horribly wrong in our code. If we use any physical engine in our stack this annotation should pop and we can fix it. I just don't see what making this 100% correct for virtual engines buys us. If you want I can fix this but thinking the more complex we make this annotation the less likely it just gets compiled out with lockdep off which is what we are aiming for. But if the annotation is missing a fundamental lock then it is surely not actually going to do any good? Not sure if you need to iterate over all child engines + parent but it seems like you should be calling might_lock() on at least one engine's mutex to feed the lockdep annotation. John. Matt John. + intel_gt_pm_might_get(engine->gt); +} + static inline void intel_engine_pm_put(struct intel_engine_cs *engine) { intel_wakeref_put(>wakeref); @@ -52,6 +60,13 @@ static inline void intel_engine_pm_flush(struct intel_engine_cs *engine) intel_wakeref_unlock_wait(>wakeref); } +static inline void intel_engine_pm_might_put(struct intel_engine_cs *engine) +{ + if (!intel_engine_is_virtual(engine)) + intel_wakeref_might_put(>wakeref); + intel_gt_pm_might_put(engine->gt); +} + static inline struct i915_request * intel_engine_create_kernel_request(struct intel_engine_cs *engine) { diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.h b/drivers/gpu/drm/i915/gt/intel_gt_pm.h index a17bf0d4592b..3c173033ce23 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.h @@ -31,6 +31,11 @@ static inline bool intel_gt_pm_get_if_awake(struct intel_gt *gt) return intel_wakeref_get_if_active(>wakeref); } +static inline void intel_gt_pm_might_get(struct intel_gt *gt) +{ + intel_wakeref_might_get(>wakeref); +} + static inline void intel_gt_pm_put(struct intel_gt *gt) { intel_wakeref_put(>wakeref); @@ -41,6 +46,11 @@ static inline void intel_gt_pm_put_async(struct intel_gt *gt) intel_wakeref_put_async(>wakeref); } +static inline void intel_gt_pm_might_put(struct intel_gt *gt) +{ + intel_wakeref_might_put(>wakeref); +} + #define with_intel_gt_pm(gt, tmp) \ for (tmp = 1, intel_gt_pm_get(gt); tmp; \ intel_gt_pm_put(gt), tmp = 0) diff --git
Re: [PATCH 1/2] drm/bridge: parade-ps8640: Use regmap APIs
On Thu, Sep 9, 2021 at 2:27 PM Stephen Boyd wrote: > > Quoting Doug Anderson (2021-09-09 14:14:29) > > On Thu, Sep 9, 2021 at 12:09 PM Stephen Boyd wrote: > > > > > > > > > Oh does this have register pages? regmap has support for pages where you > > > write some indirection register and then access the same i2c address for > > > the next page. This looks different though and has a different i2c > > > address for each page? > > > > I haven't looked in tons of detail, but I think the right solution > > here is a separate regmap config per page. > > Yes. And then a different .max_register value for each config struct. A > different .name might be useful to indicate which page it is too. I see. I posted v2 with the fix for this. PTAL.
Re: [PATCH 2/2] drm/bridge: parade-ps8640: Add support for AUX channel
On Thu, Sep 9, 2021 at 12:07 PM Stephen Boyd wrote: > > Quoting Philip Chen (2021-09-09 11:15:27) > > On Wed, Sep 8, 2021 at 3:27 PM Stephen Boyd wrote: > > > > > > Quoting Philip Chen (2021-09-08 11:18:06) > > > > > > > + > > > > + data = (len - 1) & AUX_LENGTH_MASK; > > > > + regmap_write(map, PAGE0_AUX_LENGTH, data); > > > > + > > > > + if (request == DP_AUX_NATIVE_WRITE || request == > > > > DP_AUX_I2C_WRITE) { > > > > + ret = regmap_noinc_write(map, PAGE0_AUX_WDATA, buf, > > > > len); > > > > + if (ret < 0) { > > > > + DRM_ERROR("failed to write PAGE0_AUX_WDATA"); > > > > > > Needs a newline. > > Adding an empty line here doesn't look like a common Linux style? > > Could you point me to any similar instances in the Linux codebase? > > Sorry. I meant on the DRM_ERROR message itself. Add a newline. Fixed in v2. PTAL.
[RFC PATCH v2 2/2] drm/bridge: parade-ps8640: Add support for AUX channel
Implement the first version of AUX support, which will be useful as we expand the driver to support varied use cases. WARNING: This patch is not fully verified by hardware. But as AUX CH is not implemented for ps8640 driver until now, the patch shouldn't cause any functional regression in practice. Signed-off-by: Philip Chen --- Changes in v2: - Handle the case where an AUX transaction has no payload - Add a reg polling for p0.0x83 to confirm AUX cmd is issued and read data is returned - Replace regmap_noinc_read/write with looped regmap_read/write, as regmap_noinc_read/write doesn't read one byte at a time unless max_raw_read/write is set to 1. - Register/Unregister the AUX device explicitly when the bridge is attached/detached - Remove the use of runtime PM - Program AUX addr/cmd/len in a single regmap_bulk_write() - Add newlines for DRM_ERROR mesages drivers/gpu/drm/bridge/parade-ps8640.c | 156 - 1 file changed, 153 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index 1b2414601538..3b28e992bb3e 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -13,11 +13,32 @@ #include #include +#include #include #include #include #include +#define PAGE0_AUXCH_CFG3 0x76 +#define AUXCH_CFG3_RESET 0xff +#define PAGE0_AUX_ADDR_7_0 0x7d +#define PAGE0_AUX_ADDR_15_80x7e +#define PAGE0_AUX_ADDR_23_16 0x7f +#define AUX_ADDR_19_16_MASK GENMASK(3, 0) +#define AUX_CMD_MASK GENMASK(7, 4) +#define PAGE0_AUX_LENGTH 0x80 +#define AUX_LENGTH_MASK GENMASK(3, 0) +#define AUX_NO_PAYLOADBIT(7) +#define PAGE0_AUX_WDATA0x81 +#define PAGE0_AUX_RDATA0x82 +#define PAGE0_AUX_CTRL 0x83 +#define AUX_SEND BIT(0) +#define PAGE0_AUX_STATUS 0x84 +#define AUX_STATUS_MASK GENMASK(7, 5) +#define AUX_STATUS_TIMEOUT(0x7 << 5) +#define AUX_STATUS_DEFER (0x2 << 5) +#define AUX_STATUS_NACK (0x1 << 5) + #define PAGE2_GPIO_H 0xa7 #define PS_GPIO9 BIT(1) #define PAGE2_I2C_BYPASS 0xea @@ -68,6 +89,7 @@ enum ps8640_vdo_control { struct ps8640 { struct drm_bridge bridge; struct drm_bridge *panel_bridge; + struct drm_dp_aux aux; struct mipi_dsi_device *dsi; struct i2c_client *page[MAX_DEVS]; struct regmap *regmap[MAX_DEVS]; @@ -117,6 +139,114 @@ static inline struct ps8640 *bridge_to_ps8640(struct drm_bridge *e) return container_of(e, struct ps8640, bridge); } +static inline struct ps8640 *aux_to_ps8640(struct drm_dp_aux *aux) +{ + return container_of(aux, struct ps8640, aux); +} + +static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, + struct drm_dp_aux_msg *msg) +{ + struct ps8640 *ps_bridge = aux_to_ps8640(aux); + struct regmap *map = ps_bridge->regmap[PAGE0_DP_CNTL]; + unsigned int len = msg->size; + unsigned int data; + int ret; + u8 request = msg->request & +~(DP_AUX_I2C_MOT | DP_AUX_I2C_WRITE_STATUS_UPDATE); + u8 *buf = msg->buffer; + u8 addr_len[PAGE0_AUX_LENGTH + 1 - PAGE0_AUX_ADDR_7_0]; + u8 i; + bool is_native_aux = false; + + if (len > DP_AUX_MAX_PAYLOAD_BYTES) + return -EINVAL; + + switch (request) { + case DP_AUX_NATIVE_WRITE: + case DP_AUX_NATIVE_READ: + is_native_aux = true; + case DP_AUX_I2C_WRITE: + case DP_AUX_I2C_READ: + ret = regmap_write(map, PAGE0_AUXCH_CFG3, AUXCH_CFG3_RESET); + break; + default: + ret = -EINVAL; + goto exit; + } + + /* Assume it's good */ + msg->reply = 0; + + addr_len[0] = msg->address & 0xff; + addr_len[1] = (msg->address >> 8) & 0xff; + addr_len[2] = ((request << 4) & AUX_CMD_MASK) | + ((msg->address >> 16) & AUX_ADDR_19_16_MASK); + addr_len[3] = (len == 0) ? AUX_NO_PAYLOAD : + ((len - 1) & AUX_LENGTH_MASK); + + regmap_bulk_write(map, PAGE0_AUX_ADDR_7_0, addr_len, + ARRAY_SIZE(addr_len)); + + if (len && (request == DP_AUX_NATIVE_WRITE || + request == DP_AUX_I2C_WRITE)) { + /* Write to the internal FIFO buffer */ + for (i = 0; i < len; i++) { + ret = regmap_write(map, PAGE0_AUX_WDATA, buf[i]); + if (ret < 0) { + DRM_ERROR("failed to write PAGE0_AUX_WDATA\n"); + goto exit; + } + } + } + + regmap_write(map, PAGE0_AUX_CTRL, AUX_SEND); + + /* Zero delay loop because i2c transactions are slow already */ + ret = regmap_read_poll_timeout(map,
[RFC PATCH v2 1/2] drm/bridge: parade-ps8640: Use regmap APIs
Replace the direct i2c access (i2c_smbus_* functions) with regmap APIs, which will simplify the future update on ps8640 driver. Signed-off-by: Philip Chen --- Changes in v2: - Add separate reg map config per page drivers/gpu/drm/bridge/parade-ps8640.c | 89 ++ 1 file changed, 63 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index 685e9c38b2db..1b2414601538 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -31,6 +32,11 @@ #define NUM_MIPI_LANES 4 +#define COMMON_PS8640_REGMAP_CONFIG \ + .reg_bits = 8, \ + .val_bits = 8, \ + .cache_type = REGCACHE_NONE + /* * PS8640 uses multiple addresses: * page[0]: for DP control @@ -64,12 +70,48 @@ struct ps8640 { struct drm_bridge *panel_bridge; struct mipi_dsi_device *dsi; struct i2c_client *page[MAX_DEVS]; + struct regmap *regmap[MAX_DEVS]; struct regulator_bulk_data supplies[2]; struct gpio_desc *gpio_reset; struct gpio_desc *gpio_powerdown; bool powered; }; +static const struct regmap_config ps8640_regmap_config[] = { + [PAGE0_DP_CNTL] = { + COMMON_PS8640_REGMAP_CONFIG, + .max_register = 0xbf + }, + [PAGE1_VDO_BDG] = { + COMMON_PS8640_REGMAP_CONFIG, + .max_register = 0xff + }, + [PAGE2_TOP_CNTL] = { + COMMON_PS8640_REGMAP_CONFIG, + .max_register = 0xff + }, + [PAGE3_DSI_CNTL1] = { + COMMON_PS8640_REGMAP_CONFIG, + .max_register = 0xff + }, + [PAGE4_MIPI_PHY] = { + COMMON_PS8640_REGMAP_CONFIG, + .max_register = 0xff + }, + [PAGE5_VPLL] = { + COMMON_PS8640_REGMAP_CONFIG, + .max_register = 0x7f + }, + [PAGE6_DSI_CNTL2] = { + COMMON_PS8640_REGMAP_CONFIG, + .max_register = 0xff + }, + [PAGE7_SPI_CNTL] = { + COMMON_PS8640_REGMAP_CONFIG, + .max_register = 0xff + } +}; + static inline struct ps8640 *bridge_to_ps8640(struct drm_bridge *e) { return container_of(e, struct ps8640, bridge); @@ -78,13 +120,13 @@ static inline struct ps8640 *bridge_to_ps8640(struct drm_bridge *e) static int ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, const enum ps8640_vdo_control ctrl) { - struct i2c_client *client = ps_bridge->page[PAGE3_DSI_CNTL1]; + struct regmap *map = ps_bridge->regmap[PAGE3_DSI_CNTL1]; u8 vdo_ctrl_buf[] = { VDO_CTL_ADD, ctrl }; int ret; - ret = i2c_smbus_write_i2c_block_data(client, PAGE3_SET_ADD, -sizeof(vdo_ctrl_buf), -vdo_ctrl_buf); + ret = regmap_bulk_write(map, PAGE3_SET_ADD, + vdo_ctrl_buf, sizeof(vdo_ctrl_buf)); + if (ret < 0) { DRM_ERROR("failed to %sable VDO: %d\n", ctrl == ENABLE ? "en" : "dis", ret); @@ -96,8 +138,7 @@ static int ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, static void ps8640_bridge_poweron(struct ps8640 *ps_bridge) { - struct i2c_client *client = ps_bridge->page[PAGE2_TOP_CNTL]; - unsigned long timeout; + struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; int ret, status; if (ps_bridge->powered) @@ -121,18 +162,12 @@ static void ps8640_bridge_poweron(struct ps8640 *ps_bridge) */ msleep(200); - timeout = jiffies + msecs_to_jiffies(200) + 1; + ret = regmap_read_poll_timeout(map, PAGE2_GPIO_H, status, + status & PS_GPIO9, 20 * 1000, 200 * 1000); - while (time_is_after_jiffies(timeout)) { - status = i2c_smbus_read_byte_data(client, PAGE2_GPIO_H); - if (status < 0) { - DRM_ERROR("failed read PAGE2_GPIO_H: %d\n", status); - goto err_regulators_disable; - } - if ((status & PS_GPIO9) == PS_GPIO9) - break; - - msleep(20); + if (ret < 0) { + DRM_ERROR("failed read PAGE2_GPIO_H: %d\n", ret); + goto err_regulators_disable; } msleep(50); @@ -144,22 +179,15 @@ static void ps8640_bridge_poweron(struct ps8640 *ps_bridge) * disabled by the manufacturer. Once disabled, all MCS commands are * ignored by the display interface. */ - status = i2c_smbus_read_byte_data(client, PAGE2_MCS_EN); - if (status < 0) { - DRM_ERROR("failed read PAGE2_MCS_EN: %d\n", status); - goto
Re: [PATCH 12/14] dt-bindings: msm/dp: Add bindings for HDCP registers
On Mon, 13 Sep 2021 13:57:43 -0400, Sean Paul wrote: > From: Sean Paul > > This patch adds the bindings for the MSM DisplayPort HDCP registers > which are required to write the HDCP key into the display controller as > well as the registers to enable HDCP authentication/key > exchange/encryption. > > Signed-off-by: Sean Paul > --- > .../bindings/display/msm/dp-controller.yaml | 11 +-- > 1 file changed, 9 insertions(+), 2 deletions(-) > My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check' on your patch (DT_CHECKER_FLAGS is new in v5.13): yamllint warnings/errors: ./Documentation/devicetree/bindings/display/msm/dp-controller.yaml:26:5: [error] duplication of key "const" in mapping (key-duplicates) ./Documentation/devicetree/bindings/display/msm/dp-controller.yaml:27:5: [error] duplication of key "const" in mapping (key-duplicates) dtschema/dtc warnings/errors: make[1]: *** Deleting file 'Documentation/devicetree/bindings/display/msm/dp-controller.example.dts' Traceback (most recent call last): File "/usr/local/bin/dt-extract-example", line 45, in binding = yaml.load(open(args.yamlfile, encoding='utf-8').read()) File "/usr/local/lib/python3.8/dist-packages/ruamel/yaml/main.py", line 434, in load return constructor.get_single_data() File "/usr/local/lib/python3.8/dist-packages/ruamel/yaml/constructor.py", line 122, in get_single_data return self.construct_document(node) File "/usr/local/lib/python3.8/dist-packages/ruamel/yaml/constructor.py", line 132, in construct_document for _dummy in generator: File "/usr/local/lib/python3.8/dist-packages/ruamel/yaml/constructor.py", line 722, in construct_yaml_map value = self.construct_mapping(node) File "/usr/local/lib/python3.8/dist-packages/ruamel/yaml/constructor.py", line 446, in construct_mapping return BaseConstructor.construct_mapping(self, node, deep=deep) File "/usr/local/lib/python3.8/dist-packages/ruamel/yaml/constructor.py", line 264, in construct_mapping if self.check_mapping_key(node, key_node, mapping, key, value): File "/usr/local/lib/python3.8/dist-packages/ruamel/yaml/constructor.py", line 295, in check_mapping_key raise DuplicateKeyError(*args) ruamel.yaml.constructor.DuplicateKeyError: while constructing a mapping in "", line 25, column 5 found duplicate key "const" with value "hdcp_key" (original value: "dp_controller") in "", line 26, column 5 To suppress this check see: http://yaml.readthedocs.io/en/latest/api.html#duplicate-keys make[1]: *** [Documentation/devicetree/bindings/Makefile:20: Documentation/devicetree/bindings/display/msm/dp-controller.example.dts] Error 1 make[1]: *** Waiting for unfinished jobs Traceback (most recent call last): File "/usr/local/bin/dt-doc-validate", line 25, in check_doc testtree = dtschema.load(filename, line_number=line_number) File "/usr/local/lib/python3.8/dist-packages/dtschema/lib.py", line 623, in load return yaml.load(f.read()) File "/usr/local/lib/python3.8/dist-packages/ruamel/yaml/main.py", line 434, in load return constructor.get_single_data() File "/usr/local/lib/python3.8/dist-packages/ruamel/yaml/constructor.py", line 122, in get_single_data return self.construct_document(node) File "/usr/local/lib/python3.8/dist-packages/ruamel/yaml/constructor.py", line 132, in construct_document for _dummy in generator: File "/usr/local/lib/python3.8/dist-packages/ruamel/yaml/constructor.py", line 722, in construct_yaml_map value = self.construct_mapping(node) File "/usr/local/lib/python3.8/dist-packages/ruamel/yaml/constructor.py", line 446, in construct_mapping return BaseConstructor.construct_mapping(self, node, deep=deep) File "/usr/local/lib/python3.8/dist-packages/ruamel/yaml/constructor.py", line 264, in construct_mapping if self.check_mapping_key(node, key_node, mapping, key, value): File "/usr/local/lib/python3.8/dist-packages/ruamel/yaml/constructor.py", line 295, in check_mapping_key raise DuplicateKeyError(*args) ruamel.yaml.constructor.DuplicateKeyError: while constructing a mapping in "", line 25, column 5 found duplicate key "const" with value "hdcp_key" (original value: "dp_controller") in "", line 26, column 5 To suppress this check see: http://yaml.readthedocs.io/en/latest/api.html#duplicate-keys During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/local/bin/dt-doc-validate", line 67, in ret = check_doc(f) File "/usr/local/bin/dt-doc-validate", line 30, in check_doc print(filename + ":", exc.path[-1], exc.message, file=sys.stderr) AttributeError: 'DuplicateKeyError' object has no attribute 'path' /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/msm/dp-controller.yaml: ignoring, error parsing file warning: no schema found in file: ./Documentation/devicetree/bindings/display/msm/dp-controller.yaml
Re: [Intel-gfx] [PATCH] drm/i915/guc: Refcount context during error capture
On Mon, Sep 13, 2021 at 02:10:16PM -0700, john.c.harri...@intel.com wrote: > From: John Harrison > > When i915 receives a context reset notification from GuC, it triggers > an error capture before resetting any outstanding requsts of that > context. Unfortunately, the error capture is not a time bound > operation. In certain situations it can take a long time, particularly > when multiple large LMEM buffers must be read back and eoncoded. If > this delay is longer than other timeouts (heartbeat, test recovery, > etc.) then a full GT reset can be triggered in the middle. > > That can result in the context being reset by GuC actually being > destroyed before the error capture completes and the GuC submission > code resumes. Thus, the GuC side can start dereferencing stale > pointers and Bad Things ensue. > > So add a refcount get of the context during the entire reset > operation. That way, the context can't be destroyed part way through > no matter what other resets or user interactions occur. > > Signed-off-by: John Harrison > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 14 ++ > 1 file changed, 14 insertions(+) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > index c7a41802b448..7291fd8f68a6 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > @@ -2920,6 +2920,7 @@ int intel_guc_context_reset_process_msg(struct > intel_guc *guc, > { > struct intel_context *ce; > int desc_idx; > + unsigned long flags; > > if (unlikely(len != 1)) { > drm_err(_to_gt(guc)->i915->drm, "Invalid length %u", len); > @@ -2927,11 +2928,24 @@ int intel_guc_context_reset_process_msg(struct > intel_guc *guc, > } > > desc_idx = msg[0]; > + > + /* > + * The context lookup uses the xarray but lookups only require an RCU > lock > + * not the full spinlock. So take the lock explicitly and keep it until > the > + * context has been reference count locked to ensure it can't be > destroyed > + * asynchronously until the reset is done. > + */ > + xa_lock_irqsave(>context_lookup, flags); > ce = g2h_context_lookup(guc, desc_idx); > + if (ce) > + intel_context_get(ce); > + xa_unlock_irqrestore(>context_lookup, flags); > + > if (unlikely(!ce)) > return -EPROTO; > > guc_handle_context_reset(guc, ce); > + intel_context_put(ce); So this is going to directly conflict with a patch that I'm about to post as I'm going to change the error capture to async operation. In that case the intel_context_put would need to be done once that op completes. I'll likely pull this patch into that series. I'd expect it to be posted by the end of the day. Matt > > return 0; > } > -- > 2.25.1 >
[PATCH] drm/i915/guc: Refcount context during error capture
From: John Harrison When i915 receives a context reset notification from GuC, it triggers an error capture before resetting any outstanding requsts of that context. Unfortunately, the error capture is not a time bound operation. In certain situations it can take a long time, particularly when multiple large LMEM buffers must be read back and eoncoded. If this delay is longer than other timeouts (heartbeat, test recovery, etc.) then a full GT reset can be triggered in the middle. That can result in the context being reset by GuC actually being destroyed before the error capture completes and the GuC submission code resumes. Thus, the GuC side can start dereferencing stale pointers and Bad Things ensue. So add a refcount get of the context during the entire reset operation. That way, the context can't be destroyed part way through no matter what other resets or user interactions occur. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 14 ++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index c7a41802b448..7291fd8f68a6 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -2920,6 +2920,7 @@ int intel_guc_context_reset_process_msg(struct intel_guc *guc, { struct intel_context *ce; int desc_idx; + unsigned long flags; if (unlikely(len != 1)) { drm_err(_to_gt(guc)->i915->drm, "Invalid length %u", len); @@ -2927,11 +2928,24 @@ int intel_guc_context_reset_process_msg(struct intel_guc *guc, } desc_idx = msg[0]; + + /* +* The context lookup uses the xarray but lookups only require an RCU lock +* not the full spinlock. So take the lock explicitly and keep it until the +* context has been reference count locked to ensure it can't be destroyed +* asynchronously until the reset is done. +*/ + xa_lock_irqsave(>context_lookup, flags); ce = g2h_context_lookup(guc, desc_idx); + if (ce) + intel_context_get(ce); + xa_unlock_irqrestore(>context_lookup, flags); + if (unlikely(!ce)) return -EPROTO; guc_handle_context_reset(guc, ce); + intel_context_put(ce); return 0; } -- 2.25.1
Re: [PATCH 00/14] drm/hdcp: Pull HDCP auth/exchange/check into
On 2021-09-13 3:26 p.m., Sean Paul wrote: > On Mon, Sep 13, 2021 at 2:05 PM Alex Deucher wrote: >> >> On Mon, Sep 13, 2021 at 1:57 PM Sean Paul wrote: >>> >>> From: Sean Paul >>> >>> Hello, >>> This patchset pulls the HDCP protocol auth/exchange/check logic out from >>> i915 into a HDCP helper library which drivers can use to implement the >>> proper protocol and UAPI interactions for achieving HDCP. >>> >>> Originally this was all stuffed into i915 since it was the only driver >>> supporting HDCP. Over the last while I've been working on HDCP support >>> in the msm driver and have identified the parts which can/should be >>> shared between drivers and the parts which are hw-specific. >>> >>> We can generalize all of the sink interactions in the helper as well as >>> state handling and link checks. This tends to be the trickiest part of >>> adding HDCP support, since the property state and locking is a bit of a >>> nightmare. The driver need only implement the more mechanical display >>> controller register accesses. >>> >>> The first third of the pachset is establishing the helpers, the next >>> third is converting the i915 driver to use the helpers, and the last >>> third is the msm driver implementation. >>> >>> I've left out HDCP 2.x support, since we still only have i915 as the >>> reference implementation and I'm not super comfortable speculating on >>> which parts are platform independent. >> >> FWIW, amdgpu has support for both HDCP 1.x and 2.x >> > > Thanks Alex, I knew this and neglected to mention it, apologies for > the omission. > > IIRC amdgpu is much less hands-on than i915/msm, with PSP doing most > of the heavy lifting. There's probably some value in using the helpers > since it'll handle the state transitions in a consistent manner, do > you think this is something you can use? > We might be able to use drm_hdcp_atomic_check but the HDCP protocol stuff is sitting in our hdcp module and shared with other OSes so sharing it would be difficult. Harry > Sean > > >> Alex >> >>> >>> Please take a look, >>> >>> Sean >>> >>> Sean Paul (14): >>> drm/hdcp: Add drm_hdcp_atomic_check() >>> drm/hdcp: Avoid changing crtc state in hdcp atomic check >>> drm/hdcp: Update property value on content type and user changes >>> drm/hdcp: Expand HDCP helper library for enable/disable/check >>> drm/i915/hdcp: Consolidate HDCP setup/state cache >>> drm/i915/hdcp: Retain hdcp_capable return codes >>> drm/i915/hdcp: Use HDCP helpers for i915 >>> drm/msm/dpu_kms: Re-order dpu includes >>> drm/msm/dpu: Remove useless checks in dpu_encoder >>> drm/msm/dpu: Remove encoder->enable() hack >>> drm/msm/dp: Re-order dp_audio_put in deinit_sub_modules >>> dt-bindings: msm/dp: Add bindings for HDCP registers >>> drm/msm: Add hdcp register ranges to sc7180 device tree >>> drm/msm: Implement HDCP 1.x using the new drm HDCP helpers >>> >>> .../bindings/display/msm/dp-controller.yaml | 11 +- >>> drivers/gpu/drm/drm_hdcp.c| 1198 - >>> drivers/gpu/drm/i915/display/intel_atomic.c |7 +- >>> drivers/gpu/drm/i915/display/intel_ddi.c | 29 +- >>> .../drm/i915/display/intel_display_debugfs.c | 11 +- >>> .../drm/i915/display/intel_display_types.h| 58 +- >>> drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 341 ++--- >>> drivers/gpu/drm/i915/display/intel_dp_mst.c | 17 +- >>> drivers/gpu/drm/i915/display/intel_hdcp.c | 1011 +++--- >>> drivers/gpu/drm/i915/display/intel_hdcp.h | 35 +- >>> drivers/gpu/drm/i915/display/intel_hdmi.c | 256 ++-- >>> drivers/gpu/drm/msm/Makefile |1 + >>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 17 +- >>> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 30 +- >>> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |2 - >>> drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h |4 - >>> drivers/gpu/drm/msm/dp/dp_debug.c | 49 +- >>> drivers/gpu/drm/msm/dp/dp_debug.h |6 +- >>> drivers/gpu/drm/msm/dp/dp_display.c | 47 +- >>> drivers/gpu/drm/msm/dp/dp_display.h |5 + >>> drivers/gpu/drm/msm/dp/dp_drm.c | 68 +- >>> drivers/gpu/drm/msm/dp/dp_drm.h |5 + >>> drivers/gpu/drm/msm/dp/dp_hdcp.c | 433 ++ >>> drivers/gpu/drm/msm/dp/dp_hdcp.h | 27 + >>> drivers/gpu/drm/msm/dp/dp_parser.c| 30 +- >>> drivers/gpu/drm/msm/dp/dp_parser.h|4 + >>> drivers/gpu/drm/msm/dp/dp_reg.h | 44 +- >>> drivers/gpu/drm/msm/msm_atomic.c | 15 + >>> include/drm/drm_hdcp.h| 194 +++ >>> 29 files changed, 2570 insertions(+), 1385 deletions(-) >>> create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c >>> create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h >>> >>> -- >>> Sean Paul, Software Engineer, Google / Chromium OS >>>
[PATCH] drm/i915/selftests: Add a cancel request selftest that triggers a reset
Add a cancel request selftest that results in an engine reset to cancel the request as it is non-preemptable. Also insert a NOP request after the cancelled request and confirm that it completes successfully. v2: (Tvrtko) - Skip test if preemption timeout compiled out - Skip test if engine reset isn't supported - Update debug prints to be more descriptive Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/selftests/i915_request.c | 106 ++ 1 file changed, 106 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index d67710d10615..299fc586488a 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -772,6 +772,104 @@ static int __cancel_completed(struct intel_engine_cs *engine) return err; } +static int __cancel_reset(struct drm_i915_private *i915, + struct intel_engine_cs *engine) +{ + struct intel_context *ce; + struct igt_spinner spin; + struct i915_request *rq, *nop; + unsigned long preempt_timeout_ms; + int err = 0; + + if (!CONFIG_DRM_I915_PREEMPT_TIMEOUT || + !intel_has_reset_engine(engine->gt)) + return 0; + + preempt_timeout_ms = engine->props.preempt_timeout_ms; + engine->props.preempt_timeout_ms = 100; + + if (igt_spinner_init(, engine->gt)) + goto out_restore; + + ce = intel_context_create(engine); + if (IS_ERR(ce)) { + err = PTR_ERR(ce); + goto out_spin; + } + + rq = igt_spinner_create_request(, ce, MI_NOOP); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); + goto out_ce; + } + + pr_debug("%s: Cancelling active non-preemptable request\n", +engine->name); + i915_request_get(rq); + i915_request_add(rq); + if (!igt_wait_for_spinner(, rq)) { + struct drm_printer p = drm_info_printer(engine->i915->drm.dev); + + pr_err("Failed to start spinner on %s\n", engine->name); + intel_engine_dump(engine, , "%s\n", engine->name); + err = -ETIME; + goto out_rq; + } + + nop = intel_context_create_request(ce); + if (IS_ERR(nop)) + goto out_nop; + i915_request_get(nop); + i915_request_add(nop); + + i915_request_cancel(rq, -EINTR); + + if (i915_request_wait(rq, 0, HZ) < 0) { + struct drm_printer p = drm_info_printer(engine->i915->drm.dev); + + pr_err("%s: Failed to cancel hung request\n", engine->name); + intel_engine_dump(engine, , "%s\n", engine->name); + err = -ETIME; + goto out_nop; + } + + if (rq->fence.error != -EINTR) { + pr_err("%s: fence not cancelled (%u)\n", + engine->name, rq->fence.error); + err = -EINVAL; + goto out_nop; + } + + if (i915_request_wait(nop, 0, HZ) < 0) { + struct drm_printer p = drm_info_printer(engine->i915->drm.dev); + + pr_err("%s: Failed to complete nop request\n", engine->name); + intel_engine_dump(engine, , "%s\n", engine->name); + err = -ETIME; + goto out_nop; + } + + if (nop->fence.error != 0) { + pr_err("%s: Nop request errored (%u)\n", + engine->name, nop->fence.error); + err = -EINVAL; + } + +out_nop: + i915_request_put(nop); +out_rq: + i915_request_put(rq); +out_ce: + intel_context_put(ce); +out_spin: + igt_spinner_fini(); +out_restore: + engine->props.preempt_timeout_ms = preempt_timeout_ms; + if (err) + pr_err("%s: %s error %d\n", __func__, engine->name, err); + return err; +} + static int live_cancel_request(void *arg) { struct drm_i915_private *i915 = arg; @@ -804,6 +902,14 @@ static int live_cancel_request(void *arg) return err; if (err2) return err2; + + /* Expects reset so call outside of igt_live_test_* */ + err = __cancel_reset(i915, engine); + if (err) + return err; + + if (igt_flush_test(i915)) + return -EIO; } return 0; -- 2.32.0
[Bug 214029] [NAVI] Several memory leaks in amdgpu and ttm
https://bugzilla.kernel.org/show_bug.cgi?id=214029 Erhard F. (erhar...@mailbox.org) changed: What|Removed |Added Attachment #298525|0 |1 is obsolete|| --- Comment #10 from Erhard F. (erhar...@mailbox.org) --- Created attachment 298787 --> https://bugzilla.kernel.org/attachment.cgi?id=298787=edit kernel .config (kernel 5.15-rc1, AMD FX-8370) -- You may reply to this email to add a comment. You are receiving this mail because: You are watching the assignee of the bug.
[Bug 214029] [NAVI] Several memory leaks in amdgpu and ttm
https://bugzilla.kernel.org/show_bug.cgi?id=214029 --- Comment #9 from Erhard F. (erhar...@mailbox.org) --- Created attachment 298785 --> https://bugzilla.kernel.org/attachment.cgi?id=298785=edit kernel dmesg (kernel 5.15-rc1, AMD FX-8370) -- You may reply to this email to add a comment. You are receiving this mail because: You are watching the assignee of the bug.
[Bug 214029] [NAVI] Several memory leaks in amdgpu and ttm
https://bugzilla.kernel.org/show_bug.cgi?id=214029 --- Comment #8 from Erhard F. (erhar...@mailbox.org) --- Created attachment 298783 --> https://bugzilla.kernel.org/attachment.cgi?id=298783=edit output of kmemleak (kernel 5.15-rc1, AMD FX-8370) Seems unchanged in kernel 5.15-rc1. # cat /sys/kernel/debug/kmemleak unreferenced object 0x88810830b400 (size 1024): comm "lxdm-greeter-gt", pid 624, jiffies 4294887923 (age 1566.300s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 08 b4 30 08 81 88 ff ff ..0. 08 b4 30 08 81 88 ff ff 30 f5 10 9b 81 88 ff ff ..0.0... backtrace: [] amdgpu_job_alloc+0x38/0x2f0 [amdgpu] [] amdgpu_job_alloc_with_ib+0x27/0xf0 [amdgpu] [] amdgpu_copy_buffer+0x1d3/0x700 [amdgpu] [] amdgpu_ttm_copy_mem_to_mem+0x5fa/0xf00 [amdgpu] [] amdgpu_bo_move+0x356/0x2050 [amdgpu] [] ttm_bo_handle_move_mem+0x1c7/0x620 [ttm] [] ttm_bo_validate+0x2b3/0x3b0 [ttm] [] amdgpu_bo_fault_reserve_notify+0x2a4/0x640 [amdgpu] [] amdgpu_gem_fault+0x123/0x2d0 [amdgpu] [] __do_fault+0xf3/0x3e0 [] __handle_mm_fault+0x16e5/0x2aa0 [] handle_mm_fault+0x12a/0x490 [] do_user_addr_fault+0x259/0xb70 [] exc_page_fault+0x55/0xb0 [] asm_exc_page_fault+0x1b/0x20 unreferenced object 0x8881fe3ca4c0 (size 216): comm "lxdm-greeter-gt", pid 624, jiffies 4294887923 (age 1566.300s) hex dump (first 32 bytes): 50 a5 3c fe 81 88 ff ff 20 ab 74 c0 ff ff ff ff P.<. .t. e0 ea 04 ac 08 00 00 00 50 fd c5 08 00 c9 ff ff P... backtrace: [] drm_sched_fence_create+0x1f/0x1d0 [gpu_sched] [] drm_sched_job_init+0x10e/0x240 [gpu_sched] [] amdgpu_job_submit+0x25/0x100 [amdgpu] [] amdgpu_copy_buffer+0x49e/0x700 [amdgpu] [] amdgpu_ttm_copy_mem_to_mem+0x5fa/0xf00 [amdgpu] [] amdgpu_bo_move+0x356/0x2050 [amdgpu] [] ttm_bo_handle_move_mem+0x1c7/0x620 [ttm] [] ttm_bo_validate+0x2b3/0x3b0 [ttm] [] amdgpu_bo_fault_reserve_notify+0x2a4/0x640 [amdgpu] [] amdgpu_gem_fault+0x123/0x2d0 [amdgpu] [] __do_fault+0xf3/0x3e0 [] __handle_mm_fault+0x16e5/0x2aa0 [] handle_mm_fault+0x12a/0x490 [] do_user_addr_fault+0x259/0xb70 [] exc_page_fault+0x55/0xb0 [] asm_exc_page_fault+0x1b/0x20 unreferenced object 0x8881cdbb7000 (size 1024): comm "mate-session-ch", pid 722, jiffies 4294890054 (age 1559.204s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 08 70 bb cd 81 88 ff ff .p.. 08 70 bb cd 81 88 ff ff 30 f5 10 9b 81 88 ff ff .p..0... backtrace: [] amdgpu_job_alloc+0x38/0x2f0 [amdgpu] [] amdgpu_job_alloc_with_ib+0x27/0xf0 [amdgpu] [] amdgpu_copy_buffer+0x1d3/0x700 [amdgpu] [] amdgpu_ttm_copy_mem_to_mem+0x5fa/0xf00 [amdgpu] [] amdgpu_bo_move+0x356/0x2050 [amdgpu] [] ttm_bo_handle_move_mem+0x1c7/0x620 [ttm] [] ttm_bo_validate+0x2b3/0x3b0 [ttm] [] amdgpu_bo_fault_reserve_notify+0x2a4/0x640 [amdgpu] [] amdgpu_gem_fault+0x123/0x2d0 [amdgpu] [] __do_fault+0xf3/0x3e0 [] __handle_mm_fault+0x16e5/0x2aa0 [] handle_mm_fault+0x12a/0x490 [] do_user_addr_fault+0x259/0xb70 [] exc_page_fault+0x55/0xb0 [] asm_exc_page_fault+0x1b/0x20 [...] -- You may reply to this email to add a comment. You are receiving this mail because: You are watching the assignee of the bug.
Re: [PATCH v2 1/2] drm/probe-helper: Create a HPD IRQ event helper for a single connector
Hi Maxime, thanks for the ping on irc. I had accidently deleted v2 of this patch. Sam On Mon, Aug 30, 2021 at 11:49:09AM +0200, Maxime Ripard wrote: > The drm_helper_hpd_irq_event() function is iterating over all the > connectors when an hotplug event is detected. > > During that iteration, it will call each connector detect function and > figure out if its status changed. > > Finally, if any connector changed, it will notify the user-space and the > clients that something changed on the DRM device. > > This is supposed to be used for drivers that don't have a hotplug > interrupt for individual connectors. However, drivers that can use an > interrupt for a single connector are left in the dust and can either > reimplement the logic used during the iteration for each connector or > use that helper and iterate over all connectors all the time. > > Since both are suboptimal, let's create a helper that will only perform > the status detection on a single connector. > > Signed-off-by: Maxime Ripard A few comments in the following. Sam > > --- > > Changes from v1: > - Rename the shared function > - Move the hotplug event notification out of the shared function > - Added missing locks > - Improve the documentation > - Switched to drm_dbg_kms > --- > drivers/gpu/drm/drm_probe_helper.c | 120 - > include/drm/drm_probe_helper.h | 1 + > 2 files changed, 86 insertions(+), 35 deletions(-) > > diff --git a/drivers/gpu/drm/drm_probe_helper.c > b/drivers/gpu/drm/drm_probe_helper.c > index 5606bca3caa8..fcf32ec0b0c8 100644 > --- a/drivers/gpu/drm/drm_probe_helper.c > +++ b/drivers/gpu/drm/drm_probe_helper.c > @@ -795,6 +795,86 @@ void drm_kms_helper_poll_fini(struct drm_device *dev) > } > EXPORT_SYMBOL(drm_kms_helper_poll_fini); > > +static bool check_connector_changed(struct drm_connector *connector) > +{ > + struct drm_device *dev = connector->dev; > + enum drm_connector_status old_status; > + u64 old_epoch_counter; > + bool changed = false; > + > + /* Only handle HPD capable connectors. */ > + drm_WARN_ON(dev, !(connector->polled & DRM_CONNECTOR_POLL_HPD)); > + > + drm_WARN_ON(dev, !mutex_is_locked(>mode_config.mutex)); > + > + old_status = connector->status; > + old_epoch_counter = connector->epoch_counter; > + > + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Old epoch counter %llu\n", > + connector->base.id, > + connector->name, > + old_epoch_counter); > + > + connector->status = drm_helper_probe_detect(connector, NULL, false); > + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] status updated from %s to %s\n", > + connector->base.id, > + connector->name, > + drm_get_connector_status_name(old_status), > + drm_get_connector_status_name(connector->status)); > + > + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] New epoch counter %llu\n", > + connector->base.id, > + connector->name, > + connector->epoch_counter); > + > + /* > + * Check if epoch counter had changed, meaning that we need > + * to send a uevent. > + */ > + if (old_epoch_counter != connector->epoch_counter) > + changed = true; If logging is included here we could do it like: if (old_epoch_counter != connector->epoch_counter) { drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Changed epoch counter %llu => %llu\n", connector->base.id, connector->name, old_epoch_counter, connector->epoch_counter); return true; } else { drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Same epoch counter %llu\n", connector->base.id, connector->name, connector->epoch_counter); return false; } } So we only log epoch counter once. And the changed local variable is gone. Just a suggestion. > + > + return changed; > +} > + > +/** > + * drm_connector_helper_hpd_irq_event - hotplug processing > + * @connector: drm_connector > + * > + * Drivers can use this helper function to run a detect cycle on a connector > + * which has the DRM_CONNECTOR_POLL_HPD flag set in its member. > + * > + * This helper function is useful for drivers which can track hotplug > + * interrupts for a single connector. Drivers that want to send a > + * hotplug event for all connectors or can't track hotplug interrupts > + * per connector need to use drm_helper_hpd_irq_event(). > + * > + * This function must be called from process context with no mode > + * setting locks held. > + * > + * Note that a connector can be both polled and probed from the hotplug > + * handler, in case the hotplug interrupt is known to be unreliable. Documentation of the return value would be nice. > + */ > +bool
RE: [PATCH] drm/hyperv: Fix double mouse pointers
> -Original Message- > From: Dexuan Cui > Sent: Monday, September 13, 2021 2:27 PM > To: drawat.fl...@gmail.com; Haiyang Zhang ; > airl...@linux.ie; dan...@ffwll.ch; tzimmerm...@suse.de; dri- > de...@lists.freedesktop.org > Cc: linux-hyp...@vger.kernel.org; linux-ker...@vger.kernel.org; Dexuan > Cui > Subject: [PATCH] drm/hyperv: Fix double mouse pointers > > It looks like Hyper-V supports a hardware cursor feature. It is not used > by Linux VM, but the Hyper-V host still draws a point as an extra mouse > pointer, which is unwanted, especially when Xorg is running. > > The hyperv_fb driver uses synthvid_send_ptr() to hide the unwanted > pointer. > When the hyperv_drm driver was developed, the function > synthvid_send_ptr() > was not copied from the hyperv_fb driver. Fix the issue by adding the > function into hyperv_drm. > > Fixes: 76c56a5affeb ("drm/hyperv: Add DRM driver for hyperv synthetic > video device") > Signed-off-by: Dexuan Cui > Cc: Deepak Rawat > Cc: Haiyang Zhang > --- > drivers/gpu/drm/hyperv/hyperv_drm.h | 1 + > drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 1 + > drivers/gpu/drm/hyperv/hyperv_drm_proto.c | 39 - > 3 files changed, 40 insertions(+), 1 deletion(-) Thank you! Reviewed-by: Haiyang Zhang
[PATCH] drm/i915/dp: add a delay before setting panel brightness after power on
Panel in my Dell XPS 7590, that uses Intel's HDR backlight interface to control brightness, apparently needs a delay before setting brightness after power on. Without this delay the panel does accept the setting and may come up with some arbitrary brightness (sometimes it's too dark, sometimes it's too bright, I wasn't able to find a system). I don't have access to the spec, so I'm not sure if it's expected behavior or a quirk for particular device. Delay was chosen by experiment: it works with 100ms, but fails with anything lower than 75ms. Signed-off-by: Vasily Khoruzhick --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 4f8337c7fd2e..c4f35e1b5870 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -210,6 +210,10 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, ctrl = old_ctrl; if (panel->backlight.edp.intel.sdr_uses_aux) { + /* Wait 100ms to ensure that panel is ready otherwise it may not +* set chosen backlight level +*/ + msleep(100); ctrl |= INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE; intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { -- 2.33.0
Re: [PATCH 00/14] drm/hdcp: Pull HDCP auth/exchange/check into
On Mon, Sep 13, 2021 at 2:05 PM Alex Deucher wrote: > > On Mon, Sep 13, 2021 at 1:57 PM Sean Paul wrote: > > > > From: Sean Paul > > > > Hello, > > This patchset pulls the HDCP protocol auth/exchange/check logic out from > > i915 into a HDCP helper library which drivers can use to implement the > > proper protocol and UAPI interactions for achieving HDCP. > > > > Originally this was all stuffed into i915 since it was the only driver > > supporting HDCP. Over the last while I've been working on HDCP support > > in the msm driver and have identified the parts which can/should be > > shared between drivers and the parts which are hw-specific. > > > > We can generalize all of the sink interactions in the helper as well as > > state handling and link checks. This tends to be the trickiest part of > > adding HDCP support, since the property state and locking is a bit of a > > nightmare. The driver need only implement the more mechanical display > > controller register accesses. > > > > The first third of the pachset is establishing the helpers, the next > > third is converting the i915 driver to use the helpers, and the last > > third is the msm driver implementation. > > > > I've left out HDCP 2.x support, since we still only have i915 as the > > reference implementation and I'm not super comfortable speculating on > > which parts are platform independent. > > FWIW, amdgpu has support for both HDCP 1.x and 2.x > Thanks Alex, I knew this and neglected to mention it, apologies for the omission. IIRC amdgpu is much less hands-on than i915/msm, with PSP doing most of the heavy lifting. There's probably some value in using the helpers since it'll handle the state transitions in a consistent manner, do you think this is something you can use? Sean > Alex > > > > > Please take a look, > > > > Sean > > > > Sean Paul (14): > > drm/hdcp: Add drm_hdcp_atomic_check() > > drm/hdcp: Avoid changing crtc state in hdcp atomic check > > drm/hdcp: Update property value on content type and user changes > > drm/hdcp: Expand HDCP helper library for enable/disable/check > > drm/i915/hdcp: Consolidate HDCP setup/state cache > > drm/i915/hdcp: Retain hdcp_capable return codes > > drm/i915/hdcp: Use HDCP helpers for i915 > > drm/msm/dpu_kms: Re-order dpu includes > > drm/msm/dpu: Remove useless checks in dpu_encoder > > drm/msm/dpu: Remove encoder->enable() hack > > drm/msm/dp: Re-order dp_audio_put in deinit_sub_modules > > dt-bindings: msm/dp: Add bindings for HDCP registers > > drm/msm: Add hdcp register ranges to sc7180 device tree > > drm/msm: Implement HDCP 1.x using the new drm HDCP helpers > > > > .../bindings/display/msm/dp-controller.yaml | 11 +- > > drivers/gpu/drm/drm_hdcp.c| 1198 - > > drivers/gpu/drm/i915/display/intel_atomic.c |7 +- > > drivers/gpu/drm/i915/display/intel_ddi.c | 29 +- > > .../drm/i915/display/intel_display_debugfs.c | 11 +- > > .../drm/i915/display/intel_display_types.h| 58 +- > > drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 341 ++--- > > drivers/gpu/drm/i915/display/intel_dp_mst.c | 17 +- > > drivers/gpu/drm/i915/display/intel_hdcp.c | 1011 +++--- > > drivers/gpu/drm/i915/display/intel_hdcp.h | 35 +- > > drivers/gpu/drm/i915/display/intel_hdmi.c | 256 ++-- > > drivers/gpu/drm/msm/Makefile |1 + > > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 17 +- > > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 30 +- > > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |2 - > > drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h |4 - > > drivers/gpu/drm/msm/dp/dp_debug.c | 49 +- > > drivers/gpu/drm/msm/dp/dp_debug.h |6 +- > > drivers/gpu/drm/msm/dp/dp_display.c | 47 +- > > drivers/gpu/drm/msm/dp/dp_display.h |5 + > > drivers/gpu/drm/msm/dp/dp_drm.c | 68 +- > > drivers/gpu/drm/msm/dp/dp_drm.h |5 + > > drivers/gpu/drm/msm/dp/dp_hdcp.c | 433 ++ > > drivers/gpu/drm/msm/dp/dp_hdcp.h | 27 + > > drivers/gpu/drm/msm/dp/dp_parser.c| 30 +- > > drivers/gpu/drm/msm/dp/dp_parser.h|4 + > > drivers/gpu/drm/msm/dp/dp_reg.h | 44 +- > > drivers/gpu/drm/msm/msm_atomic.c | 15 + > > include/drm/drm_hdcp.h| 194 +++ > > 29 files changed, 2570 insertions(+), 1385 deletions(-) > > create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c > > create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h > > > > -- > > Sean Paul, Software Engineer, Google / Chromium OS > >
Re: [PATCH v2 0/9] Move vfio_ccw to the new mdev API
On Mon, Sep 13, 2021 at 01:40:34PM -0400, Eric Farman wrote: > On Thu, 2021-09-09 at 16:38 -0300, Jason Gunthorpe wrote: > > This addresses Cornelia's remark on the earlier patch that ccw has a > > confusing lifecycle. While it doesn't seem like the original attempt > > was > > functionally wrong, the result can be made better with a lot of > > further > > work. > > I thought I'd take a stab at seeing how this works with the hardware > before looking at the code much. git couldn't apply patches 1, 6, or 9 > to 5.15-rc1, but I was able to hand-fit them into place. Oh? Thats odd, I had no remarks from git when rebasing onto v5.15-rc1.. Maybe this is a situation where you need "b4 am --prep-3way" ... > [ 64.585462] Call Trace: > [ 64.585464] [<0002>] 0x2 > [ 64.585467] ([<03ff80179d74>] vfio_ccw_mdev_ioctl+0x84/0x318 > [vfio_ccw]) > [ 64.585476] [] __s390x_sys_ioctl+0xbe/0x100 > [ 64.585481] [ ] __do_syscall+0x1bc/0x1e8 > [ 64.585488] [ ] system_call+0x78/0xa0 I think it is this: diff --git a/drivers/s390/cio/vfio_ccw_fsm.c b/drivers/s390/cio/vfio_ccw_fsm.c index df1490943b20ec..5ea392959c0711 100644 --- a/drivers/s390/cio/vfio_ccw_fsm.c +++ b/drivers/s390/cio/vfio_ccw_fsm.c @@ -441,6 +441,7 @@ fsm_func_t *vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_VFIO_CCW_EVENTS] = { [VFIO_CCW_EVENT_IO_REQ] = fsm_io_error, [VFIO_CCW_EVENT_ASYNC_REQ] = fsm_async_error, [VFIO_CCW_EVENT_INTERRUPT] = fsm_disabled_irq, + [VFIO_CCW_EVENT_OPEN] = fsm_nop, [VFIO_CCW_EVENT_CLOSE] = fsm_nop, }, [VFIO_CCW_STATE_CLOSED] = { I rebased it and fixed it up here: https://github.com/jgunthorpe/linux/tree/vfio_ccw Can you try again? Thanks, Jason
Re: [v5 5/5] drm/panel: Update BOE and INX init code to support touch function
Hi, On Mon, Sep 13, 2021 at 3:59 AM yangcong wrote: > > This is an incell IC, TDDI use time division multiplexing. > Init code effect touch sensing. > Support touch function we needed to handle were: > a) Update init code for the panel driver, adjust the porch value. > b) After update init code these two panels can support DSI HS mode. > > Signed-off-by: yangcong > --- > .../gpu/drm/panel/panel-boe-tv101wum-nl6.c| 399 +- > 1 file changed, 110 insertions(+), 289 deletions(-) Please squash this with patch #3 in the series. Even though you have landed patch #3 in the series in a Chrome OS tree it doesn't matter. Since patch #3 hasn't landed upstream there is no reason to post the "wrong" code and then fix it up in the same series. The Chrome OS tree can always take a revert of the old version and a re-pick of the new version. > @@ -36,7 +36,6 @@ struct panel_desc { > const struct panel_init_cmd *init_cmds; > unsigned int lanes; > bool discharge_on_disable; > - bool unsupport_dsi_hs_mode; Not that I'm complaining, but how did this suddenly get supported? > @@ -84,6 +83,8 @@ static const struct panel_init_cmd boe_tv110c9m_init_cmd[] > = { > _INIT_DCS_CMD(0x07, 0x78), > _INIT_DCS_CMD(0x08, 0x5A), > _INIT_DCS_CMD(0x0D, 0x63), > + _INIT_DCS_CMD(0x0E, 0x91), > + _INIT_DCS_CMD(0x0F, 0x73), I _really_ don't like this opaque list of commands and the fact that apparently they aren't fixed but need to change depending on how you're configuring the panel, but I won't personally block this patch just because of it since it matches what other panels in this driver are doing. If someone more familiar with MIPI panels wants to chime in though, I'm all ears. > @@ -1442,15 +1260,15 @@ static int boe_panel_enable(struct drm_panel *panel) > } > > static const struct drm_display_mode boe_tv110c9m_default_mode = { > - .clock = 162383, > + .clock = 166594, > .hdisplay = 1200, > .hsync_start = 1200 + 40, > .hsync_end = 1200 + 40 + 8, > .htotal = 1200 + 40 + 8 + 28, > .vdisplay = 2000, > .vsync_start = 2000 + 26, > - .vsync_end = 2000 + 26 + 1, > - .vtotal = 2000 + 26 + 1 + 94, > + .vsync_end = 2000 + 26 + 2, > + .vtotal = 2000 + 26 + 2 + 148, > .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, > }; > > @@ -1463,14 +1281,15 @@ static const struct panel_desc boe_tv110c9m_desc = { > }, > .lanes = 4, > .format = MIPI_DSI_FMT_RGB888, > - .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | > - MIPI_DSI_MODE_LPM, > + .mode_flags = MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_VIDEO > + | MIPI_DSI_MODE_VIDEO_HSE > + | MIPI_DSI_CLOCK_NON_CONTINUOUS > + | MIPI_DSI_MODE_VIDEO_BURST, > .init_cmds = boe_tv110c9m_init_cmd, > - .unsupport_dsi_hs_mode = true, > }; > > static const struct drm_display_mode inx_hj110iz_default_mode = { > - .clock = 162383, > + .clock = 166594, > .hdisplay = 1200, > .hsync_start = 1200 + 40, > .hsync_end = 1200 + 40 + 8, > @@ -1478,7 +1297,7 @@ static const struct drm_display_mode > inx_hj110iz_default_mode = { > .vdisplay = 2000, > .vsync_start = 2000 + 26, > .vsync_end = 2000 + 26 + 1, > - .vtotal = 2000 + 26 + 1 + 94, > + .vtotal = 2000 + 26 + 1 + 149, It seems really odd that the two panels have _exactly_ the same timing except that one of them now has: .vsync_end = 2000 + 26 + 2, ...and the other: .vsync_end = 2000 + 26 + 1, Do they really need to be different? -Doug
Re: [virtio-dev] [PATCH v1 09/12] drm/virtio: implement context init: allocate an array of fence contexts
. On Mon, Sep 13, 2021 at 10:48 AM Gurchetan Singh wrote: > > > > On Fri, Sep 10, 2021 at 12:33 PM Chia-I Wu wrote: >> >> On Wed, Sep 8, 2021 at 6:37 PM Gurchetan Singh >> wrote: >> > >> > We don't want fences from different 3D contexts (virgl, gfxstream, >> > venus) to be on the same timeline. With explicit context creation, >> > we can specify the number of ring each context wants. >> > >> > Execbuffer can specify which ring to use. >> > >> > Signed-off-by: Gurchetan Singh >> > Acked-by: Lingfeng Yang >> > --- >> > drivers/gpu/drm/virtio/virtgpu_drv.h | 3 +++ >> > drivers/gpu/drm/virtio/virtgpu_ioctl.c | 34 -- >> > 2 files changed, 35 insertions(+), 2 deletions(-) >> > >> > diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h >> > b/drivers/gpu/drm/virtio/virtgpu_drv.h >> > index a5142d60c2fa..cca9ab505deb 100644 >> > --- a/drivers/gpu/drm/virtio/virtgpu_drv.h >> > +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h >> > @@ -56,6 +56,7 @@ >> > #define STATE_ERR 2 >> > >> > #define MAX_CAPSET_ID 63 >> > +#define MAX_RINGS 64 >> > >> > struct virtio_gpu_object_params { >> > unsigned long size; >> > @@ -263,6 +264,8 @@ struct virtio_gpu_fpriv { >> > uint32_t ctx_id; >> > uint32_t context_init; >> > bool context_created; >> > + uint32_t num_rings; >> > + uint64_t base_fence_ctx; >> > struct mutex context_lock; >> > }; >> > >> > diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c >> > b/drivers/gpu/drm/virtio/virtgpu_ioctl.c >> > index f51f3393a194..262f79210283 100644 >> > --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c >> > +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c >> > @@ -99,6 +99,11 @@ static int virtio_gpu_execbuffer_ioctl(struct >> > drm_device *dev, void *data, >> > int in_fence_fd = exbuf->fence_fd; >> > int out_fence_fd = -1; >> > void *buf; >> > + uint64_t fence_ctx; >> > + uint32_t ring_idx; >> > + >> > + fence_ctx = vgdev->fence_drv.context; >> > + ring_idx = 0; >> > >> > if (vgdev->has_virgl_3d == false) >> > return -ENOSYS; >> > @@ -106,6 +111,17 @@ static int virtio_gpu_execbuffer_ioctl(struct >> > drm_device *dev, void *data, >> > if ((exbuf->flags & ~VIRTGPU_EXECBUF_FLAGS)) >> > return -EINVAL; >> > >> > + if ((exbuf->flags & VIRTGPU_EXECBUF_RING_IDX)) { >> > + if (exbuf->ring_idx >= vfpriv->num_rings) >> > + return -EINVAL; >> > + >> > + if (!vfpriv->base_fence_ctx) >> > + return -EINVAL; >> > + >> > + fence_ctx = vfpriv->base_fence_ctx; >> > + ring_idx = exbuf->ring_idx; >> > + } >> > + >> > exbuf->fence_fd = -1; >> > >> > virtio_gpu_create_context(dev, file); >> > @@ -173,7 +189,7 @@ static int virtio_gpu_execbuffer_ioctl(struct >> > drm_device *dev, void *data, >> > goto out_memdup; >> > } >> > >> > - out_fence = virtio_gpu_fence_alloc(vgdev, >> > vgdev->fence_drv.context, 0); >> > + out_fence = virtio_gpu_fence_alloc(vgdev, fence_ctx, ring_idx); >> > if(!out_fence) { >> > ret = -ENOMEM; >> > goto out_unresv; >> > @@ -691,7 +707,7 @@ static int virtio_gpu_context_init_ioctl(struct >> > drm_device *dev, >> > return -EINVAL; >> > >> > /* Number of unique parameters supported at this time. */ >> > - if (num_params > 1) >> > + if (num_params > 2) >> > return -EINVAL; >> > >> > ctx_set_params = memdup_user(u64_to_user_ptr(args->ctx_set_params), >> > @@ -731,6 +747,20 @@ static int virtio_gpu_context_init_ioctl(struct >> > drm_device *dev, >> > >> > vfpriv->context_init |= value; >> > break; >> > + case VIRTGPU_CONTEXT_PARAM_NUM_RINGS: >> > + if (vfpriv->base_fence_ctx) { >> > + ret = -EINVAL; >> > + goto out_unlock; >> > + } >> > + >> > + if (value > MAX_RINGS) { >> > + ret = -EINVAL; >> > + goto out_unlock; >> > + } >> > + >> > + vfpriv->base_fence_ctx = >> > dma_fence_context_alloc(value); >> With multiple fence contexts, we should do something about implicit fencing. >> >> The classic example is Mesa and X server. When both use virgl and the >> global fence context, no dma_fence_wait is fine. But when Mesa uses >> venus and the ring fence context, dma_fence_wait should be inserted. > > > If I read your comment correctly, the use case is: > > context A (venus) > > sharing a render target with > > context B (Xserver backed virgl) > > ? > > Which function do you envisage dma_fence_wait(...) to be inserted? Doesn't > implicit synchronization mean
[PATCH] drm/hyperv: Fix double mouse pointers
It looks like Hyper-V supports a hardware cursor feature. It is not used by Linux VM, but the Hyper-V host still draws a point as an extra mouse pointer, which is unwanted, especially when Xorg is running. The hyperv_fb driver uses synthvid_send_ptr() to hide the unwanted pointer. When the hyperv_drm driver was developed, the function synthvid_send_ptr() was not copied from the hyperv_fb driver. Fix the issue by adding the function into hyperv_drm. Fixes: 76c56a5affeb ("drm/hyperv: Add DRM driver for hyperv synthetic video device") Signed-off-by: Dexuan Cui Cc: Deepak Rawat Cc: Haiyang Zhang --- drivers/gpu/drm/hyperv/hyperv_drm.h | 1 + drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 1 + drivers/gpu/drm/hyperv/hyperv_drm_proto.c | 39 - 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/hyperv/hyperv_drm.h b/drivers/gpu/drm/hyperv/hyperv_drm.h index 886add4f9cd0..27bfd27c05be 100644 --- a/drivers/gpu/drm/hyperv/hyperv_drm.h +++ b/drivers/gpu/drm/hyperv/hyperv_drm.h @@ -46,6 +46,7 @@ int hyperv_mode_config_init(struct hyperv_drm_device *hv); int hyperv_update_vram_location(struct hv_device *hdev, phys_addr_t vram_pp); int hyperv_update_situation(struct hv_device *hdev, u8 active, u32 bpp, u32 w, u32 h, u32 pitch); +int hyperv_send_ptr(struct hv_device *hdev); int hyperv_update_dirt(struct hv_device *hdev, struct drm_rect *rect); int hyperv_connect_vsp(struct hv_device *hdev); diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c index 3aaee4730ec6..e21c82cf3326 100644 --- a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c +++ b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c @@ -101,6 +101,7 @@ static void hyperv_pipe_enable(struct drm_simple_display_pipe *pipe, struct hyperv_drm_device *hv = to_hv(pipe->crtc.dev); struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); + hyperv_send_ptr(hv->hdev); hyperv_update_situation(hv->hdev, 1, hv->screen_depth, crtc_state->mode.hdisplay, crtc_state->mode.vdisplay, diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_proto.c b/drivers/gpu/drm/hyperv/hyperv_drm_proto.c index 6d4bdccfbd1a..1ea7a0432320 100644 --- a/drivers/gpu/drm/hyperv/hyperv_drm_proto.c +++ b/drivers/gpu/drm/hyperv/hyperv_drm_proto.c @@ -299,6 +299,40 @@ int hyperv_update_situation(struct hv_device *hdev, u8 active, u32 bpp, return 0; } +/* Send mouse pointer info to host */ +int hyperv_send_ptr(struct hv_device *hdev) +{ + struct synthvid_msg msg; + + memset(, 0, sizeof(struct synthvid_msg)); + msg.vid_hdr.type = SYNTHVID_POINTER_POSITION; + msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) + + sizeof(struct synthvid_pointer_position); + msg.ptr_pos.is_visible = 1; + msg.ptr_pos.video_output = 0; + msg.ptr_pos.image_x = 0; + msg.ptr_pos.image_y = 0; + hyperv_sendpacket(hdev, ); + + memset(, 0, sizeof(struct synthvid_msg)); + msg.vid_hdr.type = SYNTHVID_POINTER_SHAPE; + msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) + + sizeof(struct synthvid_pointer_shape); + msg.ptr_shape.part_idx = SYNTHVID_CURSOR_COMPLETE; + msg.ptr_shape.is_argb = 1; + msg.ptr_shape.width = 1; + msg.ptr_shape.height = 1; + msg.ptr_shape.hot_x = 0; + msg.ptr_shape.hot_y = 0; + msg.ptr_shape.data[0] = 0; + msg.ptr_shape.data[1] = 1; + msg.ptr_shape.data[2] = 1; + msg.ptr_shape.data[3] = 1; + hyperv_sendpacket(hdev, ); + + return 0; +} + int hyperv_update_dirt(struct hv_device *hdev, struct drm_rect *rect) { struct hyperv_drm_device *hv = hv_get_drvdata(hdev); @@ -392,8 +426,11 @@ static void hyperv_receive_sub(struct hv_device *hdev) return; } - if (msg->vid_hdr.type == SYNTHVID_FEATURE_CHANGE) + if (msg->vid_hdr.type == SYNTHVID_FEATURE_CHANGE) { hv->dirt_needed = msg->feature_chg.is_dirt_needed; + if (hv->dirt_needed) + hyperv_send_ptr(hv->hdev); + } } static void hyperv_receive(void *ctx) -- 2.25.1
[PATCH 8/8] drm/i915/ttm: enable shmem tt backend
Enable shmem tt backend, and enable shrinking. Signed-off-by: Matthew Auld Cc: Thomas Hellström --- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index dbf06a2af8bf..e888111c68c4 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -1048,6 +1048,7 @@ static u64 i915_ttm_mmap_offset(struct drm_i915_gem_object *obj) static const struct drm_i915_gem_object_ops i915_gem_ttm_obj_ops = { .name = "i915_gem_object_ttm", + .flags = I915_GEM_OBJECT_IS_SHRINKABLE, .get_pages = i915_ttm_get_pages, .put_pages = i915_ttm_put_pages, -- 2.26.3
[PATCH 7/8] drm/i915/ttm: make evicted shmem pages visible to the shrinker
We currently just evict lmem objects to system memory when under memory pressure. For this case we lack the usual object mm.pages, which effectively hides the pages from the i915-gem shrinker, until we actually "attach" the TT to the object, or in the case of lmem-only objects it just gets migrated back to lmem when touched again. For such cases we can make the object visible as soon as we populate the TT with shmem pages, and then hide it again when doing the unpopulate. Signed-off-by: Matthew Auld Cc: Thomas Hellström --- drivers/gpu/drm/i915/gem/i915_gem_object.h | 1 + drivers/gpu/drm/i915/gem/i915_gem_shrinker.c | 29 +++- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 11 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index 561d6bd0a5c9..28b831c78c47 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -540,6 +540,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, void i915_gem_object_make_unshrinkable(struct drm_i915_gem_object *obj); void i915_gem_object_make_shrinkable(struct drm_i915_gem_object *obj); +void __i915_gem_object_make_shrinkable(struct drm_i915_gem_object *obj); void i915_gem_object_make_purgeable(struct drm_i915_gem_object *obj); static inline bool cpu_write_needs_clflush(struct drm_i915_gem_object *obj) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c index 6b38e4414c5a..02175e8ad069 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c @@ -482,13 +482,12 @@ void i915_gem_object_make_unshrinkable(struct drm_i915_gem_object *obj) spin_unlock_irqrestore(>mm.obj_lock, flags); } -static void __i915_gem_object_make_shrinkable(struct drm_i915_gem_object *obj, - struct list_head *head) +static void ___i915_gem_object_make_shrinkable(struct drm_i915_gem_object *obj, + struct list_head *head) { struct drm_i915_private *i915 = obj_to_i915(obj); unsigned long flags; - GEM_BUG_ON(!i915_gem_object_has_pages(obj)); if (!i915_gem_object_is_shrinkable(obj)) return; @@ -507,6 +506,21 @@ static void __i915_gem_object_make_shrinkable(struct drm_i915_gem_object *obj, spin_unlock_irqrestore(>mm.obj_lock, flags); } +/** + * __i915_gem_object_make_shrinkable - Move the object to the tail of the + * shrinkable list. Objects on this list might be swapped out. Used with + * WILLNEED objects. + * @obj: The GEM object. + * + * DO NOT USE. This is intended to be called on very special objects that don't + * yet have mm.pages, but are guaranteed to have potentially reclaimable pages + * underneath. + */ +void __i915_gem_object_make_shrinkable(struct drm_i915_gem_object *obj) +{ + ___i915_gem_object_make_shrinkable(obj, + _to_i915(obj)->mm.shrink_list); +} /** * i915_gem_object_make_shrinkable - Move the object to the tail of the @@ -518,8 +532,8 @@ static void __i915_gem_object_make_shrinkable(struct drm_i915_gem_object *obj, */ void i915_gem_object_make_shrinkable(struct drm_i915_gem_object *obj) { - __i915_gem_object_make_shrinkable(obj, - _to_i915(obj)->mm.shrink_list); + GEM_BUG_ON(!i915_gem_object_has_pages(obj)); + __i915_gem_object_make_shrinkable(obj); } /** @@ -533,6 +547,7 @@ void i915_gem_object_make_shrinkable(struct drm_i915_gem_object *obj) */ void i915_gem_object_make_purgeable(struct drm_i915_gem_object *obj) { - __i915_gem_object_make_shrinkable(obj, - _to_i915(obj)->mm.purge_list); + GEM_BUG_ON(!i915_gem_object_has_pages(obj)); + ___i915_gem_object_make_shrinkable(obj, + _to_i915(obj)->mm.purge_list); } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 08894f6a296b..dbf06a2af8bf 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -231,6 +231,15 @@ static int i915_ttm_tt_shmem_populate(struct ttm_device *bdev, if (ttm->page_flags & TTM_PAGE_FLAG_SWAPPED) ttm->page_flags &= ~TTM_PAGE_FLAG_SWAPPED; + /* +* Even if we lack mm.pages for this object(which will be the case when +* something is evicted to system memory by TTM), we still want to make +* this object visible to the shrinker, since the underlying ttm_tt +* still has the real shmem pages. When unpopulating the tt(possibly due +* to shrinking) we hide it again from the shrinker. +*/ + __i915_gem_object_make_shrinkable(obj); +
[PATCH 4/8] drm/i915/ttm: use cached system pages when evicting lmem
This should let us do an accelerated copy directly to the shmem pages when temporarily moving lmem-only objects, where the i915-gem shrinker can later kick in to swap out the pages, if needed. Signed-off-by: Matthew Auld Cc: Thomas Hellström --- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 8f022c2889c0..08894f6a296b 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -123,11 +123,11 @@ static enum ttm_caching i915_ttm_select_tt_caching(const struct drm_i915_gem_object *obj) { /* -* Objects only allowed in system get cached cpu-mappings. -* Other objects get WC mapping for now. Even if in system. +* Objects only allowed in system get cached cpu-mappings, or when +* evicting lmem-only buffers to system for swapping. Other objects get +* WC mapping for now. Even if in system. */ - if (obj->mm.region->type == INTEL_MEMORY_SYSTEM && - obj->mm.n_placements <= 1) + if (obj->mm.n_placements <= 1) return ttm_cached; return ttm_write_combined; -- 2.26.3
[PATCH 6/8] drm/i915: try to simplify make_{un}shrinkable
Drop the atomic shrink_pin stuff, and just have make_{un}shrinkable update the shrinker visible lists immediately. This at least simplifies the next patch, and does make the behaviour more obvious. The potential downside is that make_unshrinkable now grabs a global lock even when the object itself is no longer shrinkable(transitioning from purgeable <-> shrinkable doesn't seem to be a thing), for example in the ppGTT insertion paths we should now be careful not to needlessly call make_unshrinkable multiple times. Outside of that there is some fallout in intel_context which relies on nesting calls to shrink_pin. Signed-off-by: Matthew Auld Cc: Thomas Hellström --- drivers/gpu/drm/i915/gem/i915_gem_object.c| 9 .../gpu/drm/i915/gem/i915_gem_object_types.h | 3 +- drivers/gpu/drm/i915/gem/i915_gem_pages.c | 16 +- drivers/gpu/drm/i915/gem/i915_gem_shrinker.c | 52 +-- drivers/gpu/drm/i915/gt/gen6_ppgtt.c | 1 - drivers/gpu/drm/i915/gt/gen8_ppgtt.c | 1 - drivers/gpu/drm/i915/gt/intel_context.c | 9 +--- 7 files changed, 41 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c index 6fb9afb65034..e8265a432fcb 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c @@ -305,15 +305,6 @@ static void i915_gem_free_object(struct drm_gem_object *gem_obj) */ atomic_inc(>mm.free_count); - /* -* This serializes freeing with the shrinker. Since the free -* is delayed, first by RCU then by the workqueue, we want the -* shrinker to be able to free pages of unreferenced objects, -* or else we may oom whilst there are plenty of deferred -* freed objects. -*/ - i915_gem_object_make_unshrinkable(obj); - /* * Since we require blocking on struct_mutex to unbind the freed * object from the GPU before releasing resources back to the diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index 2471f36aaff3..a035ac26a090 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -453,7 +453,6 @@ struct drm_i915_gem_object { * instead go through the pin/unpin interfaces. */ atomic_t pages_pin_count; - atomic_t shrink_pin; /** * Priority list of potential placements for this object. @@ -514,7 +513,7 @@ struct drm_i915_gem_object { struct i915_gem_object_page_iter get_dma_page; /** -* Element within i915->mm.unbound_list or i915->mm.bound_list, +* Element within i915->mm.shrink_list or i915->mm.purge_list, * locked by i915->mm.obj_lock. */ struct list_head link; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c index 8eb1c3a6fc9c..f0df1394d7f6 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c @@ -64,28 +64,16 @@ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, GEM_BUG_ON(i915_gem_object_has_tiling_quirk(obj)); i915_gem_object_set_tiling_quirk(obj); GEM_BUG_ON(!list_empty(>mm.link)); - atomic_inc(>mm.shrink_pin); shrinkable = false; } if (shrinkable) { - struct list_head *list; - unsigned long flags; - assert_object_held(obj); - spin_lock_irqsave(>mm.obj_lock, flags); - - i915->mm.shrink_count++; - i915->mm.shrink_memory += obj->base.size; if (obj->mm.madv != I915_MADV_WILLNEED) - list = >mm.purge_list; + i915_gem_object_make_purgeable(obj); else - list = >mm.shrink_list; - list_add_tail(>mm.link, list); - - atomic_set(>mm.shrink_pin, 0); - spin_unlock_irqrestore(>mm.obj_lock, flags); + i915_gem_object_make_shrinkable(obj); } } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c index e382b7f2353b..6b38e4414c5a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c @@ -455,23 +455,26 @@ void i915_gem_shrinker_taints_mutex(struct drm_i915_private *i915, #define obj_to_i915(obj__) to_i915((obj__)->base.dev) +/** + * i915_gem_object_make_unshrinkable - Hide the object from the shrinker. By + * default all object types that support shrinking(see IS_SHRINKABLE), will also + * make the object visible to the shrinker after allocating
[PATCH 3/8] drm/i915/ttm: add tt shmem backend
For cached objects we can allocate our pages directly in shmem. This should make it possible(in a later patch) to utilise the existing i915-gem shrinker code for such objects. For now this is still disabled. Signed-off-by: Matthew Auld Cc: Thomas Hellström Cc: Christian König --- drivers/gpu/drm/i915/gem/i915_gem_object.h | 8 + drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 14 +- drivers/gpu/drm/i915/gem/i915_gem_ttm.c| 214 ++--- 3 files changed, 206 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index 48112b9d76df..561d6bd0a5c9 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -618,6 +618,14 @@ int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj, bool i915_gem_object_placement_possible(struct drm_i915_gem_object *obj, enum intel_memory_type type); +struct sg_table *shmem_alloc_st(struct drm_i915_private *i915, + size_t size, struct intel_memory_region *mr, + struct address_space *mapping, + unsigned int max_segment); +void shmem_free_st(struct sg_table *st, struct address_space *mapping, + bool dirty, bool backup); +void __shmem_writeback(size_t size, struct address_space *mapping); + #ifdef CONFIG_MMU_NOTIFIER static inline bool i915_gem_object_is_userptr(struct drm_i915_gem_object *obj) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c index ab02309f0752..81d8da2bede4 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c @@ -25,8 +25,8 @@ static void check_release_pagevec(struct pagevec *pvec) cond_resched(); } -static void shmem_free_st(struct sg_table *st, struct address_space *mapping, - bool dirty, bool backup) +void shmem_free_st(struct sg_table *st, struct address_space *mapping, + bool dirty, bool backup) { struct sgt_iter sgt_iter; struct pagevec pvec; @@ -52,10 +52,10 @@ static void shmem_free_st(struct sg_table *st, struct address_space *mapping, kfree(st); } -static struct sg_table *shmem_alloc_st(struct drm_i915_private *i915, - size_t size, struct intel_memory_region *mr, - struct address_space *mapping, - unsigned int max_segment) +struct sg_table *shmem_alloc_st(struct drm_i915_private *i915, + size_t size, struct intel_memory_region *mr, + struct address_space *mapping, + unsigned int max_segment) { const unsigned long page_count = size / PAGE_SIZE; unsigned long i; @@ -301,7 +301,7 @@ shmem_truncate(struct drm_i915_gem_object *obj) obj->mm.pages = ERR_PTR(-EFAULT); } -static void __shmem_writeback(size_t size, struct address_space *mapping) +void __shmem_writeback(size_t size, struct address_space *mapping) { struct writeback_control wbc = { .sync_mode = WB_SYNC_NONE, diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 59ca53a3ef6a..8f022c2889c0 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -37,6 +37,9 @@ * @ttm: The base TTM page vector. * @dev: The struct device used for dma mapping and unmapping. * @cached_st: The cached scatter-gather table. + * @obj: The GEM object. Should be valid while we have a valid bo->ttm. + * @filp: The shmem file, if using shmem backend. + * @backup: Swap out the pages when unpopulating, if using shmem backend. * * Note that DMA may be going on right up to the point where the page- * vector is unpopulated in delayed destroy. Hence keep the @@ -48,6 +51,9 @@ struct i915_ttm_tt { struct ttm_tt ttm; struct device *dev; struct sg_table *cached_st; + struct drm_i915_gem_object *obj; + struct file *filp; + bool backup; }; static const struct ttm_place sys_placement_flags = { @@ -167,12 +173,105 @@ i915_ttm_placement_from_obj(const struct drm_i915_gem_object *obj, placement->busy_placement = busy; } +static int i915_ttm_tt_shmem_populate(struct ttm_device *bdev, + struct ttm_tt *ttm, + struct ttm_operation_ctx *ctx) +{ + struct drm_i915_private *i915 = container_of(bdev, typeof(*i915), bdev); + struct intel_memory_region *mr = i915->mm.regions[INTEL_MEMORY_SYSTEM]; + struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm); + const unsigned int max_segment = i915_sg_segment_size(); + const size_t size =
[PATCH 5/8] drm/i915: remember to call i915_sw_fence_fini
Fixes some object-debug splat which appeared while debugging something unrelated. Signed-off-by: Matthew Auld Cc: Thomas Hellström --- drivers/gpu/drm/i915/gt/intel_context.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index 745e84c72c90..0e7dd12a0871 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -420,6 +420,7 @@ void intel_context_fini(struct intel_context *ce) mutex_destroy(>pin_mutex); i915_active_fini(>active); + i915_sw_fence_fini(>guc_blocked); } void i915_context_module_exit(void) -- 2.26.3
[PATCH 1/8] drm/i915/gem: Break out some shmem backend utils
From: Thomas Hellström Break out some shmem backend utils for future reuse by the TTM backend: shmem_alloc_st(), shmem_free_st() and __shmem_writeback() which we can use to provide a shmem-backed TTM page pool for cached-only TTM buffer objects. Main functional change here is that we now compute the page sizes using the dma segments rather than using the physical page address segments. Signed-off-by: Thomas Hellström Reviewed-by: Matthew Auld Signed-off-by: Matthew Auld --- drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 182 +- 1 file changed, 107 insertions(+), 75 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c index 11f072193f3b..ab02309f0752 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c @@ -25,46 +25,61 @@ static void check_release_pagevec(struct pagevec *pvec) cond_resched(); } -static int shmem_get_pages(struct drm_i915_gem_object *obj) +static void shmem_free_st(struct sg_table *st, struct address_space *mapping, + bool dirty, bool backup) { - struct drm_i915_private *i915 = to_i915(obj->base.dev); - struct intel_memory_region *mem = obj->mm.region; - const unsigned long page_count = obj->base.size / PAGE_SIZE; + struct sgt_iter sgt_iter; + struct pagevec pvec; + struct page *page; + + mapping_clear_unevictable(mapping); + + pagevec_init(); + for_each_sgt_page(page, sgt_iter, st) { + if (dirty) + set_page_dirty(page); + + if (backup) + mark_page_accessed(page); + + if (!pagevec_add(, page)) + check_release_pagevec(); + } + if (pagevec_count()) + check_release_pagevec(); + + sg_free_table(st); + kfree(st); +} + +static struct sg_table *shmem_alloc_st(struct drm_i915_private *i915, + size_t size, struct intel_memory_region *mr, + struct address_space *mapping, + unsigned int max_segment) +{ + const unsigned long page_count = size / PAGE_SIZE; unsigned long i; - struct address_space *mapping; struct sg_table *st; struct scatterlist *sg; - struct sgt_iter sgt_iter; struct page *page; unsigned long last_pfn = 0; /* suppress gcc warning */ - unsigned int max_segment = i915_sg_segment_size(); - unsigned int sg_page_sizes; gfp_t noreclaim; int ret; - /* -* Assert that the object is not currently in any GPU domain. As it -* wasn't in the GTT, there shouldn't be any way it could have been in -* a GPU cache -*/ - GEM_BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS); - GEM_BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS); - /* * If there's no chance of allocating enough pages for the whole * object, bail early. */ - if (obj->base.size > resource_size(>region)) - return -ENOMEM; + if (size > resource_size(>region)) + return ERR_PTR(-ENOMEM); st = kmalloc(sizeof(*st), GFP_KERNEL); if (!st) - return -ENOMEM; + return ERR_PTR(-ENOMEM); -rebuild_st: if (sg_alloc_table(st, page_count, GFP_KERNEL)) { kfree(st); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } /* @@ -73,14 +88,12 @@ static int shmem_get_pages(struct drm_i915_gem_object *obj) * * Fail silently without starting the shrinker */ - mapping = obj->base.filp->f_mapping; mapping_set_unevictable(mapping); noreclaim = mapping_gfp_constraint(mapping, ~__GFP_RECLAIM); noreclaim |= __GFP_NORETRY | __GFP_NOWARN; sg = st->sgl; st->nents = 0; - sg_page_sizes = 0; for (i = 0; i < page_count; i++) { const unsigned int shrink[] = { I915_SHRINK_BOUND | I915_SHRINK_UNBOUND, @@ -135,10 +148,9 @@ static int shmem_get_pages(struct drm_i915_gem_object *obj) if (!i || sg->length >= max_segment || page_to_pfn(page) != last_pfn + 1) { - if (i) { - sg_page_sizes |= sg->length; + if (i) sg = sg_next(sg); - } + st->nents++; sg_set_page(sg, page, PAGE_SIZE, 0); } else { @@ -149,14 +161,66 @@ static int shmem_get_pages(struct drm_i915_gem_object *obj) /* Check that the i965g/gm workaround works. */ GEM_BUG_ON(gfp & __GFP_DMA32 && last_pfn >= 0x0010UL); } -
[PATCH 2/8] drm/ttm: add TTM_PAGE_FLAG_SHMEM
Add new flag to indicate special shmem based tt, which can directly handle swapping itself, and should be visible to some shrinker. As part of this we should skip the ttm_pages_allocated accounting, since such tt objects should already be reachable, and potentially reclaimable by some shrinker, if under memory pressure, and so shouldn't directly count towards the swap "watermark" level. We also need to stop touching the page->mapping and page->index for such objects, like in ttm_tt_add_mapping, since shmem already uses these. Some drivers seems to depend on the tt mapping/index behaviour for their own purposes, so directly using shmem tt likely won't be usable there as-is. Signed-off-by: Matthew Auld Cc: Thomas Hellström Cc: Christian König --- drivers/gpu/drm/ttm/ttm_bo_vm.c | 4 ++-- drivers/gpu/drm/ttm/ttm_tt.c| 10 +- include/drm/ttm/ttm_tt.h| 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index f56be5bc0861..e2131c73dcb6 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -346,8 +346,8 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, } else if (unlikely(!page)) { break; } - page->index = drm_vma_node_start(>base.vma_node) + - page_offset; + if (!(bo->ttm->page_flags & TTM_PAGE_FLAG_SHMEM)) + page->index = drm_vma_node_start(>base.vma_node) + page_offset; pfn = page_to_pfn(page); } diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index dae52433beeb..cc4815c1f505 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -293,7 +293,7 @@ static void ttm_tt_add_mapping(struct ttm_device *bdev, struct ttm_tt *ttm) { pgoff_t i; - if (ttm->page_flags & TTM_PAGE_FLAG_SG) + if (ttm->page_flags & (TTM_PAGE_FLAG_SG | TTM_PAGE_FLAG_SHMEM)) return; for (i = 0; i < ttm->num_pages; ++i) @@ -311,7 +311,7 @@ int ttm_tt_populate(struct ttm_device *bdev, if (ttm_tt_is_populated(ttm)) return 0; - if (!(ttm->page_flags & TTM_PAGE_FLAG_SG)) { + if (!(ttm->page_flags & (TTM_PAGE_FLAG_SG | TTM_PAGE_FLAG_SHMEM))) { atomic_long_add(ttm->num_pages, _pages_allocated); if (bdev->pool.use_dma32) atomic_long_add(ttm->num_pages, @@ -349,7 +349,7 @@ int ttm_tt_populate(struct ttm_device *bdev, return 0; error: - if (!(ttm->page_flags & TTM_PAGE_FLAG_SG)) { + if (!(ttm->page_flags & (TTM_PAGE_FLAG_SG | TTM_PAGE_FLAG_SHMEM))) { atomic_long_sub(ttm->num_pages, _pages_allocated); if (bdev->pool.use_dma32) atomic_long_sub(ttm->num_pages, @@ -364,7 +364,7 @@ static void ttm_tt_clear_mapping(struct ttm_tt *ttm) pgoff_t i; struct page **page = ttm->pages; - if (ttm->page_flags & TTM_PAGE_FLAG_SG) + if (ttm->page_flags & (TTM_PAGE_FLAG_SG | TTM_PAGE_FLAG_SHMEM)) return; for (i = 0; i < ttm->num_pages; ++i) { @@ -384,7 +384,7 @@ void ttm_tt_unpopulate(struct ttm_device *bdev, struct ttm_tt *ttm) else ttm_pool_free(>pool, ttm); - if (!(ttm->page_flags & TTM_PAGE_FLAG_SG)) { + if (!(ttm->page_flags & (TTM_PAGE_FLAG_SG | TTM_PAGE_FLAG_SHMEM))) { atomic_long_sub(ttm->num_pages, _pages_allocated); if (bdev->pool.use_dma32) atomic_long_sub(ttm->num_pages, diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h index 89b15d673b22..20d550185065 100644 --- a/include/drm/ttm/ttm_tt.h +++ b/include/drm/ttm/ttm_tt.h @@ -42,6 +42,7 @@ struct ttm_operation_ctx; #define TTM_PAGE_FLAG_ZERO_ALLOC (1 << 6) #define TTM_PAGE_FLAG_SG (1 << 8) #define TTM_PAGE_FLAG_NO_RETRY (1 << 9) +#define TTM_PAGE_FLAG_SHMEM (1 << 10) #define TTM_PAGE_FLAG_PRIV_POPULATED (1 << 31) -- 2.26.3
Re: [PATCH 00/14] drm/hdcp: Pull HDCP auth/exchange/check into
On Mon, Sep 13, 2021 at 1:57 PM Sean Paul wrote: > > From: Sean Paul > > Hello, > This patchset pulls the HDCP protocol auth/exchange/check logic out from > i915 into a HDCP helper library which drivers can use to implement the > proper protocol and UAPI interactions for achieving HDCP. > > Originally this was all stuffed into i915 since it was the only driver > supporting HDCP. Over the last while I've been working on HDCP support > in the msm driver and have identified the parts which can/should be > shared between drivers and the parts which are hw-specific. > > We can generalize all of the sink interactions in the helper as well as > state handling and link checks. This tends to be the trickiest part of > adding HDCP support, since the property state and locking is a bit of a > nightmare. The driver need only implement the more mechanical display > controller register accesses. > > The first third of the pachset is establishing the helpers, the next > third is converting the i915 driver to use the helpers, and the last > third is the msm driver implementation. > > I've left out HDCP 2.x support, since we still only have i915 as the > reference implementation and I'm not super comfortable speculating on > which parts are platform independent. FWIW, amdgpu has support for both HDCP 1.x and 2.x Alex > > Please take a look, > > Sean > > Sean Paul (14): > drm/hdcp: Add drm_hdcp_atomic_check() > drm/hdcp: Avoid changing crtc state in hdcp atomic check > drm/hdcp: Update property value on content type and user changes > drm/hdcp: Expand HDCP helper library for enable/disable/check > drm/i915/hdcp: Consolidate HDCP setup/state cache > drm/i915/hdcp: Retain hdcp_capable return codes > drm/i915/hdcp: Use HDCP helpers for i915 > drm/msm/dpu_kms: Re-order dpu includes > drm/msm/dpu: Remove useless checks in dpu_encoder > drm/msm/dpu: Remove encoder->enable() hack > drm/msm/dp: Re-order dp_audio_put in deinit_sub_modules > dt-bindings: msm/dp: Add bindings for HDCP registers > drm/msm: Add hdcp register ranges to sc7180 device tree > drm/msm: Implement HDCP 1.x using the new drm HDCP helpers > > .../bindings/display/msm/dp-controller.yaml | 11 +- > drivers/gpu/drm/drm_hdcp.c| 1198 - > drivers/gpu/drm/i915/display/intel_atomic.c |7 +- > drivers/gpu/drm/i915/display/intel_ddi.c | 29 +- > .../drm/i915/display/intel_display_debugfs.c | 11 +- > .../drm/i915/display/intel_display_types.h| 58 +- > drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 341 ++--- > drivers/gpu/drm/i915/display/intel_dp_mst.c | 17 +- > drivers/gpu/drm/i915/display/intel_hdcp.c | 1011 +++--- > drivers/gpu/drm/i915/display/intel_hdcp.h | 35 +- > drivers/gpu/drm/i915/display/intel_hdmi.c | 256 ++-- > drivers/gpu/drm/msm/Makefile |1 + > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 17 +- > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 30 +- > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |2 - > drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h |4 - > drivers/gpu/drm/msm/dp/dp_debug.c | 49 +- > drivers/gpu/drm/msm/dp/dp_debug.h |6 +- > drivers/gpu/drm/msm/dp/dp_display.c | 47 +- > drivers/gpu/drm/msm/dp/dp_display.h |5 + > drivers/gpu/drm/msm/dp/dp_drm.c | 68 +- > drivers/gpu/drm/msm/dp/dp_drm.h |5 + > drivers/gpu/drm/msm/dp/dp_hdcp.c | 433 ++ > drivers/gpu/drm/msm/dp/dp_hdcp.h | 27 + > drivers/gpu/drm/msm/dp/dp_parser.c| 30 +- > drivers/gpu/drm/msm/dp/dp_parser.h|4 + > drivers/gpu/drm/msm/dp/dp_reg.h | 44 +- > drivers/gpu/drm/msm/msm_atomic.c | 15 + > include/drm/drm_hdcp.h| 194 +++ > 29 files changed, 2570 insertions(+), 1385 deletions(-) > create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c > create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h > > -- > Sean Paul, Software Engineer, Google / Chromium OS >
[PATCH 14/14] drm/msm: Implement HDCP 1.x using the new drm HDCP helpers
From: Sean Paul This patch adds HDCP 1.x support to msm DP connectors using the new HDCP helpers. Signed-off-by: Sean Paul --- drivers/gpu/drm/msm/Makefile| 1 + drivers/gpu/drm/msm/dp/dp_debug.c | 49 +++- drivers/gpu/drm/msm/dp/dp_debug.h | 6 +- drivers/gpu/drm/msm/dp/dp_display.c | 45 ++- drivers/gpu/drm/msm/dp/dp_display.h | 5 + drivers/gpu/drm/msm/dp/dp_drm.c | 68 - drivers/gpu/drm/msm/dp/dp_drm.h | 5 + drivers/gpu/drm/msm/dp/dp_hdcp.c| 433 drivers/gpu/drm/msm/dp/dp_hdcp.h| 27 ++ drivers/gpu/drm/msm/dp/dp_reg.h | 44 ++- drivers/gpu/drm/msm/msm_atomic.c| 15 + 11 files changed, 685 insertions(+), 13 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 904535eda0c4..98731fd262d6 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -109,6 +109,7 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_ctrl.o \ dp/dp_display.o \ dp/dp_drm.o \ + dp/dp_hdcp.o \ dp/dp_hpd.o \ dp/dp_link.o \ dp/dp_panel.o \ diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 2f6247e80e9d..de16fca8782a 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "dp_parser.h" #include "dp_catalog.h" @@ -15,6 +16,7 @@ #include "dp_ctrl.h" #include "dp_debug.h" #include "dp_display.h" +#include "dp_hdcp.h" #define DEBUG_NAME "msm_dp" @@ -24,6 +26,7 @@ struct dp_debug_private { struct dp_usbpd *usbpd; struct dp_link *link; struct dp_panel *panel; + struct dp_hdcp *hdcp; struct drm_connector **connector; struct device *dev; struct drm_device *drm_dev; @@ -349,6 +352,38 @@ static int dp_test_active_open(struct inode *inode, inode->i_private); } +static ssize_t dp_hdcp_key_write(struct file *file, const char __user *ubuf, +size_t len, loff_t *offp) +{ + char *input_buffer; + int ret = 0; + struct dp_debug_private *debug = file->private_data; + struct drm_device *dev; + + dev = debug->drm_dev; + + if (len != (DRM_HDCP_KSV_LEN + DP_HDCP_NUM_KEYS * DP_HDCP_KEY_LEN)) + return -EINVAL; + + if (!debug->hdcp) + return -ENOENT; + + input_buffer = memdup_user_nul(ubuf, len); + if (IS_ERR(input_buffer)) + return PTR_ERR(input_buffer); + + ret = dp_hdcp_ingest_key(debug->hdcp, input_buffer, len); + + kfree(input_buffer); + if (ret < 0) { + DRM_ERROR("Could not ingest HDCP key, ret=%d\n", ret); + return ret; + } + + *offp += len; + return len; +} + static const struct file_operations dp_debug_fops = { .open = simple_open, .read = dp_debug_read_info, @@ -363,6 +398,12 @@ static const struct file_operations test_active_fops = { .write = dp_test_active_write }; +static const struct file_operations dp_hdcp_key_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .write = dp_hdcp_key_write, +}; + static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor) { int rc = 0; @@ -384,6 +425,10 @@ static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor) minor->debugfs_root, debug, _test_type_fops); + debugfs_create_file("msm_dp_hdcp_key", 0222, + minor->debugfs_root, + debug, _hdcp_key_fops); + debug->root = minor->debugfs_root; return rc; @@ -391,7 +436,8 @@ static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor) struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, struct dp_usbpd *usbpd, struct dp_link *link, - struct drm_connector **connector, struct drm_minor *minor) + struct dp_hdcp *hdcp, struct drm_connector **connector, + struct drm_minor *minor) { int rc = 0; struct dp_debug_private *debug; @@ -413,6 +459,7 @@ struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, debug->usbpd = usbpd; debug->link = link; debug->panel = panel; + debug->hdcp = hdcp; debug->dev = dev; debug->drm_dev = minor->dev; debug->connector = connector; diff --git a/drivers/gpu/drm/msm/dp/dp_debug.h b/drivers/gpu/drm/msm/dp/dp_debug.h index 7eaedfbb149c..c4481339c0c5 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.h +++ b/drivers/gpu/drm/msm/dp/dp_debug.h @@ -6,6 +6,7 @@ #ifndef _DP_DEBUG_H_ #define _DP_DEBUG_H_ +#include "dp_hdcp.h" #include
[PATCH 13/14] drm/msm: Add hdcp register ranges to sc7180 device tree
From: Sean Paul This patch adds the register ranges required for HDCP to the sc7180 device tree. These registers will be used to inject HDCP key as well as toggle HDCP on and off. Signed-off-by: Sean Paul --- drivers/gpu/drm/msm/dp/dp_parser.c | 30 +++--- drivers/gpu/drm/msm/dp/dp_parser.h | 4 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index 0519dd3ac3c3..4bbe2485ce3c 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -20,11 +20,19 @@ static const struct dp_regulator_cfg sdm845_dp_reg_cfg = { }; static int msm_dss_ioremap(struct platform_device *pdev, - struct dss_io_data *io_data) + struct dss_io_data *io_data, const char *name, + int fallback_idx) { struct resource *res = NULL; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); + + /* Support dts which do not have named resources */ + if (!res) { + if (fallback_idx >= 0) + res = platform_get_resource(pdev, IORESOURCE_MEM, + fallback_idx); + } if (!res) { DRM_ERROR("%pS->%s: msm_dss_get_res failed\n", __builtin_return_address(0), __func__); @@ -55,6 +63,8 @@ static void dp_parser_unmap_io_resources(struct dp_parser *parser) { struct dp_io *io = >io; + msm_dss_iounmap(>hdcp_tz); + msm_dss_iounmap(>hdcp_key); msm_dss_iounmap(>dp_controller); } @@ -64,12 +74,26 @@ static int dp_parser_ctrl_res(struct dp_parser *parser) struct platform_device *pdev = parser->pdev; struct dp_io *io = >io; - rc = msm_dss_ioremap(pdev, >dp_controller); + rc = msm_dss_ioremap(pdev, >dp_controller, "dp_controller", 0); if (rc) { DRM_ERROR("unable to remap dp io resources, rc=%d\n", rc); goto err; } + rc = msm_dss_ioremap(pdev, >hdcp_key, "hdcp_key", -1); + if (rc) { + DRM_INFO("unable to remap dp hdcp resources, rc=%d\n", rc); + io->hdcp_key.base = NULL; + io->hdcp_key.len = 0; + } + + rc = msm_dss_ioremap(pdev, >hdcp_tz, "hdcp_tz", -1); + if (rc) { + DRM_INFO("unable to remap dp hdcp resources, rc=%d\n", rc); + io->hdcp_tz.base = NULL; + io->hdcp_tz.len = 0; + } + io->phy = devm_phy_get(>dev, "dp"); if (IS_ERR(io->phy)) { rc = PTR_ERR(io->phy); diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index 34b49628bbaf..09d876620175 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -62,10 +62,14 @@ struct dp_display_data { * struct dp_ctrl_resource - controller's IO related data * * @dp_controller: Display Port controller mapped memory address + * @hdcp_key: mapped memory for HDCP key ingestion + * @hdcp_tz: mapped memory for HDCP TZ interaction * @phy_io: phy's mapped memory address */ struct dp_io { struct dss_io_data dp_controller; + struct dss_io_data hdcp_key; + struct dss_io_data hdcp_tz; struct phy *phy; union phy_configure_opts phy_opts; }; -- Sean Paul, Software Engineer, Google / Chromium OS
[PATCH 12/14] dt-bindings: msm/dp: Add bindings for HDCP registers
From: Sean Paul This patch adds the bindings for the MSM DisplayPort HDCP registers which are required to write the HDCP key into the display controller as well as the registers to enable HDCP authentication/key exchange/encryption. Signed-off-by: Sean Paul --- .../bindings/display/msm/dp-controller.yaml | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index 64d8d9e5e47a..984301442653 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -21,6 +21,11 @@ properties: reg: maxItems: 1 + reg-names: +const: dp_controller +const: hdcp_key +const: hdcp_tz + interrupts: maxItems: 1 @@ -99,8 +104,10 @@ examples: #include displayport-controller@ae9 { -compatible = "qcom,sc7180-dp"; -reg = <0xae9 0x1400>; +reg = <0 0x0ae9 0 0x1400>, + <0 0x0aed1000 0 0x174>, + <0 0x0aee1000 0 0x2c>; +reg-names = "dp_controller", "hdcp_key", "hdcp_tz"; interrupt-parent = <>; interrupts = <12>; clocks = < DISP_CC_MDSS_AHB_CLK>, -- Sean Paul, Software Engineer, Google / Chromium OS
[PATCH 11/14] drm/msm/dp: Re-order dp_audio_put in deinit_sub_modules
From: Sean Paul Audio is initialized last, it should be de-initialized first to match the order in dp_init_sub_modules(). Signed-off-by: Sean Paul --- drivers/gpu/drm/msm/dp/dp_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index fbe4c2cd52a3..19946024e235 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -714,9 +714,9 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data) static void dp_display_deinit_sub_modules(struct dp_display_private *dp) { dp_debug_put(dp->debug); + dp_audio_put(dp->audio); dp_panel_put(dp->panel); dp_aux_put(dp->aux); - dp_audio_put(dp->audio); } static int dp_init_sub_modules(struct dp_display_private *dp) -- Sean Paul, Software Engineer, Google / Chromium OS
[PATCH 10/14] drm/msm/dpu: Remove encoder->enable() hack
From: Sean Paul encoder->commit() was being misused because there were some global resources which needed to be tweaked in encoder->enable() which were not accessible in dpu_encoder.c. That is no longer true and the redirect serves no purpose any longer. So remove the indirection. Signed-off-by: Sean Paul --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 5 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 22 - drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 2 -- drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 4 4 files changed, 1 insertion(+), 32 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 984f8a59cb73..ddc542a0d41f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2122,11 +2122,8 @@ static void dpu_encoder_frame_done_timeout(struct timer_list *t) static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = { .mode_set = dpu_encoder_virt_mode_set, .disable = dpu_encoder_virt_disable, - .enable = dpu_kms_encoder_enable, + .enable = dpu_encoder_virt_enable, .atomic_check = dpu_encoder_virt_atomic_check, - - /* This is called by dpu_kms_encoder_enable */ - .commit = dpu_encoder_virt_enable, }; static const struct drm_encoder_funcs dpu_encoder_funcs = { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index fb0d9f781c66..4a0b55d145ad 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -381,28 +381,6 @@ static void dpu_kms_flush_commit(struct msm_kms *kms, unsigned crtc_mask) } } -/* - * Override the encoder enable since we need to setup the inline rotator and do - * some crtc magic before enabling any bridge that might be present. - */ -void dpu_kms_encoder_enable(struct drm_encoder *encoder) -{ - const struct drm_encoder_helper_funcs *funcs = encoder->helper_private; - struct drm_device *dev = encoder->dev; - struct drm_crtc *crtc; - - /* Forward this enable call to the commit hook */ - if (funcs && funcs->commit) - funcs->commit(encoder); - - drm_for_each_crtc(crtc, dev) { - if (!(crtc->state->encoder_mask & drm_encoder_mask(encoder))) - continue; - - trace_dpu_kms_enc_enable(DRMID(crtc)); - } -} - static void dpu_kms_complete_commit(struct msm_kms *kms, unsigned crtc_mask) { struct dpu_kms *dpu_kms = to_dpu_kms(kms); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 323a6bce9e64..f1ebb60dacab 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -248,8 +248,6 @@ void *dpu_debugfs_get_root(struct dpu_kms *dpu_kms); int dpu_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); void dpu_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); -void dpu_kms_encoder_enable(struct drm_encoder *encoder); - /** * dpu_kms_get_clk_rate() - get the clock rate * @dpu_kms: pointer to dpu_kms structure diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h index 37bba57675a8..54d74341e690 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h @@ -266,10 +266,6 @@ DEFINE_EVENT(dpu_drm_obj_template, dpu_crtc_complete_commit, TP_PROTO(uint32_t drm_id), TP_ARGS(drm_id) ); -DEFINE_EVENT(dpu_drm_obj_template, dpu_kms_enc_enable, - TP_PROTO(uint32_t drm_id), - TP_ARGS(drm_id) -); DEFINE_EVENT(dpu_drm_obj_template, dpu_kms_commit, TP_PROTO(uint32_t drm_id), TP_ARGS(drm_id) -- Sean Paul, Software Engineer, Google / Chromium OS
[PATCH 09/14] drm/msm/dpu: Remove useless checks in dpu_encoder
From: Sean Paul A couple more useless checks to remove in dpu_encoder. Signed-off-by: Sean Paul --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 12 1 file changed, 12 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 0e9d3fa1544b..984f8a59cb73 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1153,10 +1153,6 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) struct msm_drm_private *priv; struct drm_display_mode *cur_mode = NULL; - if (!drm_enc) { - DPU_ERROR("invalid encoder\n"); - return; - } dpu_enc = to_dpu_encoder_virt(drm_enc); mutex_lock(_enc->enc_lock); @@ -1203,14 +1199,6 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) struct msm_drm_private *priv; int i = 0; - if (!drm_enc) { - DPU_ERROR("invalid encoder\n"); - return; - } else if (!drm_enc->dev) { - DPU_ERROR("invalid dev\n"); - return; - } - dpu_enc = to_dpu_encoder_virt(drm_enc); DPU_DEBUG_ENC(dpu_enc, "\n"); -- Sean Paul, Software Engineer, Google / Chromium OS
[PATCH 08/14] drm/msm/dpu_kms: Re-order dpu includes
From: Sean Paul Make includes alphabetical in dpu_kms.c Signed-off-by: Sean Paul --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index ae48f41821cf..fb0d9f781c66 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -21,14 +21,14 @@ #include "msm_gem.h" #include "disp/msm_disp_snapshot.h" -#include "dpu_kms.h" #include "dpu_core_irq.h" +#include "dpu_crtc.h" +#include "dpu_encoder.h" #include "dpu_formats.h" #include "dpu_hw_vbif.h" -#include "dpu_vbif.h" -#include "dpu_encoder.h" +#include "dpu_kms.h" #include "dpu_plane.h" -#include "dpu_crtc.h" +#include "dpu_vbif.h" #define CREATE_TRACE_POINTS #include "dpu_trace.h" -- Sean Paul, Software Engineer, Google / Chromium OS
[PATCH 07/14] drm/i915/hdcp: Use HDCP helpers for i915
From: Sean Paul Now that all of the HDCP 1.x logic has been migrated to the central HDCP helpers, use it in the i915 driver. The majority of the driver code for HDCP 1.x will live in intel_hdcp.c, however there are a few helper hooks which are connector-specific and need to be partially or fully implemented in the intel_dp_hdcp.c or intel_hdmi.c. We'll leave most of the HDCP 2.x code alone since we don't have another implementation of HDCP 2.x to use as reference for what should and should not live in the drm helpers. The helper will call the overly general enable/disable/is_capable HDCP 2.x callbacks and leave the interesting stuff for the driver. Once we have another HDCP 2.x implementation, we should do a similar migration. Signed-off-by: Sean Paul --- drivers/gpu/drm/i915/display/intel_ddi.c | 29 +- .../drm/i915/display/intel_display_debugfs.c | 6 +- .../drm/i915/display/intel_display_types.h| 58 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 341 +++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 17 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 935 +++--- drivers/gpu/drm/i915/display/intel_hdcp.h | 30 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 256 ++--- 8 files changed, 413 insertions(+), 1259 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 23ef291f7b30..8bdf41593174 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -26,6 +26,7 @@ */ #include +#include #include "i915_drv.h" #include "intel_audio.h" @@ -3131,6 +3132,9 @@ static void intel_enable_ddi(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { + struct intel_connector *connector = to_intel_connector(conn_state->connector); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); + drm_WARN_ON(state->base.dev, crtc_state->has_pch_encoder); if (!crtc_state->bigjoiner_slave) @@ -3147,12 +3151,10 @@ static void intel_enable_ddi(struct intel_atomic_state *state, else intel_enable_ddi_dp(state, encoder, crtc_state, conn_state); - /* Enable hdcp if it's desired */ - if (conn_state->content_protection == - DRM_MODE_CONTENT_PROTECTION_DESIRED) - intel_hdcp_enable(to_intel_connector(conn_state->connector), - crtc_state, - (u8)conn_state->hdcp_content_type); + if (connector->hdcp_helper_data) + drm_hdcp_helper_atomic_commit(connector->hdcp_helper_data, + >base, + _port->hdcp_mutex); } static void intel_disable_ddi_dp(struct intel_atomic_state *state, @@ -3212,7 +3214,13 @@ static void intel_disable_ddi(struct intel_atomic_state *state, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { - intel_hdcp_disable(to_intel_connector(old_conn_state->connector)); + struct intel_connector *connector = to_intel_connector(old_conn_state->connector); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); + + if (connector->hdcp_helper_data) + drm_hdcp_helper_atomic_commit(connector->hdcp_helper_data, + >base, + _port->hdcp_mutex); if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI)) intel_disable_ddi_hdmi(state, encoder, old_crtc_state, @@ -3243,13 +3251,18 @@ void intel_ddi_update_pipe(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { + struct intel_connector *connector = to_intel_connector(conn_state->connector); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && !intel_encoder_is_mst(encoder)) intel_ddi_update_pipe_dp(state, encoder, crtc_state, conn_state); - intel_hdcp_update_pipe(state, encoder, crtc_state, conn_state); + if (connector->hdcp_helper_data) + drm_hdcp_helper_atomic_commit(connector->hdcp_helper_data, + >base, + _port->hdcp_mutex); } static void diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 5ffd31e9908f..74c1f5b48797 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++
[PATCH 06/14] drm/i915/hdcp: Retain hdcp_capable return codes
From: Sean Paul The shim functions return error codes, but they are discarded in intel_hdcp.c. This patch plumbs the return codes through so they are properly handled. Signed-off-by: Sean Paul --- .../drm/i915/display/intel_display_debugfs.c | 9 +++- drivers/gpu/drm/i915/display/intel_hdcp.c | 51 ++- drivers/gpu/drm/i915/display/intel_hdcp.h | 4 +- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 68f4ba8c46e7..5ffd31e9908f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -644,6 +644,7 @@ static void intel_panel_info(struct seq_file *m, struct intel_panel *panel) static void intel_hdcp_info(struct seq_file *m, struct intel_connector *intel_connector) { + int ret; bool hdcp_cap, hdcp2_cap; if (!intel_connector->hdcp.shim) { @@ -651,8 +652,12 @@ static void intel_hdcp_info(struct seq_file *m, goto out; } - hdcp_cap = intel_hdcp_capable(intel_connector); - hdcp2_cap = intel_hdcp2_capable(intel_connector); + ret = intel_hdcp_capable(intel_connector, _cap); + if (ret) + hdcp_cap = false; + ret = intel_hdcp2_capable(intel_connector, _cap); + if (ret) + hdcp2_cap = false; if (hdcp_cap) seq_puts(m, "HDCP1.4 "); diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index af166baf8c71..59275919e7b9 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -153,50 +153,49 @@ int intel_hdcp_read_valid_bksv(struct intel_digital_port *dig_port, } /* Is HDCP1.4 capable on Platform and Sink */ -bool intel_hdcp_capable(struct intel_connector *connector) +int intel_hdcp_capable(struct intel_connector *connector, bool *capable) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); const struct intel_hdcp_shim *shim = connector->hdcp.shim; - bool capable = false; u8 bksv[5]; + *capable = false; + if (!shim) - return capable; + return 0; - if (shim->hdcp_capable) { - shim->hdcp_capable(dig_port, ); - } else { - if (!intel_hdcp_read_valid_bksv(dig_port, shim, bksv)) - capable = true; - } + if (shim->hdcp_capable) + return shim->hdcp_capable(dig_port, capable); + + if (!intel_hdcp_read_valid_bksv(dig_port, shim, bksv)) + *capable = true; - return capable; + return 0; } /* Is HDCP2.2 capable on Platform and Sink */ -bool intel_hdcp2_capable(struct intel_connector *connector) +int intel_hdcp2_capable(struct intel_connector *connector, bool *capable) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = >hdcp; - bool capable = false; + + *capable = false; /* I915 support for HDCP2.2 */ if (!hdcp->hdcp2_supported) - return false; + return 0; /* MEI interface is solid */ mutex_lock(_priv->hdcp_comp_mutex); if (!dev_priv->hdcp_comp_added || !dev_priv->hdcp_master) { mutex_unlock(_priv->hdcp_comp_mutex); - return false; + return 0; } mutex_unlock(_priv->hdcp_comp_mutex); /* Sink's capability for HDCP2.2 */ - hdcp->shim->hdcp_2_2_capable(dig_port, ); - - return capable; + return hdcp->shim->hdcp_2_2_capable(dig_port, capable); } static bool intel_hdcp_in_use(struct drm_i915_private *dev_priv, @@ -2332,6 +2331,7 @@ int intel_hdcp_enable(struct intel_connector *connector, struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct intel_hdcp *hdcp = >hdcp; unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS; + bool capable; int ret = -EINVAL; if (!hdcp->shim) @@ -2350,21 +2350,27 @@ int intel_hdcp_enable(struct intel_connector *connector, * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup * is capable of HDCP2.2, it is preferred to use HDCP2.2. */ - if (intel_hdcp2_capable(connector)) { + ret = intel_hdcp2_capable(connector, ); + if (capable) { ret = _intel_hdcp2_enable(connector); - if (!ret) + if (!ret) { check_link_interval = DRM_HDCP2_CHECK_PERIOD_MS; + goto out; + } } /* * When HDCP2.2 fails and Content Type is not Type1,
[PATCH 05/14] drm/i915/hdcp: Consolidate HDCP setup/state cache
From: Sean Paul Stick all of the setup for HDCP into a dedicated function. No functional change, but this will facilitate moving HDCP logic into helpers. Signed-off-by: Sean Paul --- drivers/gpu/drm/i915/display/intel_hdcp.c | 52 +++ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index feebafead046..af166baf8c71 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -2167,6 +2167,37 @@ static enum mei_fw_tc intel_get_mei_fw_tc(enum transcoder cpu_transcoder) } } +static int +_intel_hdcp_setup(struct intel_connector *connector, + const struct intel_crtc_state *pipe_config, u8 content_type) +{ + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); + struct intel_hdcp *hdcp = >hdcp; + int ret = 0; + + if (!connector->encoder) { + drm_err(_priv->drm, "[%s:%d] encoder is not initialized\n", + connector->base.name, connector->base.base.id); + return -ENODEV; + } + + hdcp->content_type = content_type; + + if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) { + hdcp->cpu_transcoder = pipe_config->mst_master_transcoder; + hdcp->stream_transcoder = pipe_config->cpu_transcoder; + } else { + hdcp->cpu_transcoder = pipe_config->cpu_transcoder; + hdcp->stream_transcoder = INVALID_TRANSCODER; + } + + if (DISPLAY_VER(dev_priv) >= 12) + dig_port->hdcp_port_data.fw_tc = intel_get_mei_fw_tc(hdcp->cpu_transcoder); + + return ret; +} + static int initialize_hdcp_port_data(struct intel_connector *connector, struct intel_digital_port *dig_port, const struct intel_hdcp_shim *shim) @@ -2306,28 +2337,14 @@ int intel_hdcp_enable(struct intel_connector *connector, if (!hdcp->shim) return -ENOENT; - if (!connector->encoder) { - drm_err(_priv->drm, "[%s:%d] encoder is not initialized\n", - connector->base.name, connector->base.base.id); - return -ENODEV; - } - mutex_lock(>mutex); mutex_lock(_port->hdcp_mutex); drm_WARN_ON(_priv->drm, hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED); - hdcp->content_type = content_type; - - if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) { - hdcp->cpu_transcoder = pipe_config->mst_master_transcoder; - hdcp->stream_transcoder = pipe_config->cpu_transcoder; - } else { - hdcp->cpu_transcoder = pipe_config->cpu_transcoder; - hdcp->stream_transcoder = INVALID_TRANSCODER; - } - if (DISPLAY_VER(dev_priv) >= 12) - dig_port->hdcp_port_data.fw_tc = intel_get_mei_fw_tc(hdcp->cpu_transcoder); + ret = _intel_hdcp_setup(connector, pipe_config, content_type); + if (ret) + goto out; /* * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup @@ -2355,6 +2372,7 @@ int intel_hdcp_enable(struct intel_connector *connector, true); } +out: mutex_unlock(_port->hdcp_mutex); mutex_unlock(>mutex); return ret; -- Sean Paul, Software Engineer, Google / Chromium OS
[PATCH 04/14] drm/hdcp: Expand HDCP helper library for enable/disable/check
From: Sean Paul This patch expands upon the HDCP helper library to manage HDCP enable, disable, and check. Previous to this patch, the majority of the state management and sink interaction is tucked inside the Intel driver with the understanding that once a new platform supported HDCP we could make good decisions about what should be centralized. With the addition of HDCP support for Qualcomm, it's time to migrate the protocol-specific bits of HDCP authentication, key exchange, and link checks to the HDCP helper. In terms of functionality, this migration is 1:1 with the Intel driver, however things are laid out a bit differently than with intel_hdcp.c, which is why this is a separate patch from the i915 transition to the helper. On i915, the "shim" vtable is used to account for HDMI vs. DP vs. DP-MST differences whereas the helper library uses a LUT to account for the register offsets and a remote read function to route the messages. On i915, storing the sink information in the source is done inline whereas now we use the new drm_hdcp_helper_funcs vtable to store and fetch information to/from source hw. Finally, instead of calling enable/disable directly from the driver, we'll leave that decision to the helper and by calling drm_hdcp_helper_atomic_commit() from the driver. All told, this will centralize the protocol and state handling in the helper, ensuring we collect all of our bugs^Wlogic in one place. Signed-off-by: Sean Paul --- drivers/gpu/drm/drm_hdcp.c | 1104 include/drm/drm_hdcp.h | 191 +++ 2 files changed, 1295 insertions(+) diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c index 742313ce8f6f..c22390c127a2 100644 --- a/drivers/gpu/drm/drm_hdcp.c +++ b/drivers/gpu/drm/drm_hdcp.c @@ -6,15 +6,20 @@ * Ramalingam C */ +#include #include #include #include +#include +#include #include #include #include +#include #include #include +#include #include #include #include @@ -513,3 +518,1102 @@ bool drm_hdcp_atomic_check(struct drm_connector *connector, return old_hdcp != new_hdcp; } EXPORT_SYMBOL(drm_hdcp_atomic_check); + +struct drm_hdcp_helper_data { + struct mutex mutex; + struct mutex *driver_mutex; + + struct drm_connector *connector; + const struct drm_hdcp_helper_funcs *funcs; + + u64 value; + unsigned int enabled_type; + + struct delayed_work check_work; + struct work_struct prop_work; + + struct drm_dp_aux *aux; + const struct drm_hdcp_hdcp1_receiver_reg_lut *hdcp1_lut; +}; + +struct drm_hdcp_hdcp1_receiver_reg_lut { + unsigned int bksv; + unsigned int ri; + unsigned int aksv; + unsigned int an; + unsigned int ainfo; + unsigned int v[5]; + unsigned int bcaps; + unsigned int bcaps_mask_repeater_present; + unsigned int bstatus; +}; + +static const struct drm_hdcp_hdcp1_receiver_reg_lut drm_hdcp_hdcp1_ddc_lut = { + .bksv = DRM_HDCP_DDC_BKSV, + .ri = DRM_HDCP_DDC_RI_PRIME, + .aksv = DRM_HDCP_DDC_AKSV, + .an = DRM_HDCP_DDC_AN, + .ainfo = DRM_HDCP_DDC_AINFO, + .v = { DRM_HDCP_DDC_V_PRIME(0), DRM_HDCP_DDC_V_PRIME(1), + DRM_HDCP_DDC_V_PRIME(2), DRM_HDCP_DDC_V_PRIME(3), + DRM_HDCP_DDC_V_PRIME(4) }, + .bcaps = DRM_HDCP_DDC_BCAPS, + .bcaps_mask_repeater_present = DRM_HDCP_DDC_BCAPS_REPEATER_PRESENT, + .bstatus = DRM_HDCP_DDC_BSTATUS, +}; + +static const struct drm_hdcp_hdcp1_receiver_reg_lut drm_hdcp_hdcp1_dpcd_lut = { + .bksv = DP_AUX_HDCP_BKSV, + .ri = DP_AUX_HDCP_RI_PRIME, + .aksv = DP_AUX_HDCP_AKSV, + .an = DP_AUX_HDCP_AN, + .ainfo = DP_AUX_HDCP_AINFO, + .v = { DP_AUX_HDCP_V_PRIME(0), DP_AUX_HDCP_V_PRIME(1), + DP_AUX_HDCP_V_PRIME(2), DP_AUX_HDCP_V_PRIME(3), + DP_AUX_HDCP_V_PRIME(4) }, + .bcaps = DP_AUX_HDCP_BCAPS, + .bcaps_mask_repeater_present = DP_BCAPS_REPEATER_PRESENT, + + /* +* For some reason the HDMI and DP HDCP specs call this register +* definition by different names. In the HDMI spec, it's called BSTATUS, +* but in DP it's called BINFO. +*/ + .bstatus = DP_AUX_HDCP_BINFO, +}; + +static int drm_hdcp_remote_ddc_read(struct i2c_adapter *i2c, + unsigned int offset, u8 *value, size_t len) +{ + int ret; + u8 start = offset & 0xff; + struct i2c_msg msgs[] = { + { + .addr = DRM_HDCP_DDC_ADDR, + .flags = 0, + .len = 1, + .buf = , + }, + { + .addr = DRM_HDCP_DDC_ADDR, + .flags = I2C_M_RD, + .len = len, + .buf = value + } + }; + ret = i2c_transfer(i2c, msgs, ARRAY_SIZE(msgs)); + if
[PATCH 03/14] drm/hdcp: Update property value on content type and user changes
From: Sean Paul This patch updates the connector's property value in 2 cases which were previously missed: 1- Content type changes. The value should revert back to DESIRED from ENABLED in case the driver must re-authenticate the link due to the new content type. 2- Userspace sets value to DESIRED while ENABLED. In this case, the value should be reset immediately to ENABLED since the link is actively being encrypted. To accommodate these changes, I've split up the conditionals to make things a bit more clear (as much as one can with this mess of state). Signed-off-by: Sean Paul --- drivers/gpu/drm/drm_hdcp.c | 26 +- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c index dd8fa91c51d6..742313ce8f6f 100644 --- a/drivers/gpu/drm/drm_hdcp.c +++ b/drivers/gpu/drm/drm_hdcp.c @@ -487,21 +487,29 @@ bool drm_hdcp_atomic_check(struct drm_connector *connector, return true; /* -* Nothing to do if content type is unchanged and one of: -* - state didn't change +* Content type changes require an HDCP disable/enable cycle. +*/ + if (new_conn_state->hdcp_content_type != old_conn_state->hdcp_content_type) { + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + return true; + } + + /* +* Ignore meaningless state changes: * - HDCP was activated since the last commit -* - attempting to set to desired while already enabled +* - Attempting to set to desired while already enabled */ - if (old_hdcp == new_hdcp || - (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && + if ((old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) || (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { - if (old_conn_state->hdcp_content_type == - new_conn_state->hdcp_content_type) - return false; + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_ENABLED; +return false; } - return true; + /* Finally, if state changes, we need action */ + return old_hdcp != new_hdcp; } EXPORT_SYMBOL(drm_hdcp_atomic_check); -- Sean Paul, Software Engineer, Google / Chromium OS
[PATCH 02/14] drm/hdcp: Avoid changing crtc state in hdcp atomic check
From: Sean Paul Instead of forcing a modeset in the hdcp atomic check, simply return true if the content protection value is changing and let the driver decide whether a modeset is required or not. Signed-off-by: Sean Paul --- drivers/gpu/drm/drm_hdcp.c | 33 +++-- drivers/gpu/drm/i915/display/intel_atomic.c | 5 ++-- include/drm/drm_hdcp.h | 2 +- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c index 522326b03e66..dd8fa91c51d6 100644 --- a/drivers/gpu/drm/drm_hdcp.c +++ b/drivers/gpu/drm/drm_hdcp.c @@ -430,11 +430,14 @@ EXPORT_SYMBOL(drm_hdcp_update_content_protection); * @connector: drm_connector on which content protection state needs an update * * This function can be used by display drivers to perform an atomic check on the - * hdcp state elements. If hdcp state has changed, this function will set - * mode_changed on the crtc driving the connector so it can update its hardware - * to match the hdcp state. + * hdcp state elements. If hdcp state has changed in a manner which requires the + * driver to enable or disable content protection, this function will return + * true. + * + * Returns: + * true if the driver must enable/disable hdcp, false otherwise */ -void drm_hdcp_atomic_check(struct drm_connector *connector, +bool drm_hdcp_atomic_check(struct drm_connector *connector, struct drm_atomic_state *state) { struct drm_connector_state *new_conn_state, *old_conn_state; @@ -452,10 +455,12 @@ void drm_hdcp_atomic_check(struct drm_connector *connector, * If the connector is being disabled with CP enabled, mark it * desired so it's re-enabled when the connector is brought back */ - if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) + if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) { new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; - return; + return true; + } + return false; } new_crtc_state = drm_atomic_get_new_crtc_state(state, @@ -467,9 +472,19 @@ void drm_hdcp_atomic_check(struct drm_connector *connector, */ if (drm_atomic_crtc_needs_modeset(new_crtc_state) && (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && -new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) +new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) { new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + return true; + } + + /* +* Coming back from disable or changing CRTC with DESIRED state requires +* that the driver try CP enable. +*/ + if (new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && + new_conn_state->crtc != old_conn_state->crtc) + return true; /* * Nothing to do if content type is unchanged and one of: @@ -484,9 +499,9 @@ void drm_hdcp_atomic_check(struct drm_connector *connector, new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { if (old_conn_state->hdcp_content_type == new_conn_state->hdcp_content_type) - return; + return false; } - new_crtc_state->mode_changed = true; + return true; } EXPORT_SYMBOL(drm_hdcp_atomic_check); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 1e306e8427ec..c7b5470c40aa 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -122,8 +122,6 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn, to_intel_digital_connector_state(old_state); struct drm_crtc_state *crtc_state; - drm_hdcp_atomic_check(conn, state); - if (!new_state->crtc) return 0; @@ -139,7 +137,8 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn, new_conn_state->base.picture_aspect_ratio != old_conn_state->base.picture_aspect_ratio || new_conn_state->base.content_type != old_conn_state->base.content_type || new_conn_state->base.scaling_mode != old_conn_state->base.scaling_mode || - !drm_connector_atomic_hdr_metadata_equal(old_state, new_state)) + !drm_connector_atomic_hdr_metadata_equal(old_state, new_state) || + drm_hdcp_atomic_check(conn, state)) crtc_state->mode_changed = true; return 0; diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h index d49977a042e1..e6e3d16bc7d3 100644 --- a/include/drm/drm_hdcp.h +++ b/include/drm/drm_hdcp.h @@ -301,7 +301,7 @@ int
[PATCH 01/14] drm/hdcp: Add drm_hdcp_atomic_check()
From: Sean Paul This patch moves the hdcp atomic check from i915 to drm_hdcp so other drivers can use it. No functional changes, just cleaned up some of the code when moving it over. Signed-off-by: Sean Paul --- drivers/gpu/drm/drm_hdcp.c | 71 - drivers/gpu/drm/i915/display/intel_atomic.c | 4 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 47 -- drivers/gpu/drm/i915/display/intel_hdcp.h | 3 - include/drm/drm_hdcp.h | 3 + 5 files changed, 75 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c index ca9b8f697202..522326b03e66 100644 --- a/drivers/gpu/drm/drm_hdcp.c +++ b/drivers/gpu/drm/drm_hdcp.c @@ -13,13 +13,14 @@ #include #include +#include +#include #include #include #include #include #include #include -#include #include "drm_internal.h" @@ -421,3 +422,71 @@ void drm_hdcp_update_content_protection(struct drm_connector *connector, dev->mode_config.content_protection_property); } EXPORT_SYMBOL(drm_hdcp_update_content_protection); + +/** + * drm_hdcp_atomic_check - Helper for drivers to call during connector->atomic_check + * + * @state: pointer to the atomic state being checked + * @connector: drm_connector on which content protection state needs an update + * + * This function can be used by display drivers to perform an atomic check on the + * hdcp state elements. If hdcp state has changed, this function will set + * mode_changed on the crtc driving the connector so it can update its hardware + * to match the hdcp state. + */ +void drm_hdcp_atomic_check(struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct drm_connector_state *new_conn_state, *old_conn_state; + struct drm_crtc_state *new_crtc_state; + u64 old_hdcp, new_hdcp; + + old_conn_state = drm_atomic_get_old_connector_state(state, connector); + old_hdcp = old_conn_state->content_protection; + + new_conn_state = drm_atomic_get_new_connector_state(state, connector); + new_hdcp = new_conn_state->content_protection; + + if (!new_conn_state->crtc) { + /* +* If the connector is being disabled with CP enabled, mark it +* desired so it's re-enabled when the connector is brought back +*/ + if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + return; + } + + new_crtc_state = drm_atomic_get_new_crtc_state(state, + new_conn_state->crtc); + /* + * Fix the HDCP uapi content protection state in case of modeset. + * FIXME: As per HDCP content protection property uapi doc, an uevent() + * need to be sent if there is transition from ENABLED->DESIRED. + */ + if (drm_atomic_crtc_needs_modeset(new_crtc_state) && + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && +new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + + /* +* Nothing to do if content type is unchanged and one of: +* - state didn't change +* - HDCP was activated since the last commit +* - attempting to set to desired while already enabled +*/ + if (old_hdcp == new_hdcp || + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && +new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) || + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && +new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { + if (old_conn_state->hdcp_content_type == + new_conn_state->hdcp_content_type) + return; + } + + new_crtc_state->mode_changed = true; +} +EXPORT_SYMBOL(drm_hdcp_atomic_check); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index b4e7ac51aa31..1e306e8427ec 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -32,13 +32,13 @@ #include #include #include +#include #include #include "intel_atomic.h" #include "intel_cdclk.h" #include "intel_display_types.h" #include "intel_global_state.h" -#include "intel_hdcp.h" #include "intel_psr.h" #include "skl_universal_plane.h" @@ -122,7 +122,7 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn, to_intel_digital_connector_state(old_state); struct drm_crtc_state *crtc_state; - intel_hdcp_atomic_check(conn, old_state, new_state); + drm_hdcp_atomic_check(conn, state); if
[PATCH 00/14] drm/hdcp: Pull HDCP auth/exchange/check into
From: Sean Paul Hello, This patchset pulls the HDCP protocol auth/exchange/check logic out from i915 into a HDCP helper library which drivers can use to implement the proper protocol and UAPI interactions for achieving HDCP. Originally this was all stuffed into i915 since it was the only driver supporting HDCP. Over the last while I've been working on HDCP support in the msm driver and have identified the parts which can/should be shared between drivers and the parts which are hw-specific. We can generalize all of the sink interactions in the helper as well as state handling and link checks. This tends to be the trickiest part of adding HDCP support, since the property state and locking is a bit of a nightmare. The driver need only implement the more mechanical display controller register accesses. The first third of the pachset is establishing the helpers, the next third is converting the i915 driver to use the helpers, and the last third is the msm driver implementation. I've left out HDCP 2.x support, since we still only have i915 as the reference implementation and I'm not super comfortable speculating on which parts are platform independent. Please take a look, Sean Sean Paul (14): drm/hdcp: Add drm_hdcp_atomic_check() drm/hdcp: Avoid changing crtc state in hdcp atomic check drm/hdcp: Update property value on content type and user changes drm/hdcp: Expand HDCP helper library for enable/disable/check drm/i915/hdcp: Consolidate HDCP setup/state cache drm/i915/hdcp: Retain hdcp_capable return codes drm/i915/hdcp: Use HDCP helpers for i915 drm/msm/dpu_kms: Re-order dpu includes drm/msm/dpu: Remove useless checks in dpu_encoder drm/msm/dpu: Remove encoder->enable() hack drm/msm/dp: Re-order dp_audio_put in deinit_sub_modules dt-bindings: msm/dp: Add bindings for HDCP registers drm/msm: Add hdcp register ranges to sc7180 device tree drm/msm: Implement HDCP 1.x using the new drm HDCP helpers .../bindings/display/msm/dp-controller.yaml | 11 +- drivers/gpu/drm/drm_hdcp.c| 1198 - drivers/gpu/drm/i915/display/intel_atomic.c |7 +- drivers/gpu/drm/i915/display/intel_ddi.c | 29 +- .../drm/i915/display/intel_display_debugfs.c | 11 +- .../drm/i915/display/intel_display_types.h| 58 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 341 ++--- drivers/gpu/drm/i915/display/intel_dp_mst.c | 17 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 1011 +++--- drivers/gpu/drm/i915/display/intel_hdcp.h | 35 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 256 ++-- drivers/gpu/drm/msm/Makefile |1 + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 17 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 30 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |2 - drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h |4 - drivers/gpu/drm/msm/dp/dp_debug.c | 49 +- drivers/gpu/drm/msm/dp/dp_debug.h |6 +- drivers/gpu/drm/msm/dp/dp_display.c | 47 +- drivers/gpu/drm/msm/dp/dp_display.h |5 + drivers/gpu/drm/msm/dp/dp_drm.c | 68 +- drivers/gpu/drm/msm/dp/dp_drm.h |5 + drivers/gpu/drm/msm/dp/dp_hdcp.c | 433 ++ drivers/gpu/drm/msm/dp/dp_hdcp.h | 27 + drivers/gpu/drm/msm/dp/dp_parser.c| 30 +- drivers/gpu/drm/msm/dp/dp_parser.h|4 + drivers/gpu/drm/msm/dp/dp_reg.h | 44 +- drivers/gpu/drm/msm/msm_atomic.c | 15 + include/drm/drm_hdcp.h| 194 +++ 29 files changed, 2570 insertions(+), 1385 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h -- Sean Paul, Software Engineer, Google / Chromium OS
Re: [PATCH 0/3] drm/i915: Enable -Wsometimes-uninitialized
On Tue, Aug 24, 2021 at 03:54:24PM -0700, Nathan Chancellor wrote: > Commit 46e2068081e9 ("drm/i915: Disable some extra clang warnings") > disabled -Wsometimes-uninitialized as noisy but there have been a few > fixes to clang that make the false positive rate fairly low so it should > be enabled to help catch obvious mistakes. The first two patches fix > revent instances of this warning then enables it for i915 like the rest > of the tree. > > Cheers, > Nathan > > Nathan Chancellor (3): > drm/i915/selftests: Do not use import_obj uninitialized > drm/i915/selftests: Always initialize err in > igt_dmabuf_import_same_driver_lmem() > drm/i915: Enable -Wsometimes-uninitialized > > drivers/gpu/drm/i915/Makefile| 1 - > drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c | 7 --- > 2 files changed, 4 insertions(+), 4 deletions(-) > > > base-commit: fb43ebc83e069625cfeeb2490efc3ffa0013bfa4 > -- > 2.33.0 > > Ping, could this be picked up for an -rc as these are very clearly bugs? Cheers, Nathan
Re: [virtio-dev] [PATCH v1 09/12] drm/virtio: implement context init: allocate an array of fence contexts
On Fri, Sep 10, 2021 at 12:33 PM Chia-I Wu wrote: > On Wed, Sep 8, 2021 at 6:37 PM Gurchetan Singh > wrote: > > > > We don't want fences from different 3D contexts (virgl, gfxstream, > > venus) to be on the same timeline. With explicit context creation, > > we can specify the number of ring each context wants. > > > > Execbuffer can specify which ring to use. > > > > Signed-off-by: Gurchetan Singh > > Acked-by: Lingfeng Yang > > --- > > drivers/gpu/drm/virtio/virtgpu_drv.h | 3 +++ > > drivers/gpu/drm/virtio/virtgpu_ioctl.c | 34 -- > > 2 files changed, 35 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h > b/drivers/gpu/drm/virtio/virtgpu_drv.h > > index a5142d60c2fa..cca9ab505deb 100644 > > --- a/drivers/gpu/drm/virtio/virtgpu_drv.h > > +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h > > @@ -56,6 +56,7 @@ > > #define STATE_ERR 2 > > > > #define MAX_CAPSET_ID 63 > > +#define MAX_RINGS 64 > > > > struct virtio_gpu_object_params { > > unsigned long size; > > @@ -263,6 +264,8 @@ struct virtio_gpu_fpriv { > > uint32_t ctx_id; > > uint32_t context_init; > > bool context_created; > > + uint32_t num_rings; > > + uint64_t base_fence_ctx; > > struct mutex context_lock; > > }; > > > > diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c > b/drivers/gpu/drm/virtio/virtgpu_ioctl.c > > index f51f3393a194..262f79210283 100644 > > --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c > > +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c > > @@ -99,6 +99,11 @@ static int virtio_gpu_execbuffer_ioctl(struct > drm_device *dev, void *data, > > int in_fence_fd = exbuf->fence_fd; > > int out_fence_fd = -1; > > void *buf; > > + uint64_t fence_ctx; > > + uint32_t ring_idx; > > + > > + fence_ctx = vgdev->fence_drv.context; > > + ring_idx = 0; > > > > if (vgdev->has_virgl_3d == false) > > return -ENOSYS; > > @@ -106,6 +111,17 @@ static int virtio_gpu_execbuffer_ioctl(struct > drm_device *dev, void *data, > > if ((exbuf->flags & ~VIRTGPU_EXECBUF_FLAGS)) > > return -EINVAL; > > > > + if ((exbuf->flags & VIRTGPU_EXECBUF_RING_IDX)) { > > + if (exbuf->ring_idx >= vfpriv->num_rings) > > + return -EINVAL; > > + > > + if (!vfpriv->base_fence_ctx) > > + return -EINVAL; > > + > > + fence_ctx = vfpriv->base_fence_ctx; > > + ring_idx = exbuf->ring_idx; > > + } > > + > > exbuf->fence_fd = -1; > > > > virtio_gpu_create_context(dev, file); > > @@ -173,7 +189,7 @@ static int virtio_gpu_execbuffer_ioctl(struct > drm_device *dev, void *data, > > goto out_memdup; > > } > > > > - out_fence = virtio_gpu_fence_alloc(vgdev, > vgdev->fence_drv.context, 0); > > + out_fence = virtio_gpu_fence_alloc(vgdev, fence_ctx, ring_idx); > > if(!out_fence) { > > ret = -ENOMEM; > > goto out_unresv; > > @@ -691,7 +707,7 @@ static int virtio_gpu_context_init_ioctl(struct > drm_device *dev, > > return -EINVAL; > > > > /* Number of unique parameters supported at this time. */ > > - if (num_params > 1) > > + if (num_params > 2) > > return -EINVAL; > > > > ctx_set_params = > memdup_user(u64_to_user_ptr(args->ctx_set_params), > > @@ -731,6 +747,20 @@ static int virtio_gpu_context_init_ioctl(struct > drm_device *dev, > > > > vfpriv->context_init |= value; > > break; > > + case VIRTGPU_CONTEXT_PARAM_NUM_RINGS: > > + if (vfpriv->base_fence_ctx) { > > + ret = -EINVAL; > > + goto out_unlock; > > + } > > + > > + if (value > MAX_RINGS) { > > + ret = -EINVAL; > > + goto out_unlock; > > + } > > + > > + vfpriv->base_fence_ctx = > dma_fence_context_alloc(value); > With multiple fence contexts, we should do something about implicit > fencing. > > The classic example is Mesa and X server. When both use virgl and the > global fence context, no dma_fence_wait is fine. But when Mesa uses > venus and the ring fence context, dma_fence_wait should be inserted. > If I read your comment correctly, the use case is: context A (venus) sharing a render target with context B (Xserver backed virgl) ? Which function do you envisage dma_fence_wait(...) to be inserted? Doesn't implicit synchronization mean there's no fence to share between contexts (only buffer objects)? It may be possible to wait on the reservation object associated with a buffer object from a different context (userspace can also do DRM_IOCTL_VIRTGPU_WAIT), but not sure
Re: [Intel-gfx] [PATCH 05/27] drm/i915: Add GT PM unpark worker
On Mon, Sep 13, 2021 at 11:33:46AM +0100, Tvrtko Ursulin wrote: > > On 10/09/2021 21:09, Matthew Brost wrote: > > On Fri, Sep 10, 2021 at 09:36:17AM +0100, Tvrtko Ursulin wrote: > > > > > > On 20/08/2021 23:44, Matthew Brost wrote: > > > > Sometimes it is desirable to queue work up for later if the GT PM isn't > > > > held and run that work on next GT PM unpark. > > > > > > Sounds maybe plausible, but it depends how much work can happen on unpark > > > and whether it can have too much of a negative impact on latency for > > > interactive loads? Or from a reverse angle, why the work wouldn't be done > > > on > > > > All it is does is add an interface to kick a work queue on unpark. i.e. > > All the actually work is done async in the work queue so it shouldn't > > add any latency. > > > > > parking? > > > > > > Also what kind of mechanism for dealing with too much stuff being put on > > > this list you have? Can there be pressure which triggers (or would need to > > > > No limits on pressure. See above, I don't think this is a concern. > > On unpark it has the potential to send an unbound amount of actions for the > GuC to process. Which will be competing, in GuC internal processing power, > with the user action which caused the unpark. That logically does feel like > can have effect on initial latency. Why you think it cannot? > Ah, I see what you mean. Yes, bunch of deregisters could be sent before a submission adding latency. Maybe I just drop this whole idea / patch for now. Not going to respond to individual comments because this will be dropped. Matt > Why the work wouldn't be done on parking? > > With this scheme couldn't we end up with a situation that the worker keeps > missing the GT unparked state and so keeps piling items on the > deregistration list? Can you run of some ids like that (which is related to > my question of how is pressure handled here). > > Unpark > Register context > Submit work > Retire > Schedule context deregister > Park > > Worker runs > GT parked > Work put on a list > > Unpark > Schedule deregistration worker > Register new context > Submit work > Retire > Schedule contect deregister > Park > > Worker runs (lets say there was CPU pressure) > GT already parked > -> deregistration queue now has two contexts on it > > ... repeat until disaster ... > > Unless I have misunderstood the logic. > > > > trigger) these deregistrations to happen at runtime (no park/unpark > > > transitions)? > > > > > > > Implemented with a list in the GT of all pending work, workqueues in > > > > the list, a callback to add a workqueue to the list, and finally a > > > > wakeref post_get callback that iterates / drains the list + queues the > > > > workqueues. > > > > > > > > First user of this is deregistration of GuC contexts. > > > > > > Does first imply there are more incoming? > > > > > > > Haven't found another user yet but this is generic mechanism so we can > > add more in the future if other use cases arrise. > > My feeling is it would be best to leave it for later. > > > > > Signed-off-by: Matthew Brost > > > > --- > > > >drivers/gpu/drm/i915/Makefile | 1 + > > > >drivers/gpu/drm/i915/gt/intel_gt.c| 3 ++ > > > >drivers/gpu/drm/i915/gt/intel_gt_pm.c | 8 > > > >.../gpu/drm/i915/gt/intel_gt_pm_unpark_work.c | 35 > > > >.../gpu/drm/i915/gt/intel_gt_pm_unpark_work.h | 40 > > > > +++ > > > >drivers/gpu/drm/i915/gt/intel_gt_types.h | 10 + > > > >drivers/gpu/drm/i915/gt/uc/intel_guc.h| 8 ++-- > > > >.../gpu/drm/i915/gt/uc/intel_guc_submission.c | 15 +-- > > > >drivers/gpu/drm/i915/intel_wakeref.c | 5 +++ > > > >drivers/gpu/drm/i915/intel_wakeref.h | 1 + > > > >10 files changed, 119 insertions(+), 7 deletions(-) > > > >create mode 100644 drivers/gpu/drm/i915/gt/intel_gt_pm_unpark_work.c > > > >create mode 100644 drivers/gpu/drm/i915/gt/intel_gt_pm_unpark_work.h > > > > > > > > diff --git a/drivers/gpu/drm/i915/Makefile > > > > b/drivers/gpu/drm/i915/Makefile > > > > index 642a5b5a1b81..579bdc069f25 100644 > > > > --- a/drivers/gpu/drm/i915/Makefile > > > > +++ b/drivers/gpu/drm/i915/Makefile > > > > @@ -103,6 +103,7 @@ gt-y += \ > > > > gt/intel_gt_clock_utils.o \ > > > > gt/intel_gt_irq.o \ > > > > gt/intel_gt_pm.o \ > > > > + gt/intel_gt_pm_unpark_work.o \ > > > > gt/intel_gt_pm_irq.o \ > > > > gt/intel_gt_requests.o \ > > > > gt/intel_gtt.o \ > > > > diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c > > > > b/drivers/gpu/drm/i915/gt/intel_gt.c > > > > index 62d40c986642..7e690e74baa2 100644 > > > > --- a/drivers/gpu/drm/i915/gt/intel_gt.c > > > > +++ b/drivers/gpu/drm/i915/gt/intel_gt.c > > > > @@ -29,6 +29,9 @@ void intel_gt_init_early(struct intel_gt *gt, struct > > > > drm_i915_private *i915) > > > > spin_lock_init(>irq_lock); > > >
[PATCH] drm/sun4i: dw-hdmi: Fix HDMI PHY clock setup
Recent rework, which made HDMI PHY driver a platform device, inadvertely reversed clock setup order. HW is very touchy about it. Proper way is to handle controllers resets and clocks first and HDMI PHYs second. Currently, without this fix, first mode set completely fails (nothing on HDMI monitor) on H3 era PHYs. On H6, it still somehow work. Move HDMI PHY reset & clocks handling to sun8i_hdmi_phy_init() which will assure that code is executed after controllers reset & clocks are handled. Additionally, add sun8i_hdmi_phy_deinit() which will deinit them at controllers driver unload. Tested on A64, H3, H6 and R40. Fixes: 9bf3797796f5 ("drm/sun4i: dw-hdmi: Make HDMI PHY into a platform device") Signed-off-by: Jernej Skrabec --- drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 7 +- drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 4 +- drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 97 ++ 3 files changed, 61 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c index f75fb157f2ff..5fa5407ac583 100644 --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c @@ -216,11 +216,13 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, goto err_disable_clk_tmds; } + ret = sun8i_hdmi_phy_init(hdmi->phy); + if (ret) + return ret; + drm_encoder_helper_add(encoder, _dw_hdmi_encoder_helper_funcs); drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); - sun8i_hdmi_phy_init(hdmi->phy); - plat_data->mode_valid = hdmi->quirks->mode_valid; plat_data->use_drm_infoframe = hdmi->quirks->use_drm_infoframe; sun8i_hdmi_phy_set_ops(hdmi->phy, plat_data); @@ -262,6 +264,7 @@ static void sun8i_dw_hdmi_unbind(struct device *dev, struct device *master, struct sun8i_dw_hdmi *hdmi = dev_get_drvdata(dev); dw_hdmi_unbind(hdmi->hdmi); + sun8i_hdmi_phy_deinit(hdmi->phy); clk_disable_unprepare(hdmi->clk_tmds); reset_control_assert(hdmi->rst_ctrl); gpiod_set_value(hdmi->ddc_en, 0); diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h index 74f6ed0e2570..bffe1b9cd3dc 100644 --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h @@ -169,6 +169,7 @@ struct sun8i_hdmi_phy { struct clk *clk_phy; struct clk *clk_pll0; struct clk *clk_pll1; + struct device *dev; unsigned intrcal; struct regmap *regs; struct reset_control*rst_phy; @@ -205,7 +206,8 @@ encoder_to_sun8i_dw_hdmi(struct drm_encoder *encoder) int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct device_node *node); -void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy); +int sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy); +void sun8i_hdmi_phy_deinit(struct sun8i_hdmi_phy *phy); void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy, struct dw_hdmi_plat_data *plat_data); diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c index c9239708d398..78b152973957 100644 --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c @@ -506,9 +506,60 @@ static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy *phy) phy->rcal = (val & SUN8I_HDMI_PHY_ANA_STS_RCAL_MASK) >> 2; } -void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy) +int sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy) { + int ret; + + ret = reset_control_deassert(phy->rst_phy); + if (ret) { + dev_err(phy->dev, "Cannot deassert phy reset control: %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(phy->clk_bus); + if (ret) { + dev_err(phy->dev, "Cannot enable bus clock: %d\n", ret); + goto err_deassert_rst_phy; + } + + ret = clk_prepare_enable(phy->clk_mod); + if (ret) { + dev_err(phy->dev, "Cannot enable mod clock: %d\n", ret); + goto err_disable_clk_bus; + } + + if (phy->variant->has_phy_clk) { + ret = sun8i_phy_clk_create(phy, phy->dev, + phy->variant->has_second_pll); + if (ret) { + dev_err(phy->dev, "Couldn't create the PHY clock\n"); + goto err_disable_clk_mod; + } + + clk_prepare_enable(phy->clk_phy); + } + phy->variant->phy_init(phy); + + return 0; + +err_disable_clk_mod: + clk_disable_unprepare(phy->clk_mod); +err_disable_clk_bus: + clk_disable_unprepare(phy->clk_bus); +err_deassert_rst_phy: + reset_control_assert(phy->rst_phy); + + return
Re: [Intel-gfx] [PATCH 04/27] drm/i915/guc: Take GT PM ref when deregistering context
On Mon, Sep 13, 2021 at 10:55:59AM +0100, Tvrtko Ursulin wrote: > > On 20/08/2021 23:44, Matthew Brost wrote: > > Taking a PM reference to prevent intel_gt_wait_for_idle from short > > circuiting while a deregister context H2G is in flight. > > > > FIXME: Move locking / structure changes into different patch > > > > Signed-off-by: Matthew Brost > > --- > > drivers/gpu/drm/i915/gt/intel_context.c | 2 + > > drivers/gpu/drm/i915/gt/intel_context_types.h | 13 +- > > drivers/gpu/drm/i915/gt/intel_engine_pm.h | 5 + > > drivers/gpu/drm/i915/gt/intel_gt_pm.h | 13 ++ > > .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 1 + > > drivers/gpu/drm/i915/gt/uc/intel_guc.h| 46 ++-- > > .../gpu/drm/i915/gt/uc/intel_guc_debugfs.c| 13 +- > > .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 212 +++--- > > 8 files changed, 199 insertions(+), 106 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/gt/intel_context.c > > b/drivers/gpu/drm/i915/gt/intel_context.c > > index adfe49b53b1b..c8595da64ad8 100644 > > --- a/drivers/gpu/drm/i915/gt/intel_context.c > > +++ b/drivers/gpu/drm/i915/gt/intel_context.c > > @@ -399,6 +399,8 @@ intel_context_init(struct intel_context *ce, struct > > intel_engine_cs *engine) > > ce->guc_id.id = GUC_INVALID_LRC_ID; > > INIT_LIST_HEAD(>guc_id.link); > > + INIT_LIST_HEAD(>destroyed_link); > > + > > /* > > * Initialize fence to be complete as this is expected to be complete > > * unless there is a pending schedule disable outstanding. > > diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h > > b/drivers/gpu/drm/i915/gt/intel_context_types.h > > index 80bbdc7810f6..fd338a30617e 100644 > > --- a/drivers/gpu/drm/i915/gt/intel_context_types.h > > +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h > > @@ -190,22 +190,29 @@ struct intel_context { > > /** > > * @id: unique handle which is used to communicate information > > * with the GuC about this context, protected by > > -* guc->contexts_lock > > +* guc->submission_state.lock > > */ > > u16 id; > > /** > > * @ref: the number of references to the guc_id, when > > * transitioning in and out of zero protected by > > -* guc->contexts_lock > > +* guc->submission_state.lock > > */ > > atomic_t ref; > > /** > > * @link: in guc->guc_id_list when the guc_id has no refs but is > > -* still valid, protected by guc->contexts_lock > > +* still valid, protected by guc->submission_state.lock > > */ > > struct list_head link; > > } guc_id; > > + /** > > +* @destroyed_link: link in guc->submission_state.destroyed_contexts, in > > +* list when context is pending to be destroyed (deregistered with the > > +* GuC), protected by guc->submission_state.lock > > +*/ > > + struct list_head destroyed_link; > > + > > #ifdef CONFIG_DRM_I915_SELFTEST > > /** > > * @drop_schedule_enable: Force drop of schedule enable G2H for selftest > > diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.h > > b/drivers/gpu/drm/i915/gt/intel_engine_pm.h > > index 70ea46d6cfb0..17a5028ea177 100644 > > --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.h > > +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.h > > @@ -16,6 +16,11 @@ intel_engine_pm_is_awake(const struct intel_engine_cs > > *engine) > > return intel_wakeref_is_active(>wakeref); > > } > > +static inline void __intel_engine_pm_get(struct intel_engine_cs *engine) > > +{ > > + __intel_wakeref_get(>wakeref); > > +} > > + > > static inline void intel_engine_pm_get(struct intel_engine_cs *engine) > > { > > intel_wakeref_get(>wakeref); > > diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.h > > b/drivers/gpu/drm/i915/gt/intel_gt_pm.h > > index d0588d8aaa44..a17bf0d4592b 100644 > > --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.h > > +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.h > > @@ -41,6 +41,19 @@ static inline void intel_gt_pm_put_async(struct intel_gt > > *gt) > > intel_wakeref_put_async(>wakeref); > > } > > +#define with_intel_gt_pm(gt, tmp) \ > > + for (tmp = 1, intel_gt_pm_get(gt); tmp; \ > > +intel_gt_pm_put(gt), tmp = 0) > > +#define with_intel_gt_pm_async(gt, tmp) \ > > + for (tmp = 1, intel_gt_pm_get(gt); tmp; \ > > +intel_gt_pm_put_async(gt), tmp = 0) > > +#define with_intel_gt_pm_if_awake(gt, tmp) \ > > + for (tmp = intel_gt_pm_get_if_awake(gt); tmp; \ > > +intel_gt_pm_put(gt), tmp = 0) > > +#define with_intel_gt_pm_if_awake_async(gt, tmp) \ > > + for (tmp = intel_gt_pm_get_if_awake(gt); tmp; \ > > +intel_gt_pm_put_async(gt), tmp = 0) > > + > > static inline int intel_gt_pm_wait_for_idle(struct intel_gt *gt) > > { > > return intel_wakeref_wait_for_idle(>wakeref); > > diff --git
Re: [Intel-gfx] [PATCH 07/27] drm/i915/guc: Don't call switch_to_kernel_context with GuC submission
On Thu, Sep 09, 2021 at 03:51:27PM -0700, John Harrison wrote: > On 8/20/2021 15:44, Matthew Brost wrote: > > Calling switch_to_kernel_context isn't needed if the engine PM reference > > is taken while all contexts are pinned. By not calling > > switch_to_kernel_context we save on issuing a request to the engine. > I thought the intention of the switch_to_kernel was to ensure that the GPU > is not touching any user context and is basically idle. That is not a valid > assumption with an external scheduler such as GuC. So why is the description > above only mentioning PM references? What is the connection between the PM > ref and the switch_to_kernel? > > Also, the comment in the code does not mention anything about PM references, > it just says 'not necessary with GuC' but no explanation at all. > > > > v2: > > (Daniel Vetter) > >- Add FIXME comment about pushing switch_to_kernel_context to backend > > > > Signed-off-by: Matthew Brost > > Reviewed-by: Daniel Vetter > > --- > > drivers/gpu/drm/i915/gt/intel_engine_pm.c | 9 + > > 1 file changed, 9 insertions(+) > > > > diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c > > b/drivers/gpu/drm/i915/gt/intel_engine_pm.c > > index 1f07ac4e0672..11fee66daf60 100644 > > --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c > > +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c > > @@ -162,6 +162,15 @@ static bool switch_to_kernel_context(struct > > intel_engine_cs *engine) > > unsigned long flags; > > bool result = true; > > + /* > > +* No need to switch_to_kernel_context if GuC submission > > +* > > +* FIXME: This execlists specific backend behavior in generic code, this > "This execlists" -> "This is execlist" > > "this should be" -> "it should be" > Missed this. Will fix in next rev. Matt > John. > > > +* should be pushed to the backend. > > +*/ > > + if (intel_engine_uses_guc(engine)) > > + return true; > > + > > /* GPU is pointing to the void, as good as in the kernel context. */ > > if (intel_gt_is_wedged(engine->gt)) > > return true; >
Re: [Intel-gfx] [PATCH 07/27] drm/i915/guc: Don't call switch_to_kernel_context with GuC submission
On Thu, Sep 09, 2021 at 03:51:27PM -0700, John Harrison wrote: > On 8/20/2021 15:44, Matthew Brost wrote: > > Calling switch_to_kernel_context isn't needed if the engine PM reference > > is taken while all contexts are pinned. By not calling > > switch_to_kernel_context we save on issuing a request to the engine. > I thought the intention of the switch_to_kernel was to ensure that the GPU > is not touching any user context and is basically idle. That is not a valid > assumption with an external scheduler such as GuC. So why is the description > above only mentioning PM references? What is the connection between the PM > ref and the switch_to_kernel? > > Also, the comment in the code does not mention anything about PM references, > it just says 'not necessary with GuC' but no explanation at all. > Yea, this need to be explained better. How about this? Calling switch_to_kernel_context isn't needed if the engine PM reference is take while all user contexts have scheduling enabled. Once scheduling is disabled on all user contexts the GuC is guaranteed to not touch any user context state which is effectively the same pointing to a kernel context. Matt > > > v2: > > (Daniel Vetter) > >- Add FIXME comment about pushing switch_to_kernel_context to backend > > > > Signed-off-by: Matthew Brost > > Reviewed-by: Daniel Vetter > > --- > > drivers/gpu/drm/i915/gt/intel_engine_pm.c | 9 + > > 1 file changed, 9 insertions(+) > > > > diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c > > b/drivers/gpu/drm/i915/gt/intel_engine_pm.c > > index 1f07ac4e0672..11fee66daf60 100644 > > --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c > > +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c > > @@ -162,6 +162,15 @@ static bool switch_to_kernel_context(struct > > intel_engine_cs *engine) > > unsigned long flags; > > bool result = true; > > + /* > > +* No need to switch_to_kernel_context if GuC submission > > +* > > +* FIXME: This execlists specific backend behavior in generic code, this > "This execlists" -> "This is execlist" > > "this should be" -> "it should be" > > John. > > > +* should be pushed to the backend. > > +*/ > > + if (intel_engine_uses_guc(engine)) > > + return true; > > + > > /* GPU is pointing to the void, as good as in the kernel context. */ > > if (intel_gt_is_wedged(engine->gt)) > > return true; >
Re: [Intel-gfx] [PATCH 08/27] drm/i915: Add logical engine mapping
On Mon, Sep 13, 2021 at 10:24:43AM +0100, Tvrtko Ursulin wrote: > > On 10/09/2021 20:49, Matthew Brost wrote: > > On Fri, Sep 10, 2021 at 12:12:42PM +0100, Tvrtko Ursulin wrote: > > > > > > On 20/08/2021 23:44, Matthew Brost wrote: > > > > Add logical engine mapping. This is required for split-frame, as > > > > workloads need to be placed on engines in a logically contiguous manner. > > > > > > > > v2: > > > >(Daniel Vetter) > > > > - Add kernel doc for new fields > > > > > > > > Signed-off-by: Matthew Brost > > > > --- > > > >drivers/gpu/drm/i915/gt/intel_engine_cs.c | 60 > > > > --- > > > >drivers/gpu/drm/i915/gt/intel_engine_types.h | 5 ++ > > > >.../drm/i915/gt/intel_execlists_submission.c | 1 + > > > >drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 2 +- > > > >.../gpu/drm/i915/gt/uc/intel_guc_submission.c | 21 +-- > > > >5 files changed, 60 insertions(+), 29 deletions(-) > > > > > > > > diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c > > > > b/drivers/gpu/drm/i915/gt/intel_engine_cs.c > > > > index 0d9105a31d84..4d790f9a65dd 100644 > > > > --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c > > > > +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c > > > > @@ -290,7 +290,8 @@ static void nop_irq_handler(struct intel_engine_cs > > > > *engine, u16 iir) > > > > GEM_DEBUG_WARN_ON(iir); > > > >} > > > > -static int intel_engine_setup(struct intel_gt *gt, enum > > > > intel_engine_id id) > > > > +static int intel_engine_setup(struct intel_gt *gt, enum > > > > intel_engine_id id, > > > > + u8 logical_instance) > > > >{ > > > > const struct engine_info *info = _engines[id]; > > > > struct drm_i915_private *i915 = gt->i915; > > > > @@ -334,6 +335,7 @@ static int intel_engine_setup(struct intel_gt *gt, > > > > enum intel_engine_id id) > > > > engine->class = info->class; > > > > engine->instance = info->instance; > > > > + engine->logical_mask = BIT(logical_instance); > > > > __sprint_engine_name(engine); > > > > engine->props.heartbeat_interval_ms = > > > > @@ -572,6 +574,37 @@ static intel_engine_mask_t init_engine_mask(struct > > > > intel_gt *gt) > > > > return info->engine_mask; > > > >} > > > > +static void populate_logical_ids(struct intel_gt *gt, u8 *logical_ids, > > > > +u8 class, const u8 *map, u8 > > > > num_instances) > > > > +{ > > > > + int i, j; > > > > + u8 current_logical_id = 0; > > > > + > > > > + for (j = 0; j < num_instances; ++j) { > > > > + for (i = 0; i < ARRAY_SIZE(intel_engines); ++i) { > > > > + if (!HAS_ENGINE(gt, i) || > > > > + intel_engines[i].class != class) > > > > + continue; > > > > + > > > > + if (intel_engines[i].instance == map[j]) { > > > > + logical_ids[intel_engines[i].instance] = > > > > + current_logical_id++; > > > > + break; > > > > + } > > > > + } > > > > + } > > > > +} > > > > + > > > > +static void setup_logical_ids(struct intel_gt *gt, u8 *logical_ids, u8 > > > > class) > > > > +{ > > > > + int i; > > > > + u8 map[MAX_ENGINE_INSTANCE + 1]; > > > > + > > > > + for (i = 0; i < MAX_ENGINE_INSTANCE + 1; ++i) > > > > + map[i] = i; > > > > > > What's the point of the map array since it is 1:1 with instance? > > > > > > > Future products do not have a 1 to 1 mapping and that mapping can change > > based on fusing, e.g. XeHP SDV. > > > > Also technically ICL / TGL / ADL physical instance 2 maps to logical > > instance 1. > > I don't follow the argument. All I can see is that "map[i] = i" always in > the proposed code, which is then used to check "instance == map[instance]". > So I'd suggest to remove this array from the code until there is a need for > it. > Ok, this logic is slightly confusing and makes more sense once we have non-standard mappings. Yes, map is setup in a 1 to 1 mapping by default with the value in map[i] being a physical instance. Populate_logical_ids searches the map finding all physical instances present in the map assigning each found instance a new logical id increasing by 1 each time. e.g. If the map is setup 0-N and only physical instance 0 / 2 are present they will get logical mapping 0 / 1 respectfully. This algorithm works for non-standard mappings too /w fused parts. e.g. on XeHP SDV the map is: { 0, 2, 4, 6, 1, 3, 5, 7 } and if any of the physical instances can't be found due to fusing the logical mapping is still correct per the bspec. This array is absolutely needed for multi-lrc submission to work, even on ICL / TGL / ADL as the GuC only supports logically contiguous engine instances. > > > > +