Re: EPOLL for drm_syncfile (was Re: [PATCH 4/4] RFC: dma-buf: Add an API for importing sync files (v6))

2021-05-24 Thread Daniel Vetter
On Sun, May 23, 2021 at 11:34 PM Daniel Stone  wrote:
>
> Hi Christian,
>
> On Sun, 23 May 2021 at 18:16, Christian König  
> wrote:
> > Am 22.05.21 um 22:05 schrieb Daniel Stone:
> > > Anyway, the problem with syncobj is that the ioctl to wait for a
> > > sync_file to materialise for a given timeline point only allows us to
> > > block with a timeout; this is a non-starter, because we need something
> > > which fits into epoll. The most optimal case is returning a new
> > > eventfd or similar which signals when a given timeline point becomes
> > > available or signaled, but in extremis a syncobj FD becoming readable
> > > when any activity which would change the result of any zero-timeout
> > > wait on that syncobj is more or less workable.
> >
> > I think the tricky part is to epoll for a certain value.
> >
> > Not sure how eventfd is supposed to work, but IIRC we don't have the
> > functionality to poll for a certain value/offset etc to become available.
> >
> > We could of course create a separate fd for each requested value to poll
> > for thought, but that sounds like a bit much overhead to me.
>
> Yeah, I understand the point; something like an eventfd is exactly
> what you think, that we would have to materialise a new FD for it. On
> the other hand, as soon as the sync point becomes available, the
> winsys will want to immediately extract a sync_file from it, so I
> don't think FD amplification is a big issue. If it looks like being a
> problem in practice, we could look at providing a FD which starts off
> inert, and only later becomes a sync_file after it polls readable, but
> that sounds like something we really want to avoid if we can.

We can't change personalities of filp in the kernel because there's no
locking for that. But we can add a future fence state to sync_file for
this, and then make sure sync_file_get_fence() fails on them as long
as the fence hasn't materialized. That's required because current uapi
is that sync_file is never a future fence. Also opens the door for
that, which might be useful for all our userspace fences ideas.

Then we could support poll on that sync_file to wait for the fence to
materialize using POLLPRI. man poll suggests this isn't the dumbest
thing to go with, and grep in the kernel shows plenty of users (it's
EPOLLPRI internally).

With this we'd just need a new flag for allowing this mode in
sync_handle_to_fd_ioctl, and a fairly small amount of typing to glue
it together.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


[PATCH v4 15/17] drm/i915/pxp: Add plane decryption support

2021-05-24 Thread Daniele Ceraolo Spurio
From: Anshuman Gupta 

Add support to enable/disable PLANE_SURF Decryption Request bit.
It requires only to enable plane decryption support when following
condition met.
1. PXP session is enabled.
2. Buffer object is protected.

v2:
- Used gen fb obj user_flags instead gem_object_metadata. [Krishna]

v3:
- intel_pxp_gem_object_status() API changes.

v4: use intel_pxp_is_active (Daniele)

v5: rebase and use the new protected object status checker (Daniele)

v6: used plane state for plane_decryption to handle async flip
as suggested by Ville.

v7: check pxp session while plane decrypt state computation. [Ville]
removed pointless code. [Ville]

v8 (Daniele): update PXP check

Cc: Bommu Krishnaiah 
Cc: Huang Sean Z 
Cc: Gaurav Kumar 
Cc: Ville Syrjälä 
Signed-off-by: Anshuman Gupta 
Signed-off-by: Daniele Ceraolo Spurio 
---
 .../gpu/drm/i915/display/intel_atomic_plane.c| 16 
 drivers/gpu/drm/i915/display/intel_display.c |  4 
 .../gpu/drm/i915/display/intel_display_types.h   |  3 +++
 .../gpu/drm/i915/display/skl_universal_plane.c   | 15 ---
 drivers/gpu/drm/i915/i915_reg.h  |  1 +
 5 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c 
b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
index 36f52a1d7552..88b3272c0b00 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
@@ -41,6 +41,7 @@
 #include "intel_display_types.h"
 #include "intel_pm.h"
 #include "intel_sprite.h"
+#include "pxp/intel_pxp.h"
 
 static void intel_plane_state_reset(struct intel_plane_state *plane_state,
struct intel_plane *plane)
@@ -383,6 +384,14 @@ intel_crtc_get_plane(struct intel_crtc *crtc, enum 
plane_id plane_id)
return NULL;
 }
 
+static int bo_has_valid_encryption(const struct drm_i915_gem_object *obj)
+{
+   struct drm_i915_private *i915 = to_i915(obj->base.dev);
+
+   return i915_gem_object_has_valid_protection(obj) &&
+  intel_pxp_is_active(>gt.pxp);
+}
+
 int intel_plane_atomic_check(struct intel_atomic_state *state,
 struct intel_plane *plane)
 {
@@ -397,6 +406,7 @@ int intel_plane_atomic_check(struct intel_atomic_state 
*state,
intel_atomic_get_old_crtc_state(state, crtc);
struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
+   const struct drm_framebuffer *fb;
 
if (new_crtc_state && new_crtc_state->bigjoiner_slave) {
struct intel_plane *master_plane =
@@ -413,6 +423,12 @@ int intel_plane_atomic_check(struct intel_atomic_state 
*state,
  new_master_plane_state,
  crtc);
 
+   fb = new_plane_state->hw.fb;
+   if (fb)
+   new_plane_state->decrypt = 
bo_has_valid_encryption(intel_fb_obj(fb));
+   else
+   new_plane_state->decrypt = old_plane_state->decrypt;
+
new_plane_state->uapi.visible = false;
if (!new_crtc_state)
return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 0bb2e582c87f..f7f5374114ad 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -9767,6 +9767,10 @@ static int intel_atomic_check_async(struct 
intel_atomic_state *state)
drm_dbg_kms(>drm, "Color range cannot be changed 
in async flip\n");
return -EINVAL;
}
+
+   /* plane decryption is allow to change only in synchronous 
flips */
+   if (old_plane_state->decrypt != new_plane_state->decrypt)
+   return -EINVAL;
}
 
return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index ce05475ad560..6b5dab9e1c40 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -621,6 +621,9 @@ struct intel_plane_state {
 
struct intel_fb_view view;
 
+   /* Plane pxp decryption state */
+   bool decrypt;
+
/* plane control register */
u32 ctl;
 
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c 
b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index 59e032f3687a..2c8e88e8ad83 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -18,6 +18,7 @@
 #include "intel_sprite.h"
 #include "skl_scaler.h"
 #include "skl_universal_plane.h"
+#include "pxp/intel_pxp.h"
 
 static const u32 skl_plane_formats[] = {
DRM_FORMAT_C8,
@@ -997,7 +998,7 @@ skl_program_plane(struct intel_plane *plane,
u8 alpha = plane_state->hw.alpha >> 8;
u32 

[PATCH v4 16/17] drm/i915/pxp: black pixels on pxp disabled

2021-05-24 Thread Daniele Ceraolo Spurio
From: Anshuman Gupta 

When protected sufaces has flipped and pxp session is disabled,
display black pixels by using plane color CTM correction.

v2:
- Display black pixels in async flip too.

v3:
- Removed the black pixels logic for async flip. [Ville]
- Used plane state to force black pixels. [Ville]

v4 (Daniele): update pxp_is_borked check.

Cc: Ville Syrjälä 
Cc: Gaurav Kumar 
Cc: Shankar Uma 
Signed-off-by: Anshuman Gupta 
Signed-off-by: Daniele Ceraolo Spurio 
---
 .../gpu/drm/i915/display/intel_atomic_plane.c | 13 +-
 .../drm/i915/display/intel_display_types.h|  3 ++
 .../drm/i915/display/skl_universal_plane.c| 36 ++-
 drivers/gpu/drm/i915/i915_reg.h   | 46 +++
 4 files changed, 95 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c 
b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
index 88b3272c0b00..44d7a5072090 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
@@ -392,6 +392,11 @@ static int bo_has_valid_encryption(const struct 
drm_i915_gem_object *obj)
   intel_pxp_is_active(>gt.pxp);
 }
 
+static bool pxp_is_borked(const struct drm_i915_gem_object *obj)
+{
+   return i915_gem_object_is_protected(obj) && 
!bo_has_valid_encryption(obj);
+}
+
 int intel_plane_atomic_check(struct intel_atomic_state *state,
 struct intel_plane *plane)
 {
@@ -424,10 +429,14 @@ int intel_plane_atomic_check(struct intel_atomic_state 
*state,
  crtc);
 
fb = new_plane_state->hw.fb;
-   if (fb)
+   if (fb) {
new_plane_state->decrypt = 
bo_has_valid_encryption(intel_fb_obj(fb));
-   else
+   new_plane_state->force_black = pxp_is_borked(intel_fb_obj(fb));
+
+   } else {
new_plane_state->decrypt = old_plane_state->decrypt;
+   new_plane_state->force_black = old_plane_state->force_black;
+   }
 
new_plane_state->uapi.visible = false;
if (!new_crtc_state)
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 6b5dab9e1c40..88c0b882b844 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -624,6 +624,9 @@ struct intel_plane_state {
/* Plane pxp decryption state */
bool decrypt;
 
+   /* Plane state to display black pixels when pxp is borked */
+   bool force_black;
+
/* plane control register */
u32 ctl;
 
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c 
b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index 2c8e88e8ad83..d4eb43b96ffd 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -975,6 +975,33 @@ static u32 skl_surf_address(const struct intel_plane_state 
*plane_state,
}
 }
 
+static void intel_load_plane_csc_black(struct intel_plane *intel_plane)
+{
+   struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
+   enum pipe pipe = intel_plane->pipe;
+   enum plane_id plane = intel_plane->id;
+   u16 postoff = 0;
+
+   drm_dbg_kms(_priv->drm, "plane color CTM to black  %s:%d\n",
+   intel_plane->base.name, plane);
+   intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 0), 0);
+   intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 1), 0);
+
+   intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 2), 0);
+   intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 3), 0);
+
+   intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 4), 0);
+   intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 5), 0);
+
+   intel_de_write_fw(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 0), 0);
+   intel_de_write_fw(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 1), 0);
+   intel_de_write_fw(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 2), 0);
+
+   intel_de_write_fw(dev_priv, PLANE_CSC_POSTOFF(pipe, plane, 0), postoff);
+   intel_de_write_fw(dev_priv, PLANE_CSC_POSTOFF(pipe, plane, 1), postoff);
+   intel_de_write_fw(dev_priv, PLANE_CSC_POSTOFF(pipe, plane, 2), postoff);
+}
+
 static void
 skl_program_plane(struct intel_plane *plane,
  const struct intel_crtc_state *crtc_state,
@@ -1088,14 +1115,21 @@ skl_program_plane(struct intel_plane *plane,
 */
intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
plane_surf = intel_plane_ggtt_offset(plane_state) + surf_addr;
+   plane_color_ctl = intel_de_read_fw(dev_priv, PLANE_COLOR_CTL(pipe, 
plane_id));
 
/*
 * FIXME: pxp session invalidation can hit any time even at time of 
commit
 * or after the commit, display content will be garbage.
 */
-   if (plane_state->decrypt)
+   if 

[PATCH v4 17/17] drm/i915/pxp: enable PXP for integrated Gen12

2021-05-24 Thread Daniele Ceraolo Spurio
Note that discrete cards can support PXP as well, but we haven't tested
on those yet so keeping it disabled for now.

Signed-off-by: Daniele Ceraolo Spurio 
Reviewed-by: Rodrigo Vivi 
---
 drivers/gpu/drm/i915/i915_pci.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index 97c98f4fb265..23f249797ad8 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -884,6 +884,7 @@ static const struct intel_device_info jsl_info = {
}, \
TGL_CURSOR_OFFSETS, \
.has_global_mocs = 1, \
+   .has_pxp = 1, \
.display.has_dsb = 1
 
 static const struct intel_device_info tgl_info = {
@@ -911,6 +912,7 @@ static const struct intel_device_info rkl_info = {
.memory_regions = REGION_SMEM | REGION_LMEM | REGION_STOLEN_LMEM, \
.has_master_unit_irq = 1, \
.has_llc = 0, \
+   .has_pxp = 0, \
.has_snoop = 1, \
.is_dgfx = 1
 
-- 
2.29.2



[PATCH v4 14/17] drm/i915/pxp: User interface for Protected buffer

2021-05-24 Thread Daniele Ceraolo Spurio
From: Bommu Krishnaiah 

This api allow user mode to create Protected buffers. Only contexts
marked as protected are allowed to operate on protected buffers.

We only allow setting the flags at creation time.

All protected objects that have backing storage will be considered
invalid when the session is destroyed and they won't be usable anymore.

Given that the PXP HW supports multiple modes (but we currently only
care about one), a flag variable has been reserved in the structure
used in the create_ext ioctl for possible future updates.

This is a rework of the original code by Bommu Krishnaiah. I've kept
authorship unchanged since significant chunks have not been modified.

v2: split context changes, fix defines and improve documentation (Chris),
add object invalidation logic
v3: fix spinlock definition and usage, only validate objects when
they're first added to a context lut, only remove them once (Chris),
make protected context flag not mandatory in protected object execbuf
to avoid abuse (Lionel)
v4: rebase to new gem_create_ext

Signed-off-by: Bommu Krishnaiah 
Signed-off-by: Daniele Ceraolo Spurio 
Cc: Telukuntla Sreedhar 
Cc: Kondapally Kalyan 
Cc: Gupta Anshuman 
Cc: Huang Sean Z 
Cc: Chris Wilson 
Cc: Lionel Landwerlin 
Cc: Jason Ekstrand 
Cc: Daniel Vetter 
---
 drivers/gpu/drm/i915/gem/i915_gem_create.c| 26 
 .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 15 +++
 drivers/gpu/drm/i915/gem/i915_gem_object.c|  6 +++
 drivers/gpu/drm/i915/gem/i915_gem_object.h| 12 ++
 .../gpu/drm/i915/gem/i915_gem_object_types.h  | 13 ++
 drivers/gpu/drm/i915/pxp/intel_pxp.c  | 41 +++
 drivers/gpu/drm/i915/pxp/intel_pxp.h  | 13 ++
 drivers/gpu/drm/i915/pxp/intel_pxp_types.h|  5 +++
 include/uapi/drm/i915_drm.h   | 33 ++-
 9 files changed, 163 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_create.c 
b/drivers/gpu/drm/i915/gem/i915_gem_create.c
index 548ddf39d853..c14be3882c35 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_create.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_create.c
@@ -6,6 +6,7 @@
 #include "gem/i915_gem_ioctls.h"
 #include "gem/i915_gem_lmem.h"
 #include "gem/i915_gem_region.h"
+#include "pxp/intel_pxp.h"
 
 #include "i915_drv.h"
 #include "i915_trace.h"
@@ -99,7 +100,11 @@ i915_gem_setup(struct drm_i915_gem_object *obj, u64 size)
 
GEM_BUG_ON(size != obj->base.size);
 
+   if (obj->user_flags & I915_GEM_OBJECT_PROTECTED)
+   intel_pxp_object_add(obj);
+
trace_i915_gem_object_create(obj);
+
return 0;
 }
 
@@ -344,8 +349,29 @@ static int ext_set_placements(struct i915_user_extension 
__user *base,
return set_placements(, data);
 }
 
+static int ext_set_protected(struct i915_user_extension __user *base, void 
*data)
+{
+   struct drm_i915_gem_create_ext_protected_content ext;
+   struct create_ext *ext_data = data;
+
+   if (copy_from_user(, base, sizeof(ext)))
+   return -EFAULT;
+
+   if (ext.flags)
+   return -EINVAL;
+
+   if (!intel_pxp_is_enabled(_data->i915->gt.pxp))
+   return -ENODEV;
+
+   ext_data->vanilla_object->user_flags |= I915_GEM_OBJECT_PROTECTED;
+
+   return 0;
+}
+
+
 static const i915_user_extension_fn create_extensions[] = {
[I915_GEM_CREATE_EXT_MEMORY_REGIONS] = ext_set_placements,
+   [I915_GEM_CREATE_EXT_PROTECTED_CONTENT] = ext_set_protected,
 };
 
 /**
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index c08e28847064..5dd813d04a9f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -839,6 +839,21 @@ static struct i915_vma *eb_lookup_vma(struct 
i915_execbuffer *eb, u32 handle)
if (unlikely(!obj))
return ERR_PTR(-ENOENT);
 
+   /*
+* If the user has opted-in for protected-object tracking, make
+* sure the object encryption can be used.
+* We only need to do this when the object is first used with
+* this context, because the context itself will be banned when
+* the protected objects become invalid.
+*/
+   if (i915_gem_context_uses_protected_content(eb->gem_context) &&
+   i915_gem_object_is_protected(obj)) {
+   if (!intel_pxp_is_active(>gt->pxp))
+   return ERR_PTR(-ENODEV);
+   if (!i915_gem_object_has_valid_protection(obj))
+   return ERR_PTR(-ENOEXEC);
+   }
+
vma = i915_vma_instance(obj, vm, NULL);
if (IS_ERR(vma)) {
i915_gem_object_put(obj);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c 

[PATCH v4 12/17] drm/i915/pxp: start the arb session on demand

2021-05-24 Thread Daniele Ceraolo Spurio
Now that we can handle destruction and re-creation of the arb session,
we can postpone the start of the session to the first submission that
requires it, to avoid keeping it running with no user.

Signed-off-by: Daniele Ceraolo Spurio 
---
 .../gpu/drm/i915/gem/i915_gem_execbuffer.c|  8 ++--
 drivers/gpu/drm/i915/pxp/intel_pxp.c  | 37 ---
 drivers/gpu/drm/i915/pxp/intel_pxp.h  |  4 +-
 drivers/gpu/drm/i915/pxp/intel_pxp_irq.c  |  2 +-
 drivers/gpu/drm/i915/pxp/intel_pxp_session.c  |  6 +--
 drivers/gpu/drm/i915/pxp/intel_pxp_tee.c  | 10 +
 drivers/gpu/drm/i915/pxp/intel_pxp_types.h|  3 ++
 7 files changed, 39 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index a11e9d5767bf..c08e28847064 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -2948,9 +2948,11 @@ eb_select_engine(struct i915_execbuffer *eb)
intel_gt_pm_get(ce->engine->gt);
 
if (i915_gem_context_uses_protected_content(eb->gem_context)) {
-   err = intel_pxp_wait_for_arb_start(>engine->gt->pxp);
-   if (err)
-   goto err;
+   if (!intel_pxp_is_active(>engine->gt->pxp)) {
+   err = intel_pxp_start(>engine->gt->pxp);
+   if (err)
+   goto err;
+   }
 
if (i915_gem_context_invalidated(eb->gem_context)) {
err = -EACCES;
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp.c
index f713d3423cea..2291c68fd3a0 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c
@@ -77,6 +77,7 @@ void intel_pxp_init(struct intel_pxp *pxp)
init_completion(>termination);
complete_all(>termination);
 
+   mutex_init(>arb_mutex);
INIT_WORK(>session_work, intel_pxp_session_work);
 
ret = create_vcs_context(pxp);
@@ -113,7 +114,7 @@ void intel_pxp_mark_termination_in_progress(struct 
intel_pxp *pxp)
reinit_completion(>termination);
 }
 
-static void intel_pxp_queue_termination(struct intel_pxp *pxp)
+static void pxp_queue_termination(struct intel_pxp *pxp)
 {
struct intel_gt *gt = pxp_to_gt(pxp);
 
@@ -132,31 +133,41 @@ static void intel_pxp_queue_termination(struct intel_pxp 
*pxp)
  * the arb session is restarted from the irq work when we receive the
  * termination completion interrupt
  */
-int intel_pxp_wait_for_arb_start(struct intel_pxp *pxp)
+int intel_pxp_start(struct intel_pxp *pxp)
 {
+   int ret = 0;
+
if (!intel_pxp_is_enabled(pxp))
-   return 0;
+   return -ENODEV;
+
+   mutex_lock(>arb_mutex);
+
+   if (pxp->arb_is_valid)
+   goto unlock;
+
+   pxp_queue_termination(pxp);
 
if (!wait_for_completion_timeout(>termination,
-msecs_to_jiffies(100)))
-   return -ETIMEDOUT;
+   msecs_to_jiffies(100))) {
+   ret = -ETIMEDOUT;
+   goto unlock;
+   }
+
+   /* make sure the compiler doesn't optimize the double access */
+   barrier();
 
if (!pxp->arb_is_valid)
-   return -EIO;
+   ret = -EIO;
 
-   return 0;
+unlock:
+   mutex_unlock(>arb_mutex);
+   return ret;
 }
 
 void intel_pxp_init_hw(struct intel_pxp *pxp)
 {
kcr_pxp_enable(pxp_to_gt(pxp));
intel_pxp_irq_enable(pxp);
-
-   /*
-* the session could've been attacked while we weren't loaded, so
-* handle it as if it was and re-create it.
-*/
-   intel_pxp_queue_termination(pxp);
 }
 
 void intel_pxp_fini_hw(struct intel_pxp *pxp)
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.h 
b/drivers/gpu/drm/i915/pxp/intel_pxp.h
index 91c1a2056309..1f9871e64096 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.h
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.h
@@ -32,7 +32,7 @@ void intel_pxp_init_hw(struct intel_pxp *pxp);
 void intel_pxp_fini_hw(struct intel_pxp *pxp);
 
 void intel_pxp_mark_termination_in_progress(struct intel_pxp *pxp);
-int intel_pxp_wait_for_arb_start(struct intel_pxp *pxp);
+int intel_pxp_start(struct intel_pxp *pxp);
 void intel_pxp_invalidate(struct intel_pxp *pxp);
 #else
 static inline void intel_pxp_init(struct intel_pxp *pxp)
@@ -43,7 +43,7 @@ static inline void intel_pxp_fini(struct intel_pxp *pxp)
 {
 }
 
-static inline int intel_pxp_wait_for_arb_start(struct intel_pxp *pxp)
+static inline int intel_pxp_start(struct intel_pxp *pxp)
 {
return 0;
 }
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_irq.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp_irq.c
index 196449243515..a230d0034e50 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_irq.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_irq.c
@@ -31,7 +31,7 @@ void 

[PATCH v4 11/17] drm/i915/pxp: interface for marking contexts as using protected content

2021-05-24 Thread Daniele Ceraolo Spurio
Extra tracking and checks around protected objects, coming in a follow-up
patch, will be enabled only for contexts that opt in. Contexts can only be
marked as using protected content at creation time and they must be both
bannable and not recoverable.

When a PXP teardown occurs, all gem contexts marked this way that
have been used at least once will be marked as invalid and all new
submissions using them will be rejected. All intel contexts within the
invalidated gem contexts will be marked banned.
A new flag has been added to the RESET_STATS ioctl to report the
invalidation to userspace.

v2: split to its own patch and improve doc (Chris), invalidate contexts
on teardown

v3: improve doc, use -EACCES for execbuf fail (Chris), make protected
context flag not mandatory in protected object execbuf to avoid
abuse (Lionel)

Signed-off-by: Daniele Ceraolo Spurio 
Cc: Chris Wilson 
Cc: Lionel Landwerlin 
Cc: Jason Ekstrand 
Cc: Daniel Vetter 
---
 drivers/gpu/drm/i915/gem/i915_gem_context.c   | 59 ++-
 drivers/gpu/drm/i915/gem/i915_gem_context.h   | 18 ++
 .../gpu/drm/i915/gem/i915_gem_context_types.h |  2 +
 .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 18 ++
 drivers/gpu/drm/i915/pxp/intel_pxp.c  | 48 +++
 drivers/gpu/drm/i915/pxp/intel_pxp.h  |  1 +
 drivers/gpu/drm/i915/pxp/intel_pxp_session.c  |  3 +
 include/uapi/drm/i915_drm.h   | 26 
 8 files changed, 172 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c 
b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index 188dee13e017..11b67f1f6e96 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -76,6 +76,8 @@
 #include "gt/intel_gpu_commands.h"
 #include "gt/intel_ring.h"
 
+#include "pxp/intel_pxp.h"
+
 #include "i915_gem_context.h"
 #include "i915_globals.h"
 #include "i915_trace.h"
@@ -1971,6 +1973,40 @@ static int set_priority(struct i915_gem_context *ctx,
return 0;
 }
 
+static int set_protected(struct i915_gem_context *ctx,
+const struct drm_i915_gem_context_param *args)
+{
+   int ret = 0;
+
+   if (!intel_pxp_is_enabled(>i915->gt.pxp))
+   ret = -ENODEV;
+   else if (ctx->file_priv) /* can't change this after creation! */
+   ret = -EEXIST;
+   else if (args->size)
+   ret = -EINVAL;
+   else if (!args->value)
+   clear_bit(UCONTEXT_PROTECTED, >user_flags);
+   else if (i915_gem_context_is_recoverable(ctx) ||
+!i915_gem_context_is_bannable(ctx))
+   ret = -EPERM;
+   else
+   set_bit(UCONTEXT_PROTECTED, >user_flags);
+
+   return ret;
+}
+
+static int get_protected(struct i915_gem_context *ctx,
+struct drm_i915_gem_context_param *args)
+{
+   if (!intel_pxp_is_enabled(>i915->gt.pxp))
+   return -ENODEV;
+
+   args->size = 0;
+   args->value = i915_gem_context_uses_protected_content(ctx);
+
+   return 0;
+}
+
 static int ctx_setparam(struct drm_i915_file_private *fpriv,
struct i915_gem_context *ctx,
struct drm_i915_gem_context_param *args)
@@ -2003,6 +2039,8 @@ static int ctx_setparam(struct drm_i915_file_private 
*fpriv,
ret = -EPERM;
else if (args->value)
i915_gem_context_set_bannable(ctx);
+   else if (i915_gem_context_uses_protected_content(ctx))
+   ret = -EPERM; /* can't clear this for protected 
contexts */
else
i915_gem_context_clear_bannable(ctx);
break;
@@ -2010,10 +2048,12 @@ static int ctx_setparam(struct drm_i915_file_private 
*fpriv,
case I915_CONTEXT_PARAM_RECOVERABLE:
if (args->size)
ret = -EINVAL;
-   else if (args->value)
-   i915_gem_context_set_recoverable(ctx);
-   else
+   else if (!args->value)
i915_gem_context_clear_recoverable(ctx);
+   else if (i915_gem_context_uses_protected_content(ctx))
+   ret = -EPERM; /* can't set this for protected contexts 
*/
+   else
+   i915_gem_context_set_recoverable(ctx);
break;
 
case I915_CONTEXT_PARAM_PRIORITY:
@@ -2040,6 +2080,10 @@ static int ctx_setparam(struct drm_i915_file_private 
*fpriv,
ret = set_ringsize(ctx, args);
break;
 
+   case I915_CONTEXT_PARAM_PROTECTED_CONTENT:
+   ret = set_protected(ctx, args);
+   break;
+
case I915_CONTEXT_PARAM_BAN_PERIOD:
default:
ret = -EINVAL;
@@ -2493,6 +2537,10 @@ int i915_gem_context_getparam_ioctl(struct drm_device 
*dev, void *data,
ret = get_ringsize(ctx, 

[PATCH v4 13/17] drm/i915/pxp: Enable PXP power management

2021-05-24 Thread Daniele Ceraolo Spurio
From: "Huang, Sean Z" 

During the power event S3+ sleep/resume, hardware will lose all the
encryption keys for every hardware session, even though the
session state might still be marked as alive after resume. Therefore,
we should consider the session as dead on suspend and invalidate all the
objects. The session will be automatically restarted on the first
protected submission on resume.

v2: runtime suspend also invalidates the keys
v3: fix return codes, simplify rpm ops (Chris), use the new worker func
v4: invalidate the objects on suspend, don't re-create the arb sesson on
resume (delayed to first submission).

Signed-off-by: Huang, Sean Z 
Signed-off-by: Daniele Ceraolo Spurio 
Cc: Chris Wilson 
Cc: Rodrigo Vivi 
---
 drivers/gpu/drm/i915/Makefile|  1 +
 drivers/gpu/drm/i915/gt/intel_gt_pm.c| 15 +++-
 drivers/gpu/drm/i915/i915_drv.c  |  2 +
 drivers/gpu/drm/i915/pxp/intel_pxp_irq.c | 11 --
 drivers/gpu/drm/i915/pxp/intel_pxp_pm.c  | 40 
 drivers/gpu/drm/i915/pxp/intel_pxp_pm.h  | 23 +++
 drivers/gpu/drm/i915/pxp/intel_pxp_session.c | 38 ++-
 drivers/gpu/drm/i915/pxp/intel_pxp_tee.c |  9 +
 8 files changed, 124 insertions(+), 15 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_pm.c
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_pm.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 29331bbb3e98..9cce0bf9a50f 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -278,6 +278,7 @@ i915-$(CONFIG_DRM_I915_PXP) += \
pxp/intel_pxp.o \
pxp/intel_pxp_cmd.o \
pxp/intel_pxp_irq.o \
+   pxp/intel_pxp_pm.o \
pxp/intel_pxp_session.o \
pxp/intel_pxp_tee.o
 
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c 
b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
index aef3084e8b16..91151a02f7a2 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
@@ -19,6 +19,7 @@
 #include "intel_rc6.h"
 #include "intel_rps.h"
 #include "intel_wakeref.h"
+#include "pxp/intel_pxp_pm.h"
 
 static void user_forcewake(struct intel_gt *gt, bool suspend)
 {
@@ -265,6 +266,8 @@ int intel_gt_resume(struct intel_gt *gt)
 
intel_uc_resume(>uc);
 
+   intel_pxp_resume(>pxp);
+
user_forcewake(gt, false);
 
 out_fw:
@@ -299,6 +302,7 @@ void intel_gt_suspend_prepare(struct intel_gt *gt)
user_forcewake(gt, true);
wait_for_suspend(gt);
 
+   intel_pxp_suspend(>pxp);
intel_uc_suspend(>uc);
 }
 
@@ -349,6 +353,7 @@ void intel_gt_suspend_late(struct intel_gt *gt)
 
 void intel_gt_runtime_suspend(struct intel_gt *gt)
 {
+   intel_pxp_suspend(>pxp);
intel_uc_runtime_suspend(>uc);
 
GT_TRACE(gt, "\n");
@@ -356,11 +361,19 @@ void intel_gt_runtime_suspend(struct intel_gt *gt)
 
 int intel_gt_runtime_resume(struct intel_gt *gt)
 {
+   int ret;
+
GT_TRACE(gt, "\n");
intel_gt_init_swizzling(gt);
intel_ggtt_restore_fences(gt->ggtt);
 
-   return intel_uc_runtime_resume(>uc);
+   ret = intel_uc_runtime_resume(>uc);
+   if (ret)
+   return ret;
+
+   intel_pxp_resume(>pxp);
+
+   return 0;
 }
 
 static ktime_t __intel_gt_get_awake_time(const struct intel_gt *gt)
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 2f06bb7b3ed2..6543e5577709 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -68,6 +68,8 @@
 #include "gt/intel_gt_pm.h"
 #include "gt/intel_rc6.h"
 
+#include "pxp/intel_pxp_pm.h"
+
 #include "i915_debugfs.h"
 #include "i915_drv.h"
 #include "i915_ioc32.h"
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_irq.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp_irq.c
index a230d0034e50..9e5847c653f2 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_irq.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_irq.c
@@ -9,6 +9,7 @@
 #include "gt/intel_gt_irq.h"
 #include "i915_irq.h"
 #include "i915_reg.h"
+#include "intel_runtime_pm.h"
 
 /**
  * intel_pxp_irq_handler - Handles PXP interrupts.
@@ -62,11 +63,13 @@ void intel_pxp_irq_enable(struct intel_pxp *pxp)
struct intel_gt *gt = pxp_to_gt(pxp);
 
spin_lock_irq(>irq_lock);
-   if (!pxp->irq_enabled) {
+
+   if (!pxp->irq_enabled)
WARN_ON_ONCE(gen11_gt_reset_one_iir(gt, 0, GEN11_KCR));
-   __pxp_set_interrupts(gt, GEN12_PXP_INTERRUPTS);
-   pxp->irq_enabled = true;
-   }
+
+   __pxp_set_interrupts(gt, GEN12_PXP_INTERRUPTS);
+   pxp->irq_enabled = true;
+
spin_unlock_irq(>irq_lock);
 }
 
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_pm.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp_pm.c
new file mode 100644
index ..400b3a9944c8
--- /dev/null
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_pm.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright(c) 2020 Intel Corporation.
+ */
+

[PATCH v4 09/17] drm/i915/pxp: Implement arb session teardown

2021-05-24 Thread Daniele Ceraolo Spurio
From: "Huang, Sean Z" 

Teardown is triggered when the display topology changes and no
long meets the secure playback requirement, and hardware trashes
all the encryption keys for display. Additionally, we want to emit a
teardown operation to make sure we're clean on boot and resume

v2: emit in the ring, use high prio request (Chris)
v3: better defines, stalling flush, cleaned up and renamed submission
funcs (Chris)

Signed-off-by: Huang, Sean Z 
Signed-off-by: Daniele Ceraolo Spurio 
Cc: Chris Wilson 
Reviewed-by: Rodrigo Vivi 
---
 drivers/gpu/drm/i915/Makefile|   1 +
 drivers/gpu/drm/i915/gt/intel_gpu_commands.h |  22 ++-
 drivers/gpu/drm/i915/pxp/intel_pxp.c |   7 +-
 drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c | 140 +++
 drivers/gpu/drm/i915/pxp/intel_pxp_cmd.h |  15 ++
 drivers/gpu/drm/i915/pxp/intel_pxp_session.c |  29 
 drivers/gpu/drm/i915/pxp/intel_pxp_session.h |   1 +
 7 files changed, 211 insertions(+), 4 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_cmd.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 739510549545..0fba97014512 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -276,6 +276,7 @@ i915-y += i915_perf.o
 # Protected execution platform (PXP) support
 i915-$(CONFIG_DRM_I915_PXP) += \
pxp/intel_pxp.o \
+   pxp/intel_pxp_cmd.o \
pxp/intel_pxp_session.o \
pxp/intel_pxp_tee.o
 
diff --git a/drivers/gpu/drm/i915/gt/intel_gpu_commands.h 
b/drivers/gpu/drm/i915/gt/intel_gpu_commands.h
index 2694dbb9967e..2eda14ea0162 100644
--- a/drivers/gpu/drm/i915/gt/intel_gpu_commands.h
+++ b/drivers/gpu/drm/i915/gt/intel_gpu_commands.h
@@ -28,10 +28,13 @@
 #define INSTR_26_TO_24_MASK0x700
 #define   INSTR_26_TO_24_SHIFT 24
 
+#define __INSTR(client) ((client) << INSTR_CLIENT_SHIFT)
+
 /*
  * Memory interface instructions used by the kernel
  */
-#define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags))
+#define MI_INSTR(opcode, flags) \
+   (__INSTR(INSTR_MI_CLIENT) | (opcode) << 23 | (flags))
 /* Many MI commands use bit 22 of the header dword for GGTT vs PPGTT */
 #define  MI_GLOBAL_GTT(1<<22)
 
@@ -57,6 +60,7 @@
 #define MI_SUSPEND_FLUSH   MI_INSTR(0x0b, 0)
 #define   MI_SUSPEND_FLUSH_EN  (1<<0)
 #define MI_SET_APPID   MI_INSTR(0x0e, 0)
+#define   MI_SET_APPID_SESSION_ID(x)   ((x) << 0)
 #define MI_OVERLAY_FLIPMI_INSTR(0x11, 0)
 #define   MI_OVERLAY_CONTINUE  (0x0<<21)
 #define   MI_OVERLAY_ON(0x1<<21)
@@ -144,6 +148,7 @@
 #define MI_STORE_REGISTER_MEM_GEN8   MI_INSTR(0x24, 2)
 #define   MI_SRM_LRM_GLOBAL_GTT(1<<22)
 #define MI_FLUSH_DWMI_INSTR(0x26, 1) /* for GEN6 */
+#define   MI_FLUSH_DW_PROTECTED_MEM_EN (1<<22)
 #define   MI_FLUSH_DW_STORE_INDEX  (1<<21)
 #define   MI_INVALIDATE_TLB(1<<18)
 #define   MI_FLUSH_DW_OP_STOREDW   (1<<14)
@@ -270,6 +275,19 @@
 #define   MI_MATH_REG_ZF   0x32
 #define   MI_MATH_REG_CF   0x33
 
+/*
+ * Media instructions used by the kernel
+ */
+#define MEDIA_INSTR(pipe, op, sub_op, flags) \
+   (__INSTR(INSTR_RC_CLIENT) | (pipe) << INSTR_SUBCLIENT_SHIFT | \
+   (op) << INSTR_26_TO_24_SHIFT | (sub_op) << 16 | (flags))
+
+#define MFX_WAIT   MEDIA_INSTR(1, 0, 0, 0)
+#define  MFX_WAIT_DW0_MFX_SYNC_CONTROL_FLAGREG_BIT(8)
+#define  MFX_WAIT_DW0_PXP_SYNC_CONTROL_FLAGREG_BIT(9)
+
+#define CRYPTO_KEY_EXCHANGEMEDIA_INSTR(2, 6, 9, 0)
+
 /*
  * Commands used only by the command parser
  */
@@ -326,8 +344,6 @@
 #define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS \
((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x47<<16))
 
-#define MFX_WAIT  ((0x3<<29)|(0x1<<27)|(0x0<<16))
-
 #define COLOR_BLT ((0x2<<29)|(0x40<<22))
 #define SRC_COPY_BLT  ((0x2<<29)|(0x43<<22))
 
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp.c
index 4e30e5e98522..e48debb5ca22 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c
@@ -96,9 +96,14 @@ void intel_pxp_fini(struct intel_pxp *pxp)
 
 void intel_pxp_init_hw(struct intel_pxp *pxp)
 {
+   int ret;
+
kcr_pxp_enable(pxp_to_gt(pxp));
 
-   intel_pxp_create_arb_session(pxp);
+   /* always emit a full termination to clean the state */
+   ret = intel_pxp_terminate_arb_session_and_global(pxp);
+   if (!ret)
+   intel_pxp_create_arb_session(pxp);
 }
 
 void intel_pxp_fini_hw(struct intel_pxp *pxp)
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c
new file mode 100644
index ..c577f1fbee55
--- /dev/null
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright(c) 2020, Intel Corporation. All rights reserved.
+ */
+

[PATCH v4 10/17] drm/i915/pxp: Implement PXP irq handler

2021-05-24 Thread Daniele Ceraolo Spurio
From: "Huang, Sean Z" 

The HW will generate a teardown interrupt when session termination is
required, which requires i915 to submit a terminating batch. Once the HW
is done with the termination it will generate another interrupt, at
which point it is safe to re-create the session.

Since the termination and re-creation flow is something we want to
trigger from the driver as well, use a common work function that can be
called both from the irq handler and from the driver set-up flows, which
has the addded benefit of allowing us to skip any extra locks because
the work itself serializes the operations.

v2: use struct completion instead of bool (Chris)
v3: drop locks, clean up functions and improve comments (Chris),
move to common work function.
v4: improve comments, simplify wait logic (Rodrigo)

Signed-off-by: Huang, Sean Z 
Signed-off-by: Daniele Ceraolo Spurio 
Cc: Chris Wilson 
Cc: Rodrigo Vivi 
---
 drivers/gpu/drm/i915/Makefile|  1 +
 drivers/gpu/drm/i915/gt/intel_gt_irq.c   |  7 ++
 drivers/gpu/drm/i915/i915_reg.h  |  1 +
 drivers/gpu/drm/i915/pxp/intel_pxp.c | 66 +++--
 drivers/gpu/drm/i915/pxp/intel_pxp.h |  8 ++
 drivers/gpu/drm/i915/pxp/intel_pxp_irq.c | 97 
 drivers/gpu/drm/i915/pxp/intel_pxp_irq.h | 32 +++
 drivers/gpu/drm/i915/pxp/intel_pxp_session.c | 54 ++-
 drivers/gpu/drm/i915/pxp/intel_pxp_session.h |  5 +-
 drivers/gpu/drm/i915/pxp/intel_pxp_tee.c |  8 +-
 drivers/gpu/drm/i915/pxp/intel_pxp_types.h   | 18 
 11 files changed, 281 insertions(+), 16 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_irq.c
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_irq.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 0fba97014512..29331bbb3e98 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -277,6 +277,7 @@ i915-y += i915_perf.o
 i915-$(CONFIG_DRM_I915_PXP) += \
pxp/intel_pxp.o \
pxp/intel_pxp_cmd.o \
+   pxp/intel_pxp_irq.o \
pxp/intel_pxp_session.o \
pxp/intel_pxp_tee.o
 
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c 
b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
index 9fc6c912a4e5..7c4ec8880b1a 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
@@ -13,6 +13,7 @@
 #include "intel_lrc_reg.h"
 #include "intel_uncore.h"
 #include "intel_rps.h"
+#include "pxp/intel_pxp_irq.h"
 
 static void guc_irq_handler(struct intel_guc *guc, u16 iir)
 {
@@ -106,6 +107,9 @@ gen11_other_irq_handler(struct intel_gt *gt, const u8 
instance,
if (instance == OTHER_GTPM_INSTANCE)
return gen11_rps_irq_handler(>rps, iir);
 
+   if (instance == OTHER_KCR_INSTANCE)
+   return intel_pxp_irq_handler(>pxp, iir);
+
WARN_ONCE(1, "unhandled other interrupt instance=0x%x, iir=0x%x\n",
  instance, iir);
 }
@@ -232,6 +236,9 @@ void gen11_gt_irq_reset(struct intel_gt *gt)
intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_MASK,  ~0);
intel_uncore_write(uncore, GEN11_GUC_SG_INTR_ENABLE, 0);
intel_uncore_write(uncore, GEN11_GUC_SG_INTR_MASK,  ~0);
+
+   intel_uncore_write(uncore, GEN11_CRYPTO_RSVD_INTR_ENABLE, 0);
+   intel_uncore_write(uncore, GEN11_CRYPTO_RSVD_INTR_MASK,  ~0);
 }
 
 void gen11_gt_irq_postinstall(struct intel_gt *gt)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 4dbe79009c0e..297671d78076 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -8023,6 +8023,7 @@ enum {
 /* irq instances for OTHER_CLASS */
 #define OTHER_GUC_INSTANCE 0
 #define OTHER_GTPM_INSTANCE1
+#define OTHER_KCR_INSTANCE 4
 
 #define GEN11_INTR_IDENTITY_REG(x) _MMIO(0x190060 + ((x) * 4))
 
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp.c
index e48debb5ca22..6b0e7170c29b 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c
@@ -2,7 +2,9 @@
 /*
  * Copyright(c) 2020 Intel Corporation.
  */
+#include 
 #include "intel_pxp.h"
+#include "intel_pxp_irq.h"
 #include "intel_pxp_session.h"
 #include "intel_pxp_tee.h"
 #include "gt/intel_context.h"
@@ -66,6 +68,16 @@ void intel_pxp_init(struct intel_pxp *pxp)
if (!HAS_PXP(gt->i915))
return;
 
+   /*
+* we'll use the completion to check if there is a termination pending,
+* so we start it as completed and we reinit it when a termination
+* is triggered.
+*/
+   init_completion(>termination);
+   complete_all(>termination);
+
+   INIT_WORK(>session_work, intel_pxp_session_work);
+
ret = create_vcs_context(pxp);
if (ret)
return;
@@ -94,19 +106,61 @@ void intel_pxp_fini(struct intel_pxp *pxp)
destroy_vcs_context(pxp);
 }
 
-void intel_pxp_init_hw(struct intel_pxp 

[PATCH v4 08/17] drm/i915/pxp: Create the arbitrary session after boot

2021-05-24 Thread Daniele Ceraolo Spurio
From: "Huang, Sean Z" 

Create the arbitrary session, with the fixed session id 0xf, after
system boot, for the case that application allocates the protected
buffer without establishing any protection session. Because the
hardware requires at least one alive session for protected buffer
creation. This arbitrary session will need to be re-created after
teardown or power event because hardware encryption key won't be
valid after such cases.

The session ID is exposed as part of the uapi so it can be used as part
of userspace commands.

v2: use gt->uncore->rpm (Chris)
v3: s/arb_is_in_play/arb_is_valid (Chris), move set-up to the new
init_hw function
v4: move interface defs to separate header, set arb_is valid to false
on fini (Rodrigo)

Signed-off-by: Huang, Sean Z 
Signed-off-by: Daniele Ceraolo Spurio 
Cc: Chris Wilson 
Cc: Rodrigo Vivi 
---
 drivers/gpu/drm/i915/Makefile |  1 +
 drivers/gpu/drm/i915/pxp/intel_pxp.c  |  5 ++
 drivers/gpu/drm/i915/pxp/intel_pxp.h  |  5 ++
 drivers/gpu/drm/i915/pxp/intel_pxp_session.c  | 74 +++
 drivers/gpu/drm/i915/pxp/intel_pxp_session.h  | 15 
 drivers/gpu/drm/i915/pxp/intel_pxp_tee.c  | 68 +
 drivers/gpu/drm/i915/pxp/intel_pxp_tee.h  |  3 +
 .../drm/i915/pxp/intel_pxp_tee_interface.h| 37 ++
 drivers/gpu/drm/i915/pxp/intel_pxp_types.h|  9 +++
 include/uapi/drm/i915_drm.h   |  3 +
 10 files changed, 220 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_session.c
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_session.h
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_tee_interface.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 0dfff52fea24..739510549545 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -276,6 +276,7 @@ i915-y += i915_perf.o
 # Protected execution platform (PXP) support
 i915-$(CONFIG_DRM_I915_PXP) += \
pxp/intel_pxp.o \
+   pxp/intel_pxp_session.o \
pxp/intel_pxp_tee.o
 
 # Post-mortem debug and GPU hang state capture
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp.c
index ab19d2a23ec2..4e30e5e98522 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c
@@ -3,6 +3,7 @@
  * Copyright(c) 2020 Intel Corporation.
  */
 #include "intel_pxp.h"
+#include "intel_pxp_session.h"
 #include "intel_pxp_tee.h"
 #include "gt/intel_context.h"
 #include "i915_drv.h"
@@ -86,6 +87,8 @@ void intel_pxp_fini(struct intel_pxp *pxp)
if (!intel_pxp_is_enabled(pxp))
return;
 
+   pxp->arb_is_valid = false;
+
intel_pxp_tee_component_fini(pxp);
 
destroy_vcs_context(pxp);
@@ -94,6 +97,8 @@ void intel_pxp_fini(struct intel_pxp *pxp)
 void intel_pxp_init_hw(struct intel_pxp *pxp)
 {
kcr_pxp_enable(pxp_to_gt(pxp));
+
+   intel_pxp_create_arb_session(pxp);
 }
 
 void intel_pxp_fini_hw(struct intel_pxp *pxp)
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.h 
b/drivers/gpu/drm/i915/pxp/intel_pxp.h
index 5427c3b28aa9..8eeb65af78b1 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.h
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.h
@@ -19,6 +19,11 @@ static inline bool intel_pxp_is_enabled(const struct 
intel_pxp *pxp)
return pxp->ce;
 }
 
+static inline bool intel_pxp_is_active(const struct intel_pxp *pxp)
+{
+   return pxp->arb_is_valid;
+}
+
 #ifdef CONFIG_DRM_I915_PXP
 void intel_pxp_init(struct intel_pxp *pxp);
 void intel_pxp_fini(struct intel_pxp *pxp);
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_session.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c
new file mode 100644
index ..3331868f354c
--- /dev/null
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright(c) 2020, Intel Corporation. All rights reserved.
+ */
+
+#include "drm/i915_drm.h"
+#include "i915_drv.h"
+
+#include "intel_pxp.h"
+#include "intel_pxp_session.h"
+#include "intel_pxp_tee.h"
+#include "intel_pxp_types.h"
+
+#define ARB_SESSION I915_PROTECTED_CONTENT_DEFAULT_SESSION /* shorter define */
+
+#define GEN12_KCR_SIP _MMIO(0x32260) /* KCR hwdrm session in play 0-31 */
+
+static bool intel_pxp_session_is_in_play(struct intel_pxp *pxp, u32 id)
+{
+   struct intel_gt *gt = pxp_to_gt(pxp);
+   intel_wakeref_t wakeref;
+   u32 sip = 0;
+
+   with_intel_runtime_pm(gt->uncore->rpm, wakeref)
+   sip = intel_uncore_read(gt->uncore, GEN12_KCR_SIP);
+
+   return sip & BIT(id);
+}
+
+static int pxp_wait_for_session_state(struct intel_pxp *pxp, u32 id, bool 
in_play)
+{
+   struct intel_gt *gt = pxp_to_gt(pxp);
+   intel_wakeref_t wakeref;
+   u32 mask = BIT(id);
+   int ret;
+
+   with_intel_runtime_pm(gt->uncore->rpm, wakeref)
+   ret = intel_wait_for_register(gt->uncore,
+ 

[PATCH v4 07/17] drm/i915/pxp: set KCR reg init

2021-05-24 Thread Daniele Ceraolo Spurio
The setting is required by hardware to allow us doing further protection
operation such as sending commands to GPU or TEE. The register needs to
be re-programmed on resume, so for simplicitly we bundle the programming
with the component binding, which is automatically called on resume.

Further HW set-up operations will be added in the same location in
follow-up patches, so get ready for them by using a couple of
init/fini_hw wrappers instead of calling the KCR funcs directly.

v3: move programming to component binding function, rework commit msg

Signed-off-by: Huang, Sean Z 
Signed-off-by: Daniele Ceraolo Spurio 
Reviewed-by: Rodrigo Vivi 
---
 drivers/gpu/drm/i915/pxp/intel_pxp.c | 27 
 drivers/gpu/drm/i915/pxp/intel_pxp.h |  3 +++
 drivers/gpu/drm/i915/pxp/intel_pxp_tee.c |  5 +
 3 files changed, 35 insertions(+)

diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp.c
index 5df2a09c9e4b..ab19d2a23ec2 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c
@@ -7,6 +7,24 @@
 #include "gt/intel_context.h"
 #include "i915_drv.h"
 
+/* KCR register definitions */
+#define KCR_INIT _MMIO(0x320f0)
+
+/* Setting KCR Init bit is required after system boot */
+#define KCR_INIT_ALLOW_DISPLAY_ME_WRITES REG_BIT(14)
+
+static void kcr_pxp_enable(struct intel_gt *gt)
+{
+   intel_uncore_write(gt->uncore, KCR_INIT,
+  
_MASKED_BIT_ENABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES));
+}
+
+static void kcr_pxp_disable(struct intel_gt *gt)
+{
+   intel_uncore_write(gt->uncore, KCR_INIT,
+  
_MASKED_BIT_DISABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES));
+}
+
 static int create_vcs_context(struct intel_pxp *pxp)
 {
static struct lock_class_key pxp_lock;
@@ -71,5 +89,14 @@ void intel_pxp_fini(struct intel_pxp *pxp)
intel_pxp_tee_component_fini(pxp);
 
destroy_vcs_context(pxp);
+}
+
+void intel_pxp_init_hw(struct intel_pxp *pxp)
+{
+   kcr_pxp_enable(pxp_to_gt(pxp));
+}
 
+void intel_pxp_fini_hw(struct intel_pxp *pxp)
+{
+   kcr_pxp_disable(pxp_to_gt(pxp));
 }
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.h 
b/drivers/gpu/drm/i915/pxp/intel_pxp.h
index e87550fb9821..5427c3b28aa9 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.h
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.h
@@ -22,6 +22,9 @@ static inline bool intel_pxp_is_enabled(const struct 
intel_pxp *pxp)
 #ifdef CONFIG_DRM_I915_PXP
 void intel_pxp_init(struct intel_pxp *pxp);
 void intel_pxp_fini(struct intel_pxp *pxp);
+
+void intel_pxp_init_hw(struct intel_pxp *pxp);
+void intel_pxp_fini_hw(struct intel_pxp *pxp);
 #else
 static inline void intel_pxp_init(struct intel_pxp *pxp)
 {
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
index 4ed234d8584f..dc0dcd040bf8 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
@@ -33,6 +33,9 @@ static int i915_pxp_tee_component_bind(struct device 
*i915_kdev,
pxp->pxp_component = data;
pxp->pxp_component->tee_dev = tee_kdev;
 
+   /* the component is required to fully start the PXP HW */
+   intel_pxp_init_hw(pxp);
+
return 0;
 }
 
@@ -41,6 +44,8 @@ static void i915_pxp_tee_component_unbind(struct device 
*i915_kdev,
 {
struct intel_pxp *pxp = i915_dev_to_pxp(i915_kdev);
 
+   intel_pxp_fini_hw(pxp);
+
pxp->pxp_component = NULL;
 }
 
-- 
2.29.2



[PATCH v4 06/17] drm/i915/pxp: Implement funcs to create the TEE channel

2021-05-24 Thread Daniele Ceraolo Spurio
From: "Huang, Sean Z" 

Implement the funcs to create the TEE channel, so kernel can
send the TEE commands directly to TEE for creating the arbitrary
(default) session.

v2: fix locking, don't pollute dev_priv (Chris)

v3: wait for mei PXP component to be bound.

Signed-off-by: Huang, Sean Z 
Signed-off-by: Daniele Ceraolo Spurio 
Cc: Chris Wilson 
Reviewed-by: Rodrigo Vivi  #v2
---
 drivers/gpu/drm/i915/Makefile  |  3 +-
 drivers/gpu/drm/i915/pxp/intel_pxp.c   | 13 
 drivers/gpu/drm/i915/pxp/intel_pxp_tee.c   | 87 ++
 drivers/gpu/drm/i915/pxp/intel_pxp_tee.h   | 14 
 drivers/gpu/drm/i915/pxp/intel_pxp_types.h |  3 +
 5 files changed, 119 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_tee.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index efd950122e40..0dfff52fea24 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -275,7 +275,8 @@ i915-y += i915_perf.o
 
 # Protected execution platform (PXP) support
 i915-$(CONFIG_DRM_I915_PXP) += \
-   pxp/intel_pxp.o
+   pxp/intel_pxp.o \
+   pxp/intel_pxp_tee.o
 
 # Post-mortem debug and GPU hang state capture
 i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp.c
index 3255c6da34e8..5df2a09c9e4b 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c
@@ -3,6 +3,7 @@
  * Copyright(c) 2020 Intel Corporation.
  */
 #include "intel_pxp.h"
+#include "intel_pxp_tee.h"
 #include "gt/intel_context.h"
 #include "i915_drv.h"
 
@@ -50,7 +51,16 @@ void intel_pxp_init(struct intel_pxp *pxp)
if (ret)
return;
 
+   ret = intel_pxp_tee_component_init(pxp);
+   if (ret)
+   goto out_context;
+
drm_info(>i915->drm, "Protected Xe Path (PXP) protected content 
support initialized\n");
+
+   return;
+
+out_context:
+   destroy_vcs_context(pxp);
 }
 
 void intel_pxp_fini(struct intel_pxp *pxp)
@@ -58,5 +68,8 @@ void intel_pxp_fini(struct intel_pxp *pxp)
if (!intel_pxp_is_enabled(pxp))
return;
 
+   intel_pxp_tee_component_fini(pxp);
+
destroy_vcs_context(pxp);
+
 }
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
new file mode 100644
index ..4ed234d8584f
--- /dev/null
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright(c) 2020 Intel Corporation.
+ */
+
+#include 
+#include "drm/i915_pxp_tee_interface.h"
+#include "drm/i915_component.h"
+#include "i915_drv.h"
+#include "intel_pxp.h"
+#include "intel_pxp_tee.h"
+
+static inline struct intel_pxp *i915_dev_to_pxp(struct device *i915_kdev)
+{
+   return _to_i915(i915_kdev)->gt.pxp;
+}
+
+/**
+ * i915_pxp_tee_component_bind - bind function to pass the function pointers 
to pxp_tee
+ * @i915_kdev: pointer to i915 kernel device
+ * @tee_kdev: pointer to tee kernel device
+ * @data: pointer to pxp_tee_master containing the function pointers
+ *
+ * This bind function is called during the system boot or resume from system 
sleep.
+ *
+ * Return: return 0 if successful.
+ */
+static int i915_pxp_tee_component_bind(struct device *i915_kdev,
+  struct device *tee_kdev, void *data)
+{
+   struct intel_pxp *pxp = i915_dev_to_pxp(i915_kdev);
+
+   pxp->pxp_component = data;
+   pxp->pxp_component->tee_dev = tee_kdev;
+
+   return 0;
+}
+
+static void i915_pxp_tee_component_unbind(struct device *i915_kdev,
+ struct device *tee_kdev, void *data)
+{
+   struct intel_pxp *pxp = i915_dev_to_pxp(i915_kdev);
+
+   pxp->pxp_component = NULL;
+}
+
+static const struct component_ops i915_pxp_tee_component_ops = {
+   .bind   = i915_pxp_tee_component_bind,
+   .unbind = i915_pxp_tee_component_unbind,
+};
+
+int intel_pxp_tee_component_init(struct intel_pxp *pxp)
+{
+   int ret;
+   struct intel_gt *gt = pxp_to_gt(pxp);
+   struct drm_i915_private *i915 = gt->i915;
+
+   ret = component_add_typed(i915->drm.dev, _pxp_tee_component_ops,
+ I915_COMPONENT_PXP);
+   if (ret < 0) {
+   drm_err(>drm, "Failed to add PXP component (%d)\n", ret);
+   return ret;
+   }
+
+   /*
+* Adding the component does not guarantee that it will bind properly,
+* so make sure to wait until it does.
+*/
+   ret = wait_for(pxp->pxp_component, 50);
+   if (ret) {
+   drm_err(>drm, "Failed to bind PXP component (%d)\n", ret);
+   return ret;
+   }
+
+   return 0;
+}
+
+void intel_pxp_tee_component_fini(struct intel_pxp *pxp)
+{
+   struct intel_gt *gt = pxp_to_gt(pxp);
+   

[PATCH v4 05/17] drm/i915/pxp: allocate a vcs context for pxp usage

2021-05-24 Thread Daniele Ceraolo Spurio
The context is required to send the session termination commands to the
VCS, which will be implemented in a follow-up patch. We can also use the
presence of the context as a check of pxp initialization completion.

v2: use perma-pinned context (Chris)
v3: rename pinned_context functions (Chris)
v4: split export of pinned_context functions to a separate patch (Rodrigo)

Signed-off-by: Daniele Ceraolo Spurio 
Cc: Chris Wilson 
---
 drivers/gpu/drm/i915/Makefile  |  4 ++
 drivers/gpu/drm/i915/gt/intel_engine.h |  2 +
 drivers/gpu/drm/i915/gt/intel_gt.c |  5 ++
 drivers/gpu/drm/i915/gt/intel_gt_types.h   |  3 ++
 drivers/gpu/drm/i915/pxp/intel_pxp.c   | 62 ++
 drivers/gpu/drm/i915/pxp/intel_pxp.h   | 35 
 drivers/gpu/drm/i915/pxp/intel_pxp_types.h | 15 ++
 7 files changed, 126 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp.c
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp.h
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_types.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 6947495bf34b..efd950122e40 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -273,6 +273,10 @@ i915-y += \
 
 i915-y += i915_perf.o
 
+# Protected execution platform (PXP) support
+i915-$(CONFIG_DRM_I915_PXP) += \
+   pxp/intel_pxp.o
+
 # Post-mortem debug and GPU hang state capture
 i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
 i915-$(CONFIG_DRM_I915_SELFTEST) += \
diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h 
b/drivers/gpu/drm/i915/gt/intel_engine.h
index a64d28aba257..903e498beb0b 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine.h
@@ -187,6 +187,8 @@ intel_write_status_page(struct intel_engine_cs *engine, int 
reg, u32 value)
 #define I915_GEM_HWS_PREEMPT_ADDR  (I915_GEM_HWS_PREEMPT * sizeof(u32))
 #define I915_GEM_HWS_SEQNO 0x40
 #define I915_GEM_HWS_SEQNO_ADDR(I915_GEM_HWS_SEQNO * 
sizeof(u32))
+#define I915_GEM_HWS_PXP   0x60
+#define I915_GEM_HWS_PXP_ADDR  (I915_GEM_HWS_PXP * sizeof(u32))
 #define I915_GEM_HWS_SCRATCH   0x80
 
 #define I915_HWS_CSB_BUF0_INDEX0x10
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c 
b/drivers/gpu/drm/i915/gt/intel_gt.c
index 8d77dcbad059..68f42fabc151 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -20,6 +20,7 @@
 #include "intel_uncore.h"
 #include "intel_pm.h"
 #include "shmem_utils.h"
+#include "pxp/intel_pxp.h"
 
 void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915)
 {
@@ -627,6 +628,8 @@ int intel_gt_init(struct intel_gt *gt)
if (err)
goto err_gt;
 
+   intel_pxp_init(>pxp);
+
goto out_fw;
 err_gt:
__intel_gt_disable(gt);
@@ -661,6 +664,8 @@ void intel_gt_driver_unregister(struct intel_gt *gt)
 
intel_rps_driver_unregister(>rps);
 
+   intel_pxp_fini(>pxp);
+
/*
 * Upon unregistering the device to prevent any new users, cancel
 * all in-flight requests so that we can quickly unbind the active
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h 
b/drivers/gpu/drm/i915/gt/intel_gt_types.h
index 0caf6ca0a784..53f44fd4a974 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h
@@ -25,6 +25,7 @@
 #include "intel_rc6_types.h"
 #include "intel_rps_types.h"
 #include "intel_wakeref.h"
+#include "pxp/intel_pxp_types.h"
 
 struct drm_i915_private;
 struct i915_ggtt;
@@ -148,6 +149,8 @@ struct intel_gt {
/* Slice/subslice/EU info */
struct sseu_dev_info sseu;
} info;
+
+   struct intel_pxp pxp;
 };
 
 enum intel_gt_scratch_field {
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp.c
new file mode 100644
index ..3255c6da34e8
--- /dev/null
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright(c) 2020 Intel Corporation.
+ */
+#include "intel_pxp.h"
+#include "gt/intel_context.h"
+#include "i915_drv.h"
+
+static int create_vcs_context(struct intel_pxp *pxp)
+{
+   static struct lock_class_key pxp_lock;
+   struct intel_gt *gt = pxp_to_gt(pxp);
+   struct intel_engine_cs *engine;
+   struct intel_context *ce;
+
+   /*
+* Find the first VCS engine present. We're guaranteed there is one
+* if we're in this function due to the check in has_pxp
+*/
+   for (engine = gt->engine_class[VIDEO_DECODE_CLASS][0]; !engine; 
engine++);
+   GEM_BUG_ON(!engine || engine->class != VIDEO_DECODE_CLASS);
+
+   ce = intel_engine_create_pinned_context(engine, NULL, SZ_4K,
+   I915_GEM_HWS_PXP_ADDR,
+   _lock, "pxp_context");
+   if 

[PATCH v4 04/17] drm/i915/gt: Export the pinned context constructor and destructor

2021-05-24 Thread Daniele Ceraolo Spurio
From: Chris Wilson 

Allow internal clients to create a pinned context.

v2 (Daniele): export destructor as well, allow optional usage of custom
vm for maximum flexibility.

Signed-off-by: Chris Wilson 
Signed-off-by: Daniele Ceraolo Spurio 
---
 drivers/gpu/drm/i915/gt/intel_engine.h| 10 
 drivers/gpu/drm/i915/gt/intel_engine_cs.c | 29 +++
 2 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h 
b/drivers/gpu/drm/i915/gt/intel_engine.h
index 47ee8578e511..a64d28aba257 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine.h
@@ -18,7 +18,9 @@
 #include "intel_workarounds.h"
 
 struct drm_printer;
+struct intel_context;
 struct intel_gt;
+struct lock_class_key;
 
 /* Early gen2 devices have a cacheline of just 32 bytes, using 64 is overkill,
  * but keeps the logic simple. Indeed, the whole purpose of this macro is just
@@ -255,6 +257,14 @@ struct i915_request *
 intel_engine_find_active_request(struct intel_engine_cs *engine);
 
 u32 intel_engine_context_size(struct intel_gt *gt, u8 class);
+struct intel_context *
+intel_engine_create_pinned_context(struct intel_engine_cs *engine,
+  struct i915_address_space *vm,
+  unsigned int ring_size,
+  unsigned int hwsp,
+  struct lock_class_key *key,
+  const char *name);
+void intel_engine_destroy_pinned_context(struct intel_context *ce);
 
 void intel_engine_init_active(struct intel_engine_cs *engine,
  unsigned int subclass);
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c 
b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index eba2da9679a5..8cbf11497e8e 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -801,11 +801,13 @@ intel_engine_init_active(struct intel_engine_cs *engine, 
unsigned int subclass)
 #endif
 }
 
-static struct intel_context *
-create_pinned_context(struct intel_engine_cs *engine,
- unsigned int hwsp,
- struct lock_class_key *key,
- const char *name)
+struct intel_context *
+intel_engine_create_pinned_context(struct intel_engine_cs *engine,
+  struct i915_address_space *vm,
+  unsigned int ring_size,
+  unsigned int hwsp,
+  struct lock_class_key *key,
+  const char *name)
 {
struct intel_context *ce;
int err;
@@ -816,6 +818,12 @@ create_pinned_context(struct intel_engine_cs *engine,
 
__set_bit(CONTEXT_BARRIER_BIT, >flags);
ce->timeline = page_pack_bits(NULL, hwsp);
+   ce->ring = __intel_context_ring_size(ring_size);
+
+   if (vm) {
+   i915_vm_put(ce->vm);
+   ce->vm = i915_vm_get(vm);
+   }
 
err = intel_context_pin(ce); /* perma-pin so it is always available */
if (err) {
@@ -834,7 +842,7 @@ create_pinned_context(struct intel_engine_cs *engine,
return ce;
 }
 
-static void destroy_pinned_context(struct intel_context *ce)
+void intel_engine_destroy_pinned_context(struct intel_context *ce)
 {
struct intel_engine_cs *engine = ce->engine;
struct i915_vma *hwsp = engine->status_page.vma;
@@ -854,8 +862,9 @@ create_kernel_context(struct intel_engine_cs *engine)
 {
static struct lock_class_key kernel;
 
-   return create_pinned_context(engine, I915_GEM_HWS_SEQNO_ADDR,
-, "kernel_context");
+   return intel_engine_create_pinned_context(engine, NULL, SZ_4K,
+ I915_GEM_HWS_SEQNO_ADDR,
+ , "kernel_context");
 }
 
 /**
@@ -898,7 +907,7 @@ static int engine_init_common(struct intel_engine_cs 
*engine)
return 0;
 
 err_context:
-   destroy_pinned_context(ce);
+   intel_engine_destroy_pinned_context(ce);
return ret;
 }
 
@@ -956,7 +965,7 @@ void intel_engine_cleanup_common(struct intel_engine_cs 
*engine)
fput(engine->default_state);
 
if (engine->kernel_context)
-   destroy_pinned_context(engine->kernel_context);
+   intel_engine_destroy_pinned_context(engine->kernel_context);
 
GEM_BUG_ON(!llist_empty(>barrier_tasks));
cleanup_status_page(engine);
-- 
2.29.2



[PATCH v4 03/17] drm/i915/pxp: define PXP device flag and kconfig

2021-05-24 Thread Daniele Ceraolo Spurio
Ahead of the PXP implementation, define the relevant define flag and
kconfig option.

v2: flip kconfig default to N. Some machines have IFWIs that do not
support PXP, so we need it to be an opt-in until we add support to query
the caps from the mei device.

Signed-off-by: Daniele Ceraolo Spurio 
Reviewed-by: Rodrigo Vivi  #v1
---
 drivers/gpu/drm/i915/Kconfig | 11 +++
 drivers/gpu/drm/i915/i915_drv.h  |  4 
 drivers/gpu/drm/i915/intel_device_info.h |  1 +
 3 files changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index 93f4d059fc89..3303579b41bb 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -131,6 +131,17 @@ config DRM_I915_GVT_KVMGT
  Choose this option if you want to enable KVMGT support for
  Intel GVT-g.
 
+config DRM_I915_PXP
+   bool "Enable Intel PXP support for Intel Gen12+ platform"
+   depends on DRM_I915
+   depends on INTEL_MEI && INTEL_MEI_PXP
+   default n
+   help
+ PXP (Protected Xe Path) is an i915 component, available on GEN12+
+ GPUs, that helps to establish the hardware protected session and
+ manage the status of the alive software session, as well as its life
+ cycle.
+
 menu "drm/i915 Debugging"
 depends on DRM_I915
 depends on EXPERT
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9cb02618ba15..ee7280cad3bb 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1701,6 +1701,10 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
 
 #define HAS_VRR(i915)  (INTEL_GEN(i915) >= 12)
 
+#define HAS_PXP(dev_priv) (IS_ENABLED(CONFIG_DRM_I915_PXP) && \
+  INTEL_INFO(dev_priv)->has_pxp) && \
+  VDBOX_MASK(_priv->gt)
+
 /* Only valid when HAS_DISPLAY() is true */
 #define INTEL_DISPLAY_ENABLED(dev_priv) \
(drm_WARN_ON(&(dev_priv)->drm, !HAS_DISPLAY(dev_priv)), 
!(dev_priv)->params.disable_display)
diff --git a/drivers/gpu/drm/i915/intel_device_info.h 
b/drivers/gpu/drm/i915/intel_device_info.h
index 1390fad5ec06..2252f03558ff 100644
--- a/drivers/gpu/drm/i915/intel_device_info.h
+++ b/drivers/gpu/drm/i915/intel_device_info.h
@@ -129,6 +129,7 @@ enum intel_ppgtt_type {
func(has_logical_ring_elsq); \
func(has_master_unit_irq); \
func(has_pooled_eu); \
+   func(has_pxp); \
func(has_rc6); \
func(has_rc6p); \
func(has_rps); \
-- 
2.29.2



[PATCH v4 01/17] drm/i915/pxp: Define PXP component interface

2021-05-24 Thread Daniele Ceraolo Spurio
This will be used for communication between the i915 driver and the mei
one. Defining it in a stand-alone patch to avoid circualr dependedencies
between the patches modifying the 2 drivers.

Split out from an original patch from  Huang, Sean Z

v2: rename the component struct (Rodrigo)

Signed-off-by: Daniele Ceraolo Spurio 
Cc: Rodrigo Vivi 
Reviewed-by: Rodrigo Vivi 
---
 include/drm/i915_component.h |  1 +
 include/drm/i915_pxp_tee_interface.h | 45 
 2 files changed, 46 insertions(+)
 create mode 100644 include/drm/i915_pxp_tee_interface.h

diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
index 55c3b123581b..c1e2a43d2d1e 100644
--- a/include/drm/i915_component.h
+++ b/include/drm/i915_component.h
@@ -29,6 +29,7 @@
 enum i915_component_type {
I915_COMPONENT_AUDIO = 1,
I915_COMPONENT_HDCP,
+   I915_COMPONENT_PXP
 };
 
 /* MAX_PORT is the number of port
diff --git a/include/drm/i915_pxp_tee_interface.h 
b/include/drm/i915_pxp_tee_interface.h
new file mode 100644
index ..09b8389152af
--- /dev/null
+++ b/include/drm/i915_pxp_tee_interface.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2020 Intel Corporation
+ *
+ * Authors:
+ * Vitaly Lubart 
+ */
+
+#ifndef _I915_PXP_TEE_INTERFACE_H_
+#define _I915_PXP_TEE_INTERFACE_H_
+
+#include 
+#include 
+
+/**
+ * struct i915_pxp_component_ops - ops for PXP services.
+ * @owner: Module providing the ops
+ * @send: sends data to PXP
+ * @receive: receives data from PXP
+ */
+struct i915_pxp_component_ops {
+   /**
+* @owner: owner of the module provding the ops
+*/
+   struct module *owner;
+
+   int (*send)(struct device *dev, const void *message, size_t size);
+   int (*recv)(struct device *dev, void *buffer, size_t size);
+};
+
+/**
+ * struct i915_pxp_component - Used for communication between i915 and TEE
+ * drivers for the PXP services
+ * @tee_dev: device that provide the PXP service from TEE Bus.
+ * @pxp_ops: Ops implemented by TEE driver, used by i915 driver.
+ */
+struct i915_pxp_component {
+   struct device *tee_dev;
+   const struct i915_pxp_component_ops *ops;
+
+   /* To protect the above members. */
+   struct mutex mutex;
+};
+
+#endif /* _I915_TEE_PXP_INTERFACE_H_ */
-- 
2.29.2



[PATCH v4 02/17] mei: pxp: export pavp client to me client bus

2021-05-24 Thread Daniele Ceraolo Spurio
From: Vitaly Lubart 

Export PAVP client to work with i915 driver,
for binding it uses kernel component framework.

Signed-off-by: Vitaly Lubart 
Signed-off-by: Tomas Winkler 
Signed-off-by: Daniele Ceraolo Spurio 
---
 drivers/misc/mei/Kconfig   |   2 +
 drivers/misc/mei/Makefile  |   1 +
 drivers/misc/mei/pxp/Kconfig   |  13 ++
 drivers/misc/mei/pxp/Makefile  |   7 +
 drivers/misc/mei/pxp/mei_pxp.c | 233 +
 drivers/misc/mei/pxp/mei_pxp.h |  18 +++
 6 files changed, 274 insertions(+)
 create mode 100644 drivers/misc/mei/pxp/Kconfig
 create mode 100644 drivers/misc/mei/pxp/Makefile
 create mode 100644 drivers/misc/mei/pxp/mei_pxp.c
 create mode 100644 drivers/misc/mei/pxp/mei_pxp.h

diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
index f5fd5b786607..0e0bcd0da852 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -47,3 +47,5 @@ config INTEL_MEI_TXE
  Intel Bay Trail
 
 source "drivers/misc/mei/hdcp/Kconfig"
+source "drivers/misc/mei/pxp/Kconfig"
+
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index f1c76f7ee804..d8e5165917f2 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -26,3 +26,4 @@ mei-$(CONFIG_EVENT_TRACING) += mei-trace.o
 CFLAGS_mei-trace.o = -I$(src)
 
 obj-$(CONFIG_INTEL_MEI_HDCP) += hdcp/
+obj-$(CONFIG_INTEL_MEI_PXP) += pxp/
diff --git a/drivers/misc/mei/pxp/Kconfig b/drivers/misc/mei/pxp/Kconfig
new file mode 100644
index ..4029b96afc04
--- /dev/null
+++ b/drivers/misc/mei/pxp/Kconfig
@@ -0,0 +1,13 @@
+
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2020, Intel Corporation. All rights reserved.
+#
+config INTEL_MEI_PXP
+   tristate "Intel PXP services of ME Interface"
+   select INTEL_MEI_ME
+   depends on DRM_I915
+   help
+ MEI Support for PXP Services on Intel platforms.
+
+ Enables the ME FW services required for PXP support through
+ I915 display driver of Intel.
diff --git a/drivers/misc/mei/pxp/Makefile b/drivers/misc/mei/pxp/Makefile
new file mode 100644
index ..0329950d5794
--- /dev/null
+++ b/drivers/misc/mei/pxp/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.
+#
+# Makefile - PXP client driver for Intel MEI Bus Driver.
+
+obj-$(CONFIG_INTEL_MEI_PXP) += mei_pxp.o
diff --git a/drivers/misc/mei/pxp/mei_pxp.c b/drivers/misc/mei/pxp/mei_pxp.c
new file mode 100644
index ..cacfbedb640a
--- /dev/null
+++ b/drivers/misc/mei/pxp/mei_pxp.c
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+/**
+ * DOC: MEI_PXP Client Driver
+ *
+ * The mei_pxp driver acts as a translation layer between PXP
+ * protocol  implementer (I915) and ME FW by translating PXP
+ * negotiation messages to ME FW command payloads and vice versa.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "mei_pxp.h"
+
+/**
+ * mei_pxp_send_message() - Sends a PXP message to ME FW.
+ * @dev: device corresponding to the mei_cl_device
+ * @message: a message buffer to send
+ * @size: size of the message
+ * Return: 0 on Success, <0 on Failure
+ */
+static int
+mei_pxp_send_message(struct device *dev, const void *message, size_t size)
+{
+   struct mei_cl_device *cldev;
+   ssize_t byte;
+
+   if (!dev || !message)
+   return -EINVAL;
+
+   cldev = to_mei_cl_device(dev);
+
+   /* temporary drop const qualifier till the API is fixed */
+   byte = mei_cldev_send(cldev, (u8 *)message, size);
+   if (byte < 0) {
+   dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
+   return byte;
+   }
+
+   return 0;
+}
+
+/**
+ * mei_pxp_receive_message() - Receives a PXP message from ME FW.
+ * @dev: device corresponding to the mei_cl_device
+ * @buffer: a message buffer to contain the received message
+ * @size: size of the buffer
+ * Return: bytes sent on Success, <0 on Failure
+ */
+static int
+mei_pxp_receive_message(struct device *dev, void *buffer, size_t size)
+{
+   struct mei_cl_device *cldev;
+   ssize_t byte;
+
+   if (!dev || !buffer)
+   return -EINVAL;
+
+   cldev = to_mei_cl_device(dev);
+
+   byte = mei_cldev_recv(cldev, buffer, size);
+   if (byte < 0) {
+   dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
+   return byte;
+   }
+
+   return byte;
+}
+
+static const struct i915_pxp_component_ops mei_pxp_ops = {
+   .owner = THIS_MODULE,
+   .send = mei_pxp_send_message,
+   .recv = mei_pxp_receive_message,
+};
+
+static int mei_component_master_bind(struct device *dev)
+{
+   struct mei_cl_device *cldev = to_mei_cl_device(dev);
+   struct i915_pxp_component *comp_master = mei_cldev_get_drvdata(cldev);
+   int ret;
+
+   dev_dbg(dev, "%s\n", __func__);
+   

[PATCH v4 00/17] drm/i915: Introduce Intel PXP

2021-05-24 Thread Daniele Ceraolo Spurio
PXP (Protected Xe Path) is an i915 component, available on
GEN12+, that helps to establish the hardware protected session
and manage the status of the alive software session, as well
as its life cycle.

Several minor changes and fixes, but the main changes in v4 are:

- Rebased to new create_ext ioctl implementation

- Default kconfig option is now N.

- The default session is now only started when protected objects are
  submitted via execbuf.

Tested with: https://patchwork.freedesktop.org/series/87570/

Cc: Gaurav Kumar 
Cc: Chris Wilson 
Cc: Rodrigo Vivi 
Cc: Joonas Lahtinen 
Cc: Juston Li 
Cc: Alan Previn 
Cc: Lionel Landwerlin 
Cc: Jason Ekstrand 
Cc: Daniel Vetter 

Anshuman Gupta (2):
  drm/i915/pxp: Add plane decryption support
  drm/i915/pxp: black pixels on pxp disabled

Bommu Krishnaiah (1):
  drm/i915/pxp: User interface for Protected buffer

Chris Wilson (1):
  drm/i915/gt: Export the pinned context constructor and destructor

Daniele Ceraolo Spurio (7):
  drm/i915/pxp: Define PXP component interface
  drm/i915/pxp: define PXP device flag and kconfig
  drm/i915/pxp: allocate a vcs context for pxp usage
  drm/i915/pxp: set KCR reg init
  drm/i915/pxp: interface for marking contexts as using protected
content
  drm/i915/pxp: start the arb session on demand
  drm/i915/pxp: enable PXP for integrated Gen12

Huang, Sean Z (5):
  drm/i915/pxp: Implement funcs to create the TEE channel
  drm/i915/pxp: Create the arbitrary session after boot
  drm/i915/pxp: Implement arb session teardown
  drm/i915/pxp: Implement PXP irq handler
  drm/i915/pxp: Enable PXP power management

Vitaly Lubart (1):
  mei: pxp: export pavp client to me client bus

 drivers/gpu/drm/i915/Kconfig  |  11 +
 drivers/gpu/drm/i915/Makefile |   9 +
 .../gpu/drm/i915/display/intel_atomic_plane.c |  25 ++
 drivers/gpu/drm/i915/display/intel_display.c  |   4 +
 .../drm/i915/display/intel_display_types.h|   6 +
 .../drm/i915/display/skl_universal_plane.c|  49 +++-
 drivers/gpu/drm/i915/gem/i915_gem_context.c   |  59 +++-
 drivers/gpu/drm/i915/gem/i915_gem_context.h   |  18 ++
 .../gpu/drm/i915/gem/i915_gem_context_types.h |   2 +
 drivers/gpu/drm/i915/gem/i915_gem_create.c|  26 ++
 .../gpu/drm/i915/gem/i915_gem_execbuffer.c|  35 +++
 drivers/gpu/drm/i915/gem/i915_gem_object.c|   6 +
 drivers/gpu/drm/i915/gem/i915_gem_object.h|  12 +
 .../gpu/drm/i915/gem/i915_gem_object_types.h  |  13 +
 drivers/gpu/drm/i915/gt/intel_engine.h|  12 +
 drivers/gpu/drm/i915/gt/intel_engine_cs.c |  29 +-
 drivers/gpu/drm/i915/gt/intel_gpu_commands.h  |  22 +-
 drivers/gpu/drm/i915/gt/intel_gt.c|   5 +
 drivers/gpu/drm/i915/gt/intel_gt_irq.c|   7 +
 drivers/gpu/drm/i915/gt/intel_gt_pm.c |  15 +-
 drivers/gpu/drm/i915/gt/intel_gt_types.h  |   3 +
 drivers/gpu/drm/i915/i915_drv.c   |   2 +
 drivers/gpu/drm/i915/i915_drv.h   |   4 +
 drivers/gpu/drm/i915/i915_pci.c   |   2 +
 drivers/gpu/drm/i915/i915_reg.h   |  48 
 drivers/gpu/drm/i915/intel_device_info.h  |   1 +
 drivers/gpu/drm/i915/pxp/intel_pxp.c  | 266 ++
 drivers/gpu/drm/i915/pxp/intel_pxp.h  |  65 +
 drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c  | 140 +
 drivers/gpu/drm/i915/pxp/intel_pxp_cmd.h  |  15 +
 drivers/gpu/drm/i915/pxp/intel_pxp_irq.c  | 100 +++
 drivers/gpu/drm/i915/pxp/intel_pxp_irq.h  |  32 +++
 drivers/gpu/drm/i915/pxp/intel_pxp_pm.c   |  40 +++
 drivers/gpu/drm/i915/pxp/intel_pxp_pm.h   |  23 ++
 drivers/gpu/drm/i915/pxp/intel_pxp_session.c  | 172 +++
 drivers/gpu/drm/i915/pxp/intel_pxp_session.h  |  15 +
 drivers/gpu/drm/i915/pxp/intel_pxp_tee.c  | 161 +++
 drivers/gpu/drm/i915/pxp/intel_pxp_tee.h  |  17 ++
 .../drm/i915/pxp/intel_pxp_tee_interface.h|  37 +++
 drivers/gpu/drm/i915/pxp/intel_pxp_types.h|  53 
 drivers/misc/mei/Kconfig  |   2 +
 drivers/misc/mei/Makefile |   1 +
 drivers/misc/mei/pxp/Kconfig  |  13 +
 drivers/misc/mei/pxp/Makefile |   7 +
 drivers/misc/mei/pxp/mei_pxp.c| 233 +++
 drivers/misc/mei/pxp/mei_pxp.h|  18 ++
 include/drm/i915_component.h  |   1 +
 include/drm/i915_pxp_tee_interface.h  |  45 +++
 include/uapi/drm/i915_drm.h   |  62 +++-
 49 files changed, 1922 insertions(+), 21 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp.c
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp.h
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_cmd.h
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_irq.c
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_irq.h
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_pm.c
 create mode 100644 

Re: [RFC PATCH 16/97] drm/i915/guc: Start protecting access to CTB descriptors

2021-05-24 Thread Matthew Brost
On Thu, May 06, 2021 at 12:13:30PM -0700, Matthew Brost wrote:
> From: Michal Wajdeczko 
> 
> We want to stop using guc.send_mutex while sending CTB messages
> so we have to start protecting access to CTB send descriptor.
> 
> For completeness protect also CTB send descriptor.
> 
> Add spinlock to struct intel_guc_ct_buffer and start using it.
> 
> Signed-off-by: Michal Wajdeczko 
> Signed-off-by: Matthew Brost 

Reviewed-by: Matthew Brost 

> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 14 --
>  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h |  2 ++
>  2 files changed, 14 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> index a4b2e7fe318b..bee0958d8bae 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> @@ -89,6 +89,8 @@ static void ct_incoming_request_worker_func(struct 
> work_struct *w);
>   */
>  void intel_guc_ct_init_early(struct intel_guc_ct *ct)
>  {
> + spin_lock_init(>ctbs.send.lock);
> + spin_lock_init(>ctbs.recv.lock);
>   spin_lock_init(>requests.lock);
>   INIT_LIST_HEAD(>requests.pending);
>   INIT_LIST_HEAD(>requests.incoming);
> @@ -479,17 +481,22 @@ static int ct_send(struct intel_guc_ct *ct,
>   GEM_BUG_ON(len & ~GUC_CT_MSG_LEN_MASK);
>   GEM_BUG_ON(!response_buf && response_buf_size);
>  
> + spin_lock_irqsave(>ctbs.send.lock, flags);
> +
>   fence = ct_get_next_fence(ct);
>   request.fence = fence;
>   request.status = 0;
>   request.response_len = response_buf_size;
>   request.response_buf = response_buf;
>  
> - spin_lock_irqsave(>requests.lock, flags);
> + spin_lock(>requests.lock);
>   list_add_tail(, >requests.pending);
> - spin_unlock_irqrestore(>requests.lock, flags);
> + spin_unlock(>requests.lock);
>  
>   err = ct_write(ct, action, len, fence);
> +
> + spin_unlock_irqrestore(>ctbs.send.lock, flags);
> +
>   if (unlikely(err))
>   goto unlink;
>  
> @@ -825,6 +832,7 @@ static int ct_handle_request(struct intel_guc_ct *ct, 
> const u32 *msg)
>  void intel_guc_ct_event_handler(struct intel_guc_ct *ct)
>  {
>   u32 msg[GUC_CT_MSG_LEN_MASK + 1]; /* one extra dw for the header */
> + unsigned long flags;
>   int err = 0;
>  
>   if (unlikely(!ct->enabled)) {
> @@ -833,7 +841,9 @@ void intel_guc_ct_event_handler(struct intel_guc_ct *ct)
>   }
>  
>   do {
> + spin_lock_irqsave(>ctbs.recv.lock, flags);
>   err = ct_read(ct, msg);
> + spin_unlock_irqrestore(>ctbs.recv.lock, flags);
>   if (err)
>   break;
>  
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h
> index fc9486779e87..bc52dc479a14 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h
> @@ -27,11 +27,13 @@ struct intel_guc;
>   * record (command transport buffer descriptor) and the actual buffer which
>   * holds the commands.
>   *
> + * @lock: protects access to the commands buffer and buffer descriptor
>   * @desc: pointer to the buffer descriptor
>   * @cmds: pointer to the commands buffer
>   * @size: size of the commands buffer
>   */
>  struct intel_guc_ct_buffer {
> + spinlock_t lock;
>   struct guc_ct_buffer_desc *desc;
>   u32 *cmds;
>   u32 size;
> -- 
> 2.28.0
> 


Re: [RFC PATCH 16/97] drm/i915/guc: Start protecting access to CTB descriptors

2021-05-24 Thread Matthew Brost
On Thu, May 06, 2021 at 12:13:30PM -0700, Matthew Brost wrote:
> From: Michal Wajdeczko 
> 
> We want to stop using guc.send_mutex while sending CTB messages
> so we have to start protecting access to CTB send descriptor.
> 
> For completeness protect also CTB send descriptor.

Michal I think you have a typo here, receive descriptor, right? Again
this is going to get squashed in the firmware update patch but thought
I'd mention this.

With that:
Reviewed-by: Matthew Brost  

> 
> Add spinlock to struct intel_guc_ct_buffer and start using it.
> 
> Signed-off-by: Michal Wajdeczko 
> Signed-off-by: Matthew Brost 
> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 14 --
>  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h |  2 ++
>  2 files changed, 14 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> index a4b2e7fe318b..bee0958d8bae 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> @@ -89,6 +89,8 @@ static void ct_incoming_request_worker_func(struct 
> work_struct *w);
>   */
>  void intel_guc_ct_init_early(struct intel_guc_ct *ct)
>  {
> + spin_lock_init(>ctbs.send.lock);
> + spin_lock_init(>ctbs.recv.lock);
>   spin_lock_init(>requests.lock);
>   INIT_LIST_HEAD(>requests.pending);
>   INIT_LIST_HEAD(>requests.incoming);
> @@ -479,17 +481,22 @@ static int ct_send(struct intel_guc_ct *ct,
>   GEM_BUG_ON(len & ~GUC_CT_MSG_LEN_MASK);
>   GEM_BUG_ON(!response_buf && response_buf_size);
>  
> + spin_lock_irqsave(>ctbs.send.lock, flags);
> +
>   fence = ct_get_next_fence(ct);
>   request.fence = fence;
>   request.status = 0;
>   request.response_len = response_buf_size;
>   request.response_buf = response_buf;
>  
> - spin_lock_irqsave(>requests.lock, flags);
> + spin_lock(>requests.lock);
>   list_add_tail(, >requests.pending);
> - spin_unlock_irqrestore(>requests.lock, flags);
> + spin_unlock(>requests.lock);
>  
>   err = ct_write(ct, action, len, fence);
> +
> + spin_unlock_irqrestore(>ctbs.send.lock, flags);
> +
>   if (unlikely(err))
>   goto unlink;
>  
> @@ -825,6 +832,7 @@ static int ct_handle_request(struct intel_guc_ct *ct, 
> const u32 *msg)
>  void intel_guc_ct_event_handler(struct intel_guc_ct *ct)
>  {
>   u32 msg[GUC_CT_MSG_LEN_MASK + 1]; /* one extra dw for the header */
> + unsigned long flags;
>   int err = 0;
>  
>   if (unlikely(!ct->enabled)) {
> @@ -833,7 +841,9 @@ void intel_guc_ct_event_handler(struct intel_guc_ct *ct)
>   }
>  
>   do {
> + spin_lock_irqsave(>ctbs.recv.lock, flags);
>   err = ct_read(ct, msg);
> + spin_unlock_irqrestore(>ctbs.recv.lock, flags);
>   if (err)
>   break;
>  
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h
> index fc9486779e87..bc52dc479a14 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h
> @@ -27,11 +27,13 @@ struct intel_guc;
>   * record (command transport buffer descriptor) and the actual buffer which
>   * holds the commands.
>   *
> + * @lock: protects access to the commands buffer and buffer descriptor
>   * @desc: pointer to the buffer descriptor
>   * @cmds: pointer to the commands buffer
>   * @size: size of the commands buffer
>   */
>  struct intel_guc_ct_buffer {
> + spinlock_t lock;
>   struct guc_ct_buffer_desc *desc;
>   u32 *cmds;
>   u32 size;
> -- 
> 2.28.0
> 


Re: [RFC PATCH 13/97] drm/i915/guc: Replace CTB array with explicit members

2021-05-24 Thread Matthew Brost
On Thu, May 06, 2021 at 12:13:27PM -0700, Matthew Brost wrote:
> From: Michal Wajdeczko 
> 
> Upcoming GuC firmware will always require just two CTBs and we
> also plan to configure them with different sizes, so definining
> them as array is no longer suitable.
> 
> Signed-off-by: Michal Wajdeczko 
> Signed-off-by: Matthew Brost 

Reviewed-by: Matthew Brost 

> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 46 ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h |  7 +++-
>  2 files changed, 30 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> index fbd6bd20f588..c54a29176862 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> @@ -168,10 +168,10 @@ int intel_guc_ct_init(struct intel_guc_ct *ct)
>   struct intel_guc *guc = ct_to_guc(ct);
>   struct guc_ct_buffer_desc *desc;
>   u32 blob_size;
> + u32 cmds_size;
>   void *blob;
>   u32 *cmds;
>   int err;
> - int i;
>  
>   GEM_BUG_ON(ct->vma);
>  
> @@ -207,15 +207,23 @@ int intel_guc_ct_init(struct intel_guc_ct *ct)
>  
>   CT_DEBUG(ct, "base=%#x size=%u\n", intel_guc_ggtt_offset(guc, ct->vma), 
> blob_size);
>  
> - /* store pointers to desc and cmds */
> - for (i = 0; i < ARRAY_SIZE(ct->ctbs); i++) {
> - GEM_BUG_ON((i !=  CTB_SEND) && (i != CTB_RECV));
> + /* store pointers to desc and cmds for send ctb */
> + desc = blob;
> + cmds = blob + PAGE_SIZE / 2;
> + cmds_size = PAGE_SIZE / 4;
> + CT_DEBUG(ct, "%s desc %#lx cmds %#lx size %u\n", "send",
> +  ptrdiff(desc, blob), ptrdiff(cmds, blob), cmds_size);
>  
> - desc = blob + PAGE_SIZE / 4 * i;
> - cmds = blob + PAGE_SIZE / 4 * i + PAGE_SIZE / 2;
> + guc_ct_buffer_init(>ctbs.send, desc, cmds, cmds_size);
>  
> - guc_ct_buffer_init(>ctbs[i], desc, cmds, PAGE_SIZE / 4);
> - }
> + /* store pointers to desc and cmds for recv ctb */
> + desc = blob + PAGE_SIZE / 4;
> + cmds = blob + PAGE_SIZE / 4 + PAGE_SIZE / 2;
> + cmds_size = PAGE_SIZE / 4;
> + CT_DEBUG(ct, "%s desc %#lx cmds %#lx size %u\n", "recv",
> +  ptrdiff(desc, blob), ptrdiff(cmds, blob), cmds_size);
> +
> + guc_ct_buffer_init(>ctbs.recv, desc, cmds, cmds_size);
>  
>   return 0;
>  }
> @@ -246,7 +254,6 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct)
>   u32 base, cmds;
>   void *blob;
>   int err;
> - int i;
>  
>   GEM_BUG_ON(ct->enabled);
>  
> @@ -257,28 +264,25 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct)
>  
>   /* blob should start with send descriptor */
>   blob = __px_vaddr(ct->vma->obj);
> - GEM_BUG_ON(blob != ct->ctbs[CTB_SEND].desc);
> + GEM_BUG_ON(blob != ct->ctbs.send.desc);
>  
>   /* (re)initialize descriptors */
> - for (i = 0; i < ARRAY_SIZE(ct->ctbs); i++) {
> - GEM_BUG_ON((i != CTB_SEND) && (i != CTB_RECV));
> + cmds = base + ptrdiff(ct->ctbs.send.cmds, blob);
> + guc_ct_buffer_reset(>ctbs.send, cmds);
>  
> - cmds = base + ptrdiff(ct->ctbs[i].cmds, blob);
> - CT_DEBUG(ct, "%d: cmds addr=%#x\n", i, cmds);
> -
> - guc_ct_buffer_reset(>ctbs[i], cmds);
> - }
> + cmds = base + ptrdiff(ct->ctbs.recv.cmds, blob);
> + guc_ct_buffer_reset(>ctbs.recv, cmds);
>  
>   /*
>* Register both CT buffers starting with RECV buffer.
>* Descriptors are in first half of the blob.
>*/
> - err = ct_register_buffer(ct, base + ptrdiff(ct->ctbs[CTB_RECV].desc, 
> blob),
> + err = ct_register_buffer(ct, base + ptrdiff(ct->ctbs.recv.desc, blob),
>INTEL_GUC_CT_BUFFER_TYPE_RECV);
>   if (unlikely(err))
>   goto err_out;
>  
> - err = ct_register_buffer(ct, base + ptrdiff(ct->ctbs[CTB_SEND].desc, 
> blob),
> + err = ct_register_buffer(ct, base + ptrdiff(ct->ctbs.send.desc, blob),
>INTEL_GUC_CT_BUFFER_TYPE_SEND);
>   if (unlikely(err))
>   goto err_deregister;
> @@ -341,7 +345,7 @@ static int ct_write(struct intel_guc_ct *ct,
>   u32 len /* in dwords */,
>   u32 fence)
>  {
> - struct intel_guc_ct_buffer *ctb = >ctbs[CTB_SEND];
> + struct intel_guc_ct_buffer *ctb = >ctbs.send;
>   struct guc_ct_buffer_desc *desc = ctb->desc;
>   u32 head = desc->head;
>   u32 tail = desc->tail;
> @@ -557,7 +561,7 @@ static inline bool ct_header_is_response(u32 header)
>  
>  static int ct_read(struct intel_guc_ct *ct, u32 *data)
>  {
> - struct intel_guc_ct_buffer *ctb = >ctbs[CTB_RECV];
> + struct intel_guc_ct_buffer *ctb = >ctbs.recv;
>   struct guc_ct_buffer_desc *desc = ctb->desc;
>   u32 head = desc->head;
>   u32 tail = desc->tail;
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h 
> 

[PATCH] drm/msm/dp: Drop unnecessary NULL checks after container_of

2021-05-24 Thread Guenter Roeck
The result of container_of() operations is never NULL unless the embedded
element is the first element of the structure. This is not the case here.
The NULL check on the result of container_of() is therefore unnecessary
and misleading. Remove it.

This change was made automatically with the following Coccinelle script.

@@
type t;
identifier v;
statement s;
@@

<+...
(
  t v = container_of(...);
|
  v = container_of(...);
)
  ...
  when != v
- if (\( !v \| v == NULL \) ) s
...+>

While at it, remove unused but assigned variable hpd in
dp_display_usbpd_attention_cb().

Signed-off-by: Guenter Roeck 
---
 drivers/gpu/drm/msm/dp/dp_display.c | 25 -
 1 file changed, 25 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 1784e119269b..a74e7ef96fcf 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -208,10 +208,6 @@ static int dp_display_bind(struct device *dev, struct 
device *master,
 
dp = container_of(g_dp_display,
struct dp_display_private, dp_display);
-   if (!dp) {
-   DRM_ERROR("DP driver bind failed. Invalid driver data\n");
-   return -EINVAL;
-   }
 
dp->dp_display.drm_dev = drm;
priv = drm->dev_private;
@@ -252,10 +248,6 @@ static void dp_display_unbind(struct device *dev, struct 
device *master,
 
dp = container_of(g_dp_display,
struct dp_display_private, dp_display);
-   if (!dp) {
-   DRM_ERROR("Invalid DP driver data\n");
-   return;
-   }
 
dp_power_client_deinit(dp->power);
dp_aux_unregister(dp->aux);
@@ -406,11 +398,6 @@ static int dp_display_usbpd_configure_cb(struct device 
*dev)
 
dp = container_of(g_dp_display,
struct dp_display_private, dp_display);
-   if (!dp) {
-   DRM_ERROR("no driver data found\n");
-   rc = -ENODEV;
-   goto end;
-   }
 
dp_display_host_init(dp, false);
 
@@ -437,11 +424,6 @@ static int dp_display_usbpd_disconnect_cb(struct device 
*dev)
 
dp = container_of(g_dp_display,
struct dp_display_private, dp_display);
-   if (!dp) {
-   DRM_ERROR("no driver data found\n");
-   rc = -ENODEV;
-   return rc;
-   }
 
dp_add_event(dp, EV_USER_NOTIFICATION, false, 0);
 
@@ -502,7 +484,6 @@ static int dp_display_usbpd_attention_cb(struct device *dev)
int rc = 0;
u32 sink_request;
struct dp_display_private *dp;
-   struct dp_usbpd *hpd;
 
if (!dev) {
DRM_ERROR("invalid dev\n");
@@ -511,12 +492,6 @@ static int dp_display_usbpd_attention_cb(struct device 
*dev)
 
dp = container_of(g_dp_display,
struct dp_display_private, dp_display);
-   if (!dp) {
-   DRM_ERROR("no driver data found\n");
-   return -ENODEV;
-   }
-
-   hpd = dp->usbpd;
 
/* check for any test request issued by sink */
rc = dp_link_process_request(dp->link);
-- 
2.25.1



Re: [PATCH v7 05/15] swiotlb: Add a new get_io_tlb_mem getter

2021-05-24 Thread Claire Chang
On Mon, May 24, 2021 at 11:51 PM Konrad Rzeszutek Wilk
 wrote:
>
> On Tue, May 18, 2021 at 02:51:52PM +0800, Claire Chang wrote:
> > Still keep this function because directly using dev->dma_io_tlb_mem
> > will cause issues for memory allocation for existing devices. The pool
> > can't support atomic coherent allocation so we need to distinguish the
> > per device pool and the default pool in swiotlb_alloc.
>
> This above should really be rolled in the commit. You can prefix it by
> "The reason it was done this way was because directly using .."
>

Will add it.


Re: [PATCH v7 04/15] swiotlb: Add restricted DMA pool initialization

2021-05-24 Thread Claire Chang
On Mon, May 24, 2021 at 11:49 PM Konrad Rzeszutek Wilk
 wrote:
>
> On Tue, May 18, 2021 at 02:48:35PM +0800, Claire Chang wrote:
> > I didn't move this to a separate file because I feel it might be
> > confusing for swiotlb_alloc/free (and need more functions to be
> > non-static).
> > Maybe instead of moving to a separate file, we can try to come up with
> > a better naming?
>
> I think you are referring to:
>
> rmem_swiotlb_setup
>
> ?

Yes, and the following swiotlb_alloc/free.

>
> Which is ARM specific and inside the generic code?
>
> 
>
> Christopher wants to unify it in all the code so there is one single
> source, but the "you seperate arch code out from generic" saying
> makes me want to move it out.
>
> I agree that if you move it out from generic to arch-specific we have to
> expose more of the swiotlb functions, which will undo's Christopher
> cleanup code.
>
> How about this - lets leave it as is now, and when there are more
> use-cases we can revisit it and then if need to move the code?
>
Ok! Sounds good!


Re: [PATCH v7 01/15] swiotlb: Refactor swiotlb init functions

2021-05-24 Thread Claire Chang
On Mon, May 24, 2021 at 11:53 PM Konrad Rzeszutek Wilk
 wrote:
>
> > > do the set_memory_decrypted()+memset(). Is this okay or should
> > > swiotlb_init_io_tlb_mem() add an additional argument to do this
> > > conditionally?
> >
> > I'm actually not sure if this it okay. If not, will add an additional
> > argument for it.
>
> Any observations discovered? (Want to make sure my memory-cache has the
> correct semantics for set_memory_decrypted in mind).

It works fine on my arm64 device.

> >
> > > --
> > > Florian


Re: [RFC PATCH 14/97] drm/i915/guc: Update sizes of CTB buffers

2021-05-24 Thread Matthew Brost
On Thu, May 06, 2021 at 12:13:28PM -0700, Matthew Brost wrote:
> From: Michal Wajdeczko 
> 
> Future GuC will require CTB buffers sizes to be multiple of 4K.
> Make these changes now as this shouldn't impact us too much.
> 
> Signed-off-by: Michal Wajdeczko 
> Signed-off-by: Matthew Brost 
> Cc: John Harrison 
> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 60 ---
>  1 file changed, 32 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> index c54a29176862..c87a0a8bef26 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> @@ -38,6 +38,32 @@ static inline struct drm_device *ct_to_drm(struct 
> intel_guc_ct *ct)
>  #define CT_PROBE_ERROR(_ct, _fmt, ...) \
>   i915_probe_error(ct_to_i915(ct), "CT: " _fmt, ##__VA_ARGS__);
>  
> +/**
> + * DOC: CTB Blob
> + *
> + * We allocate single blob to hold both CTB descriptors and buffers:
> + *
> + *  ++---+--+
> + *  | offset | contents  | size |
> + *  ++===+==+
> + *  | 0x | H2G `CTB Descriptor`_ (send)  |  |
> + *  ++---+  4K  |
> + *  | 0x0800 | G2H `CTB Descriptor`_ (recv)  |  |
> + *  ++---+--+
> + *  | 0x1000 | H2G `CT Buffer`_ (send)   | n*4K |
> + *  ||   |  |
> + *  ++---+--+
> + *  | 0x1000 | G2H `CT Buffer`_ (recv)   | m*4K |
> + *  | + n*4K |   |  |
> + *  ++---+--+
> + *
> + * Size of each `CT Buffer`_ must be multiple of 4K.
> + * As we don't expect too many messages, for now use minimum sizes.
> + */
> +#define CTB_DESC_SIZEALIGN(sizeof(struct 
> guc_ct_buffer_desc), SZ_2K)
> +#define CTB_H2G_BUFFER_SIZE  (SZ_4K)
> +#define CTB_G2H_BUFFER_SIZE  (SZ_4K)
> +
>  struct ct_request {
>   struct list_head link;
>   u32 fence;
> @@ -175,29 +201,7 @@ int intel_guc_ct_init(struct intel_guc_ct *ct)
>  
>   GEM_BUG_ON(ct->vma);
>  
> - /* We allocate 1 page to hold both descriptors and both buffers.
> -  *   ___.
> -  *  |desc (SEND)|   :
> -  *  |___|   PAGE/4
> -  *  :___:
> -  *  |desc (RECV)|   :
> -  *  |___|   PAGE/4
> -  *  :___:
> -  *  |cmds (SEND)|
> -  *  |   PAGE/4
> -  *  |___|
> -  *  |cmds (RECV)|
> -  *  |   PAGE/4
> -  *  |___|
> -  *
> -  * Each message can use a maximum of 32 dwords and we don't expect to
> -  * have more than 1 in flight at any time, so we have enough space.
> -  * Some logic further ahead will rely on the fact that there is only 1
> -  * page and that it is always mapped, so if the size is changed the
> -  * other code will need updating as well.
> -  */
> -
> - blob_size = PAGE_SIZE;
> + blob_size = 2 * CTB_DESC_SIZE + CTB_H2G_BUFFER_SIZE + 
> CTB_G2H_BUFFER_SIZE;
>   err = intel_guc_allocate_and_map_vma(guc, blob_size, >vma, );
>   if (unlikely(err)) {
>   CT_PROBE_ERROR(ct, "Failed to allocate %u for CTB data (%pe)\n",
> @@ -209,17 +213,17 @@ int intel_guc_ct_init(struct intel_guc_ct *ct)
>  
>   /* store pointers to desc and cmds for send ctb */
>   desc = blob;
> - cmds = blob + PAGE_SIZE / 2;
> - cmds_size = PAGE_SIZE / 4;
> + cmds = blob + 2 * CTB_DESC_SIZE;

2 is a magic number here. Think it would be more clear with
CTB_NUMBER_DESC define here.

Michal what do you think? We can fix this in the next post of this with
your blessing.

With that nit:
Reviewed-by: Matthew Brost  

> + cmds_size = CTB_H2G_BUFFER_SIZE;
>   CT_DEBUG(ct, "%s desc %#lx cmds %#lx size %u\n", "send",
>ptrdiff(desc, blob), ptrdiff(cmds, blob), cmds_size);
>  
>   guc_ct_buffer_init(>ctbs.send, desc, cmds, cmds_size);
>  
>   /* store pointers to desc and cmds for recv ctb */
> - desc = blob + PAGE_SIZE / 4;
> - cmds = blob + PAGE_SIZE / 4 + PAGE_SIZE / 2;
> - cmds_size = PAGE_SIZE / 4;
> + desc = blob + CTB_DESC_SIZE;
> + cmds = blob + 2 * CTB_DESC_SIZE + CTB_H2G_BUFFER_SIZE;
> + cmds_size = 

Re: [RFC PATCH 12/97] drm/i915/guc: Don't repeat CTB layout calculations

2021-05-24 Thread Matthew Brost
On Thu, May 06, 2021 at 12:13:26PM -0700, Matthew Brost wrote:
> From: Michal Wajdeczko 
> 
> We can retrieve offsets to cmds buffers and descriptor from
> actual pointers that we already keep locally.
> 
> Signed-off-by: Michal Wajdeczko 
> Signed-off-by: Matthew Brost 
> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 16 ++--
>  1 file changed, 10 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> index dbece569fbe4..fbd6bd20f588 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> @@ -244,6 +244,7 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct)
>  {
>   struct intel_guc *guc = ct_to_guc(ct);
>   u32 base, cmds;
> + void *blob;
>   int err;
>   int i;
>  
> @@ -251,15 +252,18 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct)
>  
>   /* vma should be already allocated and map'ed */
>   GEM_BUG_ON(!ct->vma);
> + GEM_BUG_ON(!i915_gem_object_has_pinned_pages(ct->vma->obj));

This doesn't really have anything to do with this patch, but again this
patch will be squashed into a large patch updating the GuC firmware, so
I think this is fine.

With that:
Reviewed-by: Matthew Brost 

>   base = intel_guc_ggtt_offset(guc, ct->vma);
>  
> - /* (re)initialize descriptors
> -  * cmds buffers are in the second half of the blob page
> -  */
> + /* blob should start with send descriptor */
> + blob = __px_vaddr(ct->vma->obj);
> + GEM_BUG_ON(blob != ct->ctbs[CTB_SEND].desc);
> +
> + /* (re)initialize descriptors */
>   for (i = 0; i < ARRAY_SIZE(ct->ctbs); i++) {
>   GEM_BUG_ON((i != CTB_SEND) && (i != CTB_RECV));
>  
> - cmds = base + PAGE_SIZE / 4 * i + PAGE_SIZE / 2;
> + cmds = base + ptrdiff(ct->ctbs[i].cmds, blob);
>   CT_DEBUG(ct, "%d: cmds addr=%#x\n", i, cmds);
>  
>   guc_ct_buffer_reset(>ctbs[i], cmds);
> @@ -269,12 +273,12 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct)
>* Register both CT buffers starting with RECV buffer.
>* Descriptors are in first half of the blob.
>*/
> - err = ct_register_buffer(ct, base + PAGE_SIZE / 4 * CTB_RECV,
> + err = ct_register_buffer(ct, base + ptrdiff(ct->ctbs[CTB_RECV].desc, 
> blob),
>INTEL_GUC_CT_BUFFER_TYPE_RECV);
>   if (unlikely(err))
>   goto err_out;
>  
> - err = ct_register_buffer(ct, base + PAGE_SIZE / 4 * CTB_SEND,
> + err = ct_register_buffer(ct, base + ptrdiff(ct->ctbs[CTB_SEND].desc, 
> blob),
>INTEL_GUC_CT_BUFFER_TYPE_SEND);
>   if (unlikely(err))
>   goto err_deregister;
> -- 
> 2.28.0
> 


Re: [RFC PATCH 11/97] drm/i915/guc: Only rely on own CTB size

2021-05-24 Thread Matthew Brost
On Thu, May 06, 2021 at 12:13:25PM -0700, Matthew Brost wrote:
> From: Michal Wajdeczko 
> 
> In upcoming GuC firmware, CTB size will be removed from the CTB
> descriptor so we must keep it locally for any calculations.
> 
> While around, improve some debug messages and helpers.
> 

desc->size is still used in the patch and really shouldn't be per this
comment but a patch later in the series drops it. Seeing as this patch
and that patch are going to squashed into a single patch upgrading the
GuC firmware I think that is ok.

With that:
Reviewed-by: Matthew Brost  

> Signed-off-by: Michal Wajdeczko 
> Signed-off-by: Matthew Brost 
> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 55 +--
>  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h |  2 +
>  2 files changed, 43 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> index 4cc8c0b71699..dbece569fbe4 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> @@ -90,6 +90,24 @@ static void guc_ct_buffer_desc_init(struct 
> guc_ct_buffer_desc *desc,
>   desc->owner = CTB_OWNER_HOST;
>  }
>  
> +static void guc_ct_buffer_reset(struct intel_guc_ct_buffer *ctb, u32 
> cmds_addr)
> +{
> + guc_ct_buffer_desc_init(ctb->desc, cmds_addr, ctb->size);
> +}
> +
> +static void guc_ct_buffer_init(struct intel_guc_ct_buffer *ctb,
> +struct guc_ct_buffer_desc *desc,
> +u32 *cmds, u32 size)
> +{
> + GEM_BUG_ON(size % 4);
> +
> + ctb->desc = desc;
> + ctb->cmds = cmds;
> + ctb->size = size;
> +
> + guc_ct_buffer_reset(ctb, 0);
> +}
> +
>  static int guc_action_register_ct_buffer(struct intel_guc *guc,
>u32 desc_addr,
>u32 type)
> @@ -148,7 +166,10 @@ static int ct_deregister_buffer(struct intel_guc_ct *ct, 
> u32 type)
>  int intel_guc_ct_init(struct intel_guc_ct *ct)
>  {
>   struct intel_guc *guc = ct_to_guc(ct);
> + struct guc_ct_buffer_desc *desc;
> + u32 blob_size;
>   void *blob;
> + u32 *cmds;
>   int err;
>   int i;
>  
> @@ -176,19 +197,24 @@ int intel_guc_ct_init(struct intel_guc_ct *ct)
>* other code will need updating as well.
>*/
>  
> - err = intel_guc_allocate_and_map_vma(guc, PAGE_SIZE, >vma, );
> + blob_size = PAGE_SIZE;
> + err = intel_guc_allocate_and_map_vma(guc, blob_size, >vma, );
>   if (unlikely(err)) {
> - CT_ERROR(ct, "Failed to allocate CT channel (err=%d)\n", err);
> + CT_PROBE_ERROR(ct, "Failed to allocate %u for CTB data (%pe)\n",
> +blob_size, ERR_PTR(err));
>   return err;
>   }
>  
> - CT_DEBUG(ct, "vma base=%#x\n", intel_guc_ggtt_offset(guc, ct->vma));
> + CT_DEBUG(ct, "base=%#x size=%u\n", intel_guc_ggtt_offset(guc, ct->vma), 
> blob_size);
>  
>   /* store pointers to desc and cmds */
>   for (i = 0; i < ARRAY_SIZE(ct->ctbs); i++) {
>   GEM_BUG_ON((i !=  CTB_SEND) && (i != CTB_RECV));
> - ct->ctbs[i].desc = blob + PAGE_SIZE/4 * i;
> - ct->ctbs[i].cmds = blob + PAGE_SIZE/4 * i + PAGE_SIZE/2;
> +
> + desc = blob + PAGE_SIZE / 4 * i;
> + cmds = blob + PAGE_SIZE / 4 * i + PAGE_SIZE / 2;
> +
> + guc_ct_buffer_init(>ctbs[i], desc, cmds, PAGE_SIZE / 4);
>   }
>  
>   return 0;
> @@ -217,7 +243,7 @@ void intel_guc_ct_fini(struct intel_guc_ct *ct)
>  int intel_guc_ct_enable(struct intel_guc_ct *ct)
>  {
>   struct intel_guc *guc = ct_to_guc(ct);
> - u32 base, cmds, size;
> + u32 base, cmds;
>   int err;
>   int i;
>  
> @@ -232,10 +258,11 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct)
>*/
>   for (i = 0; i < ARRAY_SIZE(ct->ctbs); i++) {
>   GEM_BUG_ON((i != CTB_SEND) && (i != CTB_RECV));
> +
>   cmds = base + PAGE_SIZE / 4 * i + PAGE_SIZE / 2;
> - size = PAGE_SIZE / 4;
> - CT_DEBUG(ct, "%d: addr=%#x size=%u\n", i, cmds, size);
> - guc_ct_buffer_desc_init(ct->ctbs[i].desc, cmds, size);
> + CT_DEBUG(ct, "%d: cmds addr=%#x\n", i, cmds);
> +
> + guc_ct_buffer_reset(>ctbs[i], cmds);
>   }
>  
>   /*
> @@ -259,7 +286,7 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct)
>  err_deregister:
>   ct_deregister_buffer(ct, INTEL_GUC_CT_BUFFER_TYPE_RECV);
>  err_out:
> - CT_PROBE_ERROR(ct, "Failed to open channel (err=%d)\n", err);
> + CT_PROBE_ERROR(ct, "Failed to enable CTB (%pe)\n", ERR_PTR(err));
>   return err;
>  }
>  
> @@ -314,7 +341,7 @@ static int ct_write(struct intel_guc_ct *ct,
>   struct guc_ct_buffer_desc *desc = ctb->desc;
>   u32 head = desc->head;
>   u32 tail = desc->tail;
> - u32 size = desc->size;
> + u32 size = ctb->size;
>   u32 used;
> 

Re: [RFC PATCH 09/97] drm/i915/guc: Stop using fence/status from CTB descriptor

2021-05-24 Thread Matthew Brost
On Thu, May 06, 2021 at 12:13:23PM -0700, Matthew Brost wrote:
> From: Michal Wajdeczko 
> 
> Stop using fence/status from CTB descriptor as future GuC ABI will
> no longer support replies over CTB descriptor.
> 
> Signed-off-by: Michal Wajdeczko 
> Signed-off-by: Matthew Brost 

Reviewed-by: Matthew Brost 

> ---
>  .../gt/uc/abi/guc_communication_ctb_abi.h |  4 +-
>  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 72 ++-
>  2 files changed, 6 insertions(+), 70 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h 
> b/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h
> index ebd8c3e0e4bb..d38935f47ecf 100644
> --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h
> +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h
> @@ -71,8 +71,8 @@ struct guc_ct_buffer_desc {
>   u32 head;   /* offset updated by GuC*/
>   u32 tail;   /* offset updated by owner */
>   u32 is_in_error;/* error indicator */
> - u32 fence;  /* fence updated by GuC */
> - u32 status; /* status updated by GuC */
> + u32 reserved1;
> + u32 reserved2;
>   u32 owner;  /* id of the channel owner */
>   u32 owner_sub_id;   /* owner-defined field for extra tracking */
>   u32 reserved[5];
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> index 25618649048f..4cc8c0b71699 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> @@ -90,13 +90,6 @@ static void guc_ct_buffer_desc_init(struct 
> guc_ct_buffer_desc *desc,
>   desc->owner = CTB_OWNER_HOST;
>  }
>  
> -static void guc_ct_buffer_desc_reset(struct guc_ct_buffer_desc *desc)
> -{
> - desc->head = 0;
> - desc->tail = 0;
> - desc->is_in_error = 0;
> -}
> -
>  static int guc_action_register_ct_buffer(struct intel_guc *guc,
>u32 desc_addr,
>u32 type)
> @@ -315,8 +308,7 @@ static u32 ct_get_next_fence(struct intel_guc_ct *ct)
>  static int ct_write(struct intel_guc_ct *ct,
>   const u32 *action,
>   u32 len /* in dwords */,
> - u32 fence,
> - bool want_response)
> + u32 fence)
>  {
>   struct intel_guc_ct_buffer *ctb = >ctbs[CTB_SEND];
>   struct guc_ct_buffer_desc *desc = ctb->desc;
> @@ -360,8 +352,7 @@ static int ct_write(struct intel_guc_ct *ct,
>* DW2+: action data
>*/
>   header = (len << GUC_CT_MSG_LEN_SHIFT) |
> -  (GUC_CT_MSG_WRITE_FENCE_TO_DESC) |
> -  (want_response ? GUC_CT_MSG_SEND_STATUS : 0) |
> +  GUC_CT_MSG_SEND_STATUS |
>(action[0] << GUC_CT_MSG_ACTION_SHIFT);
>  
>   CT_DEBUG(ct, "writing %*ph %*ph %*ph\n",
> @@ -390,56 +381,6 @@ static int ct_write(struct intel_guc_ct *ct,
>   return -EPIPE;
>  }
>  
> -/**
> - * wait_for_ctb_desc_update - Wait for the CT buffer descriptor update.
> - * @desc:buffer descriptor
> - * @fence:   response fence
> - * @status:  placeholder for status
> - *
> - * Guc will update CT buffer descriptor with new fence and status
> - * after processing the command identified by the fence. Wait for
> - * specified fence and then read from the descriptor status of the
> - * command.
> - *
> - * Return:
> - * * 0 response received (status is valid)
> - * * -ETIMEDOUT no response within hardcoded timeout
> - * * -EPROTO no response, CT buffer is in error
> - */
> -static int wait_for_ctb_desc_update(struct guc_ct_buffer_desc *desc,
> - u32 fence,
> - u32 *status)
> -{
> - int err;
> -
> - /*
> -  * Fast commands should complete in less than 10us, so sample quickly
> -  * up to that length of time, then switch to a slower sleep-wait loop.
> -  * No GuC command should ever take longer than 10ms.
> -  */
> -#define done (READ_ONCE(desc->fence) == fence)
> - err = wait_for_us(done, 10);
> - if (err)
> - err = wait_for(done, 10);
> -#undef done
> -
> - if (unlikely(err)) {
> - DRM_ERROR("CT: fence %u failed; reported fence=%u\n",
> -   fence, desc->fence);
> -
> - if (WARN_ON(desc->is_in_error)) {
> - /* Something went wrong with the messaging, try to reset
> -  * the buffer and hope for the best
> -  */
> - guc_ct_buffer_desc_reset(desc);
> - err = -EPROTO;
> - }
> - }
> -
> - *status = desc->status;
> - return err;
> -}
> -
>  /**
>   * wait_for_ct_request_update - Wait for CT request state update.
>   * @req: pointer to pending request
> @@ -483,8 +424,6 @@ static int ct_send(struct intel_guc_ct *ct,
>  

[PATCH] drm/ast: Add detect function support

2021-05-24 Thread ainux . wang
From: Ainux 

The existence of the connector cannot be detected,
so add the detect function to support.

Signed-off-by: Ainux 
---
 drivers/gpu/drm/ast/ast_drv.c  |  2 ++
 drivers/gpu/drm/ast/ast_mode.c | 19 ++-
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
index 5aa452b4efe6..6698bbc405e3 100644
--- a/drivers/gpu/drm/ast/ast_drv.c
+++ b/drivers/gpu/drm/ast/ast_drv.c
@@ -128,6 +128,8 @@ static int ast_pci_probe(struct pci_dev *pdev, const struct 
pci_device_id *ent)
 
drm_fbdev_generic_setup(dev, 32);
 
+   drm_kms_helper_poll_init(dev);
+
return 0;
 }
 
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 36d9575aa27b..b4dd4c29b353 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -1293,6 +1293,21 @@ static enum drm_mode_status ast_mode_valid(struct 
drm_connector *connector,
return flags;
 }
 
+static enum drm_connector_status ast_connector_detect(struct drm_connector
+  *connector, bool force)
+{
+   int r;
+   enum drm_connector_status ret = connector_status_connected;
+
+   r = ast_get_modes(connector);
+   if (r)
+   ret = connector_status_connected;
+   else
+   ret = connector_status_disconnected;
+
+   return ret;
+}
+
 static void ast_connector_destroy(struct drm_connector *connector)
 {
struct ast_connector *ast_connector = to_ast_connector(connector);
@@ -1307,6 +1322,7 @@ static const struct drm_connector_helper_funcs 
ast_connector_helper_funcs = {
 
 static const struct drm_connector_funcs ast_connector_funcs = {
.reset = drm_atomic_helper_connector_reset,
+   .detect = ast_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = ast_connector_destroy,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
@@ -1334,7 +1350,8 @@ static int ast_connector_init(struct drm_device *dev)
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;
 
-   connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+   connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+   DRM_CONNECTOR_POLL_DISCONNECT;
 
drm_connector_attach_encoder(connector, encoder);
 
-- 
2.18.1



Re: [PATCH v9 07/10] mm: Device exclusive memory access

2021-05-24 Thread John Hubbard

On 5/24/21 3:11 PM, Andrew Morton wrote:

...

  Documentation/vm/hmm.rst |  17 
  include/linux/mmu_notifier.h |   6 ++
  include/linux/rmap.h |   4 +
  include/linux/swap.h |   7 +-
  include/linux/swapops.h  |  44 -
  mm/hmm.c |   5 +
  mm/memory.c  | 128 +++-
  mm/mprotect.c|   8 ++
  mm/page_vma_mapped.c |   9 +-
  mm/rmap.c| 186 +++
  10 files changed, 405 insertions(+), 9 deletions(-)



This is quite a lot of code added to core MM for a single driver.

Is there any expectation that other drivers will use this code?


Yes! This should work for GPUs (and potentially, other devices) that support
OpenCL SVM atomic accesses on the device. I haven't looked into how amdgpu
works in any detail, but that's certainly at the top of the list of likely
additional callers.



Is there a way of reducing the impact (code size, at least) for systems
which don't need this code?


I'll leave this question to others for the moment, in order to answer
the "do we need it at all" points.



How beneficial is this code to nouveau users?  I see that it permits a
part of OpenCL to be implemented, but how useful/important is this in
the real world?



So this is interesting. Right now, OpenCL support in Nouveau is rather new
and so probably not a huge impact yet. However, we've built up enough experience
with CUDA and OpenCL to learn that atomic operations, as part of the user
space programming model, are a super big deal. Atomic operations are so
useful and important that I'd expect many OpenCL SVM users to be uninterested in
programming models that lack atomic operations for GPU compute programs.

Again, this doesn't rule out future, non-GPU accelerator devices that may
come along.

Atomic ops are just a really important piece of high-end multi-threaded
programming, it turns out. So this is the beginning of support for an
important building block for general purpose programming on devices that
have GPU-like memory models.


thanks,
--
John Hubbard
NVIDIA


Re: [RFC PATCH 23/97] drm/i915/guc: Support per context scheduling policies

2021-05-24 Thread Matthew Brost
On Thu, May 06, 2021 at 12:13:37PM -0700, Matthew Brost wrote:
> From: John Harrison 
> 
> GuC firmware v53.0.0 introduced per context scheduling policies. This
> includes changes to some of the ADS structures which are required to
> load the firmware even if not using GuC submission.
> 
> Signed-off-by: John Harrison 
> Signed-off-by: Matthew Brost 

Reviewed-by: Matthew Brost 

> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c  | 26 +++--
>  drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 31 +
>  2 files changed, 11 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
> index 17526717368c..648e1767b17a 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
> @@ -58,30 +58,12 @@ static u32 guc_ads_blob_size(struct intel_guc *guc)
>  guc_ads_private_data_size(guc);
>  }
>  
> -static void guc_policy_init(struct guc_policy *policy)
> -{
> - policy->execution_quantum = POLICY_DEFAULT_EXECUTION_QUANTUM_US;
> - policy->preemption_time = POLICY_DEFAULT_PREEMPTION_TIME_US;
> - policy->fault_time = POLICY_DEFAULT_FAULT_TIME_US;
> - policy->policy_flags = 0;
> -}
> -
>  static void guc_policies_init(struct guc_policies *policies)
>  {
> - struct guc_policy *policy;
> - u32 p, i;
> -
> - policies->dpc_promote_time = POLICY_DEFAULT_DPC_PROMOTE_TIME_US;
> - policies->max_num_work_items = POLICY_MAX_NUM_WI;
> -
> - for (p = 0; p < GUC_CLIENT_PRIORITY_NUM; p++) {
> - for (i = 0; i < GUC_MAX_ENGINE_CLASSES; i++) {
> - policy = >policy[p][i];
> -
> - guc_policy_init(policy);
> - }
> - }
> -
> + policies->dpc_promote_time = GLOBAL_POLICY_DEFAULT_DPC_PROMOTE_TIME_US;
> + policies->max_num_work_items = GLOBAL_POLICY_MAX_NUM_WI;
> + /* Disable automatic resets as not yet supported. */
> + policies->global_flags = GLOBAL_POLICY_DISABLE_ENGINE_RESET;
>   policies->is_valid = 1;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> index d445f6b77db4..95db4a7d3f4d 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> @@ -221,32 +221,14 @@ struct guc_stage_desc {
>  
>  /* Scheduling policy settings */
>  
> -/* Reset engine upon preempt failure */
> -#define POLICY_RESET_ENGINE  (1<<0)
> -/* Preempt to idle on quantum expiry */
> -#define POLICY_PREEMPT_TO_IDLE   (1<<1)
> -
> -#define POLICY_MAX_NUM_WI 15
> -#define POLICY_DEFAULT_DPC_PROMOTE_TIME_US 50
> -#define POLICY_DEFAULT_EXECUTION_QUANTUM_US 100
> -#define POLICY_DEFAULT_PREEMPTION_TIME_US 50
> -#define POLICY_DEFAULT_FAULT_TIME_US 25
> -
> -struct guc_policy {
> - /* Time for one workload to execute. (in micro seconds) */
> - u32 execution_quantum;
> - /* Time to wait for a preemption request to completed before issuing a
> -  * reset. (in micro seconds). */
> - u32 preemption_time;
> - /* How much time to allow to run after the first fault is observed.
> -  * Then preempt afterwards. (in micro seconds) */
> - u32 fault_time;
> - u32 policy_flags;
> - u32 reserved[8];
> -} __packed;
> +#define GLOBAL_POLICY_MAX_NUM_WI 15
> +
> +/* Don't reset an engine upon preemption failure */
> +#define GLOBAL_POLICY_DISABLE_ENGINE_RESET   BIT(0)
> +
> +#define GLOBAL_POLICY_DEFAULT_DPC_PROMOTE_TIME_US 50
>  
>  struct guc_policies {
> - struct guc_policy 
> policy[GUC_CLIENT_PRIORITY_NUM][GUC_MAX_ENGINE_CLASSES];
>   u32 submission_queue_depth[GUC_MAX_ENGINE_CLASSES];
>   /* In micro seconds. How much time to allow before DPC processing is
>* called back via interrupt (to prevent DPC queue drain starving).
> @@ -260,6 +242,7 @@ struct guc_policies {
>* idle. */
>   u32 max_num_work_items;
>  
> + u32 global_flags;
>   u32 reserved[4];
>  } __packed;
>  
> -- 
> 2.28.0
> 


Re: [RFC PATCH 28/97] drm/i915/guc: Kill guc_clients.ct_pool

2021-05-24 Thread Matthew Brost
On Thu, May 06, 2021 at 12:13:42PM -0700, Matthew Brost wrote:
> From: Michal Wajdeczko 
> 
> CTB pool is now maintained internally by the GuC as part of its
> "private data". No need to allocate separate buffer and pass it
> to GuC as yet another ADS.
> 
> GuC: 57.0.0
> Signed-off-by: Michal Wajdeczko 
> Signed-off-by: Matthew Brost 
> Cc: Janusz Krzysztofik 
> Cc: Matthew Brost 

Reviewed-by: Matthew Brost 

> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c  | 12 
>  drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 12 +---
>  2 files changed, 1 insertion(+), 23 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
> index 648e1767b17a..775f00d706fa 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
> @@ -25,8 +25,6 @@
>   *  +---+
>   *  | guc_clients_info  |
>   *  +---+
> - *  | guc_ct_pool_entry[size]   |
> - *  +---+
>   *  | padding   |
>   *  +---+ <== 4K aligned
>   *  | private data  |
> @@ -39,7 +37,6 @@ struct __guc_ads_blob {
>   struct guc_policies policies;
>   struct guc_gt_system_info system_info;
>   struct guc_clients_info clients_info;
> - struct guc_ct_pool_entry ct_pool[GUC_CT_POOL_SIZE];
>  } __packed;
>  
>  static u32 guc_ads_private_data_size(struct intel_guc *guc)
> @@ -67,11 +64,6 @@ static void guc_policies_init(struct guc_policies 
> *policies)
>   policies->is_valid = 1;
>  }
>  
> -static void guc_ct_pool_entries_init(struct guc_ct_pool_entry *pool, u32 num)
> -{
> - memset(pool, 0, num * sizeof(*pool));
> -}
> -
>  static void guc_mapping_table_init(struct intel_gt *gt,
>  struct guc_gt_system_info *system_info)
>  {
> @@ -157,11 +149,7 @@ static void __guc_ads_init(struct intel_guc *guc)
>   base = intel_guc_ggtt_offset(guc, guc->ads_vma);
>  
>   /* Clients info  */
> - guc_ct_pool_entries_init(blob->ct_pool, ARRAY_SIZE(blob->ct_pool));
> -
>   blob->clients_info.clients_num = 1;
> - blob->clients_info.ct_pool_addr = base + ptr_offset(blob, ct_pool);
> - blob->clients_info.ct_pool_count = ARRAY_SIZE(blob->ct_pool);
>  
>   /* ADS */
>   blob->ads.scheduler_policies = base + ptr_offset(blob, policies);
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> index 95db4a7d3f4d..301b173a26bc 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> @@ -269,19 +269,9 @@ struct guc_gt_system_info {
>  } __packed;
>  
>  /* Clients info */
> -struct guc_ct_pool_entry {
> - struct guc_ct_buffer_desc desc;
> - u32 reserved[7];
> -} __packed;
> -
> -#define GUC_CT_POOL_SIZE 2
> -
>  struct guc_clients_info {
>   u32 clients_num;
> - u32 reserved0[13];
> - u32 ct_pool_addr;
> - u32 ct_pool_count;
> - u32 reserved[4];
> + u32 reserved[19];
>  } __packed;
>  
>  /* GuC Additional Data Struct */
> -- 
> 2.28.0
> 


[PATCH v5 3/3] drm_dp_cec: add MST support

2021-05-24 Thread Sam McNally
With DP v2.0 errata E5, CEC tunneling can be supported through an MST
topology.

When tunneling CEC through an MST port, CEC IRQs are delivered via a
sink event notify message; when a sink event notify message is received,
trigger CEC IRQ handling - ESI1 is not used for remote CEC IRQs so its
value is not checked.

Register and unregister for all MST connectors, ensuring their
drm_dp_aux_cec struct won't be accessed uninitialized.

Reviewed-by: Hans Verkuil 
Signed-off-by: Sam McNally 
---

(no changes since v4)

Changes in v4:
- Removed use of work queues
- Updated checks of aux.transfer to accept aux.is_remote

Changes in v3:
- Fixed whitespace in drm_dp_cec_mst_irq_work()
- Moved drm_dp_cec_mst_set_edid_work() with the other set_edid functions

Changes in v2:
- Used aux->is_remote instead of aux->cec.is_mst, removing the need for
  the previous patch in the series
- Added a defensive check for null edid in the deferred set_edid work,
  in case the edid is no longer valid at that point

 drivers/gpu/drm/drm_dp_cec.c  | 20 
 drivers/gpu/drm/drm_dp_mst_topology.c | 24 
 2 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_cec.c b/drivers/gpu/drm/drm_dp_cec.c
index 3ab2609f9ec7..1abd3f4654dc 100644
--- a/drivers/gpu/drm/drm_dp_cec.c
+++ b/drivers/gpu/drm/drm_dp_cec.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /*
  * Unfortunately it turns out that we have a chicken-and-egg situation
@@ -245,13 +246,22 @@ void drm_dp_cec_irq(struct drm_dp_aux *aux)
int ret;
 
/* No transfer function was set, so not a DP connector */
-   if (!aux->transfer)
+   if (!aux->transfer && !aux->is_remote)
return;
 
mutex_lock(>cec.lock);
if (!aux->cec.adap)
goto unlock;
 
+   if (aux->is_remote) {
+   /*
+* For remote connectors, CEC IRQ is triggered by an explicit
+* message so ESI1 is not involved.
+*/
+   drm_dp_cec_handle_irq(aux);
+   goto unlock;
+   }
+
ret = drm_dp_dpcd_readb(aux, DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1,
_irq);
if (ret < 0 || !(cec_irq & DP_CEC_IRQ))
@@ -307,7 +317,7 @@ void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const 
struct edid *edid)
u8 cap;
 
/* No transfer function was set, so not a DP connector */
-   if (!aux->transfer)
+   if (!aux->transfer && !aux->is_remote)
return;
 
 #ifndef CONFIG_MEDIA_CEC_RC
@@ -375,6 +385,7 @@ void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const 
struct edid *edid)
 unlock:
mutex_unlock(>cec.lock);
 }
+
 EXPORT_SYMBOL(drm_dp_cec_set_edid);
 
 /*
@@ -383,7 +394,7 @@ EXPORT_SYMBOL(drm_dp_cec_set_edid);
 void drm_dp_cec_unset_edid(struct drm_dp_aux *aux)
 {
/* No transfer function was set, so not a DP connector */
-   if (!aux->transfer)
+   if (!aux->transfer && !aux->is_remote)
return;
 
cancel_delayed_work_sync(>cec.unregister_work);
@@ -393,6 +404,7 @@ void drm_dp_cec_unset_edid(struct drm_dp_aux *aux)
goto unlock;
 
cec_phys_addr_invalidate(aux->cec.adap);
+
/*
 * We're done if we want to keep the CEC device
 * (drm_dp_cec_unregister_delay is >= NEVER_UNREG_DELAY) or if the
@@ -428,7 +440,7 @@ void drm_dp_cec_register_connector(struct drm_dp_aux *aux,
   struct drm_connector *connector)
 {
WARN_ON(aux->cec.adap);
-   if (WARN_ON(!aux->transfer))
+   if (WARN_ON(!aux->transfer && !aux->is_remote))
return;
aux->cec.connector = connector;
INIT_DELAYED_WORK(>cec.unregister_work,
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 29aad3b6b31a..5612caf9fb49 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -2359,6 +2359,8 @@ static void build_mst_prop_path(const struct 
drm_dp_mst_branch *mstb,
 int drm_dp_mst_connector_late_register(struct drm_connector *connector,
   struct drm_dp_mst_port *port)
 {
+   drm_dp_cec_register_connector(>aux, connector);
+
drm_dbg_kms(port->mgr->dev, "registering %s remote bus for %s\n",
port->aux.name, connector->kdev->kobj.name);
 
@@ -2382,6 +2384,8 @@ void drm_dp_mst_connector_early_unregister(struct 
drm_connector *connector,
drm_dbg_kms(port->mgr->dev, "unregistering %s remote bus for %s\n",
port->aux.name, connector->kdev->kobj.name);
drm_dp_aux_unregister_devnode(>aux);
+
+   drm_dp_cec_unregister_connector(>aux);
 }
 EXPORT_SYMBOL(drm_dp_mst_connector_early_unregister);
 
@@ -2682,6 +2686,21 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch 
*mstb,
queue_work(system_long_wq, >mgr->work);

[PATCH v5 1/3] drm/dp_mst: Add self-tests for up requests

2021-05-24 Thread Sam McNally
Up requests are decoded by drm_dp_sideband_parse_req(), which operates
on a drm_dp_sideband_msg_rx, unlike down requests. Expand the existing
self-test helper sideband_msg_req_encode_decode() to copy the message
contents and length from a drm_dp_sideband_msg_tx to
drm_dp_sideband_msg_rx and use the parse function under test in place of
decode. Add an additional helper for testing clearly-invalid up
messages, verifying that parse rejects them.

Add support for currently-supported up requests to
drm_dp_dump_sideband_msg_req_body(); add support to
drm_dp_encode_sideband_req() to allow encoding for the self-tests.

Add self-tests for CONNECTION_STATUS_NOTIFY and RESOURCE_STATUS_NOTIFY.

Signed-off-by: Sam McNally 
---

Changes in v5:
- Set mock device name to more clearly attribute error/debug logging to
  the self-test, in particular for cases where failures are expected

Changes in v4:
- New in v4

 drivers/gpu/drm/drm_dp_mst_topology.c |  54 ++-
 .../gpu/drm/drm_dp_mst_topology_internal.h|   4 +
 .../drm/selftests/test-drm_dp_mst_helper.c| 149 --
 3 files changed, 192 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 54604633e65c..573f39a3dc16 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -442,6 +442,37 @@ drm_dp_encode_sideband_req(const struct 
drm_dp_sideband_msg_req_body *req,
idx++;
}
break;
+   case DP_CONNECTION_STATUS_NOTIFY: {
+   const struct drm_dp_connection_status_notify *msg;
+
+   msg = >u.conn_stat;
+   buf[idx] = (msg->port_number & 0xf) << 4;
+   idx++;
+   memcpy(>msg[idx], msg->guid, 16);
+   idx += 16;
+   raw->msg[idx] = 0;
+   raw->msg[idx] |= msg->legacy_device_plug_status ? BIT(6) : 0;
+   raw->msg[idx] |= msg->displayport_device_plug_status ? BIT(5) : 
0;
+   raw->msg[idx] |= msg->message_capability_status ? BIT(4) : 0;
+   raw->msg[idx] |= msg->input_port ? BIT(3) : 0;
+   raw->msg[idx] |= FIELD_PREP(GENMASK(2, 0), 
msg->peer_device_type);
+   idx++;
+   break;
+   }
+   case DP_RESOURCE_STATUS_NOTIFY: {
+   const struct drm_dp_resource_status_notify *msg;
+
+   msg = >u.resource_stat;
+   buf[idx] = (msg->port_number & 0xf) << 4;
+   idx++;
+   memcpy(>msg[idx], msg->guid, 16);
+   idx += 16;
+   buf[idx] = (msg->available_pbn & 0xff00) >> 8;
+   idx++;
+   buf[idx] = (msg->available_pbn & 0xff);
+   idx++;
+   break;
+   }
}
raw->cur_len = idx;
 }
@@ -672,6 +703,22 @@ drm_dp_dump_sideband_msg_req_body(const struct 
drm_dp_sideband_msg_req_body *req
  req->u.enc_status.stream_behavior,
  req->u.enc_status.valid_stream_behavior);
break;
+   case DP_CONNECTION_STATUS_NOTIFY:
+   P("port=%d guid=%*ph legacy=%d displayport=%d messaging=%d 
input=%d peer_type=%d",
+ req->u.conn_stat.port_number,
+ (int)ARRAY_SIZE(req->u.conn_stat.guid), req->u.conn_stat.guid,
+ req->u.conn_stat.legacy_device_plug_status,
+ req->u.conn_stat.displayport_device_plug_status,
+ req->u.conn_stat.message_capability_status,
+ req->u.conn_stat.input_port,
+ req->u.conn_stat.peer_device_type);
+   break;
+   case DP_RESOURCE_STATUS_NOTIFY:
+   P("port=%d guid=%*ph pbn=%d",
+ req->u.resource_stat.port_number,
+ (int)ARRAY_SIZE(req->u.resource_stat.guid), 
req->u.resource_stat.guid,
+ req->u.resource_stat.available_pbn);
+   break;
default:
P("???\n");
break;
@@ -1116,9 +1163,9 @@ static bool 
drm_dp_sideband_parse_resource_status_notify(const struct drm_dp_mst
return false;
 }
 
-static bool drm_dp_sideband_parse_req(const struct drm_dp_mst_topology_mgr 
*mgr,
- struct drm_dp_sideband_msg_rx *raw,
- struct drm_dp_sideband_msg_req_body *msg)
+bool drm_dp_sideband_parse_req(const struct drm_dp_mst_topology_mgr *mgr,
+  struct drm_dp_sideband_msg_rx *raw,
+  struct drm_dp_sideband_msg_req_body *msg)
 {
memset(msg, 0, sizeof(*msg));
msg->req_type = (raw->msg[0] & 0x7f);
@@ -1134,6 +1181,7 @@ static bool drm_dp_sideband_parse_req(const struct 
drm_dp_mst_topology_mgr *mgr,
return false;
}
 }
+EXPORT_SYMBOL_FOR_TESTS_ONLY(drm_dp_sideband_parse_req);
 
 static void build_dpcd_write(struct 

[PATCH v5 2/3] drm/dp_mst: Add support for sink event notify messages

2021-05-24 Thread Sam McNally
Sink event notify messages are used for MST CEC IRQs. Add parsing
support for sink event notify messages in preparation for handling MST
CEC IRQs.

Signed-off-by: Sam McNally 
---

(no changes since v4)

Changes in v4:
- Changed logging to use drm_dbg_kms()
- Added self-test

 drivers/gpu/drm/drm_dp_mst_topology.c | 57 ++-
 .../drm/selftests/test-drm_dp_mst_helper.c|  8 +++
 include/drm/drm_dp_mst_helper.h   | 14 +
 3 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 573f39a3dc16..29aad3b6b31a 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -473,6 +473,20 @@ drm_dp_encode_sideband_req(const struct 
drm_dp_sideband_msg_req_body *req,
idx++;
break;
}
+   case DP_SINK_EVENT_NOTIFY: {
+   const struct drm_dp_sink_event_notify *msg;
+
+   msg = >u.sink_event;
+   buf[idx] = (msg->port_number & 0xf) << 4;
+   idx++;
+   memcpy(>msg[idx], msg->guid, 16);
+   idx += 16;
+   buf[idx] = (msg->event_id & 0xff00) >> 8;
+   idx++;
+   buf[idx] = (msg->event_id & 0xff);
+   idx++;
+   break;
+   }
}
raw->cur_len = idx;
 }
@@ -719,6 +733,12 @@ drm_dp_dump_sideband_msg_req_body(const struct 
drm_dp_sideband_msg_req_body *req
  (int)ARRAY_SIZE(req->u.resource_stat.guid), 
req->u.resource_stat.guid,
  req->u.resource_stat.available_pbn);
break;
+   case DP_SINK_EVENT_NOTIFY:
+   P("port=%d guid=%*ph event=%d",
+ req->u.sink_event.port_number,
+ (int)ARRAY_SIZE(req->u.sink_event.guid), 
req->u.sink_event.guid,
+ req->u.sink_event.event_id);
+   break;
default:
P("???\n");
break;
@@ -1163,6 +1183,30 @@ static bool 
drm_dp_sideband_parse_resource_status_notify(const struct drm_dp_mst
return false;
 }
 
+static bool drm_dp_sideband_parse_sink_event_notify(const struct 
drm_dp_mst_topology_mgr *mgr,
+   struct drm_dp_sideband_msg_rx *raw,
+   struct drm_dp_sideband_msg_req_body *msg)
+{
+   int idx = 1;
+
+   msg->u.sink_event.port_number = (raw->msg[idx] & 0xf0) >> 4;
+   idx++;
+   if (idx > raw->curlen)
+   goto fail_len;
+
+   memcpy(msg->u.sink_event.guid, >msg[idx], 16);
+   idx += 16;
+   if (idx > raw->curlen)
+   goto fail_len;
+
+   msg->u.sink_event.event_id = (raw->msg[idx] << 8) | (raw->msg[idx + 1]);
+   idx++;
+   return true;
+fail_len:
+   drm_dbg_kms(mgr->dev, "sink event notify parse length fail %d %d\n", 
idx, raw->curlen);
+   return false;
+}
+
 bool drm_dp_sideband_parse_req(const struct drm_dp_mst_topology_mgr *mgr,
   struct drm_dp_sideband_msg_rx *raw,
   struct drm_dp_sideband_msg_req_body *msg)
@@ -1175,6 +1219,8 @@ bool drm_dp_sideband_parse_req(const struct 
drm_dp_mst_topology_mgr *mgr,
return drm_dp_sideband_parse_connection_status_notify(mgr, raw, 
msg);
case DP_RESOURCE_STATUS_NOTIFY:
return drm_dp_sideband_parse_resource_status_notify(mgr, raw, 
msg);
+   case DP_SINK_EVENT_NOTIFY:
+   return drm_dp_sideband_parse_sink_event_notify(mgr, raw, msg);
default:
drm_err(mgr->dev, "Got unknown request 0x%02x (%s)\n",
msg->req_type, drm_dp_mst_req_type_str(msg->req_type));
@@ -4106,6 +4152,8 @@ drm_dp_mst_process_up_req(struct drm_dp_mst_topology_mgr 
*mgr,
guid = msg->u.conn_stat.guid;
else if (msg->req_type == DP_RESOURCE_STATUS_NOTIFY)
guid = msg->u.resource_stat.guid;
+   else if (msg->req_type == DP_SINK_EVENT_NOTIFY)
+   guid = msg->u.sink_event.guid;
 
if (guid)
mstb = drm_dp_get_mst_branch_device_by_guid(mgr, guid);
@@ -4177,7 +4225,8 @@ static int drm_dp_mst_handle_up_req(struct 
drm_dp_mst_topology_mgr *mgr)
drm_dp_sideband_parse_req(mgr, >up_req_recv, _req->msg);
 
if (up_req->msg.req_type != DP_CONNECTION_STATUS_NOTIFY &&
-   up_req->msg.req_type != DP_RESOURCE_STATUS_NOTIFY) {
+   up_req->msg.req_type != DP_RESOURCE_STATUS_NOTIFY &&
+   up_req->msg.req_type != DP_SINK_EVENT_NOTIFY) {
drm_dbg_kms(mgr->dev, "Received unknown up req type, ignoring: 
%x\n",
up_req->msg.req_type);
kfree(up_req);
@@ -4205,6 +4254,12 @@ static int drm_dp_mst_handle_up_req(struct 
drm_dp_mst_topology_mgr *mgr)
drm_dbg_kms(mgr->dev, "Got RSN: pn: %d avail_pbn %d\n",
   

Re: [RFC PATCH 10/97] drm/i915: Promote ptrdiff() to i915_utils.h

2021-05-24 Thread Matthew Brost
On Thu, May 06, 2021 at 12:13:24PM -0700, Matthew Brost wrote:
> From: Michal Wajdeczko 
> 
> Generic helpers should be placed in i915_utils.h.
> 
> Signed-off-by: Michal Wajdeczko 
> Signed-off-by: Matthew Brost 

Reviewed-by: Matthew Brost 

> ---
>  drivers/gpu/drm/i915/i915_utils.h | 5 +
>  drivers/gpu/drm/i915/i915_vma.h   | 5 -
>  2 files changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_utils.h 
> b/drivers/gpu/drm/i915/i915_utils.h
> index f02f52ab5070..5259edacde38 100644
> --- a/drivers/gpu/drm/i915/i915_utils.h
> +++ b/drivers/gpu/drm/i915/i915_utils.h
> @@ -201,6 +201,11 @@ __check_struct_size(size_t base, size_t arr, size_t 
> count, size_t *size)
>   __T;\
>  })
>  
> +static __always_inline ptrdiff_t ptrdiff(const void *a, const void *b)
> +{
> + return a - b;
> +}
> +
>  /*
>   * container_of_user: Extract the superclass from a pointer to a member.
>   *
> diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h
> index 8df784a026d2..a29a158990c6 100644
> --- a/drivers/gpu/drm/i915/i915_vma.h
> +++ b/drivers/gpu/drm/i915/i915_vma.h
> @@ -146,11 +146,6 @@ static inline void i915_vma_put(struct i915_vma *vma)
>   i915_gem_object_put(vma->obj);
>  }
>  
> -static __always_inline ptrdiff_t ptrdiff(const void *a, const void *b)
> -{
> - return a - b;
> -}
> -
>  static inline long
>  i915_vma_compare(struct i915_vma *vma,
>struct i915_address_space *vm,
> -- 
> 2.28.0
> 


Re: [RFC PATCH 07/97] drm/i915/guc: Remove sample_forcewake h2g action

2021-05-24 Thread Matthew Brost
On Thu, May 06, 2021 at 12:13:21PM -0700, Matthew Brost wrote:
> From: Rodrigo Vivi 
> 
> This action is no-op in the GuC side for a few versions already
> and it is getting entirely removed soon, in an upcoming version.
> 
> Time to remove before we face communication issues.
> 
> Cc:  Vinay Belgaumkar 
> Signed-off-by: Rodrigo Vivi 
> Signed-off-by: Matthew Brost 

Reviewed-by: Matthew Brost 

> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc.c  | 16 
>  drivers/gpu/drm/i915/gt/uc/intel_guc.h  |  1 -
>  drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h |  4 
>  drivers/gpu/drm/i915/gt/uc/intel_uc.c   |  4 
>  4 files changed, 25 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> index adae04c47aab..ab2c8fe8cdfa 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> @@ -469,22 +469,6 @@ int intel_guc_to_host_process_recv_msg(struct intel_guc 
> *guc,
>   return 0;
>  }
>  
> -int intel_guc_sample_forcewake(struct intel_guc *guc)
> -{
> - struct drm_i915_private *dev_priv = guc_to_gt(guc)->i915;
> - u32 action[2];
> -
> - action[0] = INTEL_GUC_ACTION_SAMPLE_FORCEWAKE;
> - /* WaRsDisableCoarsePowerGating:skl,cnl */
> - if (!HAS_RC6(dev_priv) || NEEDS_WaRsDisableCoarsePowerGating(dev_priv))
> - action[1] = 0;
> - else
> - /* bit 0 and 1 are for Render and Media domain separately */
> - action[1] = GUC_FORCEWAKE_RENDER | GUC_FORCEWAKE_MEDIA;
> -
> - return intel_guc_send(guc, action, ARRAY_SIZE(action));
> -}
> -
>  /**
>   * intel_guc_auth_huc() - Send action to GuC to authenticate HuC ucode
>   * @guc: intel_guc structure
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> index bc2ba7d0626c..c20f3839de12 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> @@ -128,7 +128,6 @@ int intel_guc_send_mmio(struct intel_guc *guc, const u32 
> *action, u32 len,
>   u32 *response_buf, u32 response_buf_size);
>  int intel_guc_to_host_process_recv_msg(struct intel_guc *guc,
>  const u32 *payload, u32 len);
> -int intel_guc_sample_forcewake(struct intel_guc *guc);
>  int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset);
>  int intel_guc_suspend(struct intel_guc *guc);
>  int intel_guc_resume(struct intel_guc *guc);
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> index 79c560d9c0b6..0f9afcde1d0b 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> @@ -302,9 +302,6 @@ struct guc_ct_buffer_desc {
>  #define GUC_CT_MSG_ACTION_SHIFT  16
>  #define GUC_CT_MSG_ACTION_MASK   0x
>  
> -#define GUC_FORCEWAKE_RENDER (1 << 0)
> -#define GUC_FORCEWAKE_MEDIA  (1 << 1)
> -
>  #define GUC_POWER_UNSPECIFIED0
>  #define GUC_POWER_D0 1
>  #define GUC_POWER_D1 2
> @@ -558,7 +555,6 @@ enum intel_guc_action {
>   INTEL_GUC_ACTION_ENTER_S_STATE = 0x501,
>   INTEL_GUC_ACTION_EXIT_S_STATE = 0x502,
>   INTEL_GUC_ACTION_SLPC_REQUEST = 0x3003,
> - INTEL_GUC_ACTION_SAMPLE_FORCEWAKE = 0x3005,
>   INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000,
>   INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER = 0x4505,
>   INTEL_GUC_ACTION_DEREGISTER_COMMAND_TRANSPORT_BUFFER = 0x4506,
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c 
> b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
> index 892c1315ce49..ab0789d66e06 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
> @@ -502,10 +502,6 @@ static int __uc_init_hw(struct intel_uc *uc)
>  
>   intel_huc_auth(huc);
>  
> - ret = intel_guc_sample_forcewake(guc);
> - if (ret)
> - goto err_log_capture;
> -
>   if (intel_uc_uses_guc_submission(uc))
>   intel_guc_submission_enable(guc);
>  
> -- 
> 2.28.0
> 


Re: [RFC PATCH 06/97] drm/i915/guc: enable only the user interrupt when using GuC submission

2021-05-24 Thread Matthew Brost
On Thu, May 06, 2021 at 12:13:20PM -0700, Matthew Brost wrote:
> From: Daniele Ceraolo Spurio 
> 
> In GuC submission mode the CS is owned by the GuC FW, so all CS status
> interrupts are handled by it. We only need the user interrupt as that
> signals request completion.
> 
> Since we're now starting the engines directly in GuC submission mode
> when selected, we can stop switching back and forth between the
> execlists and the GuC programming and select directly the correct
> interrupt mask.
> 
> Signed-off-by: Daniele Ceraolo Spurio 
> Signed-off-by: Matthew Brost 

Reviewed-by: Matthew Brost 

> Cc: John Harrison 
> Cc: Michal Wajdeczko 
> ---
>  drivers/gpu/drm/i915/gt/intel_gt_irq.c| 18 ++-
>  .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 31 ---
>  2 files changed, 11 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c 
> b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
> index d29126c458ba..f88c10366e58 100644
> --- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c
> +++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
> @@ -194,14 +194,18 @@ void gen11_gt_irq_reset(struct intel_gt *gt)
>  
>  void gen11_gt_irq_postinstall(struct intel_gt *gt)
>  {
> - const u32 irqs =
> - GT_CS_MASTER_ERROR_INTERRUPT |
> - GT_RENDER_USER_INTERRUPT |
> - GT_CONTEXT_SWITCH_INTERRUPT |
> - GT_WAIT_SEMAPHORE_INTERRUPT;
>   struct intel_uncore *uncore = gt->uncore;
> - const u32 dmask = irqs << 16 | irqs;
> - const u32 smask = irqs << 16;
> + u32 irqs = GT_RENDER_USER_INTERRUPT;
> + u32 dmask;
> + u32 smask;
> +
> + if (!intel_uc_wants_guc_submission(>uc))
> + irqs |= GT_CS_MASTER_ERROR_INTERRUPT |
> + GT_CONTEXT_SWITCH_INTERRUPT |
> + GT_WAIT_SEMAPHORE_INTERRUPT;
> +
> + dmask = irqs << 16 | irqs;
> + smask = irqs << 16;
>  
>   BUILD_BUG_ON(irqs & 0x);
>  
> 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 335719f17490..38cda5d599a6 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
> @@ -432,32 +432,6 @@ void intel_guc_submission_fini(struct intel_guc *guc)
>   }
>  }
>  
> -static void guc_interrupts_capture(struct intel_gt *gt)
> -{
> - struct intel_uncore *uncore = gt->uncore;
> - u32 irqs = GT_CONTEXT_SWITCH_INTERRUPT;
> - u32 dmask = irqs << 16 | irqs;
> -
> - GEM_BUG_ON(INTEL_GEN(gt->i915) < 11);
> -
> - /* Don't handle the ctx switch interrupt in GuC submission mode */
> - intel_uncore_rmw(uncore, GEN11_RENDER_COPY_INTR_ENABLE, dmask, 0);
> - intel_uncore_rmw(uncore, GEN11_VCS_VECS_INTR_ENABLE, dmask, 0);
> -}
> -
> -static void guc_interrupts_release(struct intel_gt *gt)
> -{
> - struct intel_uncore *uncore = gt->uncore;
> - u32 irqs = GT_CONTEXT_SWITCH_INTERRUPT;
> - u32 dmask = irqs << 16 | irqs;
> -
> - GEM_BUG_ON(INTEL_GEN(gt->i915) < 11);
> -
> - /* Handle ctx switch interrupts again */
> - intel_uncore_rmw(uncore, GEN11_RENDER_COPY_INTR_ENABLE, 0, dmask);
> - intel_uncore_rmw(uncore, GEN11_VCS_VECS_INTR_ENABLE, 0, dmask);
> -}
> -
>  static int guc_context_alloc(struct intel_context *ce)
>  {
>   return lrc_alloc(ce, ce->engine);
> @@ -722,9 +696,6 @@ int intel_guc_submission_setup(struct intel_engine_cs 
> *engine)
>  void intel_guc_submission_enable(struct intel_guc *guc)
>  {
>   guc_stage_desc_init(guc);
> -
> - /* Take over from manual control of ELSP (execlists) */
> - guc_interrupts_capture(guc_to_gt(guc));
>  }
>  
>  void intel_guc_submission_disable(struct intel_guc *guc)
> @@ -735,8 +706,6 @@ void intel_guc_submission_disable(struct intel_guc *guc)
>  
>   /* Note: By the time we're here, GuC may have already been reset */
>  
> - guc_interrupts_release(gt);
> -
>   guc_stage_desc_fini(guc);
>  }
>  
> -- 
> 2.28.0
> 


[PATCH v8 11/11] arm64: dts: qcom: sc7180-trogdor: Move panel under the bridge chip

2021-05-24 Thread Douglas Anderson
Putting the panel under the bridge chip (under the aux-bus node)
allows the panel driver to get access to the DP AUX bus, enabling all
sorts of fabulous new features.

While we're at this, get rid of a level of hierarchy for the panel
node. It doesn't need "ports / port" and can just have a "port" child.

For Linux, this patch has a hard requirement on the patches adding DP
AUX bus support to the ti-sn65dsi86 bridge chip driver. See the patch
("drm/bridge: ti-sn65dsi86: Add support for the DP AUX bus").

Signed-off-by: Douglas Anderson 
Acked-by: Linus Walleij 
---

(no changes since v7)

Changes in v7:
- Panel now under bridge chip instead of getting a link to ddc-i2c

 arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi | 30 ++--
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi 
b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
index 24d293ef56d7..c76afd857b54 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
@@ -260,21 +260,6 @@ max98357a: audio-codec-0 {
#sound-dai-cells = <0>;
};
 
-   panel: panel {
-   /* Compatible will be filled in per-board */
-   power-supply = <_dx_edp>;
-   backlight = <>;
-   hpd-gpios = <_bridge 2 GPIO_ACTIVE_HIGH>;
-
-   ports {
-   port {
-   panel_in_edp: endpoint {
-   remote-endpoint = <_out>;
-   };
-   };
-   };
-   };
-
pwmleds {
compatible = "pwm-leds";
keyboard_backlight: keyboard-backlight {
@@ -674,6 +659,21 @@ sn65dsi86_out: endpoint {
};
};
};
+
+   aux-bus {
+   panel: panel {
+   /* Compatible will be filled in per-board */
+   power-supply = <_dx_edp>;
+   backlight = <>;
+   hpd-gpios = <_bridge 2 
GPIO_ACTIVE_HIGH>;
+
+   port {
+   panel_in_edp: endpoint {
+   remote-endpoint = 
<_out>;
+   };
+   };
+   };
+   };
};
 };
 
-- 
2.31.1.818.g46aad6cb9e-goog



[PATCH v8 07/11] drm/panel: panel-simple: Stash DP AUX bus; allow using it for DDC

2021-05-24 Thread Douglas Anderson
If panel-simple is instantiated as a DP AUX bus endpoint then we have
access to the DP AUX bus. Let's stash it in the panel-simple
structure, leaving it NULL for the cases where the panel is
instantiated in other ways.

If we happen to have access to the DP AUX bus and we weren't provided
the ddc-i2c-bus in some other manner, let's use the DP AUX bus for it.

Signed-off-by: Douglas Anderson 
Reviewed-by: Lyude Paul 
---

(no changes since v7)

Changes in v7:
- Patch using the DP AUX for DDC new for v7.

 drivers/gpu/drm/panel/panel-simple.c | 14 ++
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index d3b5ae22d939..b09be6e5e147 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -37,6 +37,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -186,6 +187,7 @@ struct panel_simple {
 
struct regulator *supply;
struct i2c_adapter *ddc;
+   struct drm_dp_aux *aux;
 
struct gpio_desc *enable_gpio;
struct gpio_desc *hpd_gpio;
@@ -658,7 +660,8 @@ static void panel_simple_parse_panel_timing_node(struct 
device *dev,
dev_err(dev, "Reject override mode: No display_timing found\n");
 }
 
-static int panel_simple_probe(struct device *dev, const struct panel_desc 
*desc)
+static int panel_simple_probe(struct device *dev, const struct panel_desc 
*desc,
+ struct drm_dp_aux *aux)
 {
struct panel_simple *panel;
struct display_timing dt;
@@ -674,6 +677,7 @@ static int panel_simple_probe(struct device *dev, const 
struct panel_desc *desc)
panel->enabled = false;
panel->prepared_time = 0;
panel->desc = desc;
+   panel->aux = aux;
 
panel->no_hpd = of_property_read_bool(dev->of_node, "no-hpd");
if (!panel->no_hpd) {
@@ -708,6 +712,8 @@ static int panel_simple_probe(struct device *dev, const 
struct panel_desc *desc)
 
if (!panel->ddc)
return -EPROBE_DEFER;
+   } else if (aux) {
+   panel->ddc = >ddc;
}
 
if (desc == _dpi) {
@@ -4633,7 +4639,7 @@ static int panel_simple_platform_probe(struct 
platform_device *pdev)
if (!id)
return -ENODEV;
 
-   return panel_simple_probe(>dev, id->data);
+   return panel_simple_probe(>dev, id->data, NULL);
 }
 
 static int panel_simple_platform_remove(struct platform_device *pdev)
@@ -4913,7 +4919,7 @@ static int panel_simple_dsi_probe(struct mipi_dsi_device 
*dsi)
 
desc = id->data;
 
-   err = panel_simple_probe(>dev, >desc);
+   err = panel_simple_probe(>dev, >desc, NULL);
if (err < 0)
return err;
 
@@ -4966,7 +4972,7 @@ static int panel_simple_dp_aux_ep_probe(struct 
dp_aux_ep_device *aux_ep)
if (!id)
return -ENODEV;
 
-   return panel_simple_probe(_ep->dev, id->data);
+   return panel_simple_probe(_ep->dev, id->data, aux_ep->aux);
 }
 
 static void panel_simple_dp_aux_ep_remove(struct dp_aux_ep_device *aux_ep)
-- 
2.31.1.818.g46aad6cb9e-goog



[PATCH v8 10/11] drm/bridge: ti-sn65dsi86: Don't read EDID blob over DDC

2021-05-24 Thread Douglas Anderson
This is really just a revert of commit 58074b08c04a ("drm/bridge:
ti-sn65dsi86: Read EDID blob over DDC"), resolving conflicts.

The old code failed to read the EDID properly in a very important
case: before the bridge's pre_enable() was called. The way things need
to work:
1. Read the EDID.
2. Based on the EDID, decide on video settings and pixel clock.
3. Enable the bridge w/ the desired settings.

The way things were working:
1. Try to read the EDID but fail; fall back to hardcoded values.
2. Based on hardcoded values, decide on video settings and pixel clock.
3. Enable the bridge w/ the desired settings.
4. Try again to read the EDID, it works now!
5. Realize that the hardcoded settings weren't quite right.
6. Disable / reenable the bridge w/ the right settings.

The reasons for the failures were twofold:
a) Since we never ran the bridge chip's pre-enable then we never set
   the bit to ignore HPD. This meant the bridge chip didn't even _try_
   to go out on the bus and communicate with the panel.
b) Even if we fixed things to ignore HPD, the EDID still wouldn't read
   if the panel wasn't on.

Instead of reverting the code, we could fix it to set the HPD bit and
also power on the panel. However, it also works nicely to just let the
panel code read the EDID. Now that we've split the driver up we can
expose the DDC AUX channel bus to the panel node. The panel can take
charge of reading the EDID.

NOTE: in order for things to work, anyone that needs to read the EDID
will need to instantiate their panel using the new DP AUX bus (AKA by
listing their panel under the "aux-bus" node of the bridge chip in the
device tree).

In the future if we want to use the bridge chip to provide a full
external DP port (which won't have a panel) then we will have to
conditinally add EDID reading back in.

Suggested-by: Andrzej Hajda 
Signed-off-by: Douglas Anderson 
Reviewed-by: Bjorn Andersson 
---

(no changes since v7)

Changes in v7:
- Adjusted commit message to talk about DP AUX bus.

 drivers/gpu/drm/bridge/ti-sn65dsi86.c | 22 --
 1 file changed, 22 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c 
b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index 5263206792f6..b7453c80cdb8 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -126,7 +126,6 @@
  * @connector:Our connector.
  * @host_node:Remote DSI node.
  * @dsi:  Our MIPI DSI source.
- * @edid: Detected EDID of eDP panel.
  * @refclk:   Our reference clock.
  * @panel:Our panel.
  * @enable_gpio:  The GPIO we toggle to enable the bridge.
@@ -157,7 +156,6 @@ struct ti_sn65dsi86 {
struct drm_dp_aux   aux;
struct drm_bridge   bridge;
struct drm_connectorconnector;
-   struct edid *edid;
struct device_node  *host_node;
struct mipi_dsi_device  *dsi;
struct clk  *refclk;
@@ -406,24 +404,6 @@ connector_to_ti_sn65dsi86(struct drm_connector *connector)
 static int ti_sn_bridge_connector_get_modes(struct drm_connector *connector)
 {
struct ti_sn65dsi86 *pdata = connector_to_ti_sn65dsi86(connector);
-   struct edid *edid = pdata->edid;
-   int num, ret;
-
-   if (!edid) {
-   pm_runtime_get_sync(pdata->dev);
-   edid = pdata->edid = drm_get_edid(connector, >aux.ddc);
-   pm_runtime_put_autosuspend(pdata->dev);
-   }
-
-   if (edid && drm_edid_is_valid(edid)) {
-   ret = drm_connector_update_edid_property(connector, edid);
-   if (!ret) {
-   num = drm_add_edid_modes(connector, edid);
-   if (num)
-   return num;
-   }
-   }
-
return drm_panel_get_modes(pdata->panel, connector);
 }
 
@@ -1356,8 +1336,6 @@ static void ti_sn_bridge_remove(struct auxiliary_device 
*adev)
mipi_dsi_device_unregister(pdata->dsi);
}
 
-   kfree(pdata->edid);
-
drm_bridge_remove(>bridge);
 
of_node_put(pdata->host_node);
-- 
2.31.1.818.g46aad6cb9e-goog



[PATCH v8 09/11] drm/bridge: ti-sn65dsi86: Add support for the DP AUX bus

2021-05-24 Thread Douglas Anderson
We want to provide our panel with access to the DP AUX channel. The
way to do this is to let our panel be a child of ours using the fancy
new DP AUX bus support.

Signed-off-by: Douglas Anderson 
Acked-by: Linus Walleij 
Reviewed-by: Lyude Paul 
---

(no changes since v7)

Changes in v7:
- Patch to support for DP AUX bus on ti-sn65dsi86 new for v7.

 drivers/gpu/drm/bridge/Kconfig|  1 +
 drivers/gpu/drm/bridge/ti-sn65dsi86.c | 13 +++--
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 7e7f28eb9546..a82952a85db4 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -292,6 +292,7 @@ config DRM_TI_SN65DSI86
select DRM_PANEL
select DRM_MIPI_DSI
select AUXILIARY_BUS
+   select DRM_DP_AUX_BUS
help
  Texas Instruments SN65DSI86 DSI to eDP Bridge driver
 
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c 
b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index 1ea07d704705..5263206792f6 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1448,19 +1449,27 @@ static int ti_sn_aux_probe(struct auxiliary_device 
*adev,
pdata->aux.transfer = ti_sn_aux_transfer;
drm_dp_aux_init(>aux);
 
+   ret = devm_of_dp_aux_populate_ep_devices(>aux);
+   if (ret)
+   goto err;
+
/*
 * The eDP to MIPI bridge parts don't work until the AUX channel is
 * setup so we don't add it in the main driver probe, we add it now.
 */
ret = ti_sn65dsi86_add_aux_device(pdata, >bridge_aux, "bridge");
 
+   if (ret)
+   goto err;
+
+   return 0;
+err:
/*
 * Clear of_node on any errors. Really this only matters if the error
 * is -EPROBE_DEFER to avoid (again) keep pinctrl from claiming when
 * it tries the probe again, but it shouldn't hurt on any error.
 */
-   if (ret)
-   adev->dev.of_node = NULL;
+   adev->dev.of_node = NULL;
 
return ret;
 }
-- 
2.31.1.818.g46aad6cb9e-goog



[PATCH v8 08/11] drm/bridge: ti-sn65dsi86: Promote the AUX channel to its own sub-dev

2021-05-24 Thread Douglas Anderson
On its own, this change looks a little strange and doesn't do too much
useful. To understand why we're doing this we need to look forward to
future patches where we're going to probe our panel using the new DP
AUX bus. See the patch ("drm/bridge: ti-sn65dsi86: Add support for the
DP AUX bus").

Let's think about the set of steps we'll want to happen when we have
the DP AUX bus:

1. We'll create the DP AUX bus.
2. We'll populate the devices on the DP AUX bus (AKA our panel).
3. For setting up the bridge-related functions of ti-sn65dsi86 we'll
   need to get a reference to the panel.

If we do #1 - #3 in a single probe call things _mostly_ will work, but
it won't be massively robust. Let's explore.

First let's think of the easy case of no -EPROBE_DEFER. In that case
in step #2 when we populate the devices on the DP AUX bus it will
actually try probing the panel right away. Since the panel probe
doesn't defer then in step #3 we'll get a reference to the panel and
we're golden.

Second, let's think of the case when the panel returns
-EPROBE_DEFER. In that case step #2 won't synchronously create the
panel (it'll just add the device to the defer list to do it
later). Step #3 will fail to get the panel and the bridge sub-device
will return -EPROBE_DEFER. We'll depopulate the DP AUX bus. Later
we'll try the whole sequence again. Presumably the panel will
eventually stop returning -EPROBE_DEFER and we'll go back to the first
case where things were golden. So this case is OK too even if it's a
bit ugly that we have to keep creating / deleting the AUX bus over and
over.

So where is the problem? As I said, it's mostly about robustness. I
don't believe that step #2 (creating the sub-devices) is really
guaranteed to be synchronous. This is evidenced by the fact that it's
allowed to "succeed" by just sticking the device on the deferred
list. If anything about the process changes in Linux as a whole and
step #2 just kicks off the probe of the DP AUX endpoints (our panel)
in the background then we'd be in trouble because we might never get
the panel in step #3.

Adding an extra sub-device means we just don't need to worry about
it. We'll create the sub-device for the DP AUX bus and it won't go
away until the whole ti-sn65dsi86 driver goes away. If the bridge
sub-device defers (maybe because it can't find the panel) that won't
depopulate the DP AUX bus and so we don't need to worry about it.

NOTE: there's a little bit of a trick here. Though the AUX channel can
run without the MIPI-to-eDP bits of the code, the MIPI-to-eDP bits
can't run without the AUX channel. We could come up a complicated
signaling scheme (have the MIPI-to-eDP bits return EPROBE_DEFER for a
while or wait on some sort of completion), but it seems simple enough
to just not even bother creating the bridge device until the AUX
channel probes. That's what we'll do.

Signed-off-by: Douglas Anderson 
Reviewed-by: Lyude Paul 
---

(no changes since v7)

Changes in v7:
- Beefed up commit message in context of the DP AUX bus.
- Remove use of now-dropped drm_dp_aux_register_ddc() call.
- Set the proper sub-device "dev" pointer in the AUX structure.

Changes in v6:
- Use new drm_dp_aux_register_ddc() calls.

 drivers/gpu/drm/bridge/ti-sn65dsi86.c | 80 +++
 1 file changed, 69 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c 
b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index 45a2969afb2b..1ea07d704705 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -116,6 +116,7 @@
  * struct ti_sn65dsi86 - Platform data for ti-sn65dsi86 driver.
  * @bridge_aux:   AUX-bus sub device for MIPI-to-eDP bridge functionality.
  * @gpio_aux: AUX-bus sub device for GPIO controller functionality.
+ * @aux_aux:  AUX-bus sub device for eDP AUX channel functionality.
  *
  * @dev:  Pointer to the top level (i2c) device.
  * @regmap:   Regmap for accessing i2c.
@@ -148,6 +149,7 @@
 struct ti_sn65dsi86 {
struct auxiliary_device bridge_aux;
struct auxiliary_device gpio_aux;
+   struct auxiliary_device aux_aux;
 
struct device   *dev;
struct regmap   *regmap;
@@ -1333,11 +1335,6 @@ static int ti_sn_bridge_probe(struct auxiliary_device 
*adev,
if (ret)
return ret;
 
-   pdata->aux.name = "ti-sn65dsi86-aux";
-   pdata->aux.dev = pdata->dev;
-   pdata->aux.transfer = ti_sn_aux_transfer;
-   drm_dp_aux_init(>aux);
-
pdata->bridge.funcs = _sn_bridge_funcs;
pdata->bridge.of_node = np;
 
@@ -1432,6 +1429,53 @@ static int ti_sn65dsi86_add_aux_device(struct 
ti_sn65dsi86 *pdata,
return ret;
 }
 
+static int ti_sn_aux_probe(struct auxiliary_device *adev,
+  const struct auxiliary_device_id *id)
+{
+   struct ti_sn65dsi86 *pdata = dev_get_drvdata(adev->dev.parent);
+   int ret;
+
+   /*
+* 

[PATCH v8 05/11] drm: Introduce the DP AUX bus

2021-05-24 Thread Douglas Anderson
Historically "simple" eDP panels have been handled by panel-simple
which is a basic platform_device. In the device tree, the panel node
was at the top level and not connected to anything else.

Let's change it so that, instead, panels can be represented as being
children of the "DP AUX bus". Essentially we're saying that the
hierarchy that we're going to represent is the "control" connections
between devices. The DP AUX bus is a control bus provided by an eDP
controller (the parent) and consumed by a device like a panel (the
child).

The primary incentive here is to cleanly provide the panel driver the
ability to communicate over the AUX bus while handling lifetime issues
properly. The panel driver may want the AUX bus for controlling the
backlight or querying the panel's EDID.

The idea for this bus's design was hashed out over IRC [1].

[1] 
https://people.freedesktop.org/~cbrill/dri-log/?channel=dri-devel=2021-05-11

Cc: Laurent Pinchart 
Cc: Lyude Paul 
Cc: Rajeev Nandan 
Suggested-by: Laurent Pinchart 
Signed-off-by: Douglas Anderson 
Acked-by: Linus Walleij 
---
There's a whole lot of boilerplate code here. I've tried my best to
grok what all of it should be, drawing inspiration from other similar
bus drivers (auxiliary, i2c, serdev, platform) and I've tried to test
several of the corner cases, but I can't actually believe that I've
touched every code path. Please yell if you see something dumb.

Changes in v8:
- Allow dp-aux-bus to be a module to fix allmodconfig builds

Changes in v7:
- Patch introducing the DP AUX bus is new for v7.

 drivers/gpu/drm/Kconfig  |   5 +
 drivers/gpu/drm/Makefile |   2 +
 drivers/gpu/drm/drm_dp_aux_bus.c | 326 +++
 include/drm/drm_dp_aux_bus.h |  57 ++
 4 files changed, 390 insertions(+)
 create mode 100644 drivers/gpu/drm/drm_dp_aux_bus.c
 create mode 100644 include/drm/drm_dp_aux_bus.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index d3a9ca4b1cec..be5c82e55ef6 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -35,6 +35,11 @@ config DRM_MIPI_DSI
bool
depends on DRM
 
+config DRM_DP_AUX_BUS
+   tristate
+   depends on DRM
+   depends on OF
+
 config DRM_DP_AUX_CHARDEV
bool "DRM DP AUX Interface"
depends on DRM
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index a91cc7684904..0cff2ad2973b 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -33,6 +33,8 @@ drm-$(CONFIG_PCI) += drm_pci.o
 drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
 drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
 
+obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
+
 drm_vram_helper-y := drm_gem_vram_helper.o
 obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
 
diff --git a/drivers/gpu/drm/drm_dp_aux_bus.c b/drivers/gpu/drm/drm_dp_aux_bus.c
new file mode 100644
index ..d0e44de287d4
--- /dev/null
+++ b/drivers/gpu/drm/drm_dp_aux_bus.c
@@ -0,0 +1,326 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2021 Google Inc.
+ *
+ * The DP AUX bus is used for devices that are connected over a DisplayPort
+ * AUX bus. The devices on the far side of the bus are referred to as
+ * endpoints in this code.
+ *
+ * Commonly there is only one device connected to the DP AUX bus: a panel.
+ * Though historically panels (even DP panels) have been modeled as simple
+ * platform devices, putting them under the DP AUX bus allows the panel driver
+ * to perform transactions on that bus.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+
+/**
+ * dp_aux_ep_match() - The match function for the dp_aux_bus.
+ * @dev: The device to match.
+ * @drv: The driver to try to match against.
+ *
+ * At the moment, we just match on device tree.
+ *
+ * Return: True if this driver matches this device; false otherwise.
+ */
+static int dp_aux_ep_match(struct device *dev, struct device_driver *drv)
+{
+   return !!of_match_device(drv->of_match_table, dev);
+}
+
+/**
+ * dp_aux_ep_probe() - The probe function for the dp_aux_bus.
+ * @dev: The device to probe.
+ *
+ * Calls through to the endpoint driver probe.
+ *
+ * Return: 0 if no error or negative error code.
+ */
+static int dp_aux_ep_probe(struct device *dev)
+{
+   struct dp_aux_ep_driver *aux_ep_drv = to_dp_aux_ep_drv(dev->driver);
+   struct dp_aux_ep_device *aux_ep = to_dp_aux_ep_dev(dev);
+   int ret;
+
+   ret = dev_pm_domain_attach(dev, true);
+   if (ret)
+   return dev_err_probe(dev, ret, "Failed to attach to PM 
Domain\n");
+
+   ret = aux_ep_drv->probe(aux_ep);
+   if (ret)
+   dev_pm_domain_detach(dev, true);
+
+   return ret;
+}
+
+/**
+ * dp_aux_ep_remove() - The remove function for the dp_aux_bus.
+ * @dev: The device to remove.
+ *
+ * Calls through to the endpoint driver remove.
+ *
+ * Return: 0 if no error or negative error code.
+ */
+static int 

[PATCH v8 06/11] drm/panel: panel-simple: Allow panel-simple be a DP AUX endpoint device

2021-05-24 Thread Douglas Anderson
The panel-simple driver can already have devices instantiated as
platform devices or MIPI DSI devices. Let's add a 3rd way to
instantiate it: as DP AUX endpoint devices.

At the moment there is no benefit to instantiating it in this way,
but:
- In the next patch we'll give it access to the DDC channel via the DP
  AUX bus.
- Possibly in the future we may use this channel to configure the
  backlight.

Signed-off-by: Douglas Anderson 
Reviewed-by: Lyude Paul 
---

(no changes since v7)

Changes in v7:
- Patch to allow panel-simple to be DP AUX EP new for v7.

 drivers/gpu/drm/panel/Kconfig|  1 +
 drivers/gpu/drm/panel/panel-simple.c | 52 +---
 2 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index ef87d92cdf49..b1ea86d9fdaf 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -82,6 +82,7 @@ config DRM_PANEL_SIMPLE
depends on BACKLIGHT_CLASS_DEVICE
depends on PM
select VIDEOMODE_HELPERS
+   select DRM_DP_AUX_BUS
help
  DRM panel driver for dumb panels that need at most a regulator and
  a GPIO to be powered up. Optionally a backlight can be attached so
diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index 21939d4352cf..d3b5ae22d939 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -36,6 +36,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -4957,6 +4958,38 @@ static struct mipi_dsi_driver panel_simple_dsi_driver = {
.shutdown = panel_simple_dsi_shutdown,
 };
 
+static int panel_simple_dp_aux_ep_probe(struct dp_aux_ep_device *aux_ep)
+{
+   const struct of_device_id *id;
+
+   id = of_match_node(platform_of_match, aux_ep->dev.of_node);
+   if (!id)
+   return -ENODEV;
+
+   return panel_simple_probe(_ep->dev, id->data);
+}
+
+static void panel_simple_dp_aux_ep_remove(struct dp_aux_ep_device *aux_ep)
+{
+   panel_simple_remove(_ep->dev);
+}
+
+static void panel_simple_dp_aux_ep_shutdown(struct dp_aux_ep_device *aux_ep)
+{
+   panel_simple_shutdown(_ep->dev);
+}
+
+static struct dp_aux_ep_driver panel_simple_dp_aux_ep_driver = {
+   .driver = {
+   .name = "panel-simple-dp-aux",
+   .of_match_table = platform_of_match,/* Same as platform 
one! */
+   .pm = _simple_pm_ops,
+   },
+   .probe = panel_simple_dp_aux_ep_probe,
+   .remove = panel_simple_dp_aux_ep_remove,
+   .shutdown = panel_simple_dp_aux_ep_shutdown,
+};
+
 static int __init panel_simple_init(void)
 {
int err;
@@ -4965,15 +4998,25 @@ static int __init panel_simple_init(void)
if (err < 0)
return err;
 
+   err = dp_aux_dp_driver_register(_simple_dp_aux_ep_driver);
+   if (err < 0)
+   goto err_did_platform_register;
+
if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) {
err = mipi_dsi_driver_register(_simple_dsi_driver);
-   if (err < 0) {
-   
platform_driver_unregister(_simple_platform_driver);
-   return err;
-   }
+   if (err < 0)
+   goto err_did_aux_ep_register;
}
 
return 0;
+
+err_did_aux_ep_register:
+   dp_aux_dp_driver_unregister(_simple_dp_aux_ep_driver);
+
+err_did_platform_register:
+   platform_driver_unregister(_simple_platform_driver);
+
+   return err;
 }
 module_init(panel_simple_init);
 
@@ -4982,6 +5025,7 @@ static void __exit panel_simple_exit(void)
if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
mipi_dsi_driver_unregister(_simple_dsi_driver);
 
+   dp_aux_dp_driver_unregister(_simple_dp_aux_ep_driver);
platform_driver_unregister(_simple_platform_driver);
 }
 module_exit(panel_simple_exit);
-- 
2.31.1.818.g46aad6cb9e-goog



[PATCH v8 04/11] dt-bindings: drm/aux-bus: Add an example

2021-05-24 Thread Douglas Anderson
Now that we have an eDP controller that lists aux-bus, we can safely
add an example to the aux-bus bindings.

NOTE: this example is just a copy of the one in the 'ti-sn65dsi86'
one. It feels useful to have the example in both places simply because
it's important to document the interaction between the two bindings in
both places.

Signed-off-by: Douglas Anderson 
---

Changes in v8:
- Separate DP AUX bus binding is new for v8.

 .../bindings/display/dp-aux-bus.yaml  | 65 +++
 1 file changed, 65 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/dp-aux-bus.yaml 
b/Documentation/devicetree/bindings/display/dp-aux-bus.yaml
index 5e4afe9f98fb..43494d2a32a1 100644
--- a/Documentation/devicetree/bindings/display/dp-aux-bus.yaml
+++ b/Documentation/devicetree/bindings/display/dp-aux-bus.yaml
@@ -35,3 +35,68 @@ additionalProperties: false
 
 required:
   - panel
+
+examples:
+  - |
+#include 
+#include 
+#include 
+
+i2c {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  bridge@2d {
+compatible = "ti,sn65dsi86";
+reg = <0x2d>;
+
+interrupt-parent = <>;
+interrupts = <10 IRQ_TYPE_LEVEL_HIGH>;
+
+enable-gpios = < 102 GPIO_ACTIVE_HIGH>;
+
+vpll-supply = <_pp1800_s4a>;
+vccio-supply = <_pp1800_s4a>;
+vcca-supply = <_pp1200_l2a>;
+vcc-supply = <_pp1200_l2a>;
+
+clocks = < RPMH_LN_BB_CLK2>;
+clock-names = "refclk";
+
+no-hpd;
+
+ports {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  port@0 {
+reg = <0>;
+endpoint {
+  remote-endpoint = <_out>;
+};
+  };
+
+  port@1 {
+reg = <1>;
+sn65dsi86_out: endpoint {
+  remote-endpoint = <_in_edp>;
+};
+  };
+};
+
+aux-bus {
+  panel {
+compatible = "boe,nv133fhm-n62";
+power-supply = <_dx_edp>;
+backlight = <>;
+hpd-gpios = <_bridge 2 GPIO_ACTIVE_HIGH>;
+
+port {
+  panel_in_edp: endpoint {
+remote-endpoint = <_out>;
+  };
+};
+  };
+};
+  };
+};
-- 
2.31.1.818.g46aad6cb9e-goog



[PATCH v8 03/11] dt-bindings: drm/bridge: ti-sn65dsi86: Add aux-bus child

2021-05-24 Thread Douglas Anderson
The patch ("dt-bindings: drm: Introduce the DP AUX bus") talks about
how using the DP AUX bus is better than learning how to slice
bread. Let's add it to the ti-sn65dsi86 bindings.

Signed-off-by: Douglas Anderson 
---

Changes in v8:
- ti-sn65dsi86 references the new aux bus bindings.

Changes in v7:
- ti-sn65dsi86: Add aux-bus child patch new for v7.

 .../bindings/display/bridge/ti,sn65dsi86.yaml | 20 ++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.yaml 
b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.yaml
index 26932d2e86ab..4007f36d04ba 100644
--- a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.yaml
@@ -70,6 +70,9 @@ properties:
 const: 1
 description: See ../../pwm/pwm.yaml for description of the cell formats.
 
+  aux-bus:
+$ref: ../dp-aux-bus.yaml#
+
   ports:
 $ref: /schemas/graph.yaml#/properties/ports
 
@@ -201,11 +204,26 @@ examples:
 
   port@1 {
 reg = <1>;
-endpoint {
+sn65dsi86_out: endpoint {
   remote-endpoint = <_in_edp>;
 };
   };
 };
+
+aux-bus {
+  panel {
+compatible = "boe,nv133fhm-n62";
+power-supply = <_dx_edp>;
+backlight = <>;
+hpd-gpios = <_bridge 2 GPIO_ACTIVE_HIGH>;
+
+port {
+  panel_in_edp: endpoint {
+remote-endpoint = <_out>;
+  };
+};
+  };
+};
   };
 };
   - |
-- 
2.31.1.818.g46aad6cb9e-goog



[PATCH v8 02/11] dt-bindings: drm: Introduce the DP AUX bus

2021-05-24 Thread Douglas Anderson
We want to be able to list an eDP panel as a child of an eDP
controller node to represent the fact that the panel is connected to
the controller's DP AUX bus. Though the panel and the controller are
connected in several ways, the DP AUX bus is the primary control
interface between the two and thus makes the most sense to model in
device tree hierarchy.

Listing a panel in this way makes it possible for the panel driver to
easily get access to the DP AUX bus that it resides on, which can be
useful to help in auto-detecting the panel and for turning on various
bits.

NOTE: historically eDP panels were _not_ listed under their controller
but were listed at the top level of the device tree. This will still
be supported for backward compatibility (and while DP controller
drivers are adapted to support the new DT syntax) but should be
considered deprecated since there is no downside to listing the panel
under the controller.

For now, the DP AUX bus bindings will only support an eDP panel
underneath. It's possible it could be extended to allow having a DP
connector under it in the future.

The idea for this bus's design was hashed out over IRC [1].

[1] 
https://people.freedesktop.org/~cbrill/dri-log/?channel=dri-devel=2021-05-11

Signed-off-by: Douglas Anderson 
---
My DT yaml-fu is still weak. If I did something stupid, please help me
learn how to do this better!

NOTE: there is no "Example" in this bindings file. Yikes! This is
because I wanted to keep this patch separate from the one that enables
the first eDP controller. See the patch ("dt-bindings: drm/aux-bus:
Add an example") for the example.

ALSO: if anyone else would like to be listed as a "Maintainer" in this
file then please shout!

Changes in v8:
- Separate DP AUX bus binding is new for v8.

 .../bindings/display/dp-aux-bus.yaml  | 37 +++
 1 file changed, 37 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/dp-aux-bus.yaml

diff --git a/Documentation/devicetree/bindings/display/dp-aux-bus.yaml 
b/Documentation/devicetree/bindings/display/dp-aux-bus.yaml
new file mode 100644
index ..5e4afe9f98fb
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/dp-aux-bus.yaml
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/dp-aux-bus.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: DisplayPort AUX bus
+
+maintainers:
+  - Douglas Anderson 
+
+description:
+  DisplayPort controllers provide a control channel to the sinks that
+  are hooked up to them. This is the DP AUX bus. Over the DP AUX bus
+  we can query properties about a sink and also configure it. In
+  particular, DP sinks support DDC over DP AUX which allows tunneling
+  a standard I2C DDC connection over the AUX channel.
+
+  To model this relationship, DP sinks should be placed as children
+  of the DP controller under the "aux-bus" node.
+
+  At the moment, this binding only handles the eDP case. It is
+  possible it will be extended in the future to handle the DP case.
+  For DP, presumably a connector would be listed under the DP AUX
+  bus instead of a panel.
+
+properties:
+  $nodename:
+const: "aux-bus"
+
+  panel:
+$ref: panel/panel-common.yaml#
+
+additionalProperties: false
+
+required:
+  - panel
-- 
2.31.1.818.g46aad6cb9e-goog



[PATCH v8 01/11] dt-bindings: display: simple: List hpd properties in panel-simple

2021-05-24 Thread Douglas Anderson
The HPD (Hot Plug Detect) signal is present in many (probably even
"most") eDP panels. For eDP, this signal isn't actually used for
detecting hot-plugs of the panel but is more akin to a "panel ready"
signal. After you provide power to the panel, panel timing diagrams
typically say that you should wait for HPD to be asserted (or wait a
fixed amount of time) before talking to the panel.

The panel-simple bindings describes many eDP panels and many of these
panels provide the HPD signal. We should add the HPD-related
properties to the panel-simple bindings. The HPD properties are
actually defined in panel-common.yaml, so adding them here just
documents that they are OK for panels handled by the panel-simple
bindings.

NOTE: whether or not we'd include HPD properties in the panel node is
more a property of the board design than the panel itself. For most
boards using these eDP panels everything "magically" works without
specifying any HPD properties and that's been why we haven't needed to
allow the HPD properties earlier. On these boards the HPD signal goes
directly to a dedicated "HPD" input to the eDP controller and this
connection doesn't need to be described in the device tree. The only
time the HPD properties are needed in the device tree are if HPD is
hooked up to a GPIO or if HPD is normally on the panel but isn't used
on a given board. That means that if we don't allow the HPD properties
in panel-simple then one could argue that we've got to boot all eDP
panels (or at least all those that someone could conceivably put on a
system where HPD goes to a GPIO or isn't hooked up) from panel-simple.

Signed-off-by: Douglas Anderson 
---

Changes in v8:
- Explain better why HPD needs to be in panel-simple in commit msg.

Changes in v7:
- List hpd properties bindings patch new for v7.

 .../devicetree/bindings/display/panel/panel-simple.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml 
b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
index b3797ba2698b..4a0a5e1ee252 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
@@ -298,6 +298,8 @@ properties:
   enable-gpios: true
   port: true
   power-supply: true
+  no-hpd: true
+  hpd-gpios: true
 
 additionalProperties: false
 
-- 
2.31.1.818.g46aad6cb9e-goog



[PATCH v8 00/11] drm: Fix EDID reading on ti-sn65dsi86 by introducing the DP AUX bus

2021-05-24 Thread Douglas Anderson
The primary goal of this series is to try to properly fix EDID reading
for eDP panels using the ti-sn65dsi86 bridge.

Previously we had a patch that added EDID reading but it turned out
not to work at bootup. This caused some extra churn at bootup as we
tried (and failed) to read the EDID several times and also ended up
forcing us to use the hardcoded mode at boot. With this patch series I
believe EDID reading is reliable at boot now and we never use the
hardcoded mode.

High level note: in this series the EDID reading is driven by the
panel driver, not by the bridge chip driver. I believe this makes a
reasonable amount of sense since the panel driver already _could_
drive reading the EDID if provided with the DDC bus and in future
planned work we'll want to give the panel driver the DDC bus (to make
decisions based on EDID) and the AUX bus (to control the
backlight). There are also planned patches from Laurent to make
ti-sn65dsi86 able to drive full DP monitors. In that case the bridge
chip will still be in charge of reading the EDID, but it's not hard to
make this dynamic.

This series is the logical successor to the 3-part series containing
the patch ("drm/bridge: ti-sn65dsi86: Properly get the EDID, but only
if refclk") [1].

This patch was tested against drm-misc-next commit a596fcd9cbc7
("drm/panel: panel-simple: Add missing
pm_runtime_dont_use_autosuspend() calls") on a sc7180-trogdor-lazor
device.

At v8 now, the bindings patches have been beefed up from v7 and
review/ack tags were added. Also allmodconfig was fixed.

Between v2 and v3, high-level view of changes:
- stop doing the EDID caching in the core.

Between v3 and v4, high-level view of changes:
- EDID reading is actually driven by the panel driver now. See above.
- Lots of chicken-and-egg problems solved w/ sub-devices.

Between v4 and v5, high-level view of changes.
- Some of the early patches landed, so dropped from series.
- New pm_runtime_disable() fix (fixed a patch that already landed).
- Added Bjorn's tags to most patches
- Fixed problems when building as a module.
- Reordered debugfs patch and fixed error handling there.
- Dropped last patch. I'm not convinced it's safe w/out more work.

Between v5 and v6, high-level view of changes:
- Added the patch ("drm/dp: Allow an early call to register DDC i2c
  bus")
- Many patches had been landed, so only a few "controversial" ones
  left.

Between v6 and v7, high-level view of changes:
- New AUX DP bus!

Between v7 and v8, high-level view of changes:
- More bindings work.
- Fixed allmodconfig.

[1] 
https://lore.kernel.org/r/20210304155144.3.I60a7fb23ce4589006bc95c64ab8d15c74b876e68@changeid/

Changes in v8:
- Allow dp-aux-bus to be a module to fix allmodconfig builds
- Explain better why HPD needs to be in panel-simple in commit msg.
- Separate DP AUX bus binding is new for v8.
- ti-sn65dsi86 references the new aux bus bindings.

Changes in v7:
- Adjusted commit message to talk about DP AUX bus.
- Beefed up commit message in context of the DP AUX bus.
- List hpd properties bindings patch new for v7.
- Panel now under bridge chip instead of getting a link to ddc-i2c
- Patch introducing the DP AUX bus is new for v7.
- Patch to allow panel-simple to be DP AUX EP new for v7.
- Patch to support for DP AUX bus on ti-sn65dsi86 new for v7.
- Patch using the DP AUX for DDC new for v7.
- Remove use of now-dropped drm_dp_aux_register_ddc() call.
- Set the proper sub-device "dev" pointer in the AUX structure.
- ti-sn65dsi86: Add aux-bus child patch new for v7.

Changes in v6:
- Use new drm_dp_aux_register_ddc() calls.

Douglas Anderson (11):
  dt-bindings: display: simple: List hpd properties in panel-simple
  dt-bindings: drm: Introduce the DP AUX bus
  dt-bindings: drm/bridge: ti-sn65dsi86: Add aux-bus child
  dt-bindings: drm/aux-bus: Add an example
  drm: Introduce the DP AUX bus
  drm/panel: panel-simple: Allow panel-simple be a DP AUX endpoint
device
  drm/panel: panel-simple: Stash DP AUX bus; allow using it for DDC
  drm/bridge: ti-sn65dsi86: Promote the AUX channel to its own sub-dev
  drm/bridge: ti-sn65dsi86: Add support for the DP AUX bus
  drm/bridge: ti-sn65dsi86: Don't read EDID blob over DDC
  arm64: dts: qcom: sc7180-trogdor: Move panel under the bridge chip

 .../bindings/display/bridge/ti,sn65dsi86.yaml |  20 +-
 .../bindings/display/dp-aux-bus.yaml  | 102 ++
 .../bindings/display/panel/panel-simple.yaml  |   2 +
 arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi  |  30 +-
 drivers/gpu/drm/Kconfig   |   5 +
 drivers/gpu/drm/Makefile  |   2 +
 drivers/gpu/drm/bridge/Kconfig|   1 +
 drivers/gpu/drm/bridge/ti-sn65dsi86.c | 111 --
 drivers/gpu/drm/drm_dp_aux_bus.c  | 326 ++
 drivers/gpu/drm/panel/Kconfig |   1 +
 drivers/gpu/drm/panel/panel-simple.c  |  64 +++-
 include/drm/drm_dp_aux_bus.h  |  57 +++
 12 files changed, 665 insertions(+), 

Re: [RFC PATCH 08/97] drm/i915/guc: Keep strict GuC ABI definitions

2021-05-24 Thread Michał Winiarski
Quoting Matthew Brost (2021-05-06 21:13:22)
> From: Michal Wajdeczko 
> 
> Our fwif.h file is now mix of strict firmware ABI definitions and
> set of our helpers. In anticipation of upcoming changes to the GuC
> interface try to keep them separate in smaller maintainable files.
> 
> Signed-off-by: Michal Wajdeczko 
> Signed-off-by: Matthew Brost 
> Cc: Michał Winiarski 

Reviewed-by: Michał Winiarski 

-Michał

> ---
>  .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h  |  51 +
>  .../gt/uc/abi/guc_communication_ctb_abi.h | 106 +
>  .../gt/uc/abi/guc_communication_mmio_abi.h|  52 +
>  .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h   |  14 ++
>  .../gpu/drm/i915/gt/uc/abi/guc_messages_abi.h |  21 ++
>  drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h   | 203 +-
>  6 files changed, 250 insertions(+), 197 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
>  create mode 100644 drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h
>  create mode 100644 
> drivers/gpu/drm/i915/gt/uc/abi/guc_communication_mmio_abi.h
>  create mode 100644 drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h
>  create mode 100644 drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h


Re: [PATCH v18 2/4] dt-bindings: msm: dsi: add yaml schemas for DSI bindings

2021-05-24 Thread Rob Herring
On Mon, 24 May 2021 17:14:11 +0530, Krishna Manikandan wrote:
> Add YAML schema for the device tree bindings for DSI
> 
> Signed-off-by: Krishna Manikandan 
> Reviewed-by: Bjorn Andersson 
> Reviewed-by: Stephen Boyd 
> ---
> Changes in v1:
> - Separate dsi controller bindings to a separate patch (Stephen Boyd)
> - Merge dsi-common-controller.yaml and dsi-controller-main.yaml to
>   a single file (Stephen Boyd)
> - Drop supply entries and definitions from properties (Stephen Boyd)
> - Modify phy-names property for dsi controller (Stephen Boyd)
> - Remove boolean from description (Stephen Boyd)
> - Drop pinctrl properties as they are standard entries (Stephen Boyd)
> - Modify the description for ports property and keep the reference
>   to the generic binding where this is defined (Stephen Boyd)
> - Add description to clock names (Stephen Boyd)
> - Correct the indendation (Stephen Boyd)
> - Drop the label for display dt nodes and correct the node
>   name (Stephen Boyd)
> 
> Changes in v2:
> - Drop maxItems for clock (Stephen Boyd)
> - Drop qcom,mdss-mdp-transfer-time-us as it is not used in upstream
>   dt file (Stephen Boyd)
> - Keep child node directly under soc node (Stephen Boyd)
> - Drop qcom,sync-dual-dsi as it is not used in upstream dt
> 
> Changes in v3:
> - Add description for register property (Stephen Boyd)
> 
> Changes in v4:
> - Add maxItems for phys property (Stephen Boyd)
> - Add maxItems for reg property (Stephen Boyd)
> - Add reference for data-lanes property (Stephen Boyd)
> - Remove soc from example (Stephen Boyd)
> 
> Changes in v5:
> - Modify title and description (Stephen Boyd)
> - Add required properties for ports node (Stephen Boyd)
> - Add data-lanes in the example (Stephen Boyd)
> - Drop qcom,master-dsi property (Stephen Boyd)
> 
> Changes in v6:
> - Add required properties for port@0, port@1 and corresponding
>   endpoints (Stephen Boyd)
> - Add address-cells and size-cells for ports (Stephen Boyd)
> - Use additionalProperties instead of unevaluatedProperties (Stephen Boyd)
> 
> Changes in v7:
> - Add reference for ports and data-lanes (Rob Herring)
> - Add maxItems and minItems for data-lanes (Rob Herring)
> 
> Changes in v8:
> - Drop common properties and description from ports (Rob Herring)
> - Add reference for endpoint (Rob Herring)
> - Add correct reference for data-lanes (Rob Herring)
> - Drop common properties from required list for ports (Rob Herring)
> 
> Changes in v9:
> - Drop reference for data-lanes (Rob Herring)
> - Add unevaluatedProperties for endpoint (Rob Herring)
> 
>  .../bindings/display/msm/dsi-controller-main.yaml  | 185 +++
>  .../devicetree/bindings/display/msm/dsi.txt| 249 
> -
>  2 files changed, 185 insertions(+), 249 deletions(-)
>  create mode 100644 
> Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
>  delete mode 100644 Documentation/devicetree/bindings/display/msm/dsi.txt
> 

Reviewed-by: Rob Herring 


Re: (subset) [PATCHv2 0/5] Support for GE B1x5v2 and B1x5Pv2

2021-05-24 Thread Alexandre Belloni
On Thu, 29 Apr 2021 00:29:48 +0200, Sebastian Reichel wrote:
> This series adds support for another General Electric patient
> monitor series (similar to existing Bx50v3), which is based on
> i.MX6DL using Congatec's QMX6 module.
> 
> The module uses an I2C RTC to provide the i.MX6 32768 Hz clock,
> so it's important to keep it enabled. Not doing so results in
> incorrect timings of watchdog and i.MX6 RTC. The bootloader
> enables the watchdog, so disabling the clock results in system
> reboot. [0]
> 
> [...]

Applied, thanks!

[1/5] rtc: m41t80: add support for fixed clock
  commit: f765e349c3e1f2e676ad4bd61197216b26976022

Best regards,
-- 
Alexandre Belloni 


Re: [Freedreno] [PATCH v2 6/6] drm/msm/dpu: simplify IRQ enabling/disabling

2021-05-24 Thread abhinavk

On 2021-05-16 13:29, Dmitry Baryshkov wrote:

Merge dpu_core_irq_enable() into dpu_core_irq_register_callback() and
dpu_core_irq_disable() into dpu_core_irq_unregister_callback(), because
they are called in pairs. There is no need to have separate
enable/disable pair, we can enable hardware IRQ when first callback is
registered and when the last callback is unregistered.

Since this change also removes the enable_counts atomic counter, I was a 
bit hesitant
because its helpful to protect against vblank discrepancies from 
usermode during enable/disable

but i think we have more protection for blank using vblank_refcount

413 if (enable && atomic_inc_return(_enc->vblank_refcount) == 1)
414 ret = dpu_encoder_helper_register_irq(phys_enc, INTR_IDX_VSYNC);
415 	else if (!enable && atomic_dec_return(_enc->vblank_refcount) 
== 0)

416 ret = dpu_encoder_helper_unregister_irq(phys_enc,
417 INTR_IDX_VSYNC);
418
419 end:

So this should still be okay. Hence

Signed-off-by: Dmitry Baryshkov 

Reviewed-by: Abhinav Kumar 

---
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c | 168 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h |  30 
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c  |  18 --
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h  |   2 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h|   8 -
 5 files changed, 27 insertions(+), 199 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
index 11c0abed21ee..4f110c428b60 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
@@ -26,10 +26,8 @@ static void dpu_core_irq_callback_handler(void
*arg, int irq_idx)

pr_debug("irq_idx=%d\n", irq_idx);

-   if (list_empty(_obj->irq_cb_tbl[irq_idx])) {
-   DRM_ERROR("no registered cb, idx:%d enable_count:%d\n", irq_idx,
-   atomic_read(_kms->irq_obj.enable_counts[irq_idx]));
-   }
+   if (list_empty(_obj->irq_cb_tbl[irq_idx]))
+   DRM_ERROR("no registered cb, idx:%d\n", irq_idx);

atomic_inc(_obj->irq_counts[irq_idx]);

@@ -43,127 +41,6 @@ static void dpu_core_irq_callback_handler(void
*arg, int irq_idx)
spin_unlock_irqrestore(_kms->irq_obj.cb_lock, irq_flags);
 }

-/**
- * _dpu_core_irq_enable - enable core interrupt given by the index
- * @dpu_kms:   Pointer to dpu kms context
- * @irq_idx:   interrupt index
- */
-static int _dpu_core_irq_enable(struct dpu_kms *dpu_kms, int irq_idx)
-{
-   unsigned long irq_flags;
-   int ret = 0, enable_count;
-
-   if (!dpu_kms->hw_intr ||
-   !dpu_kms->irq_obj.enable_counts ||
-   !dpu_kms->irq_obj.irq_counts) {
-   DPU_ERROR("invalid params\n");
-   return -EINVAL;
-   }
-
-   if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) {
-   DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
-   return -EINVAL;
-   }
-
-   enable_count = atomic_read(_kms->irq_obj.enable_counts[irq_idx]);
-   DRM_DEBUG_KMS("irq_idx=%d enable_count=%d\n", irq_idx, enable_count);
-   trace_dpu_core_irq_enable_idx(irq_idx, enable_count);
-
-	if (atomic_inc_return(_kms->irq_obj.enable_counts[irq_idx]) == 1) 
{

-   ret = dpu_kms->hw_intr->ops.enable_irq(
-   dpu_kms->hw_intr,
-   irq_idx);
-   if (ret)
-   DPU_ERROR("Fail to enable IRQ for irq_idx:%d\n",
-   irq_idx);
-
-   DPU_DEBUG("irq_idx=%d ret=%d\n", irq_idx, ret);
-
-   spin_lock_irqsave(_kms->irq_obj.cb_lock, irq_flags);
-   /* empty callback list but interrupt is enabled */
-   if (list_empty(_kms->irq_obj.irq_cb_tbl[irq_idx]))
-   DPU_ERROR("irq_idx=%d enabled with no callback\n",
-   irq_idx);
-   spin_unlock_irqrestore(_kms->irq_obj.cb_lock, irq_flags);
-   }
-
-   return ret;
-}
-
-int dpu_core_irq_enable(struct dpu_kms *dpu_kms, int *irq_idxs, u32 
irq_count)

-{
-   int i, ret = 0, counts;
-
-   if (!irq_idxs || !irq_count) {
-   DPU_ERROR("invalid params\n");
-   return -EINVAL;
-   }
-
-   counts = atomic_read(_kms->irq_obj.enable_counts[irq_idxs[0]]);
-   if (counts)
-   DRM_ERROR("irq_idx=%d enable_count=%d\n", irq_idxs[0], counts);
-
-   for (i = 0; (i < irq_count) && !ret; i++)
-   ret = _dpu_core_irq_enable(dpu_kms, irq_idxs[i]);
-
-   return ret;
-}
-
-/**
- * _dpu_core_irq_disable - disable core interrupt given by the index
- * @dpu_kms:   Pointer to dpu kms context
- * @irq_idx:   interrupt index
- */
-static int _dpu_core_irq_disable(struct dpu_kms *dpu_kms, int irq_idx)
-{
-   int 

Re: [PATCH v9 07/10] mm: Device exclusive memory access

2021-05-24 Thread Andrew Morton
On Mon, 24 May 2021 23:27:22 +1000 Alistair Popple  wrote:

> Some devices require exclusive write access to shared virtual
> memory (SVM) ranges to perform atomic operations on that memory. This
> requires CPU page tables to be updated to deny access whilst atomic
> operations are occurring.
> 
> In order to do this introduce a new swap entry
> type (SWP_DEVICE_EXCLUSIVE). When a SVM range needs to be marked for
> exclusive access by a device all page table mappings for the particular
> range are replaced with device exclusive swap entries. This causes any
> CPU access to the page to result in a fault.
> 
> Faults are resovled by replacing the faulting entry with the original
> mapping. This results in MMU notifiers being called which a driver uses
> to update access permissions such as revoking atomic access. After
> notifiers have been called the device will no longer have exclusive
> access to the region.
> 
> Walking of the page tables to find the target pages is handled by
> get_user_pages() rather than a direct page table walk. A direct page
> table walk similar to what migrate_vma_collect()/unmap() does could also
> have been utilised. However this resulted in more code similar in
> functionality to what get_user_pages() provides as page faulting is
> required to make the PTEs present and to break COW.
> 
> ...
>
>  Documentation/vm/hmm.rst |  17 
>  include/linux/mmu_notifier.h |   6 ++
>  include/linux/rmap.h |   4 +
>  include/linux/swap.h |   7 +-
>  include/linux/swapops.h  |  44 -
>  mm/hmm.c |   5 +
>  mm/memory.c  | 128 +++-
>  mm/mprotect.c|   8 ++
>  mm/page_vma_mapped.c |   9 +-
>  mm/rmap.c| 186 +++
>  10 files changed, 405 insertions(+), 9 deletions(-)
> 

This is quite a lot of code added to core MM for a single driver.

Is there any expectation that other drivers will use this code?

Is there a way of reducing the impact (code size, at least) for systems
which don't need this code?

How beneficial is this code to nouveau users?  I see that it permits a
part of OpenCL to be implemented, but how useful/important is this in
the real world?

Thanks.


Re: [Freedreno] [PATCH v2 5/6] drm/msm/dpu: drop remains of old irq lookup subsystem

2021-05-24 Thread abhinavk

On 2021-05-16 13:29, Dmitry Baryshkov wrote:

There is no more need for the dpu_intr_type types, dpu_irq_map table,
individual intr defines and obsolete_irq field. Drop all of them now.

Signed-off-by: Dmitry Baryshkov 

Reviewed-by: Abhinav Kumar 

---
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |2 -
 .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  |4 -
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  |2 -
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c|9 -
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h|2 -
 .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 1234 -
 .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h |   64 -
 7 files changed, 1317 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 3bd12ce45a80..e7270eb6b84b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -165,7 +165,6 @@ enum dpu_intr_idx {
 /**
  * dpu_encoder_irq - tracking structure for interrupts
  * @name:  string name of interrupt
- * @intr_type: Encoder interrupt type
  * @intr_idx:  Encoder interrupt enumeration
  * @irq_idx:   IRQ interface lookup index from DPU IRQ framework
  * will be -EINVAL if IRQ is not registered
@@ -173,7 +172,6 @@ enum dpu_intr_idx {
  */
 struct dpu_encoder_irq {
const char *name;
-   enum dpu_intr_type intr_type;
enum dpu_intr_idx intr_idx;
int irq_idx;
struct dpu_irq_callback cb;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
index 6f06e379b97f..36064004d6ff 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -789,25 +789,21 @@ struct dpu_encoder_phys 
*dpu_encoder_phys_cmd_init(


irq = _enc->irq[INTR_IDX_CTL_START];
irq->name = "ctl_start";
-   irq->intr_type = DPU_IRQ_TYPE_CTL_START;
irq->intr_idx = INTR_IDX_CTL_START;
irq->cb.func = dpu_encoder_phys_cmd_ctl_start_irq;

irq = _enc->irq[INTR_IDX_PINGPONG];
irq->name = "pp_done";
-   irq->intr_type = DPU_IRQ_TYPE_PING_PONG_COMP;
irq->intr_idx = INTR_IDX_PINGPONG;
irq->cb.func = dpu_encoder_phys_cmd_pp_tx_done_irq;

irq = _enc->irq[INTR_IDX_RDPTR];
irq->name = "pp_rd_ptr";
-   irq->intr_type = DPU_IRQ_TYPE_PING_PONG_RD_PTR;
irq->intr_idx = INTR_IDX_RDPTR;
irq->cb.func = dpu_encoder_phys_cmd_pp_rd_ptr_irq;

irq = _enc->irq[INTR_IDX_UNDERRUN];
irq->name = "underrun";
-   irq->intr_type = DPU_IRQ_TYPE_INTF_UNDER_RUN;
irq->intr_idx = INTR_IDX_UNDERRUN;
irq->cb.func = dpu_encoder_phys_cmd_underrun_irq;

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index 6cdb4ecbc173..4ef3d7357c2d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -729,13 +729,11 @@ struct dpu_encoder_phys 
*dpu_encoder_phys_vid_init(


irq = _enc->irq[INTR_IDX_VSYNC];
irq->name = "vsync_irq";
-   irq->intr_type = DPU_IRQ_TYPE_INTF_VSYNC;
irq->intr_idx = INTR_IDX_VSYNC;
irq->cb.func = dpu_encoder_phys_vid_vblank_irq;

irq = _enc->irq[INTR_IDX_UNDERRUN];
irq->name = "underrun";
-   irq->intr_type = DPU_IRQ_TYPE_INTF_UNDER_RUN;
irq->intr_idx = INTR_IDX_UNDERRUN;
irq->cb.func = dpu_encoder_phys_vid_underrun_irq;

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 f929131ed260..d01c4c919504 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -74,13 +74,6 @@
 BIT(MDP_INTF0_INTR) | \
 BIT(MDP_INTF1_INTR))

-#define INTR_SC7180_MASK \
-   (BIT(DPU_IRQ_TYPE_PING_PONG_RD_PTR) |\
-   BIT(DPU_IRQ_TYPE_PING_PONG_WR_PTR) |\
-   BIT(DPU_IRQ_TYPE_PING_PONG_AUTO_REF) |\
-   BIT(DPU_IRQ_TYPE_PING_PONG_TEAR_CHECK) |\
-   BIT(DPU_IRQ_TYPE_PING_PONG_TE_CHECK))
-
 #define IRQ_SC7280_MASK (BIT(MDP_SSPP_TOP0_INTR) | \
 BIT(MDP_SSPP_TOP0_INTR2) | \
 BIT(MDP_SSPP_TOP0_HIST_INTR) | \
@@ -1171,7 +1164,6 @@ static void sc7180_cfg_init(struct dpu_mdss_cfg 
*dpu_cfg)

.dma_cfg = sdm845_regdma,
.perf = sc7180_perf_data,
.mdss_irqs = IRQ_SC7180_MASK,
-   .obsolete_irq = INTR_SC7180_MASK,
};
 }

@@ -1261,7 +1253,6 @@ static void sc7280_cfg_init(struct dpu_mdss_cfg 
*dpu_cfg)

.vbif = sdm845_vbif,
.perf = sc7280_perf_data,
.mdss_irqs = IRQ_SC7280_MASK,
-   .obsolete_irq = 

Re: [Freedreno] [PATCH v2 4/6] drm/msm/dpu: replace IRQ lookup with the data in hw catalog

2021-05-24 Thread abhinavk

On 2021-05-16 13:29, Dmitry Baryshkov wrote:

The IRQ table in the dpu_hw_interrupts.h is big, ugly, and hard to
maintain. There are only few interrupts used from that table. Newer
generations use different IRQ locations. Move this data to hw catalog.

I think you can drop the line that "only few interrupts ..." are used as 
that
was specific to sc7280 as you mentioned on IRC or give the example of 
sc7280

here to explain that as being one of the motivations for this cleanup.


Signed-off-by: Dmitry Baryshkov 


With that fixed, I think this cleanup looks quite reasonable to me.
I computed a few of the intr offsets and the values were matching the 
prev hard-coded
offsets. Since I dont have the sc7280 HW to test this, I am checking if 
someone with that
hw in our team can test it out as well to make sure that it covers that 
hw as well.


But otherwise,

Reviewed-by: Abhinav Kumar 

---
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c  |  20 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h  |  13 --
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   |  64 +++-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   2 -
 .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  |  36 ++---
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  |  31 +---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 150 +++---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h|  12 +-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 137 +++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h |  17 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h |  28 ++--
 11 files changed, 229 insertions(+), 281 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
index fd11a2aeab6c..11c0abed21ee 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
@@ -43,16 +43,6 @@ static void dpu_core_irq_callback_handler(void
*arg, int irq_idx)
spin_unlock_irqrestore(_kms->irq_obj.cb_lock, irq_flags);
 }

-int dpu_core_irq_idx_lookup(struct dpu_kms *dpu_kms,
-   enum dpu_intr_type intr_type, u32 instance_idx)
-{
-   if (!dpu_kms->hw_intr || !dpu_kms->hw_intr->ops.irq_idx_lookup)
-   return -EINVAL;
-
-   return dpu_kms->hw_intr->ops.irq_idx_lookup(dpu_kms->hw_intr,
-   intr_type, instance_idx);
-}
-
 /**
  * _dpu_core_irq_enable - enable core interrupt given by the index
  * @dpu_kms:   Pointer to dpu kms context
@@ -70,7 +60,7 @@ static int _dpu_core_irq_enable(struct dpu_kms
*dpu_kms, int irq_idx)
return -EINVAL;
}

-   if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->irq_idx_tbl_size) {
+   if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) {
DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
return -EINVAL;
}
@@ -133,7 +123,7 @@ static int _dpu_core_irq_disable(struct dpu_kms
*dpu_kms, int irq_idx)
return -EINVAL;
}

-   if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->irq_idx_tbl_size) {
+   if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) {
DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
return -EINVAL;
}
@@ -208,7 +198,7 @@ int dpu_core_irq_register_callback(struct dpu_kms
*dpu_kms, int irq_idx,
return -EINVAL;
}

-   if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->irq_idx_tbl_size) {
+   if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) {
DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
return -EINVAL;
}
@@ -243,7 +233,7 @@ int dpu_core_irq_unregister_callback(struct
dpu_kms *dpu_kms, int irq_idx,
return -EINVAL;
}

-   if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->irq_idx_tbl_size) {
+   if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) {
DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
return -EINVAL;
}
@@ -328,7 +318,7 @@ void dpu_core_irq_preinstall(struct dpu_kms 
*dpu_kms)

spin_lock_init(_kms->irq_obj.cb_lock);

/* Create irq callbacks for all possible irq_idx */
-   dpu_kms->irq_obj.total_irqs = dpu_kms->hw_intr->irq_idx_tbl_size;
+   dpu_kms->irq_obj.total_irqs = dpu_kms->hw_intr->total_irqs;
dpu_kms->irq_obj.irq_cb_tbl = kcalloc(dpu_kms->irq_obj.total_irqs,
sizeof(struct list_head), GFP_KERNEL);
dpu_kms->irq_obj.enable_counts = kcalloc(dpu_kms->irq_obj.total_irqs,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
index e30775e6585b..d147784d5531 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
@@ -29,19 +29,6 @@ void dpu_core_irq_uninstall(struct dpu_kms 
*dpu_kms);

  */
 irqreturn_t dpu_core_irq(struct dpu_kms *dpu_kms);

-/**
- * 

Re: [Freedreno] [PATCH v2 3/6] drm/msm/dpu: define interrupt register names

2021-05-24 Thread abhinavk

On 2021-05-16 13:29, Dmitry Baryshkov wrote:

In order to make mdss_irqs readable (and error-prone) define names for

I think you meant "less error-prone" here.

interrupt register indices.

Signed-off-by: Dmitry Baryshkov 

With that nit fixed,
Reviewed-by: Abhinav Kumar 

---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 45 ---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 18 
 2 files changed, 58 insertions(+), 5 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 b569030a0847..9a77d64d3fd4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include "dpu_hw_mdss.h"
+#include "dpu_hw_interrupts.h"
 #include "dpu_hw_catalog.h"
 #include "dpu_kms.h"

@@ -56,6 +57,23 @@

 #define INTF_SC7280_MASK INTF_SC7180_MASK | BIT(DPU_DATA_HCTL_EN)

+#define IRQ_SDM845_MASK (BIT(MDP_SSPP_TOP0_INTR) | \
+BIT(MDP_SSPP_TOP0_INTR2) | \
+BIT(MDP_SSPP_TOP0_HIST_INTR) | \
+BIT(MDP_INTF0_INTR) | \
+BIT(MDP_INTF1_INTR) | \
+BIT(MDP_INTF2_INTR) | \
+BIT(MDP_INTF3_INTR) | \
+BIT(MDP_INTF4_INTR) | \
+BIT(MDP_AD4_0_INTR) | \
+BIT(MDP_AD4_1_INTR))
+
+#define IRQ_SC7180_MASK (BIT(MDP_SSPP_TOP0_INTR) | \
+BIT(MDP_SSPP_TOP0_INTR2) | \
+BIT(MDP_SSPP_TOP0_HIST_INTR) | \
+BIT(MDP_INTF0_INTR) | \
+BIT(MDP_INTF1_INTR))
+
 #define INTR_SC7180_MASK \
(BIT(DPU_IRQ_TYPE_PING_PONG_RD_PTR) |\
BIT(DPU_IRQ_TYPE_PING_PONG_WR_PTR) |\
@@ -63,6 +81,23 @@
BIT(DPU_IRQ_TYPE_PING_PONG_TEAR_CHECK) |\
BIT(DPU_IRQ_TYPE_PING_PONG_TE_CHECK))

+#define IRQ_SC7280_MASK (BIT(MDP_SSPP_TOP0_INTR) | \
+BIT(MDP_SSPP_TOP0_INTR2) | \
+BIT(MDP_SSPP_TOP0_HIST_INTR) | \
+BIT(MDP_INTF0_7xxx_INTR) | \
+BIT(MDP_INTF1_7xxx_INTR) | \
+BIT(MDP_INTF5_7xxx_INTR))
+
+#define IRQ_SM8250_MASK (BIT(MDP_SSPP_TOP0_INTR) | \
+BIT(MDP_SSPP_TOP0_INTR2) | \
+BIT(MDP_SSPP_TOP0_HIST_INTR) | \
+BIT(MDP_INTF0_INTR) | \
+BIT(MDP_INTF1_INTR) | \
+BIT(MDP_INTF2_INTR) | \
+BIT(MDP_INTF3_INTR) | \
+BIT(MDP_INTF4_INTR))
+
+
 #define DEFAULT_PIXEL_RAM_SIZE (50 * 1024)
 #define DEFAULT_DPU_LINE_WIDTH 2048
 #define DEFAULT_DPU_OUTPUT_LINE_WIDTH  2560
@@ -1060,7 +1095,7 @@ static void sdm845_cfg_init(struct dpu_mdss_cfg 
*dpu_cfg)

.reg_dma_count = 1,
.dma_cfg = sdm845_regdma,
.perf = sdm845_perf_data,
-   .mdss_irqs = 0x3ff,
+   .mdss_irqs = IRQ_SDM845_MASK,
};
 }

@@ -1091,7 +1126,7 @@ static void sc7180_cfg_init(struct dpu_mdss_cfg 
*dpu_cfg)

.reg_dma_count = 1,
.dma_cfg = sdm845_regdma,
.perf = sc7180_perf_data,
-   .mdss_irqs = 0x3f,
+   .mdss_irqs = IRQ_SC7180_MASK,
.obsolete_irq = INTR_SC7180_MASK,
};
 }
@@ -1125,7 +1160,7 @@ static void sm8150_cfg_init(struct dpu_mdss_cfg 
*dpu_cfg)

.reg_dma_count = 1,
.dma_cfg = sm8150_regdma,
.perf = sm8150_perf_data,
-   .mdss_irqs = 0x3ff,
+   .mdss_irqs = IRQ_SDM845_MASK,
};
 }

@@ -1158,7 +1193,7 @@ static void sm8250_cfg_init(struct dpu_mdss_cfg 
*dpu_cfg)

.reg_dma_count = 1,
.dma_cfg = sm8250_regdma,
.perf = sm8250_perf_data,
-   .mdss_irqs = 0xff,
+   .mdss_irqs = IRQ_SM8250_MASK,
};
 }

@@ -1181,7 +1216,7 @@ static void sc7280_cfg_init(struct dpu_mdss_cfg 
*dpu_cfg)

.vbif_count = ARRAY_SIZE(sdm845_vbif),
.vbif = sdm845_vbif,
.perf = sc7280_perf_data,
-   .mdss_irqs = 0x1c07,
+   .mdss_irqs = IRQ_SC7280_MASK,
.obsolete_irq = INTR_SC7180_MASK,
};
 }
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
index 5bade5637ecc..b26a3445a8eb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
@@ -74,6 +74,24 @@ enum dpu_intr_type {
DPU_IRQ_TYPE_RESERVED,
 };

+/* When making changes be sure to sync with dpu_intr_set */
+enum dpu_hw_intr_reg {
+   MDP_SSPP_TOP0_INTR,
+   MDP_SSPP_TOP0_INTR2,
+   MDP_SSPP_TOP0_HIST_INTR,
+   MDP_INTF0_INTR,
+ 

Re: [Freedreno] [PATCH v2 2/6] drm/msm/dpu: hw_intr: always call dpu_hw_intr_clear_intr_status_nolock

2021-05-24 Thread abhinavk

On 2021-05-16 13:29, Dmitry Baryshkov wrote:

Always call dpu_hw_intr_clear_intr_status_nolock() from the
dpu_hw_intr_dispatch_irqs(). This simplifies the callback function
(which call clears the interrupts anyway) and enforces clearing the hw
interrupt status.


In the subject line you can remove the "hw_intr:"


Signed-off-by: Dmitry Baryshkov 
Reviewed-by: Bjorn Andersson 

With that nit fixed,
Reviewed-by: Abhinav Kumar 

---
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c  |  9 -
 .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 39 +--
 .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h |  9 -
 3 files changed, 18 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
index 54b34746a587..fd11a2aeab6c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
@@ -41,15 +41,6 @@ static void dpu_core_irq_callback_handler(void
*arg, int irq_idx)
if (cb->func)
cb->func(cb->arg, irq_idx);
spin_unlock_irqrestore(_kms->irq_obj.cb_lock, irq_flags);
-
-   /*
-* Clear pending interrupt status in HW.
-* NOTE: dpu_core_irq_callback_handler is protected by top-level
-*   spinlock, so it is safe to clear any interrupt status here.
-*/
-   dpu_kms->hw_intr->ops.clear_intr_status_nolock(
-   dpu_kms->hw_intr,
-   irq_idx);
 }

 int dpu_core_irq_idx_lookup(struct dpu_kms *dpu_kms,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
index cf9bfd45aa59..8bd22e060437 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
@@ -1362,6 +1362,22 @@ static int dpu_hw_intr_irqidx_lookup(struct
dpu_hw_intr *intr,
return -EINVAL;
 }

+static void dpu_hw_intr_clear_intr_status_nolock(struct dpu_hw_intr 
*intr,

+   int irq_idx)
+{
+   int reg_idx;
+
+   if (!intr)
+   return;
+
+   reg_idx = dpu_irq_map[irq_idx].reg_idx;
+   DPU_REG_WRITE(>hw, dpu_intr_set[reg_idx].clr_off,
+   dpu_irq_map[irq_idx].irq_mask);
+
+   /* ensure register writes go through */
+   wmb();
+}
+
 static void dpu_hw_intr_dispatch_irq(struct dpu_hw_intr *intr,
void (*cbfunc)(void *, int),
void *arg)
@@ -1430,9 +1446,8 @@ static void dpu_hw_intr_dispatch_irq(struct
dpu_hw_intr *intr,
 */
if (cbfunc)
cbfunc(arg, irq_idx);
-   else
-   intr->ops.clear_intr_status_nolock(
-   intr, irq_idx);
+
+   dpu_hw_intr_clear_intr_status_nolock(intr, 
irq_idx);

/*
 * When callback finish, clear the irq_status
@@ -1597,23 +1612,6 @@ static int dpu_hw_intr_disable_irqs(struct
dpu_hw_intr *intr)
return 0;
 }

-
-static void dpu_hw_intr_clear_intr_status_nolock(struct dpu_hw_intr 
*intr,

-   int irq_idx)
-{
-   int reg_idx;
-
-   if (!intr)
-   return;
-
-   reg_idx = dpu_irq_map[irq_idx].reg_idx;
-   DPU_REG_WRITE(>hw, dpu_intr_set[reg_idx].clr_off,
-   dpu_irq_map[irq_idx].irq_mask);
-
-   /* ensure register writes go through */
-   wmb();
-}
-
 static u32 dpu_hw_intr_get_interrupt_status(struct dpu_hw_intr *intr,
int irq_idx, bool clear)
 {
@@ -1655,7 +1653,6 @@ static void __setup_intr_ops(struct 
dpu_hw_intr_ops *ops)

ops->dispatch_irqs = dpu_hw_intr_dispatch_irq;
ops->clear_all_irqs = dpu_hw_intr_clear_irqs;
ops->disable_all_irqs = dpu_hw_intr_disable_irqs;
-   ops->clear_intr_status_nolock = dpu_hw_intr_clear_intr_status_nolock;
ops->get_interrupt_status = dpu_hw_intr_get_interrupt_status;
 }

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
index 5a1c304ba93f..5bade5637ecc 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
@@ -142,15 +142,6 @@ struct dpu_hw_intr_ops {
void (*cbfunc)(void *arg, int irq_idx),
void *arg);

-   /**
-* clear_intr_status_nolock() - clears the HW interrupts without lock
-* @intr:   HW interrupt handle
-* @irq_idx:Lookup irq index return from irq_idx_lookup
-*/
-   void (*clear_intr_status_nolock)(
-   struct dpu_hw_intr *intr,
-   int irq_idx);
-
/**
 * get_interrupt_status - Gets HW interrupt status, and clear if set,
   

Re: [Freedreno] [PATCH v2 1/6] drm/msm/dpu: merge dpu_hw_intr_get_interrupt_statuses into dpu_hw_intr_dispatch_irqs

2021-05-24 Thread abhinavk

On 2021-05-16 13:29, Dmitry Baryshkov wrote:
There is little sense in reading interrupt statuses and right after 
that

going after the array of statuses to dispatch them. Merge both loops
into single function doing read and dispatch.

Signed-off-by: Dmitry Baryshkov 
Reviewed-by: Bjorn Andersson 

Reviewed-by: Abhinav Kumar 

---
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c  | 10 +--
 .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 66 ++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h |  8 ---
 3 files changed, 20 insertions(+), 64 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
index cdec3fbe6ff4..54b34746a587 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
@@ -376,15 +376,6 @@ void dpu_core_irq_uninstall(struct dpu_kms 
*dpu_kms)


 irqreturn_t dpu_core_irq(struct dpu_kms *dpu_kms)
 {
-   /*
-* Read interrupt status from all sources. Interrupt status are
-* stored within hw_intr.
-* Function will also clear the interrupt status after reading.
-* Individual interrupt status bit will only get stored if it
-* is enabled.
-*/
-   dpu_kms->hw_intr->ops.get_interrupt_statuses(dpu_kms->hw_intr);
-
/*
 * Dispatch to HW driver to handle interrupt lookup that is being
 * fired. When matching interrupt is located, HW driver will call to
@@ -392,6 +383,7 @@ irqreturn_t dpu_core_irq(struct dpu_kms *dpu_kms)
 * dpu_core_irq_callback_handler will perform the registered function
 * callback, and do the interrupt status clearing once the registered
 * callback is finished.
+* Function will also clear the interrupt status after reading.
 */
dpu_kms->hw_intr->ops.dispatch_irqs(
dpu_kms->hw_intr,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
index 48c96b812126..cf9bfd45aa59 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
@@ -1371,6 +1371,7 @@ static void dpu_hw_intr_dispatch_irq(struct
dpu_hw_intr *intr,
int start_idx;
int end_idx;
u32 irq_status;
+   u32 enable_mask;
unsigned long irq_flags;

if (!intr)
@@ -1383,8 +1384,6 @@ static void dpu_hw_intr_dispatch_irq(struct
dpu_hw_intr *intr,
 */
spin_lock_irqsave(>irq_lock, irq_flags);
for (reg_idx = 0; reg_idx < ARRAY_SIZE(dpu_intr_set); reg_idx++) {
-   irq_status = intr->save_irq_status[reg_idx];
-
/*
 * Each Interrupt register has a range of 64 indexes, and
 * that is static for dpu_irq_map.
@@ -1396,6 +1395,20 @@ static void dpu_hw_intr_dispatch_irq(struct
dpu_hw_intr *intr,
start_idx >= ARRAY_SIZE(dpu_irq_map))
continue;

+   /* Read interrupt status */
+		irq_status = DPU_REG_READ(>hw, 
dpu_intr_set[reg_idx].status_off);

+
+   /* Read enable mask */
+   enable_mask = DPU_REG_READ(>hw, 
dpu_intr_set[reg_idx].en_off);
+
+   /* and clear the interrupt */
+   if (irq_status)
+   DPU_REG_WRITE(>hw, dpu_intr_set[reg_idx].clr_off,
+irq_status);
+
+   /* Finally update IRQ status based on enable mask */
+   irq_status &= enable_mask;
+
/*
 * Search through matching intr status from irq map.
 * start_idx and end_idx defined the search range in
@@ -1429,6 +1442,10 @@ static void dpu_hw_intr_dispatch_irq(struct
dpu_hw_intr *intr,
irq_status &= ~dpu_irq_map[irq_idx].irq_mask;
}
}
+
+   /* ensure register writes go through */
+   wmb();
+
spin_unlock_irqrestore(>irq_lock, irq_flags);
 }

@@ -1580,41 +1597,6 @@ static int dpu_hw_intr_disable_irqs(struct
dpu_hw_intr *intr)
return 0;
 }

-static void dpu_hw_intr_get_interrupt_statuses(struct dpu_hw_intr 
*intr)

-{
-   int i;
-   u32 enable_mask;
-   unsigned long irq_flags;
-
-   if (!intr)
-   return;
-
-   spin_lock_irqsave(>irq_lock, irq_flags);
-   for (i = 0; i < ARRAY_SIZE(dpu_intr_set); i++) {
-   if (!test_bit(i, >irq_mask))
-   continue;
-
-   /* Read interrupt status */
-   intr->save_irq_status[i] = DPU_REG_READ(>hw,
-   dpu_intr_set[i].status_off);
-
-   /* Read enable mask */
-   enable_mask = DPU_REG_READ(>hw, dpu_intr_set[i].en_off);
-
-   /* and clear the interrupt */
-   if (intr->save_irq_status[i])
-   DPU_REG_WRITE(>hw, dpu_intr_set[i].clr_off,
-   

[Bug 213201] [KAVERI] memory leak - unreferenced object 0xffff8881700cf988 (size 56)

2021-05-24 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=213201

--- Comment #4 from Erhard F. (erhar...@mailbox.org) ---
Happens on 5.11.x and 5.10.x too. This may take a while...

-- 
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 v7 01/10] drm/panel: panel-simple: Add missing pm_runtime_dont_use_autosuspend() calls

2021-05-24 Thread Doug Anderson
Hi,

On Mon, May 24, 2021 at 1:22 PM Laurent Pinchart
 wrote:
>
> Hi Doug,
>
> Thank you for the patch.
>
> On Mon, May 17, 2021 at 01:08:58PM -0700, Douglas Anderson wrote:
> > The PM Runtime docs specifically call out the need to call
> > pm_runtime_dont_use_autosuspend() in the remove() callback if
> > pm_runtime_use_autosuspend() was called in probe():
> >
> > > Drivers in ->remove() callback should undo the runtime PM changes done
> > > in ->probe(). Usually this means calling pm_runtime_disable(),
> > > pm_runtime_dont_use_autosuspend() etc.
>
> ~/src/kernel/linux $ git grep pm_runtime_use_autosuspend -- drivers | wc -l
> 209
> ~/src/kernel/linux $ git grep pm_runtime_dont_use_autosuspend -- drivers | wc 
> -l
> 80
>
> Seems like a lost battle :-(
>
> The fix is right, but I wonder if this shouldn't be handled
> automatically by the runtime PM core. The runtime PM API is notoriously
> difficult to use correctly.

No kidding.


> > We should do this. This fixes a warning splat that I saw when I was
> > testing out the panel-simple's remove().
> >
> > Fixes: 3235b0f20a0a ("drm/panel: panel-simple: Use runtime pm to avoid 
> > excessive unprepare / prepare")
> > Signed-off-by: Douglas Anderson 
>
> Reviewed-by: Laurent Pinchart 

Thanks! I have pushed just this patch for now.

-Doug


[PATCH 5/6] RFC: dma-buf: Add an extra fence to dma_resv_get_singleton_unlocked

2021-05-24 Thread Jason Ekstrand
For dma-buf sync_file import, we want to get all the fences on a
dma_resv plus one more.  We could wrap the fence we get back in an array
fence or we could make dma_resv_get_singleton_unlocked take "one more"
to make this case easier.

Signed-off-by: Jason Ekstrand 
---
 drivers/dma-buf/dma-buf.c  |  2 +-
 drivers/dma-buf/dma-resv.c | 23 +--
 include/linux/dma-resv.h   |  3 ++-
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 86efe71c0db96..f23d939e0e833 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -386,7 +386,7 @@ static long dma_buf_export_sync_file(struct dma_buf *dmabuf,
return fd;
 
if (arg.flags & DMA_BUF_SYNC_WRITE) {
-   fence = dma_resv_get_singleton_unlocked(dmabuf->resv);
+   fence = dma_resv_get_singleton_unlocked(dmabuf->resv, NULL);
if (IS_ERR(fence)) {
ret = PTR_ERR(fence);
goto err_put_fd;
diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
index 312a3a59dac6a..3c0ef8d0f599b 100644
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -527,6 +527,7 @@ EXPORT_SYMBOL_GPL(dma_resv_get_fences_unlocked);
 /**
  * dma_resv_get_singleton_unlocked - get a single fence for the dma_resv object
  * @obj: the reservation object
+ * @extra: extra fence to add to the resulting array
  * @result: resulting dma_fence
  *
  * Get a single fence representing all unsignaled fences in the dma_resv object
@@ -536,7 +537,8 @@ EXPORT_SYMBOL_GPL(dma_resv_get_fences_unlocked);
  * RETURNS
  * Returns -NOMEM if allocations fail, zero otherwise.
  */
-struct dma_fence *dma_resv_get_singleton_unlocked(struct dma_resv *obj)
+struct dma_fence *dma_resv_get_singleton_unlocked(struct dma_resv *obj,
+ struct dma_fence *extra)
 {
struct dma_fence *result, **resv_fences, *fence, *chain, **fences;
struct dma_fence_array *array;
@@ -547,7 +549,7 @@ struct dma_fence *dma_resv_get_singleton_unlocked(struct 
dma_resv *obj)
if (err)
return ERR_PTR(err);
 
-   if (num_resv_fences == 0)
+   if (num_resv_fences == 0 && !extra)
return NULL;
 
num_fences = 0;
@@ -563,6 +565,16 @@ struct dma_fence *dma_resv_get_singleton_unlocked(struct 
dma_resv *obj)
}
}
 
+   if (extra) {
+   dma_fence_deep_dive_for_each(fence, chain, j, extra) {
+   if (dma_fence_is_signaled(fence))
+   continue;
+
+   result = fence;
+   ++num_fences;
+   }
+   }
+
if (num_fences <= 1) {
result = dma_fence_get(result);
goto put_resv_fences;
@@ -583,6 +595,13 @@ struct dma_fence *dma_resv_get_singleton_unlocked(struct 
dma_resv *obj)
}
}
 
+   if (extra) {
+   dma_fence_deep_dive_for_each(fence, chain, j, extra) {
+   if (dma_fence_is_signaled(fence))
+   fences[num_fences++] = dma_fence_get(fence);
+   }
+   }
+
if (num_fences <= 1) {
result = num_fences ? fences[0] : NULL;
kfree(fences);
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h
index c529ccee94bc5..156d989e95ab4 100644
--- a/include/linux/dma-resv.h
+++ b/include/linux/dma-resv.h
@@ -285,7 +285,8 @@ int dma_resv_get_fences_unlocked(struct dma_resv *obj,
 
 int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src);
 
-struct dma_fence *dma_resv_get_singleton_unlocked(struct dma_resv *obj);
+struct dma_fence *dma_resv_get_singleton_unlocked(struct dma_resv *obj,
+ struct dma_fence *extra);
 
 long dma_resv_wait_timeout_unlocked(struct dma_resv *obj, bool wait_all, bool 
intr,
unsigned long timeout);
-- 
2.31.1



[PATCH 1/6] dma-buf: add dma_fence_array_for_each (v2)

2021-05-24 Thread Jason Ekstrand
From: Christian König 

Add a helper to iterate over all fences in a dma_fence_array object.

v2 (Jason Ekstrand)
 - Return NULL from dma_fence_array_first if head == NULL.  This matches
   the iterator behavior of dma_fence_chain_for_each in that it iterates
   zero times if head == NULL.
 - Return NULL from dma_fence_array_next if index > array->num_fences.

Signed-off-by: Jason Ekstrand 
Reviewed-by: Jason Ekstrand 
Reviewed-by: Christian König 
---
 drivers/dma-buf/dma-fence-array.c | 27 +++
 include/linux/dma-fence-array.h   | 17 +
 2 files changed, 44 insertions(+)

diff --git a/drivers/dma-buf/dma-fence-array.c 
b/drivers/dma-buf/dma-fence-array.c
index d3fbd950be944..2ac1afc697d0f 100644
--- a/drivers/dma-buf/dma-fence-array.c
+++ b/drivers/dma-buf/dma-fence-array.c
@@ -201,3 +201,30 @@ bool dma_fence_match_context(struct dma_fence *fence, u64 
context)
return true;
 }
 EXPORT_SYMBOL(dma_fence_match_context);
+
+struct dma_fence *dma_fence_array_first(struct dma_fence *head)
+{
+   struct dma_fence_array *array;
+
+   if (!head)
+   return NULL;
+
+   array = to_dma_fence_array(head);
+   if (!array)
+   return head;
+
+   return array->fences[0];
+}
+EXPORT_SYMBOL(dma_fence_array_first);
+
+struct dma_fence *dma_fence_array_next(struct dma_fence *head,
+  unsigned int index)
+{
+   struct dma_fence_array *array = to_dma_fence_array(head);
+
+   if (!array || index >= array->num_fences)
+   return NULL;
+
+   return array->fences[index];
+}
+EXPORT_SYMBOL(dma_fence_array_next);
diff --git a/include/linux/dma-fence-array.h b/include/linux/dma-fence-array.h
index 303dd712220fd..588ac8089dd61 100644
--- a/include/linux/dma-fence-array.h
+++ b/include/linux/dma-fence-array.h
@@ -74,6 +74,19 @@ to_dma_fence_array(struct dma_fence *fence)
return container_of(fence, struct dma_fence_array, base);
 }
 
+/**
+ * dma_fence_array_for_each - iterate over all fences in array
+ * @fence: current fence
+ * @index: index into the array
+ * @head: potential dma_fence_array object
+ *
+ * Test if @array is a dma_fence_array object and if yes iterate over all 
fences
+ * in the array. If not just iterate over the fence in @array itself.
+ */
+#define dma_fence_array_for_each(fence, index, head)   \
+   for (index = 0, fence = dma_fence_array_first(head); fence; \
+++(index), fence = dma_fence_array_next(head, index))
+
 struct dma_fence_array *dma_fence_array_create(int num_fences,
   struct dma_fence **fences,
   u64 context, unsigned seqno,
@@ -81,4 +94,8 @@ struct dma_fence_array *dma_fence_array_create(int num_fences,
 
 bool dma_fence_match_context(struct dma_fence *fence, u64 context);
 
+struct dma_fence *dma_fence_array_first(struct dma_fence *head);
+struct dma_fence *dma_fence_array_next(struct dma_fence *head,
+  unsigned int index);
+
 #endif /* __LINUX_DMA_FENCE_ARRAY_H */
-- 
2.31.1



[PATCH 3/6] dma-buf: add dma_resv_get_singleton_unlocked (v4)

2021-05-24 Thread Jason Ekstrand
Add a helper function to get a single fence representing
all fences in a dma_resv object.

This fence is either the only one in the object or all not
signaled fences of the object in a flatted out dma_fence_array.

v2 (Jason Ekstrand):
 - Take reference of fences both for creating the dma_fence_array and in
   the case where we return one fence.
 - Handle the case where dma_resv_get_list() returns NULL

v3 (Jason Ekstrand):
 - Add an _rcu suffix because it is read-only
 - Rewrite to use dma_resv_get_fences_rcu so it's RCU-safe
 - Add an EXPORT_SYMBOL_GPL declaration
 - Re-author the patch to Jason since very little is left of Christian
   König's original patch
 - Remove the extra fence argument

v4 (Jason Ekstrand):
 - Restore the extra fence argument

v5 (Daniel Vetter):
 - Rename from _rcu to _unlocked since it doesn't leak RCU details to
   the caller
 - Fix docs
 - Use ERR_PTR for error handling rather than an output dma_fence**

v5 (Jason Ekstrand):
 - Drop the extra fence param and leave that to a separate patch

Signed-off-by: Jason Ekstrand 
Reviewed-by: Daniel Vetter 
---
 drivers/dma-buf/dma-resv.c | 93 ++
 include/linux/dma-resv.h   |  2 +
 2 files changed, 95 insertions(+)

diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
index d6f1ed4cd4d55..312a3a59dac6a 100644
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -33,6 +33,8 @@
  */
 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -49,6 +51,11 @@
  * write-side updates.
  */
 
+/* deep dive into the fence containers */
+#define dma_fence_deep_dive_for_each(fence, chain, index, head)\
+   dma_fence_chain_for_each(chain, head)   \
+   dma_fence_array_for_each(fence, index, chain)
+
 DEFINE_WD_CLASS(reservation_ww_class);
 EXPORT_SYMBOL(reservation_ww_class);
 
@@ -517,6 +524,92 @@ int dma_resv_get_fences_unlocked(struct dma_resv *obj,
 }
 EXPORT_SYMBOL_GPL(dma_resv_get_fences_unlocked);
 
+/**
+ * dma_resv_get_singleton_unlocked - get a single fence for the dma_resv object
+ * @obj: the reservation object
+ * @result: resulting dma_fence
+ *
+ * Get a single fence representing all unsignaled fences in the dma_resv object
+ * plus the given extra fence. If we got only one fence return a new
+ * reference to that, otherwise return a dma_fence_array object.
+ *
+ * RETURNS
+ * Returns -NOMEM if allocations fail, zero otherwise.
+ */
+struct dma_fence *dma_resv_get_singleton_unlocked(struct dma_resv *obj)
+{
+   struct dma_fence *result, **resv_fences, *fence, *chain, **fences;
+   struct dma_fence_array *array;
+   unsigned int num_resv_fences, num_fences;
+   unsigned int err, i, j;
+
+   err = dma_resv_get_fences_unlocked(obj, NULL, _resv_fences, 
_fences);
+   if (err)
+   return ERR_PTR(err);
+
+   if (num_resv_fences == 0)
+   return NULL;
+
+   num_fences = 0;
+   result = NULL;
+
+   for (i = 0; i < num_resv_fences; ++i) {
+   dma_fence_deep_dive_for_each(fence, chain, j, resv_fences[i]) {
+   if (dma_fence_is_signaled(fence))
+   continue;
+
+   result = fence;
+   ++num_fences;
+   }
+   }
+
+   if (num_fences <= 1) {
+   result = dma_fence_get(result);
+   goto put_resv_fences;
+   }
+
+   fences = kmalloc_array(num_fences, sizeof(struct dma_fence*),
+  GFP_KERNEL);
+   if (!fences) {
+   result = ERR_PTR(-ENOMEM);
+   goto put_resv_fences;
+   }
+
+   num_fences = 0;
+   for (i = 0; i < num_resv_fences; ++i) {
+   dma_fence_deep_dive_for_each(fence, chain, j, resv_fences[i]) {
+   if (!dma_fence_is_signaled(fence))
+   fences[num_fences++] = dma_fence_get(fence);
+   }
+   }
+
+   if (num_fences <= 1) {
+   result = num_fences ? fences[0] : NULL;
+   kfree(fences);
+   goto put_resv_fences;
+   }
+
+   array = dma_fence_array_create(num_fences, fences,
+  dma_fence_context_alloc(1),
+  1, false);
+   if (array) {
+   result = >base;
+   } else {
+   result = ERR_PTR(-ENOMEM);
+   while (num_fences--)
+   dma_fence_put(fences[num_fences]);
+   kfree(fences);
+   }
+
+put_resv_fences:
+   while (num_resv_fences--)
+   dma_fence_put(resv_fences[num_resv_fences]);
+   kfree(resv_fences);
+
+   return result;
+}
+EXPORT_SYMBOL_GPL(dma_resv_get_singleton_unlocked);
+
 /**
  * dma_resv_wait_timeout_unlocked - Wait on reservation's objects
  * shared and/or exclusive fences.
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h

[PATCH 2/6] dma-buf: Rename dma_resv helpers from _rcu to _unlocked

2021-05-24 Thread Jason Ekstrand
None of these helpers actually leak any RCU details to the caller.  They
all assume you have a genuine reference, take the RCU read lock, and
retry if needed.  Naming them with an _rcu is likely to cause callers
more panic than needed.

Signed-off-by: Jason Ekstrand 
Suggested-by: Daniel Vetter 
---
 drivers/dma-buf/dma-buf.c |  2 +-
 drivers/dma-buf/dma-resv.c| 28 +--
 drivers/gpu/drm/amd/amdgpu/amdgpu_display.c   |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c   |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c   |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c   |  4 +--
 drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c|  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_object.c|  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c   |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c|  8 +++---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  2 +-
 drivers/gpu/drm/drm_gem.c |  6 ++--
 drivers/gpu/drm/drm_gem_atomic_helper.c   |  2 +-
 drivers/gpu/drm/etnaviv/etnaviv_gem.c |  4 +--
 drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c  |  4 +--
 drivers/gpu/drm/i915/display/intel_display.c  |  2 +-
 drivers/gpu/drm/i915/dma_resv_utils.c |  2 +-
 drivers/gpu/drm/i915/gem/i915_gem_busy.c  |  2 +-
 .../gpu/drm/i915/gem/i915_gem_execbuffer.c|  2 +-
 drivers/gpu/drm/i915/gem/i915_gem_object.h|  2 +-
 drivers/gpu/drm/i915/gem/i915_gem_userptr.c   |  2 +-
 drivers/gpu/drm/i915/gem/i915_gem_wait.c  | 10 +++
 drivers/gpu/drm/i915/i915_request.c   |  4 +--
 drivers/gpu/drm/i915/i915_sw_fence.c  |  4 +--
 drivers/gpu/drm/msm/msm_gem.c |  2 +-
 drivers/gpu/drm/nouveau/dispnv50/wndw.c   |  2 +-
 drivers/gpu/drm/nouveau/nouveau_gem.c |  2 +-
 drivers/gpu/drm/panfrost/panfrost_drv.c   |  2 +-
 drivers/gpu/drm/panfrost/panfrost_job.c   |  2 +-
 drivers/gpu/drm/radeon/radeon_gem.c   |  6 ++--
 drivers/gpu/drm/radeon/radeon_mn.c|  2 +-
 drivers/gpu/drm/ttm/ttm_bo.c  | 12 
 drivers/gpu/drm/vgem/vgem_fence.c |  2 +-
 drivers/gpu/drm/virtio/virtgpu_ioctl.c|  4 +--
 drivers/gpu/drm/vmwgfx/vmwgfx_bo.c|  2 +-
 include/linux/dma-resv.h  | 18 ++--
 36 files changed, 79 insertions(+), 79 deletions(-)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index f264b70c383eb..d4529aa9d1a5a 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -1147,7 +1147,7 @@ static int __dma_buf_begin_cpu_access(struct dma_buf 
*dmabuf,
long ret;
 
/* Wait on any implicit rendering fences */
-   ret = dma_resv_wait_timeout_rcu(resv, write, true,
+   ret = dma_resv_wait_timeout_unlocked(resv, write, true,
  MAX_SCHEDULE_TIMEOUT);
if (ret < 0)
return ret;
diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
index 6ddbeb5dfbf65..d6f1ed4cd4d55 100644
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -417,7 +417,7 @@ int dma_resv_copy_fences(struct dma_resv *dst, struct 
dma_resv *src)
 EXPORT_SYMBOL(dma_resv_copy_fences);
 
 /**
- * dma_resv_get_fences_rcu - Get an object's shared and exclusive
+ * dma_resv_get_fences_unlocked - Get an object's shared and exclusive
  * fences without update side lock held
  * @obj: the reservation object
  * @pfence_excl: the returned exclusive fence (or NULL)
@@ -429,10 +429,10 @@ EXPORT_SYMBOL(dma_resv_copy_fences);
  * exclusive fence is not specified the fence is put into the array of the
  * shared fences as well. Returns either zero or -ENOMEM.
  */
-int dma_resv_get_fences_rcu(struct dma_resv *obj,
-   struct dma_fence **pfence_excl,
-   unsigned *pshared_count,
-   struct dma_fence ***pshared)
+int dma_resv_get_fences_unlocked(struct dma_resv *obj,
+struct dma_fence **pfence_excl,
+unsigned *pshared_count,
+struct dma_fence ***pshared)
 {
struct dma_fence **shared = NULL;
struct dma_fence *fence_excl;
@@ -515,10 +515,10 @@ int dma_resv_get_fences_rcu(struct dma_resv *obj,
*pshared = shared;
return ret;
 }
-EXPORT_SYMBOL_GPL(dma_resv_get_fences_rcu);
+EXPORT_SYMBOL_GPL(dma_resv_get_fences_unlocked);
 
 /**
- * dma_resv_wait_timeout_rcu - Wait on reservation's objects
+ * dma_resv_wait_timeout_unlocked - Wait on reservation's objects
  * shared and/or exclusive fences.
  * @obj: the reservation object
  * @wait_all: if true, wait on all fences, else wait on just exclusive fence
@@ -529,9 +529,9 @@ EXPORT_SYMBOL_GPL(dma_resv_get_fences_rcu);
  * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or
  * greater than zer on success.
  */
-long dma_resv_wait_timeout_rcu(struct 

[PATCH 0/6] dma-buf: Add an API for exporting sync files (v10)

2021-05-24 Thread Jason Ekstrand
Modern userspace APIs like Vulkan are built on an explicit
synchronization model.  This doesn't always play nicely with the
implicit synchronization used in the kernel and assumed by X11 and
Wayland.  The client -> compositor half of the synchronization isn't too
bad, at least on intel, because we can control whether or not i915
synchronizes on the buffer and whether or not it's considered written.

The harder part is the compositor -> client synchronization when we get
the buffer back from the compositor.  We're required to be able to
provide the client with a VkSemaphore and VkFence representing the point
in time where the window system (compositor and/or display) finished
using the buffer.  With current APIs, it's very hard to do this in such
a way that we don't get confused by the Vulkan driver's access of the
buffer.  In particular, once we tell the kernel that we're rendering to
the buffer again, any CPU waits on the buffer or GPU dependencies will
wait on some of the client rendering and not just the compositor.

This new IOCTL solves this problem by allowing us to get a snapshot of
the implicit synchronization state of a given dma-buf in the form of a
sync file.  It's effectively the same as a poll() or I915_GEM_WAIT only,
instead of CPU waiting directly, it encapsulates the wait operation, at
the current moment in time, in a sync_file so we can check/wait on it
later.  As long as the Vulkan driver does the sync_file export from the
dma-buf before we re-introduce it for rendering, it will only contain
fences from the compositor or display.  This allows to accurately turn
it into a VkFence or VkSemaphore without any over- synchronization.

This patch series actually contains two new ioctls.  There is the export
one mentioned above as well as an RFC for an import ioctl which provides
the other half.  The intention is to land the export ioctl since it seems
like there's no real disagreement on that one.  The import ioctl, however,
has a lot of debate around it so it's intended to be RFC-only for now.

Mesa MR: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4037
IGT tests: https://patchwork.freedesktop.org/series/90490/

v10 (Jason Ekstrand, Daniel Vetter):
 - Add reviews/acks
 - Add a patch to rename _rcu to _unlocked
 - Split things better so import is clearly RFC status

Cc: Christian König 
Cc: Michel Dänzer 
Cc: Dave Airlie 
Cc: Bas Nieuwenhuizen 
Cc: Daniel Stone 
Cc: mesa-...@lists.freedesktop.org
Cc: wayland-de...@lists.freedesktop.org
Test-with: 20210524205225.872316-1-ja...@jlekstrand.net

Christian König (1):
  dma-buf: add dma_fence_array_for_each (v2)

Jason Ekstrand (5):
  dma-buf: Rename dma_resv helpers from _rcu to _unlocked
  dma-buf: add dma_resv_get_singleton_unlocked (v4)
  dma-buf: Add an API for exporting sync files (v9)
  RFC: dma-buf: Add an extra fence to dma_resv_get_singleton_unlocked
  RFC: dma-buf: Add an API for importing sync files (v6)

 drivers/dma-buf/dma-buf.c | 100 -
 drivers/dma-buf/dma-fence-array.c |  27 
 drivers/dma-buf/dma-resv.c| 140 --
 drivers/gpu/drm/amd/amdgpu/amdgpu_display.c   |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c   |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c   |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c   |   4 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c|   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_object.c|   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c   |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c|   8 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   2 +-
 drivers/gpu/drm/drm_gem.c |   6 +-
 drivers/gpu/drm/drm_gem_atomic_helper.c   |   2 +-
 drivers/gpu/drm/etnaviv/etnaviv_gem.c |   4 +-
 drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c  |   4 +-
 drivers/gpu/drm/i915/display/intel_display.c  |   2 +-
 drivers/gpu/drm/i915/dma_resv_utils.c |   2 +-
 drivers/gpu/drm/i915/gem/i915_gem_busy.c  |   2 +-
 .../gpu/drm/i915/gem/i915_gem_execbuffer.c|   2 +-
 drivers/gpu/drm/i915/gem/i915_gem_object.h|   2 +-
 drivers/gpu/drm/i915/gem/i915_gem_userptr.c   |   2 +-
 drivers/gpu/drm/i915/gem/i915_gem_wait.c  |  10 +-
 drivers/gpu/drm/i915/i915_request.c   |   4 +-
 drivers/gpu/drm/i915/i915_sw_fence.c  |   4 +-
 drivers/gpu/drm/msm/msm_gem.c |   2 +-
 drivers/gpu/drm/nouveau/dispnv50/wndw.c   |   2 +-
 drivers/gpu/drm/nouveau/nouveau_gem.c |   2 +-
 drivers/gpu/drm/panfrost/panfrost_drv.c   |   2 +-
 drivers/gpu/drm/panfrost/panfrost_job.c   |   2 +-
 drivers/gpu/drm/radeon/radeon_gem.c   |   6 +-
 drivers/gpu/drm/radeon/radeon_mn.c|   2 +-
 drivers/gpu/drm/ttm/ttm_bo.c  |  12 +-
 drivers/gpu/drm/vgem/vgem_fence.c |   2 +-
 drivers/gpu/drm/virtio/virtgpu_ioctl.c|   4 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_bo.c|   2 +-
 

[PATCH 6/6] RFC: dma-buf: Add an API for importing sync files (v6)

2021-05-24 Thread Jason Ekstrand
This patch is analogous to the previous sync file export patch in that
it allows you to import a sync_file into a dma-buf.  Unlike the previous
patch, however, this does add genuinely new functionality to dma-buf.
Without this, the only way to attach a sync_file to a dma-buf is to
submit a batch to your driver of choice which waits on the sync_file and
claims to write to the dma-buf.  Even if said batch is a no-op, a submit
is typically way more overhead than just attaching a fence.  A submit
may also imply extra synchronization with other work because it happens
on a hardware queue.

In the Vulkan world, this is useful for dealing with the out-fence from
vkQueuePresent.  Current Linux window-systems (X11, Wayland, etc.) all
rely on dma-buf implicit sync.  Since Vulkan is an explicit sync API, we
get a set of fences (VkSemaphores) in vkQueuePresent and have to stash
those as an exclusive (write) fence on the dma-buf.  We handle it in
Mesa today with the above mentioned dummy submit trick.  This ioctl
would allow us to set it directly without the dummy submit.

This may also open up possibilities for GPU drivers to move away from
implicit sync for their kernel driver uAPI and instead provide sync
files and rely on dma-buf import/export for communicating with other
implicit sync clients.

We make the explicit choice here to only allow setting RW fences which
translates to an exclusive fence on the dma_resv.  There's no use for
read-only fences for communicating with other implicit sync userspace
and any such attempts are likely to be racy at best.  When we got to
insert the RW fence, the actual fence we set as the new exclusive fence
is a combination of the sync_file provided by the user and all the other
fences on the dma_resv.  This ensures that the newly added exclusive
fence will never signal before the old one would have and ensures that
we don't break any dma_resv contracts.  We require userspace to specify
RW in the flags for symmetry with the export ioctl and in case we ever
want to support read fences in the future.

There is one downside here that's worth documenting:  If two clients
writing to the same dma-buf using this API race with each other, their
actions on the dma-buf may happen in parallel or in an undefined order.
Both with and without this API, the pattern is the same:  Collect all
the fences on dma-buf, submit work which depends on said fences, and
then set a new exclusive (write) fence on the dma-buf which depends on
said work.  The difference is that, when it's all handled by the GPU
driver's submit ioctl, the three operations happen atomically under the
dma_resv lock.  If two userspace submits race, one will happen before
the other.  You aren't guaranteed which but you are guaranteed that
they're strictly ordered.  If userspace manages the fences itself, then
these three operations happen separately and the two render operations
may happen genuinely in parallel or get interleaved.  However, this is a
case of userspace racing with itself.  As long as we ensure userspace
can't back the kernel into a corner, it should be fine.

v2 (Jason Ekstrand):
 - Use a wrapper dma_fence_array of all fences including the new one
   when importing an exclusive fence.

v3 (Jason Ekstrand):
 - Lock around setting shared fences as well as exclusive
 - Mark SIGNAL_SYNC_FILE as a read-write ioctl.
 - Initialize ret to 0 in dma_buf_wait_sync_file

v4 (Jason Ekstrand):
 - Use the new dma_resv_get_singleton helper

v5 (Jason Ekstrand):
 - Rename the IOCTLs to import/export rather than wait/signal
 - Drop the WRITE flag and always get/set the exclusive fence

v5 (Jason Ekstrand):
 - Split import and export into separate patches
 - New commit message

Signed-off-by: Jason Ekstrand 
---
 drivers/dma-buf/dma-buf.c| 34 ++
 include/uapi/linux/dma-buf.h |  1 +
 2 files changed, 35 insertions(+)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index f23d939e0e833..0a50c19dcf015 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -419,6 +419,38 @@ static long dma_buf_export_sync_file(struct dma_buf 
*dmabuf,
put_unused_fd(fd);
return ret;
 }
+
+static long dma_buf_import_sync_file(struct dma_buf *dmabuf,
+const void __user *user_data)
+{
+   struct dma_buf_sync_file arg;
+   struct dma_fence *fence, *singleton = NULL;
+   int ret = 0;
+
+   if (copy_from_user(, user_data, sizeof(arg)))
+   return -EFAULT;
+
+   if (arg.flags != DMA_BUF_SYNC_RW)
+   return -EINVAL;
+
+   fence = sync_file_get_fence(arg.fd);
+   if (!fence)
+   return -EINVAL;
+
+   dma_resv_lock(dmabuf->resv, NULL);
+
+   singleton = dma_resv_get_singleton_unlocked(dmabuf->resv, fence);
+   if (IS_ERR(singleton))
+   ret = PTR_ERR(singleton);
+   else if (singleton)
+   dma_resv_add_excl_fence(dmabuf->resv, singleton);
+

[PATCH 4/6] dma-buf: Add an API for exporting sync files (v9)

2021-05-24 Thread Jason Ekstrand
Modern userspace APIs like Vulkan are built on an explicit
synchronization model.  This doesn't always play nicely with the
implicit synchronization used in the kernel and assumed by X11 and
Wayland.  The client -> compositor half of the synchronization isn't too
bad, at least on intel, because we can control whether or not i915
synchronizes on the buffer and whether or not it's considered written.

The harder part is the compositor -> client synchronization when we get
the buffer back from the compositor.  We're required to be able to
provide the client with a VkSemaphore and VkFence representing the point
in time where the window system (compositor and/or display) finished
using the buffer.  With current APIs, it's very hard to do this in such
a way that we don't get confused by the Vulkan driver's access of the
buffer.  In particular, once we tell the kernel that we're rendering to
the buffer again, any CPU waits on the buffer or GPU dependencies will
wait on some of the client rendering and not just the compositor.

This new IOCTL solves this problem by allowing us to get a snapshot of
the implicit synchronization state of a given dma-buf in the form of a
sync file.  It's effectively the same as a poll() or I915_GEM_WAIT only,
instead of CPU waiting directly, it encapsulates the wait operation, at
the current moment in time, in a sync_file so we can check/wait on it
later.  As long as the Vulkan driver does the sync_file export from the
dma-buf before we re-introduce it for rendering, it will only contain
fences from the compositor or display.  This allows to accurately turn
it into a VkFence or VkSemaphore without any over- synchronization.

v2 (Jason Ekstrand):
 - Use a wrapper dma_fence_array of all fences including the new one
   when importing an exclusive fence.

v3 (Jason Ekstrand):
 - Lock around setting shared fences as well as exclusive
 - Mark SIGNAL_SYNC_FILE as a read-write ioctl.
 - Initialize ret to 0 in dma_buf_wait_sync_file

v4 (Jason Ekstrand):
 - Use the new dma_resv_get_singleton helper

v5 (Jason Ekstrand):
 - Rename the IOCTLs to import/export rather than wait/signal
 - Drop the WRITE flag and always get/set the exclusive fence

v6 (Jason Ekstrand):
 - Drop the sync_file import as it was all-around sketchy and not nearly
   as useful as import.
 - Re-introduce READ/WRITE flag support for export
 - Rework the commit message

v7 (Jason Ekstrand):
 - Require at least one sync flag
 - Fix a refcounting bug: dma_resv_get_excl() doesn't take a reference
 - Use _rcu helpers since we're accessing the dma_resv read-only

v8 (Jason Ekstrand):
 - Return -ENOMEM if the sync_file_create fails
 - Predicate support on IS_ENABLED(CONFIG_SYNC_FILE)

v9 (Jason Ekstrand):
 - Add documentation for the new ioctl

v10 (Jason Ekstrand):
 - Go back to dma_buf_sync_file as the ioctl struct name

Signed-off-by: Jason Ekstrand 
Acked-by: Simon Ser 
Acked-by: Christian König 
---
 drivers/dma-buf/dma-buf.c| 64 
 include/uapi/linux/dma-buf.h | 24 ++
 2 files changed, 88 insertions(+)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index d4529aa9d1a5a..86efe71c0db96 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -362,6 +363,64 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const 
char __user *buf)
return ret;
 }
 
+#if IS_ENABLED(CONFIG_SYNC_FILE)
+static long dma_buf_export_sync_file(struct dma_buf *dmabuf,
+void __user *user_data)
+{
+   struct dma_buf_sync_file arg;
+   struct dma_fence *fence = NULL;
+   struct sync_file *sync_file;
+   int fd, ret;
+
+   if (copy_from_user(, user_data, sizeof(arg)))
+   return -EFAULT;
+
+   if (arg.flags & ~DMA_BUF_SYNC_RW)
+   return -EINVAL;
+
+   if ((arg.flags & DMA_BUF_SYNC_RW) == 0)
+   return -EINVAL;
+
+   fd = get_unused_fd_flags(O_CLOEXEC);
+   if (fd < 0)
+   return fd;
+
+   if (arg.flags & DMA_BUF_SYNC_WRITE) {
+   fence = dma_resv_get_singleton_unlocked(dmabuf->resv);
+   if (IS_ERR(fence)) {
+   ret = PTR_ERR(fence);
+   goto err_put_fd;
+   }
+   } else if (arg.flags & DMA_BUF_SYNC_READ) {
+   fence = dma_resv_get_excl_unlocked(dmabuf->resv);
+   }
+
+   if (!fence)
+   fence = dma_fence_get_stub();
+
+   sync_file = sync_file_create(fence);
+
+   dma_fence_put(fence);
+
+   if (!sync_file) {
+   ret = -ENOMEM;
+   goto err_put_fd;
+   }
+
+   fd_install(fd, sync_file->file);
+
+   arg.fd = fd;
+   if (copy_to_user(user_data, , sizeof(arg)))
+   return -EFAULT;
+
+   return 0;
+
+err_put_fd:
+   put_unused_fd(fd);
+   return ret;
+}
+#endif

Re: [PATCH v7 08/10] drm/bridge: ti-sn65dsi86: Add support for the DP AUX bus

2021-05-24 Thread Lyude Paul
For 7 and 8:

Reviewed-by: Lyude Paul 

On Mon, 2021-05-17 at 13:09 -0700, Douglas Anderson wrote:
> We want to provide our panel with access to the DP AUX channel. The
> way to do this is to let our panel be a child of ours using the fancy
> new DP AUX bus support.
> 
> Signed-off-by: Douglas Anderson 
> ---
> 
> Changes in v7:
> - Patch to support for DP AUX bus on ti-sn65dsi86 new for v7.
> 
>  drivers/gpu/drm/bridge/Kconfig    |  1 +
>  drivers/gpu/drm/bridge/ti-sn65dsi86.c | 13 +++--
>  2 files changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
> index d25e900f07ef..294d0bdd4cbe 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -280,6 +280,7 @@ config DRM_TI_SN65DSI86
> select DRM_PANEL
> select DRM_MIPI_DSI
> select AUXILIARY_BUS
> +   select DRM_DP_AUX_BUS
> help
>   Texas Instruments SN65DSI86 DSI to eDP Bridge driver
>  
> diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> index 42a55d13864b..a59497f7e504 100644
> --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> @@ -23,6 +23,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -1446,19 +1447,27 @@ static int ti_sn_aux_probe(struct auxiliary_device
> *adev,
> pdata->aux.transfer = ti_sn_aux_transfer;
> drm_dp_aux_init(>aux);
>  
> +   ret = devm_of_dp_aux_populate_ep_devices(>aux);
> +   if (ret)
> +   goto err;
> +
> /*
>  * The eDP to MIPI bridge parts don't work until the AUX channel is
>  * setup so we don't add it in the main driver probe, we add it now.
>  */
> ret = ti_sn65dsi86_add_aux_device(pdata, >bridge_aux,
> "bridge");
>  
> +   if (ret)
> +   goto err;
> +
> +   return 0;
> +err:
> /*
>  * Clear of_node on any errors. Really this only matters if the
> error
>  * is -EPROBE_DEFER to avoid (again) keep pinctrl from claiming when
>  * it tries the probe again, but it shouldn't hurt on any error.
>  */
> -   if (ret)
> -   adev->dev.of_node = NULL;
> +   adev->dev.of_node = NULL;
>  
> return ret;
>  }

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH v7 01/10] drm/panel: panel-simple: Add missing pm_runtime_dont_use_autosuspend() calls

2021-05-24 Thread Laurent Pinchart
Hi Doug,

Thank you for the patch.

On Mon, May 17, 2021 at 01:08:58PM -0700, Douglas Anderson wrote:
> The PM Runtime docs specifically call out the need to call
> pm_runtime_dont_use_autosuspend() in the remove() callback if
> pm_runtime_use_autosuspend() was called in probe():
> 
> > Drivers in ->remove() callback should undo the runtime PM changes done
> > in ->probe(). Usually this means calling pm_runtime_disable(),
> > pm_runtime_dont_use_autosuspend() etc.

~/src/kernel/linux $ git grep pm_runtime_use_autosuspend -- drivers | wc -l
209
~/src/kernel/linux $ git grep pm_runtime_dont_use_autosuspend -- drivers | wc -l
80

Seems like a lost battle :-(

The fix is right, but I wonder if this shouldn't be handled
automatically by the runtime PM core. The runtime PM API is notoriously
difficult to use correctly.

> We should do this. This fixes a warning splat that I saw when I was
> testing out the panel-simple's remove().
>
> Fixes: 3235b0f20a0a ("drm/panel: panel-simple: Use runtime pm to avoid 
> excessive unprepare / prepare")
> Signed-off-by: Douglas Anderson 

Reviewed-by: Laurent Pinchart 

> ---
> 
> Changes in v7:
> - pm_runtime_dont_use_autosuspend() fix new for v7.
> 
>  drivers/gpu/drm/panel/panel-simple.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/gpu/drm/panel/panel-simple.c 
> b/drivers/gpu/drm/panel/panel-simple.c
> index 9be050ab372f..21939d4352cf 100644
> --- a/drivers/gpu/drm/panel/panel-simple.c
> +++ b/drivers/gpu/drm/panel/panel-simple.c
> @@ -798,6 +798,7 @@ static int panel_simple_probe(struct device *dev, const 
> struct panel_desc *desc)
>   return 0;
>  
>  disable_pm_runtime:
> + pm_runtime_dont_use_autosuspend(dev);
>   pm_runtime_disable(dev);
>  free_ddc:
>   if (panel->ddc)
> @@ -814,6 +815,7 @@ static int panel_simple_remove(struct device *dev)
>   drm_panel_disable(>base);
>   drm_panel_unprepare(>base);
>  
> + pm_runtime_dont_use_autosuspend(dev);
>   pm_runtime_disable(dev);
>   if (panel->ddc)
>   put_device(>ddc->dev);

-- 
Regards,

Laurent Pinchart


Re: [PATCH 2/4] dma-buf: add dma_resv_get_singleton_rcu (v4)

2021-05-24 Thread Jason Ekstrand
On Fri, May 21, 2021 at 12:48 PM Daniel Vetter  wrote:
>
> On Thu, May 20, 2021 at 02:00:05PM -0500, Jason Ekstrand wrote:
> > Add a helper function to get a single fence representing
> > all fences in a dma_resv object.
> >
> > This fence is either the only one in the object or all not
> > signaled fences of the object in a flatted out dma_fence_array.
> >
> > v2 (Jason Ekstrand):
> >  - Take reference of fences both for creating the dma_fence_array and in
> >the case where we return one fence.
> >  - Handle the case where dma_resv_get_list() returns NULL
> >
> > v3 (Jason Ekstrand):
> >  - Add an _rcu suffix because it is read-only
> >  - Rewrite to use dma_resv_get_fences_rcu so it's RCU-safe
> >  - Add an EXPORT_SYMBOL_GPL declaration
> >  - Re-author the patch to Jason since very little is left of Christian
> >König's original patch
> >  - Remove the extra fence argument
> >
> > v4 (Jason Ekstrand):
> >  - Restore the extra fence argument
> >
> > Signed-off-by: Jason Ekstrand 
> >
> > get_singleton
>
> Spurious thing here.

Fixed.

> > ---
> >  drivers/dma-buf/dma-resv.c | 122 +
> >  include/linux/dma-resv.h   |   3 +
> >  2 files changed, 125 insertions(+)
> >
> > diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
> > index 6ddbeb5dfbf65..25995fc15c370 100644
> > --- a/drivers/dma-buf/dma-resv.c
> > +++ b/drivers/dma-buf/dma-resv.c
> > @@ -33,6 +33,8 @@
> >   */
> >
> >  #include 
> > +#include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -49,6 +51,19 @@
> >   * write-side updates.
> >   */
> >
> > +/**
> > + * dma_fence_deep_dive_for_each - deep dive into the fence containers
> > + * @fence: resulting fence
> > + * @chain: variable for a dma_fence_chain
> > + * @index: index into a dma_fence_array
> > + * @head: starting point
> > + *
> > + * Helper to deep dive into the fence containers for flattening them.
> > + */
> > +#define dma_fence_deep_dive_for_each(fence, chain, index, head)  \
> > + dma_fence_chain_for_each(chain, head)   \
> > + dma_fence_array_for_each(fence, index, chain)
>
> Since this is is just internal helper in the .c file we generally don't
> document it. Maybe small comment if you feel it's worth it.

Sure, I can write LESS documentation. :-P

> > +
> >  DEFINE_WD_CLASS(reservation_ww_class);
> >  EXPORT_SYMBOL(reservation_ww_class);
> >
> > @@ -517,6 +532,113 @@ int dma_resv_get_fences_rcu(struct dma_resv *obj,
> >  }
> >  EXPORT_SYMBOL_GPL(dma_resv_get_fences_rcu);
> >
> > +/**
> > + * dma_resv_get_singleton - get a single fence for the dma_resv object
>
> Name doesn't match here.

Fixed.

> > + * @obj: the reservation object
> > + * @extra: extra fence to add to the resulting array
> > + * @result: resulting dma_fence
> > + *
> > + * Get a single fence representing all unsignaled fences in the dma_resv 
> > object
> > + * plus the given extra fence. If we got only one fence return a new
> > + * reference to that, otherwise return a dma_fence_array object.
> > + *
> > + * RETURNS
> > + * Returns -NOMEM if allocations fail, zero otherwise.
>
> Kernel often encodes this in ERR_PTR so that you don't have to pass a
> pointer to store the result. Would feel more kerenl-y I think that way. So
> no result parameter, and on alloc failure you'd return

Done.

> return ERR_PTR(-ENOMEM);
>
> > + */
> > +int dma_resv_get_singleton_rcu(struct dma_resv *obj, struct dma_fence 
> > *extra,
>
> tbh the _rcu here is confusing. I think _unlocked is the better suffix,
> maybe we should rename dma_resv_get_fences_rcu too for consistency. The
> rcu-ness of the lookup isn't leaked to callers at all, so no point giving
> them a panic.

I can make that change.  I'll also include a patch in the next re-send
that renames all the _rcu helpers to _unlocked for consistency.

--Jason

> > +struct dma_fence **result)
> > +{
> > + struct dma_fence **resv_fences, *fence, *chain, **fences;
> > + struct dma_fence_array *array;
> > + unsigned int num_resv_fences, num_fences;
> > + unsigned int ret, i, j;
> > +
> > + ret = dma_resv_get_fences_rcu(obj, NULL, _resv_fences, 
> > _fences);
> > + if (ret)
> > + return ret;
> > +
> > + num_fences = 0;
> > + *result = NULL;
> > +
> > + if (num_resv_fences == 0 && !extra)
> > + return 0;
> > +
> > + for (i = 0; i < num_resv_fences; ++i) {
> > + dma_fence_deep_dive_for_each(fence, chain, j, resv_fences[i]) 
> > {
> > + if (dma_fence_is_signaled(fence))
> > + continue;
> > +
> > + *result = fence;
> > + ++num_fences;
> > + }
> > + }
> > +
> > + if (extra) {
> > + dma_fence_deep_dive_for_each(fence, chain, j, extra) {
> > + if (dma_fence_is_signaled(fence))
> > + continue;
> > +
> 

Re: [PATCH 3/3] drm/msm/dp: Handle aux timeouts, nacks, defers

2021-05-24 Thread khsieh

On 2021-05-07 14:25, Stephen Boyd wrote:

Let's look at the irq status bits after a transfer and see if we got a
nack or a defer or a timeout, instead of telling drm layers that
everything was fine, while still printing an error message. I wasn't
sure about NACK+DEFER so I lumped all those various errors along with a
nack so that the drm core can figure out that things are just not going
well. The important thing is that we're now returning -ETIMEDOUT when
the message times out and nacks for bad addresses.

Cc: Dmitry Baryshkov 
Cc: Abhinav Kumar 
Cc: Kuogee Hsieh 
Cc: aravi...@codeaurora.org
Cc: Sean Paul 
Signed-off-by: Stephen Boyd 


Reviewed-by: Kuogee Hsieh 


---
 drivers/gpu/drm/msm/dp/dp_aux.c | 140 ++--
 drivers/gpu/drm/msm/dp/dp_aux.h |   8 --
 2 files changed, 61 insertions(+), 87 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c 
b/drivers/gpu/drm/msm/dp/dp_aux.c

index b49810396513..4a3293b590b0 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -9,7 +9,15 @@
 #include "dp_reg.h"
 #include "dp_aux.h"

-#define DP_AUX_ENUM_STR(x) #x
+enum msm_dp_aux_err {
+   DP_AUX_ERR_NONE,
+   DP_AUX_ERR_ADDR,
+   DP_AUX_ERR_TOUT,
+   DP_AUX_ERR_NACK,
+   DP_AUX_ERR_DEFER,
+   DP_AUX_ERR_NACK_DEFER,
+   DP_AUX_ERR_PHY,
+};

 struct dp_aux_private {
struct device *dev;
@@ -18,7 +26,7 @@ struct dp_aux_private {
struct mutex mutex;
struct completion comp;

-   u32 aux_error_num;
+   enum msm_dp_aux_err aux_error_num;
u32 retry_cnt;
bool cmd_busy;
bool native;
@@ -33,62 +41,45 @@ struct dp_aux_private {

 #define MAX_AUX_RETRIES5

-static const char *dp_aux_get_error(u32 aux_error)
-{
-   switch (aux_error) {
-   case DP_AUX_ERR_NONE:
-   return DP_AUX_ENUM_STR(DP_AUX_ERR_NONE);
-   case DP_AUX_ERR_ADDR:
-   return DP_AUX_ENUM_STR(DP_AUX_ERR_ADDR);
-   case DP_AUX_ERR_TOUT:
-   return DP_AUX_ENUM_STR(DP_AUX_ERR_TOUT);
-   case DP_AUX_ERR_NACK:
-   return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK);
-   case DP_AUX_ERR_DEFER:
-   return DP_AUX_ENUM_STR(DP_AUX_ERR_DEFER);
-   case DP_AUX_ERR_NACK_DEFER:
-   return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK_DEFER);
-   default:
-   return "unknown";
-   }
-}
-
-static u32 dp_aux_write(struct dp_aux_private *aux,
+static ssize_t dp_aux_write(struct dp_aux_private *aux,
struct drm_dp_aux_msg *msg)
 {
-   u32 data[4], reg, len;
+   u8 data[4];
+   u32 reg;
+   ssize_t len;
u8 *msgdata = msg->buffer;
int const AUX_CMD_FIFO_LEN = 128;
int i = 0;

if (aux->read)
-   len = 4;
+   len = 0;
else
-   len = msg->size + 4;
+   len = msg->size;

/*
 * cmd fifo only has depth of 144 bytes
 * limit buf length to 128 bytes here
 */
-   if (len > AUX_CMD_FIFO_LEN) {
+   if (len > AUX_CMD_FIFO_LEN - 4) {
DRM_ERROR("buf size greater than allowed size of 128 bytes\n");
-   return 0;
+   return -EINVAL;
}

/* Pack cmd and write to HW */
-   data[0] = (msg->address >> 16) & 0xf; /* addr[19:16] */
+   data[0] = (msg->address >> 16) & 0xf;  /* addr[19:16] */
if (aux->read)
-   data[0] |=  BIT(4); /* R/W */
+   data[0] |=  BIT(4); /* R/W */

-   data[1] = (msg->address >> 8) & 0xff;  /* addr[15:8] */
-   data[2] = msg->address & 0xff;   /* addr[7:0] */
-   data[3] = (msg->size - 1) & 0xff;/* len[7:0] */
+   data[1] = msg->address >> 8;   /* addr[15:8] */
+   data[2] = msg->address;  /* addr[7:0] */
+   data[3] = msg->size - 1; /* len[7:0] */

-   for (i = 0; i < len; i++) {
+   for (i = 0; i < len + 4; i++) {
reg = (i < 4) ? data[i] : msgdata[i - 4];
+   reg <<= DP_AUX_DATA_OFFSET;
+   reg &= DP_AUX_DATA_MASK;
+   reg |= DP_AUX_DATA_WRITE;
/* index = 0, write */
-   reg = (((reg) << DP_AUX_DATA_OFFSET)
-  & DP_AUX_DATA_MASK) | DP_AUX_DATA_WRITE;
if (i == 0)
reg |= DP_AUX_DATA_INDEX_WRITE;
aux->catalog->aux_data = reg;
@@ -116,39 +107,27 @@ static u32 dp_aux_write(struct dp_aux_private 
*aux,

return len;
 }

-static int dp_aux_cmd_fifo_tx(struct dp_aux_private *aux,
+static ssize_t dp_aux_cmd_fifo_tx(struct dp_aux_private *aux,
  struct drm_dp_aux_msg *msg)
 {
-   u32 ret, len, timeout;
-   int aux_timeout_ms = HZ/4;
+   ssize_t ret;
+   unsigned long time_left;

reinit_completion(>comp);

-   len = dp_aux_write(aux, 

Re: [PATCH 3/3] drm: Add orientation quirk for GPD Win Max

2021-05-24 Thread Hans de Goede
Hi,

On 5/24/21 6:47 PM, Anisse Astier wrote:
> Panel is 800x1280, but mounted on a laptop form factor, sideways.
> 
> Signed-off-by: Anisse Astier 

Thanks, patch looks good to me:

Reviewed-by: Hans de Goede 

Regards,

Hans


> ---
>  drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c 
> b/drivers/gpu/drm/drm_panel_orientation_quirks.c
> index f6bdec7fa925..3c3f4ed89173 100644
> --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
> +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
> @@ -148,6 +148,12 @@ static const struct dmi_system_id orientation_data[] = {
> DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MicroPC"),
>   },
>   .driver_data = (void *)_rightside_up,
> + }, {/* GPD Win Max */
> + .matches = {
> +   DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
> +   DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1619-01"),
> + },
> + .driver_data = (void *)_rightside_up,
>   }, {/*
>* GPD Pocket, note that the the DMI data is less generic then
>* it seems, devices with a board-vendor of "AMI Corporation"
> 



Re: [PATCH 3/3] drm/msm/dp: Handle aux timeouts, nacks, defers

2021-05-24 Thread khsieh

On 2021-05-24 12:19, Stephen Boyd wrote:

Quoting khs...@codeaurora.org (2021-05-24 09:33:49)

On 2021-05-07 14:25, Stephen Boyd wrote:
> @@ -367,36 +347,38 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux
> *dp_aux,
>   }
>
>   ret = dp_aux_cmd_fifo_tx(aux, msg);
> -
>   if (ret < 0) {
>   if (aux->native) {
>   aux->retry_cnt++;
>   if (!(aux->retry_cnt % MAX_AUX_RETRIES))
>   dp_catalog_aux_update_cfg(aux->catalog);
>   }
> - usleep_range(400, 500); /* at least 400us to next try */
> - goto unlock_exit;
> - }

1) dp_catalog_aux_update_cfg(aux->catalog) will not work without
dp_catalog_aux_reset(aux->catalog);
dp_catalog_aux_reset(aux->catalog) will reset hpd control block and
potentially cause pending hpd interrupts got lost.
Therefore I think we should not do
dp_catalog_aux_update_cfg(aux->catalog) for now.
reset aux controller will reset hpd control block probolem will be 
fixed

at next chipset.
after that we can add dp_catalog_aux_update_cfg(aux->catalog) followed
by dp_catalog_aux_reset(aux->catalog) back at next chipset.


Hmm ok. So the phy calibration logic that tweaks the tuning values is
never used? Why can't the phy be tuned while it is active? I don't
understand why we would ever want to reset the aux phy when changing 
the

settings for a retry. Either way, this is not actually changing in this
patch so it would be another patch to remove this code.

ok,




2) according to DP specification, aux read/write failed have to wait 
at

least 400us before next try can start.
Otherwise, DP compliant test will failed


Yes. The caller of this function, drm_dp_dpcd_access(), has the delay
already

if (ret != 0 && ret != -ETIMEDOUT) {
usleep_range(AUX_RETRY_INTERVAL,
 AUX_RETRY_INTERVAL + 100);
}

so this delay here is redundant.

yes, you are right. This is enough.



RE: [PATCH 1/3] virtio-gpu uapi: Add VIRTIO_GPU_F_EXPLICIT_FLUSH feature

2021-05-24 Thread Kasireddy, Vivek
Hi Gerd,
Any further comments on this?

Thanks,
Vivek

> 
> Hi Gerd,
> 
> > > [Kasireddy, Vivek] Correct, that is exactly what I want -- make the
> > > Guest wait until it gets notified that the Host is completely done 
> > > processing/using the
> fb.
> > > However, there can be two resources the guest can be made to wait
> > > on: wait for the new/current fb that is being submitted to be
> > > processed (explicit flush)
> >
> > That would be wait on resource_flush case, right?
> [Kasireddy, Vivek] Yes, correct.
> 
> >
> > > or wait for the previous fb that was submitted earlier (in the
> > > previous repaint cycle) to be processed (explicit sync).
> >
> > That would be the wait on set_scanout case, right?
> [Kasireddy, Vivek] Right.
> 
> >
> > And it would effectively wait on the previous fb not being needed by
> > the host any more (because the page-flip to the new fb completed) so
> > the guest can re-use the previous fb to render the next frame, right?
> [Kasireddy, Vivek] Yup.
> 
> >
> > (also when doing front-buffer rendering with xorg/fbcon and then doing
> > a virtual console switch the guest could wait for the console switch
> > being completed).
> >
> > > IIUC, Explicit sync only makes sense if 1) the Host windowing system
> > > also supports that feature/protocol (currently only upstream Weston
> > > does but I'd like to add it to Mutter if no one else does) or if
> > > there is a way to figure out (dma-buf sync file?) if the Host has
> > > completely processed the fb and 2) if Qemu UI is not doing a blit and 
> > > instead
> submitting the guest fb/dmabuf directly to the Host windowing system.
> > > As you are aware, 2) can possibly be done with dbus/pipewire Qemu UI
> > > backends (I'll explore this soon) but not with GTK or SDL.
> >
> > Well, I think we need to clearly define the wait flag semantics.
> [Kasireddy, Vivek] At-least with our passthrough use-case (maybe not with 
> Virgl), I think
> we need to ensure the following criteria:
> 1) With Blobs, ensure that the Guest and Host would never use the dmabuf/FB 
> at the same
> time.
> 2) The Guest should not render more frames than the refresh rate of the Host 
> so that GPU
> resources are not wasted.
> 
> > Should resource_flush with wait flag wait until the host is done
> > reading the resource (blit done)?
> [Kasireddy, Vivek] I started with this but did not find it useful as it did 
> not meet
> 2) above. However, I think we could have a flag for this if the Guest is 
> using a virtual
> vblank/timer and only wants to wait until the blit is done.
> 
> > Or should it wait until the host screen has been updated (gtk draw
> > callback completed)?
> [Kasireddy, Vivek] This is what the last 7 patches of my Blob series (v3) do. 
> So, we'd want
> to have a separate flag for this as well. And, lastly, we are going to need 
> another flag for
> the set_scanout case where we wait for the previous fb to be synchronized.
> 
> >
> > Everything else will be a host/guest implementation detail then, and
> > of course this needs some integration with the UI on the host side and
> > different UIs might have to do different things.
> [Kasireddy, Vivek] Sure, I think we can start with GTK and go from there.
> 
> >
> > On the guest side integrating this with fences will give us enough
> > flexibility on how we want handle the waits.  Simplest would be to
> > just block.
> [Kasireddy, Vivek] I agree; simply blocking (dma_fence_wait) is more than 
> enough for
> most use-cases.
> 
> >We could implement virtual vblanks, which would probably make  most
> >userspace work fine without explicit virtio-gpu support.  If needed  we
> >could even give userspace access to the fence so it can choose how to
> >wait.
> [Kasireddy, Vivek] Virtual vblanks is not a bad idea but I think blocking 
> with fences in the
> Guest kernel space seems more simpler. And, sharing fences with the Guest 
> compositor is
> also very interesting but I suspect we might need to modify the compositor 
> for this use-
> case, which might be a non-starter. Lastly, even with virtual vblanks, we 
> still need to make
> sure that we meet the two criteria mentioned above.
> 
> Thanks,
> Vivek



[Bug 213201] [KAVERI] memory leak - unreferenced object 0xffff8881700cf988 (size 56)

2021-05-24 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=213201

--- Comment #3 from Erhard F. (erhar...@mailbox.org) ---
As I bought this machine just recently I can't tell. But I will try to bisect.

I got this Kaveri-based one instead of the Excavator-based one from bug
#211875. With bug #211875 it was not fit for it's purpose unfortunately so I
sold it again. This Kaveri-based one here fares much better. Only this memory
leak but no grave issues otherwise.

-- 
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 3/3] drm/msm/dp: Handle aux timeouts, nacks, defers

2021-05-24 Thread Stephen Boyd
Quoting khs...@codeaurora.org (2021-05-24 09:33:49)
> On 2021-05-07 14:25, Stephen Boyd wrote:
> > @@ -367,36 +347,38 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux
> > *dp_aux,
> >   }
> >
> >   ret = dp_aux_cmd_fifo_tx(aux, msg);
> > -
> >   if (ret < 0) {
> >   if (aux->native) {
> >   aux->retry_cnt++;
> >   if (!(aux->retry_cnt % MAX_AUX_RETRIES))
> >   dp_catalog_aux_update_cfg(aux->catalog);
> >   }
> > - usleep_range(400, 500); /* at least 400us to next try */
> > - goto unlock_exit;
> > - }
>
> 1) dp_catalog_aux_update_cfg(aux->catalog) will not work without
> dp_catalog_aux_reset(aux->catalog);
> dp_catalog_aux_reset(aux->catalog) will reset hpd control block and
> potentially cause pending hpd interrupts got lost.
> Therefore I think we should not do
> dp_catalog_aux_update_cfg(aux->catalog) for now.
> reset aux controller will reset hpd control block probolem will be fixed
> at next chipset.
> after that we can add dp_catalog_aux_update_cfg(aux->catalog) followed
> by dp_catalog_aux_reset(aux->catalog) back at next chipset.

Hmm ok. So the phy calibration logic that tweaks the tuning values is
never used? Why can't the phy be tuned while it is active? I don't
understand why we would ever want to reset the aux phy when changing the
settings for a retry. Either way, this is not actually changing in this
patch so it would be another patch to remove this code.

>
> 2) according to DP specification, aux read/write failed have to wait at
> least 400us before next try can start.
> Otherwise, DP compliant test will failed

Yes. The caller of this function, drm_dp_dpcd_access(), has the delay
already

if (ret != 0 && ret != -ETIMEDOUT) {
usleep_range(AUX_RETRY_INTERVAL,
 AUX_RETRY_INTERVAL + 100);
}

so this delay here is redundant.


Re: [PATCH] drm/amdgpu: fix typo

2021-05-24 Thread Alex Deucher
Applied.  Thanks!

Alex

On Mon, May 24, 2021 at 3:45 AM  wrote:
>
> From: "tony.huang_cp" 
>
> change 'interupt' to 'interrupt'
>
> Signed-off-by: tony.huang_cp 
> ---
>  drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c 
> b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c
> index 284447d..6c0e914 100644
> --- a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c
> +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c
> @@ -340,7 +340,7 @@ static int uvd_v3_1_start(struct amdgpu_device *adev)
> /* enable VCPU clock */
> WREG32(mmUVD_VCPU_CNTL,  1 << 9);
>
> -   /* disable interupt */
> +   /* disable interrupt */
> WREG32_P(mmUVD_MASTINT_EN, 0, ~(1 << 1));
>
>  #ifdef __BIG_ENDIAN
> @@ -405,7 +405,7 @@ static int uvd_v3_1_start(struct amdgpu_device *adev)
> return r;
> }
>
> -   /* enable interupt */
> +   /* enable interrupt */
> WREG32_P(mmUVD_MASTINT_EN, 3<<1, ~(3 << 1));
>
> WREG32_P(mmUVD_STATUS, 0, ~(1<<2));
> --
> 1.9.1
>


Re: [PATCH] drm/amdgpu: remove unreachable code

2021-05-24 Thread Alex Deucher
Applied.  Thanks!

Alex

On Mon, May 24, 2021 at 6:47 AM Jiapeng Chong
 wrote:
>
> In the function amdgpu_uvd_cs_msg(), every branch in the switch
> statement will have a return, so the code below the switch statement
> will not be executed.
>
> Eliminate the follow smatch warning:
>
> drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c:845 amdgpu_uvd_cs_msg() warn:
> ignoring unreachable code.
>
> Reported-by: Abaci Robot 
> Signed-off-by: Jiapeng Chong 
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 2 --
>  1 file changed, 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
> index 82f0542..375b346 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
> @@ -842,8 +842,6 @@ static int amdgpu_uvd_cs_msg(struct amdgpu_uvd_cs_ctx 
> *ctx,
> DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
> return -EINVAL;
> }
> -   BUG();
> -   return -EINVAL;
>  }
>
>  /**
> --
> 1.8.3.1
>


Re: [Intel-gfx] [RFC PATCH 39/97] drm/i915/guc: Increase size of CTB buffers

2021-05-24 Thread Matthew Brost
On Mon, May 24, 2021 at 03:43:11PM +0200, Michal Wajdeczko wrote:
> 
> 
> On 06.05.2021 21:13, Matthew Brost wrote:
> > With the introduction of non-blocking CTBs more than one CTB can be in
> > flight at a time. Increasing the size of the CTBs should reduce how
> > often software hits the case where no space is available in the CTB
> > buffer.
> > 
> > Cc: John Harrison 
> > Signed-off-by: Matthew Brost 
> > ---
> >  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 11 ---
> >  1 file changed, 8 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c 
> > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> > index 77dfbc94dcc3..d6895d29ed2d 100644
> > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> > @@ -63,11 +63,16 @@ static inline struct drm_device *ct_to_drm(struct 
> > intel_guc_ct *ct)
> >   *  ++---+--+
> >   *
> >   * Size of each `CT Buffer`_ must be multiple of 4K.
> > - * As we don't expect too many messages, for now use minimum sizes.
> > + * We don't expect too many messages in flight at any time, unless we are
> > + * using the GuC submission. In that case each request requires a minimum
> > + * 16 bytes which gives us a maximum 256 queue'd requests. Hopefully this
> 
> nit: all our CTB calculations are in dwords now, not bytes
> 

I can change the wording to DW sizes.

> > + * enough space to avoid backpressure on the driver. We increase the size
> > + * of the receive buffer (relative to the send) to ensure a G2H response
> > + * CTB has a landing spot.
> 
> hmm, but we are not checking G2H CTB yet
> will start doing it around patch 54/97
> so maybe this other patch should be introduced earlier ?
>

Yes, that patch is going to be pulled down to an earlier spot in the
series.
 
> >   */
> >  #define CTB_DESC_SIZE  ALIGN(sizeof(struct 
> > guc_ct_buffer_desc), SZ_2K)
> >  #define CTB_H2G_BUFFER_SIZE(SZ_4K)
> > -#define CTB_G2H_BUFFER_SIZE(SZ_4K)
> > +#define CTB_G2H_BUFFER_SIZE(4 * CTB_H2G_BUFFER_SIZE)
> 
> in theory, we (host) should be faster than GuC, so G2H CTB shall be
> almost always empty, if this is not a case, maybe we should start
> monitoring what is happening and report some warnings if G2H is half full ?
>

Certainly some IGTs put some more pressure on the G2H channel than the
H2G channel at least I think. This is something we can tune over time
after this lands upstream. IMO a message at this point is overkill.

Matt
 
> >  
> >  #define MAX_US_STALL_CTB   100
> >  
> > @@ -753,7 +758,7 @@ static int ct_read(struct intel_guc_ct *ct, struct 
> > ct_incoming_msg **msg)
> > /* beware of buffer wrap case */
> > if (unlikely(available < 0))
> > available += size;
> > -   CT_DEBUG(ct, "available %d (%u:%u)\n", available, head, tail);
> > +   CT_DEBUG(ct, "available %d (%u:%u:%u)\n", available, head, tail, size);
> > GEM_BUG_ON(available < 0);
> >  
> > header = cmds[head];
> > 


Re: [PATCH v3 08/12] drm/ttm: Use drm_memcpy_from_wc_dbm for TTM bo moves

2021-05-24 Thread Thomas Hellström
On Mon, 2021-05-24 at 19:16 +0100, Matthew Auld wrote:
> On Fri, 21 May 2021 at 16:33, Thomas Hellström
>  wrote:
> > 
> > Use fast wc memcpy for reading out of wc memory for TTM bo moves.
> > 
> > Cc: Dave Airlie 
> > Cc: Christian König 
> > Cc: Daniel Vetter 
> > Signed-off-by: Thomas Hellström 
> > ---
> >  drivers/gpu/drm/ttm/ttm_bo_util.c | 9 -
> >  1 file changed, 8 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c
> > b/drivers/gpu/drm/ttm/ttm_bo_util.c
> > index 912cbe8e60a2..4a7d3d672f9a 100644
> > --- a/drivers/gpu/drm/ttm/ttm_bo_util.c
> > +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
> > @@ -31,6 +31,7 @@
> > 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -91,6 +92,7 @@ void ttm_move_memcpy(struct ttm_buffer_object
> > *bo,
> >     const struct ttm_kmap_iter_ops *src_ops = src_iter->ops;
> >     struct ttm_tt *ttm = bo->ttm;
> >     struct dma_buf_map src_map, dst_map;
> > +   bool wc_memcpy;
> >     pgoff_t i;
> > 
> >     /* Single TTM move. NOP */
> > @@ -114,11 +116,16 @@ void ttm_move_memcpy(struct ttm_buffer_object
> > *bo,
> >     return;
> >     }
> > 
> > +   wc_memcpy = ((!src_ops->maps_tt || ttm->caching !=
> > ttm_cached) &&
> 
> Why do we only consider the caching value for the maps_tt case? Or am
> I misreading this?

Hmm, you're right we should probably check also the iomem caching or
ignore the tt caching. Sometimes these special memcpys tend to be less
cpu cache thrashing and should be used wherever possible, but I guess
we should start out with only using it when source is WC.

> 
> > +    drm_has_memcpy_from_wc());
> > +
> >     for (i = 0; i < dst_mem->num_pages; ++i) {
> >     dst_ops->map_local(dst_iter, _map, i);
> >     src_ops->map_local(src_iter, _map, i);
> > 
> > -   if (!src_map.is_iomem && !dst_map.is_iomem) {
> > +   if (wc_memcpy) {
> > +   drm_memcpy_from_wc_dbm(_map, _map,
> > PAGE_SIZE);
> 
> Do we need to check the return value here? memcpy_from_wc expects
> certain address alignment, or is that always guaranteed here? Maybe
> throw a warning just for paranoia?

It should always be PAGE_SIZE aligned. But I guess it doesn't hurt to
do 
if (wc_memcpy && drm_memcpy_from_wc_dbm())
;

> 
> > +   } else if (!src_map.is_iomem && !dst_map.is_iomem)
> > {
> >     memcpy(dst_map.vaddr, src_map.vaddr,
> > PAGE_SIZE);
> >     } else if (!src_map.is_iomem) {
> >     dma_buf_map_memcpy_to(_map,
> > src_map.vaddr,
> > --
> > 2.31.1
> > 




[Bug 213201] [KAVERI] memory leak - unreferenced object 0xffff8881700cf988 (size 56)

2021-05-24 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=213201

Alex Deucher (alexdeuc...@gmail.com) changed:

   What|Removed |Added

 CC||alexdeuc...@gmail.com

--- Comment #2 from Alex Deucher (alexdeuc...@gmail.com) ---
The amdgpu acpi handling hasn't really changed in ages.  If this is new for
5.13 can you bisect?

-- 
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: [RFC PATCH 37/97] drm/i915/guc: Add stall timer to non blocking CTB send function

2021-05-24 Thread Matthew Brost
On Mon, May 24, 2021 at 02:58:12PM +0200, Michal Wajdeczko wrote:
> 
> 
> On 06.05.2021 21:13, Matthew Brost wrote:
> > Implement a stall timer which fails H2G CTBs once a period of time
> > with no forward progress is reached to prevent deadlock.
> > 
> > Also update to ct_write to return -EDEADLK rather than -EPIPE on a
> > corrupted descriptor.
> 
> broken descriptor is really separate issue compared to no progress from
> GuC side, I would really like to keep old error code
>

I know you do as you have brought it up several times. Again to the rest
of the stack these two things mean the exact same thing.
 
> note that broken CTB descriptor is unrecoverable error, while on other
> hand, in theory, we could recover from temporary non-moving CTB
> 

Yea but we don't, in both cases we disable submission which in turn
triggers a full GPU reset.

> > 
> > Signed-off-by: John Harrison 
> > Signed-off-by: Daniele Ceraolo Spurio 
> > Signed-off-by: Matthew Brost 
> > ---
> >  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 48 +--
> >  1 file changed, 45 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c 
> > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> > index af7314d45a78..4eab319d61be 100644
> > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> > @@ -69,6 +69,8 @@ static inline struct drm_device *ct_to_drm(struct 
> > intel_guc_ct *ct)
> >  #define CTB_H2G_BUFFER_SIZE(SZ_4K)
> >  #define CTB_G2H_BUFFER_SIZE(SZ_4K)
> >  
> > +#define MAX_US_STALL_CTB   100
> 
> nit: maybe we should make it a CONFIG value ?
> 

Sure.

> > +
> >  struct ct_request {
> > struct list_head link;
> > u32 fence;
> > @@ -315,6 +317,7 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct)
> >  
> > ct->requests.last_fence = 1;
> > ct->enabled = true;
> > +   ct->stall_time = KTIME_MAX;
> >  
> > return 0;
> >  
> > @@ -378,7 +381,7 @@ static int ct_write(struct intel_guc_ct *ct,
> > unsigned int i;
> >  
> > if (unlikely(ctb->broken))
> > -   return -EPIPE;
> > +   return -EDEADLK;
> >  
> > if (unlikely(desc->status))
> > goto corrupted;
> > @@ -449,7 +452,7 @@ static int ct_write(struct intel_guc_ct *ct,
> > CT_ERROR(ct, "Corrupted descriptor head=%u tail=%u status=%#x\n",
> >  desc->head, desc->tail, desc->status);
> > ctb->broken = true;
> > -   return -EPIPE;
> > +   return -EDEADLK;
> >  }
> >  
> >  /**
> > @@ -494,6 +497,17 @@ static int wait_for_ct_request_update(struct 
> > ct_request *req, u32 *status)
> > return err;
> >  }
> >  
> > +static inline bool ct_deadlocked(struct intel_guc_ct *ct)
> > +{
> > +   bool ret = ktime_us_delta(ktime_get(), ct->stall_time) >
> > +   MAX_US_STALL_CTB;
> > +
> > +   if (unlikely(ret))
> > +   CT_ERROR(ct, "CT deadlocked\n");
> > +
> > +   return ret;
> > +}
> > +
> >  static inline bool ctb_has_room(struct intel_guc_ct_buffer *ctb, u32 
> > len_dw)
> >  {
> > struct guc_ct_buffer_desc *desc = ctb->desc;
> > @@ -505,6 +519,26 @@ static inline bool ctb_has_room(struct 
> > intel_guc_ct_buffer *ctb, u32 len_dw)
> > return space >= len_dw;
> >  }
> >  
> > +static int has_room_nb(struct intel_guc_ct *ct, u32 len_dw)
> > +{
> > +   struct intel_guc_ct_buffer *ctb = >ctbs.send;
> > +
> > +   lockdep_assert_held(>ctbs.send.lock);
> > +
> > +   if (unlikely(!ctb_has_room(ctb, len_dw))) {
> > +   if (ct->stall_time == KTIME_MAX)
> > +   ct->stall_time = ktime_get();
> > +
> > +   if (unlikely(ct_deadlocked(ct)))
> > +   return -EDEADLK;
> > +   else
> > +   return -EBUSY;
> > +   }
> > +
> > +   ct->stall_time = KTIME_MAX;
> > +   return 0;
> > +}
> > +
> >  static int ct_send_nb(struct intel_guc_ct *ct,
> >   const u32 *action,
> >   u32 len,
> > @@ -517,7 +551,7 @@ static int ct_send_nb(struct intel_guc_ct *ct,
> >  
> > spin_lock_irqsave(>lock, spin_flags);
> >  
> > -   ret = ctb_has_room(ctb, len + 1);
> > +   ret = has_room_nb(ct, len + 1);
> > if (unlikely(ret))
> > goto out;
> >  
> > @@ -561,11 +595,19 @@ static int ct_send(struct intel_guc_ct *ct,
> >  retry:
> > spin_lock_irqsave(>ctbs.send.lock, flags);
> > if (unlikely(!ctb_has_room(ctb, len + 1))) {
> > +   if (ct->stall_time == KTIME_MAX)
> > +   ct->stall_time = ktime_get();
> > spin_unlock_irqrestore(>ctbs.send.lock, flags);
> > +
> > +   if (unlikely(ct_deadlocked(ct)))
> > +   return -EDEADLK;
> > +
> 
> likely, instead of duplicating code, you can reuse has_room_nb here
>

In this patch yes, in the following patch no as this check changes
between non-blockig and blocking once we introduce G2H credits. I'd
rather just leave it as is than churning on the patches.

Matt 
 
> > cond_resched();
> >   

[PATCH] drm/panel: panel-simple: Fix proper bpc for ytc700tlag_05_201c

2021-05-24 Thread Jagan Teki
ytc700tlag_05_201c panel support 8 bpc not 6 bpc as per
recent testing in i.MX8MM platform.

Fix it.

Signed-off-by: Jagan Teki 
---
 drivers/gpu/drm/panel/panel-simple.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index 9be050ab372f..6f4151729fb7 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -4164,7 +4164,7 @@ static const struct drm_display_mode 
yes_optoelectronics_ytc700tlag_05_201c_mode
 static const struct panel_desc yes_optoelectronics_ytc700tlag_05_201c = {
.modes = _optoelectronics_ytc700tlag_05_201c_mode,
.num_modes = 1,
-   .bpc = 6,
+   .bpc = 8,
.size = {
.width = 154,
.height = 90,
-- 
2.25.1



Re: [PATCH v3 08/12] drm/ttm: Use drm_memcpy_from_wc_dbm for TTM bo moves

2021-05-24 Thread Matthew Auld
On Fri, 21 May 2021 at 16:33, Thomas Hellström
 wrote:
>
> Use fast wc memcpy for reading out of wc memory for TTM bo moves.
>
> Cc: Dave Airlie 
> Cc: Christian König 
> Cc: Daniel Vetter 
> Signed-off-by: Thomas Hellström 
> ---
>  drivers/gpu/drm/ttm/ttm_bo_util.c | 9 -
>  1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c 
> b/drivers/gpu/drm/ttm/ttm_bo_util.c
> index 912cbe8e60a2..4a7d3d672f9a 100644
> --- a/drivers/gpu/drm/ttm/ttm_bo_util.c
> +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
> @@ -31,6 +31,7 @@
>
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -91,6 +92,7 @@ void ttm_move_memcpy(struct ttm_buffer_object *bo,
> const struct ttm_kmap_iter_ops *src_ops = src_iter->ops;
> struct ttm_tt *ttm = bo->ttm;
> struct dma_buf_map src_map, dst_map;
> +   bool wc_memcpy;
> pgoff_t i;
>
> /* Single TTM move. NOP */
> @@ -114,11 +116,16 @@ void ttm_move_memcpy(struct ttm_buffer_object *bo,
> return;
> }
>
> +   wc_memcpy = ((!src_ops->maps_tt || ttm->caching != ttm_cached) &&

Why do we only consider the caching value for the maps_tt case? Or am
I misreading this?

> +drm_has_memcpy_from_wc());
> +
> for (i = 0; i < dst_mem->num_pages; ++i) {
> dst_ops->map_local(dst_iter, _map, i);
> src_ops->map_local(src_iter, _map, i);
>
> -   if (!src_map.is_iomem && !dst_map.is_iomem) {
> +   if (wc_memcpy) {
> +   drm_memcpy_from_wc_dbm(_map, _map, PAGE_SIZE);

Do we need to check the return value here? memcpy_from_wc expects
certain address alignment, or is that always guaranteed here? Maybe
throw a warning just for paranoia?

> +   } else if (!src_map.is_iomem && !dst_map.is_iomem) {
> memcpy(dst_map.vaddr, src_map.vaddr, PAGE_SIZE);
> } else if (!src_map.is_iomem) {
> dma_buf_map_memcpy_to(_map, src_map.vaddr,
> --
> 2.31.1
>


Re: [Intel-gfx] [PATCH v3 07/12] drm, drm/i915: Move the memcpy_from_wc functionality to core drm

2021-05-24 Thread Thomas Hellström
On Mon, 2021-05-24 at 17:45 +0100, Matthew Auld wrote:
> On Fri, 21 May 2021 at 16:33, Thomas Hellström
>  wrote:
> > 
> > Memcpy from wc will be used as well by TTM memcpy.
> > Move it to core drm, and make the interface do the right thing
> > even on !X86.
> > 
> > Cc: Christian König 
> > Cc: Daniel Vetter 
> > Cc: Dave Airlie 
> > Signed-off-by: Thomas Hellström 
> > ---
> 
> 
> 
> > +
> > +#ifdef CONFIG_X86
> > +bool drm_memcpy_from_wc(void *dst, const void *src, unsigned long
> > len);
> > +bool drm_memcpy_from_wc_dbm(struct dma_buf_map *dst,
> > +   const struct dma_buf_map *src,
> > +   unsigned long len);
> > +void drm_unaligned_memcpy_from_wc(void *dst, const void *src,
> > unsigned long len);
> > +
> > +/* The movntdqa instructions used for memcpy-from-wc require 16-
> > byte alignment,
> > + * as well as SSE4.1 support. drm_memcpy_from_wc() will report if
> > it cannot
> > + * perform the operation. To check beforehand, pass in the
> > parameters to
> > + * drm_can_memcpy_from_wc() - since we only care about the low 4
> > bits,
> > + * you only need to pass in the minor offsets, page-aligned
> > pointers are
> > + * always valid.
> > + *
> > + * For just checking for SSE4.1, in the foreknowledge that the
> > future use
> > + * will be correctly aligned, just use drm_has_memcpy_from_wc().
> > + */
> > +#define drm_can_memcpy_from_wc(dst, src, len) \
> > +   drm_memcpy_from_wc((void *)((unsigned long)(dst) |
> > (unsigned long)(src) | (len)), NULL, 0)
> > +
> > +#define drm_has_memcpy_from_wc() \
> > +   drm_memcpy_from_wc(NULL, NULL, 0)
> > +
> > +void drm_memcpy_init_early(void);
> > +
> > +#else
> > +
> > +#define drm_memcpy_from_wc(_dst, _src, _len) (false)
> > +#define drm_memcpy_from_wc_dbm(_dst, _src, _len) (false)
> > +#define drm_can_memcpy_from_wc(_dst, _src, _len) (false)
> > +#define drm_has_memcpy_from_wc() (false)
> 
> Does the compiler not complain for these on !x86, if called without
> checking the result of the statement? Maybe just make these function
> stubs?
> 
> Otherwise,
> Reviewed-by: Matthew Auld 

Hmm, you're right. I'll fix. Thanks for reviewing!

/Thomas




Re: [PATCH -next] drm/amdgpu: fix error return code in amdgpu_acpi_init()

2021-05-24 Thread Alex Deucher
On Mon, May 24, 2021 at 9:25 AM Wei Yongjun  wrote:
>
> Fix to return a negative error code from the error handling
> case instead of 0, as done elsewhere in this function.

I don't see any other cases in this function where we return an error.
It could arguably be made a void.  All of these APCI methods are
optional.

Alex

>
> Fixes: 77bf762f8b30 ("drm/amdgpu/acpi: unify ATCS handling (v3)")
> Reported-by: Hulk Robot 
> Signed-off-by: Wei Yongjun 
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> index 49563ff87f1a..9564690b21b4 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> @@ -895,12 +895,15 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
>  atcs:
> /* Probe for ATCS, and initialize it if found */
> atcs_handle = amdgpu_atcs_probe_handle(handle);
> -   if (!atcs_handle)
> +   if (!atcs_handle) {
> +   ret = -ENODEV;
> goto out;
> +   }
>
> atcs = kzalloc(sizeof(*atcs), GFP_KERNEL);
> if (!atcs) {
> DRM_WARN("Not enough memory to initialize ATCS\n");
> +   ret = -ENOMEM;
> goto out;
> }
> atcs->handle = atcs_handle;
>


[Bug 208573] Black screen on boot if two displays plugged in with NAVI 10

2021-05-24 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=208573

--- Comment #14 from Alex Deucher (alexdeuc...@gmail.com) ---
Can you bisect?
https://www.kernel.org/doc/html/latest/admin-guide/bug-bisect.html

-- 
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 4/4] RFC: dma-buf: Add an API for importing sync files (v6)

2021-05-24 Thread Jason Ekstrand
On Sat, May 22, 2021 at 3:05 PM Daniel Stone  wrote:
>
> Hi,
>
> On Thu, 20 May 2021 at 20:00, Jason Ekstrand  wrote:
> > In the Vulkan world, this is useful for dealing with the out-fence from
> > vkQueuePresent.  Current Linux window-systems (X11, Wayland, etc.) all
> > rely on dma-buf implicit sync.  Since Vulkan is an explicit sync API, we
> > get a set of fences (VkSemaphores) in vkQueuePresent and have to stash
> > those as an exclusive (write) fence on the dma-buf.  We handle it in
> > Mesa today with the above mentioned dummy submit trick.  This ioctl
> > would allow us to set it directly without the dummy submit.
> >
> > This may also open up possibilities for GPU drivers to move away from
> > implicit sync for their kernel driver uAPI and instead provide sync
> > files and rely on dma-buf import/export for communicating with other
> > implicit sync clients.
> >
> > We make the explicit choice here to only allow setting RW fences which
> > translates to an exclusive fence on the dma_resv.  There's no use for
> > read-only fences for communicating with other implicit sync userspace
> > and any such attempts are likely to be racy at best.
>
> I think I almost follow, but I'm not quite seeing the race you allude
> to. Let me talk through my understanding so it's hopefully more clear
> for others as a summary. Please correct me on anything I've
> misunderstood or just missed completely. (I thought when I wrote this
> intro that the email might be relatively snappy, but it's really long
> and takes in a lot of breadth. Sorry.)
>
> So as far as I'm reading this patchset and the Mesa MR, this _only_
> concerns the out-fence (i.e. compositor -> client AcquireNextImage
> semaphore/fence) so far. The in-fence (client->compositor QueuePresent
> wait-semaphores/fences) is handled by the driver ensuring that an
> exclusive resv is placed on the union of the signal semaphores passed
> to QueuePresent, either through flags on its CS ioctl, or amdgpu's BO
> flags, or ... either way, no problem as it should always be exclusive,
> and it seems pretty uncontroversial that we should pull the wait
> semaphore into an exclusive fence so that no downstream consumer will
> begin using it until the client ops have fully retired.
>
> For AcquireNextImage, your patchset exports all the fences (shared and
> exclusive both) on the dma_resv out into the semaphore/fence such that
> the client can't progress (CPU-side for VkFence, GPU-side for
> VkSemaphore) until all currently queued operations have completely
> retired. So, as long as the server ensures that all its kernel-side
> work is flushed before its IPC to unblock ANI (wl_buffer.release or
> DRI3 PresentIdle, both indicating that the client is free to reuse the
> buffer, subject to synchronising against implicit fences on the resv),
> all good: we snapshot the current resv state, wrap the relevant
> driver-side Vulkan primitive around it, and go back to explicit
> synchronisation. The client can't race generating new work against
> this, because it can't queue any work until ANI has returned and
> queued a signaling op on the semaphore/fence.
>
> So far, so good. I really like both your series up until this
> narrative point; as I was saying in the userspace-fence thread, the
> WSI<->client thread is certainly pulling a very big lever with a
> heavyweight transition between the two different worlds, and I like
> that the new export ioctl lets us be very clear about what exactly is
> happening under the hood. Good stuff.

Glad to hear.  If you turned that into RBs on the first three patches
in this series and all but the last patch on the Mesa MR, it'd make me
even happier. :-D

At this point, I think everyone is pretty happy with the first three
patches and the export ioctl.  In the Vulkan WSI code, it solves a
significant over-synchronization issue for ANV.  Also, the uAPI
shouldn't be controversial at all because it's identical to poll()
except that it gives you a FD you can poll on later to get the result
of the poll as it would be now.  I think if we get some Mesa reviews,
we should be able to land those.  It's import that's trickier.

> So, what gives with the import ioctl? Taking a guess at where you're
> going, the import ioctl is going to be used in QueuePresent just as
> the export ioctl is in ANI: instead of having CS flags to write into
> the resv exclusive slot or per-BO flags to always dump in exclusive,
> there's a forthcoming patch somewhere which lets drivers skip this and
> instead have common QueuePresent code dump the wait semaphore into the
> resv, so servers on the other side of an implicit-only protocol will
> synchronise their access against the fence imported as part of
> client-side QueuePresent?

Correct.  And the patch isn't forthcoming.  It already exists as the
top patch in the Mesa MR (!4037).

> That makes sense to me and is nicely symmetrical, plus it gets GPU
> drivers further out of the business of doing magic winsys/display
> 

Re: [Intel-gfx] [PATCH v3 07/12] drm, drm/i915: Move the memcpy_from_wc functionality to core drm

2021-05-24 Thread Matthew Auld
On Fri, 21 May 2021 at 16:33, Thomas Hellström
 wrote:
>
> Memcpy from wc will be used as well by TTM memcpy.
> Move it to core drm, and make the interface do the right thing
> even on !X86.
>
> Cc: Christian König 
> Cc: Daniel Vetter 
> Cc: Dave Airlie 
> Signed-off-by: Thomas Hellström 
> ---



> +
> +#ifdef CONFIG_X86
> +bool drm_memcpy_from_wc(void *dst, const void *src, unsigned long len);
> +bool drm_memcpy_from_wc_dbm(struct dma_buf_map *dst,
> +   const struct dma_buf_map *src,
> +   unsigned long len);
> +void drm_unaligned_memcpy_from_wc(void *dst, const void *src, unsigned long 
> len);
> +
> +/* The movntdqa instructions used for memcpy-from-wc require 16-byte 
> alignment,
> + * as well as SSE4.1 support. drm_memcpy_from_wc() will report if it cannot
> + * perform the operation. To check beforehand, pass in the parameters to
> + * drm_can_memcpy_from_wc() - since we only care about the low 4 bits,
> + * you only need to pass in the minor offsets, page-aligned pointers are
> + * always valid.
> + *
> + * For just checking for SSE4.1, in the foreknowledge that the future use
> + * will be correctly aligned, just use drm_has_memcpy_from_wc().
> + */
> +#define drm_can_memcpy_from_wc(dst, src, len) \
> +   drm_memcpy_from_wc((void *)((unsigned long)(dst) | (unsigned 
> long)(src) | (len)), NULL, 0)
> +
> +#define drm_has_memcpy_from_wc() \
> +   drm_memcpy_from_wc(NULL, NULL, 0)
> +
> +void drm_memcpy_init_early(void);
> +
> +#else
> +
> +#define drm_memcpy_from_wc(_dst, _src, _len) (false)
> +#define drm_memcpy_from_wc_dbm(_dst, _src, _len) (false)
> +#define drm_can_memcpy_from_wc(_dst, _src, _len) (false)
> +#define drm_has_memcpy_from_wc() (false)

Does the compiler not complain for these on !x86, if called without
checking the result of the statement? Maybe just make these function
stubs?

Otherwise,
Reviewed-by: Matthew Auld 

> +#define drm_unaligned_memcpy_from_wc(_dst, _src, _len) WARN_ON(1)
> +#define drm_memcpy_init_early() do {} while (0)
> +#endif /* CONFIG_X86 */
> +#endif /* __DRM_MEMCPY_H__ */
> --
> 2.31.1
>
> ___
> Intel-gfx mailing list
> intel-...@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [PATCH 3/3] drm/msm/dp: Handle aux timeouts, nacks, defers

2021-05-24 Thread khsieh

On 2021-05-07 14:25, Stephen Boyd wrote:

Let's look at the irq status bits after a transfer and see if we got a
nack or a defer or a timeout, instead of telling drm layers that
everything was fine, while still printing an error message. I wasn't
sure about NACK+DEFER so I lumped all those various errors along with a
nack so that the drm core can figure out that things are just not going
well. The important thing is that we're now returning -ETIMEDOUT when
the message times out and nacks for bad addresses.

Cc: Dmitry Baryshkov 
Cc: Abhinav Kumar 
Cc: Kuogee Hsieh 
Cc: aravi...@codeaurora.org
Cc: Sean Paul 
Signed-off-by: Stephen Boyd 
---
 drivers/gpu/drm/msm/dp/dp_aux.c | 140 ++--
 drivers/gpu/drm/msm/dp/dp_aux.h |   8 --
 2 files changed, 61 insertions(+), 87 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c 
b/drivers/gpu/drm/msm/dp/dp_aux.c

index b49810396513..4a3293b590b0 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -9,7 +9,15 @@
 #include "dp_reg.h"
 #include "dp_aux.h"

-#define DP_AUX_ENUM_STR(x) #x
+enum msm_dp_aux_err {
+   DP_AUX_ERR_NONE,
+   DP_AUX_ERR_ADDR,
+   DP_AUX_ERR_TOUT,
+   DP_AUX_ERR_NACK,
+   DP_AUX_ERR_DEFER,
+   DP_AUX_ERR_NACK_DEFER,
+   DP_AUX_ERR_PHY,
+};

 struct dp_aux_private {
struct device *dev;
@@ -18,7 +26,7 @@ struct dp_aux_private {
struct mutex mutex;
struct completion comp;

-   u32 aux_error_num;
+   enum msm_dp_aux_err aux_error_num;
u32 retry_cnt;
bool cmd_busy;
bool native;
@@ -33,62 +41,45 @@ struct dp_aux_private {

 #define MAX_AUX_RETRIES5

-static const char *dp_aux_get_error(u32 aux_error)
-{
-   switch (aux_error) {
-   case DP_AUX_ERR_NONE:
-   return DP_AUX_ENUM_STR(DP_AUX_ERR_NONE);
-   case DP_AUX_ERR_ADDR:
-   return DP_AUX_ENUM_STR(DP_AUX_ERR_ADDR);
-   case DP_AUX_ERR_TOUT:
-   return DP_AUX_ENUM_STR(DP_AUX_ERR_TOUT);
-   case DP_AUX_ERR_NACK:
-   return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK);
-   case DP_AUX_ERR_DEFER:
-   return DP_AUX_ENUM_STR(DP_AUX_ERR_DEFER);
-   case DP_AUX_ERR_NACK_DEFER:
-   return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK_DEFER);
-   default:
-   return "unknown";
-   }
-}
-
-static u32 dp_aux_write(struct dp_aux_private *aux,
+static ssize_t dp_aux_write(struct dp_aux_private *aux,
struct drm_dp_aux_msg *msg)
 {
-   u32 data[4], reg, len;
+   u8 data[4];
+   u32 reg;
+   ssize_t len;
u8 *msgdata = msg->buffer;
int const AUX_CMD_FIFO_LEN = 128;
int i = 0;

if (aux->read)
-   len = 4;
+   len = 0;
else
-   len = msg->size + 4;
+   len = msg->size;

/*
 * cmd fifo only has depth of 144 bytes
 * limit buf length to 128 bytes here
 */
-   if (len > AUX_CMD_FIFO_LEN) {
+   if (len > AUX_CMD_FIFO_LEN - 4) {
DRM_ERROR("buf size greater than allowed size of 128 bytes\n");
-   return 0;
+   return -EINVAL;
}

/* Pack cmd and write to HW */
-   data[0] = (msg->address >> 16) & 0xf; /* addr[19:16] */
+   data[0] = (msg->address >> 16) & 0xf;  /* addr[19:16] */
if (aux->read)
-   data[0] |=  BIT(4); /* R/W */
+   data[0] |=  BIT(4); /* R/W */

-   data[1] = (msg->address >> 8) & 0xff;  /* addr[15:8] */
-   data[2] = msg->address & 0xff;   /* addr[7:0] */
-   data[3] = (msg->size - 1) & 0xff;/* len[7:0] */
+   data[1] = msg->address >> 8;   /* addr[15:8] */
+   data[2] = msg->address;  /* addr[7:0] */
+   data[3] = msg->size - 1; /* len[7:0] */

-   for (i = 0; i < len; i++) {
+   for (i = 0; i < len + 4; i++) {
reg = (i < 4) ? data[i] : msgdata[i - 4];
+   reg <<= DP_AUX_DATA_OFFSET;
+   reg &= DP_AUX_DATA_MASK;
+   reg |= DP_AUX_DATA_WRITE;
/* index = 0, write */
-   reg = (((reg) << DP_AUX_DATA_OFFSET)
-  & DP_AUX_DATA_MASK) | DP_AUX_DATA_WRITE;
if (i == 0)
reg |= DP_AUX_DATA_INDEX_WRITE;
aux->catalog->aux_data = reg;
@@ -116,39 +107,27 @@ static u32 dp_aux_write(struct dp_aux_private 
*aux,

return len;
 }

-static int dp_aux_cmd_fifo_tx(struct dp_aux_private *aux,
+static ssize_t dp_aux_cmd_fifo_tx(struct dp_aux_private *aux,
  struct drm_dp_aux_msg *msg)
 {
-   u32 ret, len, timeout;
-   int aux_timeout_ms = HZ/4;
+   ssize_t ret;
+   unsigned long time_left;

reinit_completion(>comp);

-   len = dp_aux_write(aux, msg);
-   if (len == 0) {
- 

Re: [PATCH v7 01/15] swiotlb: Refactor swiotlb init functions

2021-05-24 Thread Konrad Rzeszutek Wilk
> > do the set_memory_decrypted()+memset(). Is this okay or should
> > swiotlb_init_io_tlb_mem() add an additional argument to do this
> > conditionally?
> 
> I'm actually not sure if this it okay. If not, will add an additional
> argument for it.

Any observations discovered? (Want to make sure my memory-cache has the
correct semantics for set_memory_decrypted in mind).
> 
> > --
> > Florian


Re: [PATCH v7 05/15] swiotlb: Add a new get_io_tlb_mem getter

2021-05-24 Thread Konrad Rzeszutek Wilk
On Tue, May 18, 2021 at 02:51:52PM +0800, Claire Chang wrote:
> Still keep this function because directly using dev->dma_io_tlb_mem
> will cause issues for memory allocation for existing devices. The pool
> can't support atomic coherent allocation so we need to distinguish the
> per device pool and the default pool in swiotlb_alloc.

This above should really be rolled in the commit. You can prefix it by
"The reason it was done this way was because directly using .."




Re: [PATCH 2/3] drm/msm/dp: Shrink locking area of dp_aux_transfer()

2021-05-24 Thread khsieh

On 2021-05-07 14:25, Stephen Boyd wrote:

We don't need to hold the lock to inspect the message we're going to
transfer, and we don't need to clear the busy flag either. Take the 
lock

later and bail out earlier if conditions aren't met.

Cc: Dmitry Baryshkov 
Cc: Abhinav Kumar 
Cc: Kuogee Hsieh 
Cc: aravi...@codeaurora.org
Cc: Sean Paul 
Signed-off-by: Stephen Boyd 


Reviewed-by: Kuogee Hsieh 

---
 drivers/gpu/drm/msm/dp/dp_aux.c | 19 +--
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c 
b/drivers/gpu/drm/msm/dp/dp_aux.c

index 91188466cece..b49810396513 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -329,30 +329,29 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux 
*dp_aux,

ssize_t ret;
int const aux_cmd_native_max = 16;
int const aux_cmd_i2c_max = 128;
-   struct dp_aux_private *aux = container_of(dp_aux,
-   struct dp_aux_private, dp_aux);
+   struct dp_aux_private *aux;

-   mutex_lock(>mutex);
+   aux = container_of(dp_aux, struct dp_aux_private, dp_aux);

 	aux->native = msg->request & (DP_AUX_NATIVE_WRITE & 
DP_AUX_NATIVE_READ);


/* Ignore address only message */
-   if ((msg->size == 0) || (msg->buffer == NULL)) {
+   if (msg->size == 0 || !msg->buffer) {
msg->reply = aux->native ?
DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
-   ret = msg->size;
-   goto unlock_exit;
+   return msg->size;
}

/* msg sanity check */
-   if ((aux->native && (msg->size > aux_cmd_native_max)) ||
-   (msg->size > aux_cmd_i2c_max)) {
+   if ((aux->native && msg->size > aux_cmd_native_max) ||
+   msg->size > aux_cmd_i2c_max) {
DRM_ERROR("%s: invalid msg: size(%zu), request(%x)\n",
__func__, msg->size, msg->request);
-   ret = -EINVAL;
-   goto unlock_exit;
+   return -EINVAL;
}

+   mutex_lock(>mutex);
+
dp_aux_update_offset_and_segment(aux, msg);
dp_aux_transfer_helper(aux, msg, true);


Re: [PATCH 1/3] drm/msm/dp: Simplify aux irq handling code

2021-05-24 Thread khsieh

On 2021-05-07 14:25, Stephen Boyd wrote:

We don't need to stash away 'isr' in the aux structure to pass to two
functions. Let's use a local variable instead. And we can complete the
completion variable in one place instead of two to simplify the code.

Cc: Dmitry Baryshkov 
Cc: Abhinav Kumar 
Cc: Kuogee Hsieh 
Cc: aravi...@codeaurora.org
Cc: Sean Paul 
Signed-off-by: Stephen Boyd 


Reviewed-by: Kuogee Hsieh 

---
 drivers/gpu/drm/msm/dp/dp_aux.c | 22 --
 drivers/gpu/drm/msm/dp/dp_catalog.c |  2 +-
 drivers/gpu/drm/msm/dp/dp_catalog.h |  2 +-
 3 files changed, 10 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c 
b/drivers/gpu/drm/msm/dp/dp_aux.c

index 7c22bfe0fc7d..91188466cece 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -27,7 +27,6 @@ struct dp_aux_private {
bool no_send_stop;
u32 offset;
u32 segment;
-   u32 isr;

struct drm_dp_aux dp_aux;
 };
@@ -181,10 +180,8 @@ static void dp_aux_cmd_fifo_rx(struct 
dp_aux_private *aux,

}
 }

-static void dp_aux_native_handler(struct dp_aux_private *aux)
+static void dp_aux_native_handler(struct dp_aux_private *aux, u32 isr)
 {
-   u32 isr = aux->isr;
-
if (isr & DP_INTR_AUX_I2C_DONE)
aux->aux_error_num = DP_AUX_ERR_NONE;
else if (isr & DP_INTR_WRONG_ADDR)
@@ -197,14 +194,10 @@ static void dp_aux_native_handler(struct
dp_aux_private *aux)
aux->aux_error_num = DP_AUX_ERR_PHY;
dp_catalog_aux_clear_hw_interrupts(aux->catalog);
}
-
-   complete(>comp);
 }

-static void dp_aux_i2c_handler(struct dp_aux_private *aux)
+static void dp_aux_i2c_handler(struct dp_aux_private *aux, u32 isr)
 {
-   u32 isr = aux->isr;
-
if (isr & DP_INTR_AUX_I2C_DONE) {
if (isr & (DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER))
aux->aux_error_num = DP_AUX_ERR_NACK;
@@ -226,8 +219,6 @@ static void dp_aux_i2c_handler(struct 
dp_aux_private *aux)

dp_catalog_aux_clear_hw_interrupts(aux->catalog);
}
}
-
-   complete(>comp);
 }

 static void dp_aux_update_offset_and_segment(struct dp_aux_private 
*aux,
@@ -412,6 +403,7 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux 
*dp_aux,


 void dp_aux_isr(struct drm_dp_aux *dp_aux)
 {
+   u32 isr;
struct dp_aux_private *aux;

if (!dp_aux) {
@@ -421,15 +413,17 @@ void dp_aux_isr(struct drm_dp_aux *dp_aux)

aux = container_of(dp_aux, struct dp_aux_private, dp_aux);

-   aux->isr = dp_catalog_aux_get_irq(aux->catalog);
+   isr = dp_catalog_aux_get_irq(aux->catalog);

if (!aux->cmd_busy)
return;

if (aux->native)
-   dp_aux_native_handler(aux);
+   dp_aux_native_handler(aux, isr);
else
-   dp_aux_i2c_handler(aux);
+   dp_aux_i2c_handler(aux, isr);
+
+   complete(>comp);
 }

 void dp_aux_reconfig(struct drm_dp_aux *dp_aux)
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c
b/drivers/gpu/drm/msm/dp/dp_catalog.c
index b1a9b1b98f5f..a70c238f34b0 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -292,7 +292,7 @@ void dp_catalog_dump_regs(struct dp_catalog 
*dp_catalog)

dump_regs(catalog->io->dp_controller.base + offset, len);
 }

-int dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog)
+u32 dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog)
 {
struct dp_catalog_private *catalog = container_of(dp_catalog,
struct dp_catalog_private, dp_catalog);
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h
b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 176a9020a520..502bc0dc7787 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -80,7 +80,7 @@ int dp_catalog_aux_clear_hw_interrupts(struct
dp_catalog *dp_catalog);
 void dp_catalog_aux_reset(struct dp_catalog *dp_catalog);
 void dp_catalog_aux_enable(struct dp_catalog *dp_catalog, bool 
enable);

 void dp_catalog_aux_update_cfg(struct dp_catalog *dp_catalog);
-int dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog);
+u32 dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog);

 /* DP Controller APIs */
 void dp_catalog_ctrl_state_ctrl(struct dp_catalog *dp_catalog, u32 
state);


Re: [PATCH v7 04/15] swiotlb: Add restricted DMA pool initialization

2021-05-24 Thread Konrad Rzeszutek Wilk
On Tue, May 18, 2021 at 02:48:35PM +0800, Claire Chang wrote:
> I didn't move this to a separate file because I feel it might be
> confusing for swiotlb_alloc/free (and need more functions to be
> non-static).
> Maybe instead of moving to a separate file, we can try to come up with
> a better naming?

I think you are referring to:

rmem_swiotlb_setup

?

Which is ARM specific and inside the generic code?



Christopher wants to unify it in all the code so there is one single
source, but the "you seperate arch code out from generic" saying
makes me want to move it out.

I agree that if you move it out from generic to arch-specific we have to
expose more of the swiotlb functions, which will undo's Christopher
cleanup code.

How about this - lets leave it as is now, and when there are more
use-cases we can revisit it and then if need to move the code?



Re: [Intel-gfx] [RFC 2/2] drm/doc/rfc: i915 new parallel submission uAPI plan

2021-05-24 Thread Tvrtko Ursulin



On 21/05/2021 17:48, Matthew Brost wrote:

On Fri, May 21, 2021 at 01:00:54PM +0100, Tvrtko Ursulin wrote:


[snip]


+ * enables parallel submission across multiple engine classes. In this case 
each
+ * context's logical engine mask indicates where that context can placed. It is
+ * implied in this mode that all contexts have mutual exclusive placement (e.g.
+ * if one context is running CS0 no other contexts can run on CS0).


I think talk about logical context and its mask is too implementation detail
at the uapi level. Instead I would suggest more userspace programmer centric
description.


Ok, can you give me suggestion? Writing DOC isn't really my strength.


Yeah, not mine either. Maybe we need to hire a technical writer. :)

I think in general I would just talk a bit how until now submission was 
along a single engine only and this is adding a wide submission model, 
expanding how it works with more details and only then talking about 
logical contexts if needed.


It depends a bit whether our userspace clients still predominantly think 
in terms of engines, or is it contexts? I don't have an answer there.


It probably isn't the most important thing and probably with a few 
tweaks of what you have it can be good enough. Key probably is simply 
coming up with as intuitive as possible diagrams, with consistent 
naming, showing how the wide engine is built and how it works.



+ *
+ * Example 1 pseudo code:
+ * CSX[Y] = engine class X, logical instance Y
+ * INVALID = I915_ENGINE_CLASS_INVALID, I915_ENGINE_CLASS_INVALID_NONE
+ * set_engines(INVALID)
+ * set_parallel(engine_index=0, width=2, num_siblings=2,
+ * engines=CS0[0],CS0[1],CS1[0],CS1[1])
+ *
+ * Results in the following valid placements:
+ * CS0[0], CS1[0]
+ * CS0[0], CS1[1]
+ * CS0[1], CS1[0]
+ * CS0[1], CS1[1]
+ *
+ * This can also be though of as 2 virtual engines:
+ * VE[0] = CS0[0], CS0[1]
+ * VE[1] = CS1[0], CS1[1]


Ah okay so essentially similar to what I was proposing a year ago. But then
it is no longer "set_parallel" really. It is one slot in the engine map,
right, with the idea to super class intel_context in the implementation?



Yes, it is bascially a super class intel_context. In the implementation is
parent-child with the parent having a linked list of child intel_contexts.
  

So really a wide virtual engine, as opposed to single one. In which case I
think it makes sense to stay close to the existing naming of the
load_balance extension for consistency. Load_balance_wide?
Load_balance_parallel? Multi?


I like the way is named but I also don't want to argue about this as I don't
really care. If someone else says this should be renamed, let's do it.


I don't care too much apart from a general desire for more consistency 
and fewer terms in use.



I also have to say the notation "CS0[0]" - I who know this problem space am
finding it hard to penetrate what that actually means. (Also uppercase IMO
makes it hard to read, but maybe it is just me.)



Yea, now I think about it CS0[0] is bad because of using numbers twice. How
about CSX[0] & CSY[1]? I used upper case because in the i915 all engine classes
defines are upper case but agree it might be easier to read it lower case.


What would X and Y represent? Or if I paste this part:

 * VE[0] = CS0[0], CS0[1]
 * VE[1] = CS1[0], CS1[1]

Which index is engine instance and what is the other index?


Looking a bit lower below, extension seems to be taking a 2d array of
class:instance pairs, right? If so then reading these docs in order, or even
just looking further down, I don't think that is explicitly called out
clearly enough.

So I think a paragraph or two explaining clearly how the 2d array of engines
corresponds to the allowed engines for full virtual engine width. Or maybe
just a 2d diagram?

   2-wide virtual engine:
 .engines = [
   /* channel 0 allowed engines: */  [cs0, cs1],
   /* channel 1 allowed engines: */  [cs0, cs1]
  ]

Not sure if that's better.



Yes, it is a 2-d array. Agree the explaination could be better.


Also to be noted, this only allows uniform number of allowed engines per
channel. I am not saying we need the non-uniform setup today but with bonds
there isn't this limitation.



Not exactly. You could do something like this.

witdth = 2
siblings = 2
engines = CSX[0], CSX[1], CSY[0], INVALID

This would allow a placement of:

CSX[0], CSY[0]
CSX[1], CSY[0]

In this case the siblings is just a max value of each entry.


Okay fair, did not think about that or saw it mentioned.

Regards,

Tvrtko


  1   2   >