[PATCH] drm/v3d: fix wait for TMU write combiner flush

2021-09-13 Thread Iago Toral Quiroga
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Dave Airlie
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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.

2021-09-13 Thread imran . f . khan




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.

2021-09-13 Thread Imran Khan
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.

2021-09-13 Thread Imran Khan
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

2021-09-13 Thread Randy Dunlap

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

2021-09-13 Thread Stephen Boyd
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.

2021-09-13 Thread kernel test robot

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

2021-09-13 Thread kernel test robot
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

2021-09-13 Thread Quan, Evan
[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

2021-09-13 Thread kernel test robot
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

2021-09-13 Thread Gurchetan Singh
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

2021-09-13 Thread Stephen Boyd
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Stephen Boyd
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Doug Anderson
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

2021-09-13 Thread Vivek Kasireddy
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

2021-09-13 Thread Vivek Kasireddy
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

2021-09-13 Thread Vivek Kasireddy
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

2021-09-13 Thread Vivek Kasireddy
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

2021-09-13 Thread Vivek Kasireddy
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

2021-09-13 Thread Vivek Kasireddy
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

2021-09-13 Thread Vivek Kasireddy
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

2021-09-13 Thread Doug Anderson
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

2021-09-13 Thread Chun-Kuang Hu
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

2021-09-13 Thread John Harrison

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

2021-09-13 Thread John Harrison

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

2021-09-13 Thread John Harrison

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

2021-09-13 Thread John Harrison

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

2021-09-13 Thread Philip Chen
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

2021-09-13 Thread Philip Chen
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

2021-09-13 Thread Philip Chen
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

2021-09-13 Thread Philip Chen
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

2021-09-13 Thread Rob Herring
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread John . C . Harrison
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

2021-09-13 Thread Harry Wentland



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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread bugzilla-daemon
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

2021-09-13 Thread bugzilla-daemon
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

2021-09-13 Thread bugzilla-daemon
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

2021-09-13 Thread Sam Ravnborg
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

2021-09-13 Thread Haiyang Zhang



> -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

2021-09-13 Thread Vasily Khoruzhick
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

2021-09-13 Thread Sean Paul
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

2021-09-13 Thread Jason Gunthorpe
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

2021-09-13 Thread Doug Anderson
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

2021-09-13 Thread Chia-I Wu
.

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

2021-09-13 Thread Dexuan Cui
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

2021-09-13 Thread Matthew Auld
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

2021-09-13 Thread Matthew Auld
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

2021-09-13 Thread Matthew Auld
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

2021-09-13 Thread Matthew Auld
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

2021-09-13 Thread Matthew Auld
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

2021-09-13 Thread Matthew Auld
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

2021-09-13 Thread Matthew Auld
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

2021-09-13 Thread Matthew Auld
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

2021-09-13 Thread Alex Deucher
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

2021-09-13 Thread Sean Paul
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

2021-09-13 Thread Sean Paul
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

2021-09-13 Thread Sean Paul
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

2021-09-13 Thread Sean Paul
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

2021-09-13 Thread Sean Paul
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

2021-09-13 Thread Sean Paul
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

2021-09-13 Thread Sean Paul
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

2021-09-13 Thread Sean Paul
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

2021-09-13 Thread Sean Paul
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

2021-09-13 Thread Sean Paul
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

2021-09-13 Thread Sean Paul
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

2021-09-13 Thread Sean Paul
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

2021-09-13 Thread Sean Paul
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()

2021-09-13 Thread Sean Paul
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

2021-09-13 Thread Sean Paul
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

2021-09-13 Thread Nathan Chancellor
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

2021-09-13 Thread Gurchetan Singh
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Jernej Skrabec
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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

2021-09-13 Thread Matthew Brost
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.

> > > > +   

  1   2   >