[Bug 216119] 087451f372bf76d breaks hibernation on amdgpu Radeon R9 390

2022-08-08 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=216119

Mario Limonciello (AMD) (mario.limoncie...@amd.com) changed:

   What|Removed |Added

 CC||mario.limoncie...@amd.com

--- Comment #34 from Mario Limonciello (AMD) (mario.limoncie...@amd.com) ---
I recently became aware that the WX3200 in my workstation wasn't working
properly after suspend-to-ram.

61:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc.
[AMD/ATI] Lexa XT [Radeon PRO WX 3200] [1002:6981] (rev 10)

I ran a bisect, and unfortunately it came up to the commit that was created for
this bug
(https://github.com/torvalds/linux/commit/3a4b1cc28fbdc2325b3e3ed7d8024995a75f9216)

$ git bisect log
git bisect start '--term-new=broken' '--term-old=good'
# good: [4b0986a3613c92f4ec1bdc7f60ec66fea135991f] Linux 5.18
git bisect good 4b0986a3613c92f4ec1bdc7f60ec66fea135991f
# broken: [8843bf1f0737ecea456d2bbd19d4263d49f2d110] Linux 5.18.16
git bisect broken 8843bf1f0737ecea456d2bbd19d4263d49f2d110
# good: [ffd4c4d5293e4985092ea45ba21cad9326e2e434] drivers: staging: rtl8192e:
Fix deadlock in rtllib_beacons_stop()
git bisect good ffd4c4d5293e4985092ea45ba21cad9326e2e434
# good: [164f0714bae175e2f5737070d037d7475417228d] pinctrl: sunxi: a83t: Fix
NAND function name for some pins
git bisect good 164f0714bae175e2f5737070d037d7475417228d
# broken: [86fbd2844858c5aef57a28ebc3d53d298f37cc67] x86/retpoline: Use
-mfunction-return
git bisect broken 86fbd2844858c5aef57a28ebc3d53d298f37cc67
# broken: [7fc7c6d053cfca70bb81892f3f00937e5c459d5a] arm64: dts: broadcom:
bcm4908: Fix cpu node for smp boot
git bisect broken 7fc7c6d053cfca70bb81892f3f00937e5c459d5a
# good: [cd52154b924f2ea05069d4296045d9fd56a8da23] ALSA: hda - Add fixup for
Dell Latitidue E5430
git bisect good cd52154b924f2ea05069d4296045d9fd56a8da23
# good: [b8651049bdd77fa652bcf0f3157911a3a6fc4f2f] net/mlx5e: CT: Use own
workqueue instead of mlx5e priv
git bisect good b8651049bdd77fa652bcf0f3157911a3a6fc4f2f
# broken: [594cea2c09f7cd440d1ee1c4547d5bc6a646b0e4] netfilter: conntrack:
remove the percpu dying list
git bisect broken 594cea2c09f7cd440d1ee1c4547d5bc6a646b0e4
# broken: [cd486308d773d6d062a0140062458b48f8a0eb6b] ASoC: tas2764: Add post
reset delays
git bisect broken cd486308d773d6d062a0140062458b48f8a0eb6b
# broken: [4ffcacab7145080187330accafae69e87a481eec] drm/amdgpu/display:
disable prefer_shadow for generic fb helpers
git bisect broken 4ffcacab7145080187330accafae69e87a481eec
# good: [16427298f3dc02ec90bdfa31c8ef9b384ea5534a] net/mlx5e: Ring the TX
doorbell on DMA errors
git bisect good 16427298f3dc02ec90bdfa31c8ef9b384ea5534a
# good: [27dccf616a0a82f4d8004b7ee04560e7de419e63] drm/amdgpu: keep fbdev
buffers pinned during suspend
git bisect good 27dccf616a0a82f4d8004b7ee04560e7de419e63
# first broken commit: [4ffcacab7145080187330accafae69e87a481eec]
drm/amdgpu/display: disable prefer_shadow for generic fb helpers

It seems that a revert of that commit isn't the best solution as it's just
trading the S3 failure I see for your S4 failure.  But also it seems that from
your comment #32 there is still an underlying problem with using the fbdev
helper, albeit improved for you in S3.

Would you mind contrasting if S3 is working for you with/without that commit?

-- 
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: imx8mm lcdif->dsi->adv7535 no video, no errors

2022-08-08 Thread Adam Ford
On Mon, Aug 8, 2022 at 5:13 AM Adam Ford  wrote:
>
> On Mon, Aug 8, 2022 at 3:54 AM Marco Felsch  wrote:
> >
> > On 22-08-07, Adam Ford wrote:
> > > On Fri, Aug 5, 2022 at 4:05 PM Adam Ford  wrote:
> > > >
> > > > On Fri, Aug 5, 2022 at 7:56 AM Adam Ford  wrote:
> > > > >
> > > > > On Fri, Aug 5, 2022 at 5:55 AM Adam Ford  wrote:
> > > > > >
> > > > > > On Fri, Aug 5, 2022 at 3:44 AM Biju Das 
> > > > > >  wrote:
> > > > > > >
> > > > > > > Hi Adam and all,
> > > > > > >
> > > > > > > > Subject: Re: imx8mm lcdif->dsi->adv7535 no video, no errors
> > > > > > > >
> > > > > > > > On Thu, Aug 4, 2022 at 9:52 AM Dave Stevenson
> > > > > > > >  wrote:
> > > > > > > > >
> > > > > > > > > On Thu, 4 Aug 2022 at 13:51, Marco Felsch 
> > > > > > > > > 
> > > > > > > > wrote:
> > > > > > > > > >
> > > > > > > > > > Hi Dave,
> > > > > > > > > >
> > > > > > > > > > On 22-08-04, Dave Stevenson wrote:
> > > > > > > > > > > Hi Marco
> > > > > > > > > > >
> > > > > > > > > > > On Thu, 4 Aug 2022 at 10:38, Marco Felsch
> > > > > > > >  wrote:
> > > > > > > > > > > >
> > > > > > > > > > > > Hi Dave, Adam,
> > > > > > > > > > > >
> > > > > > > > > > > > On 22-08-03, Dave Stevenson wrote:
> > > > > > > > > > > > > Hi Adam
> > > > > > > > > > > > >
> > > > > > > > > > > > > On Wed, 3 Aug 2022 at 12:03, Adam Ford 
> > > > > > > > > > > > > 
> > > > > > > > wrote:
> > > > > > > > > > > >
> > > > > > > > > > > > ...
> > > > > > > > > > > >
> > > > > > > > > > > > > > > Did managed to get access to the ADV7535 
> > > > > > > > > > > > > > > programming
> > > > > > > > > > > > > > > guide? This is the black box here. Let me check 
> > > > > > > > > > > > > > > if I can
> > > > > > > > > > > > > > > provide you a link with our repo so you can test 
> > > > > > > > > > > > > > > our
> > > > > > > > current DSIM state if you want.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > I do have access to the programming guide, but it's 
> > > > > > > > > > > > > > under
> > > > > > > > > > > > > > NDA, but I'll try to answer questions if I can.
> > > > > > > > > > > > >
> > > > > > > > > > > > > Not meaning to butt in, but I have datasheets for 
> > > > > > > > > > > > > ADV7533 and
> > > > > > > > > > > > > 7535 from previously looking at these chips.
> > > > > > > > > > > >
> > > > > > > > > > > > Thanks for stepping into :)
> > > > > > > > > > > >
> > > > > > > > > > > > > Mine fairly plainly states:
> > > > > > > > > > > > > "The DSI receiver input supports DSI video mode 
> > > > > > > > > > > > > operation
> > > > > > > > > > > > > only, and specifically, only supports nonburst mode 
> > > > > > > > > > > > > with sync
> > > > > > > > pulses".
> > > > > > > > > > > >
> > > > > > > > > > > > I've read this also, and we are working in nonburst 
> > > > > > > > > > > > mode with
> > > > > > > > > > > > sync pulses. I have no access to an MIPI-DSI analyzer 
> > > > > > > > > > > > therefore
> > > > > > > > > > > > I can't verify it.
> > > > > > > > > > > >
> > > > > > > > > > > > > Non-burst mode meaning that the DSI pixel rate MUST 
> > > > > > > > > > > > > be the
> > > > > > > > > > > > > same as the HDMI pixel rate.
> > > > > > > > > > > >
> > > > > > > > > > > > On DSI side you don't have a pixel-clock instead there 
> > > > > > > > > > > > is bit-
> > > > > > > > clock.
> > > > > > > > > > >
> > > > > > > > > > > You have an effective pixel clock, with a fixed 
> > > > > > > > > > > conversion for the
> > > > > > > > > > > configuration.
> > > > > > > > > > >
> > > > > > > > > > > DSI bit-clock * number of lanes / bits_per_pixel = pixel 
> > > > > > > > > > > rate.
> > > > > > > > > > > 891Mbit/s * 4 lanes / 24bpp = 148.5 Mpixels/s
> > > > > > > > > >
> > > > > > > > > > Okay, I just checked the bandwidth which must equal.
> > > > > > > > > >
> > > > > > > > > > > As noted elsewhere, the DSI is DDR, so the clock lane 
> > > > > > > > > > > itself is
> > > > > > > > > > > only running at 891 / 2 = 445.5MHz.
> > > > > > > > > > >
> > > > > > > > > > > > > Section 6.1.1 "DSI Input Modes" of
> > > > > > > > > > > > > adv7533_hardware_user_s_guide is even more explicit 
> > > > > > > > > > > > > about the
> > > > > > > > > > > > > requirement of DSI timing matching
> > > > > > > > > > > >
> > > > > > > > > > > > Is it possible to share the key points of the 
> > > > > > > > > > > > requirements?
> > > > > > > > > > >
> > > > > > > > > > > "Specifically the ADV7533 supports the Non-Burst Mode 
> > > > > > > > > > > with syncs.
> > > > > > > > > > > This mode requires real time data generation as a pulse 
> > > > > > > > > > > packet
> > > > > > > > > > > received becomes a pulse generated. Therefore this mode 
> > > > > > > > > > > requires a
> > > > > > > > > > > continuous stream of data with correct video timing to 
> > > > > > > > > > > avoid any
> > > > > > > > > > > visual artifacts."
> > > > > > > > > > >
> > > > > > > > > > > LP mode is supported on data lanes. Clock lane must 
> > > > > > > > > > > remain in HS
> > > > > > 

Re: [PATCH v2] drm/gem: Fix GEM handle release errors

2022-08-08 Thread Chen Jeffy

Hi Christian,

On 8/9 星期二 2:03, Christian König wrote:

Hi Jeffy,

Am 08.08.22 um 05:51 schrieb Chen Jeffy:

Hi Christian,

Thanks for your reply, and sorry i didn't make it clear.

On 8/8 星期一 0:52, Christian König wrote:

Am 03.08.22 um 10:32 schrieb Jeffy Chen:
Currently we are assuming a one to one mapping between dmabuf and 
handle

when releasing GEM handles.

But that is not always true, since we would create extra handles for 
the

GEM obj in cases like gem_open() and getfb{,2}().

A similar issue was reported at:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fall%2F20211105083308.392156-1-jay.xu%40rock-chips.com%2Fdata=05%7C01%7Cchristian.koenig%40amd.com%7Cd7488e9f235041f7e84408da78f14882%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637955274964656400%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7Csdata=9G2YbHcYUs1VQYyvjXwLzYawNw%2BP8i%2BjjPBSHx3r2yg%3Dreserved=0

Another problem is that the drm_gem_remove_prime_handles() now only
remove handle to the exported dmabuf (gem_obj->dma_buf), so the 
imported

ones would leak:
WARNING: CPU: 2 PID: 236 at drivers/gpu/drm/drm_prime.c:228 
drm_prime_destroy_file_private+0x18/0x24


Let's fix these by using handle to find the exact map to remove.


Well we are clearly something missing here. As far as I can see the 
current code is correct.


Creating multiple GEM handles for the same DMA-buf is possible, but 
illegal. >
In other words when a GEM handle is exported as DMA-buf and imported 
again you should intentionally always get the same handle.


These issue are not about having handles for importing an exported 
dma-buf case, but for having multiple handles to a GEM object(which 
means having multiple handles to a dma-buf).


I know the drm-prime is trying to make dma-buf and handle maps one to 
one, but the drm-gem is allowing to create extra handles for a GEM 
object, for example:

drm_gem_open_ioctl -> drm_gem_handle_create_tail
drm_mode_getfb2_ioctl -> drm_gem_handle_create
drm_mode_getfb -> fb->funcs->create_handle


Yes, so far that's correct.




So we are allowing GEM object to have multiple handles, and GEM object 
could have at most one dma-buf, doesn't that means that dma-buf could 
map to multiple handles?


No, at least not for the same GEM file private. That's the reason why 
the rb is indexed by the dma_buf object and not the handle.


In other words the rb is so that you have exactly one handle for each 
dma_buf in each file private.


I don't think so, because if user get multiple handles for the same GEM 
obj and use drm_gem_prime_handle_to_fd() for those handles, the current 
code would try to add multiple maps to rb:

drm_prime_add_buf_handle(buf_1, hdl_1)
drm_prime_add_buf_handle(buf_1, hdl_2)
...
drm_prime_add_buf_handle(buf_1, hdl_n)





Or should we rewrite the GEM framework to limit GEM object with uniq 
handle?


No, the extra handles are expected because when you call 
drm_mode_getfb*() and drm_gem_open_ioctl() the caller now owns the 
returned GEM handle.




The other issue is that we are leaking dma-buf <-> handle map for the 
imported dma-buf, since the drm_gem_remove_prime_handles doesn't take 
care of obj->import_attach->dmabuf.


No, that's correct as well. obj->dma_buf is set even for imported 
DMA-buf objects. See drm_gem_prime_fd_to_handle().


Well, that obj->dma_buf would be set in 
drm_gem_prime_fd_to_handle(create new handle), and cleared when 
releasing the latest handle(release handle).


So it doesn't cover other handle creating path.

For example, a imported dma buf:
drm_gem_prime_fd_to_handle <-- we got a handle and obj->dma_buf and 
obj->import_attach->dmabuf

drm_gem_handle_delete <-- we lost that handle and obj->dma_buf cleared
drm_gem_open_ioctl/or getfb* <-- we got a new handle and 
obj->import_attach->dmabuf
drm_gem_handle_delete <-- we lost that handle and obj->dma_buf is null, 
which means rb leaks.




Regards,
Christian.



But of cause this can be fixed in other way:
+++ b/drivers/gpu/drm/drm_gem.c
@@ -180,6 +180,9 @@ drm_gem_remove_prime_handles(struct drm_gem_object 
*obj, struct drm_file *filp)

drm_prime_remove_buf_handle_locked(>prime,
obj->dma_buf);
    }
+   if (obj->import_attach)
+ drm_prime_remove_buf_handle_locked(>prime,
+ obj->import_attach->dmabuf);
    mutex_unlock(>prime.lock);
 }


So this is pretty much a clear NAK to this patch since it shouldn't 
be necessary or something is seriously broken somewhere else.


Regards,
Christian.



Signed-off-by: Jeffy Chen 
---

Changes in v2:
Fix a typo of rbtree.

  drivers/gpu/drm/drm_gem.c  | 17 +
  drivers/gpu/drm/drm_internal.h |  4 ++--
  drivers/gpu/drm/drm_prime.c    | 20 
  3 files changed, 15 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index eb0c2d041f13..ed39da383570 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ 

Re: [PATCH v3 2/4] dt-bindings: display: add new bus-format property for panel-dpi

2022-08-08 Thread Marek Vasut

On 8/8/22 15:56, Max Krummenacher wrote:

Hi Marek


Hello Max,

[...]


+properties:
+  bus-format:
+$ref: /schemas/types.yaml#/definitions/uint32
+minimum: 0x1001
+maximum: 0x1fff
+description: |
+  Describes how the display panel is connected to the display 
interface.
+  Valid values are defined in 
.
+  The mapping between the color/significance of the panel lines to 
the
+  parallel data lines are defined in:
+  
https://www.kernel.org/doc/html/v5.17/userspace-api/media/v4l/subdev-formats.html#packed-rgb-formats


I am not sure whether I should re-open this discussion, but I still
wonder, wouldn't it be better to describe the DPI bus color channel
ordering (RGB, BGR, ...), width of each color channel in bits, pixel
format (RGB, YUV, ...) instead of using specific constants for the
entire format ?



From a system view it would be hard to define that structure which

will catch any and all future requirements. Assume that there will be
3D panels and they will need an additional depth field.


You can very much say you have panels which require Y/U/V color channels 
instead of R/G/B , and then just add more color channels as needed. But 
that -- color channel, their order, offset, bit width, can be described 
rather easily, something like:


color-channel-names = "R", "G", "B";
color-channel-width = <8 8 8>;
color-channel-shift = <16 8 0>;


Or in
in addition to RGB data there will be a fourth color component. Or
whatever the panel manufacturers might come up with...
Or consider the Tegra 30 example I brought up in this thread. Tegras can
output RGB666 for 18bit panels, and then use the next 8 bits to extend
to 24bit (Maybe RGB666RGB222 ?).


I think there are two options here:

1) Look at 'data-lanes' property on DSI ? Both the DSI host and DSI
   device define the 'data-lanes' property per endpoint and they might
   not be the same.

But with DPI, the better option might be:

2) Implement something like LVDS codec, some sort of transparent DPI
   bridge driver which can be defined in DT and represent the "glue"
   wiring adapter between the mismatched DPI source and sink formats.


https://lore.kernel.org/all/71ef1b35301330d0bbb64844247b6c4c2237ad1c.ca...@gmail.com/
If such requirements pop up the enumeration can be extended with a new
value without changing the binding in any way, with a structured
approach this will require changed bindings, maybe even with issues
in backward compatibility.


If we have 2) which would describe how the DPI wires were connected, 
like "channel R got shifted by two bits, bottom two bits got replicated, 
etc.", then maybe we can avoid introducing new non-standard formats 
altogether ?



From an implementation perspective for Linux the busformat in code is

currently an enumeration. So one would have to take the device tree
structured busformat and run it through a potentially complicated
function to get to the Linux busformat enumeration value. The final
consumer has no advantage over what is there today.

IMHO a change away from one enumeration value to a structured approach
creates some drawbacks without any obvious advantages.

Comments, other views on that?


See above.


Re: [PATCH] drm/gem: Fix GEM handle release errors

2022-08-08 Thread Chen Jeffy

Hi Christian,

Sorry, i've sent a v2 before, please check that.

On 8/9 星期二 2:05, Christian König wrote:



Am 02.08.22 um 13:33 schrieb Jeffy Chen:

Currently we are assuming a one to one mapping between dmabuf and handle
when releasing GEM handles.

But that is not always true, since we would create extra handles for the
GEM obj in cases like gem_open() and getfb{,2}().

A similar issue was reported at:
https://lore.kernel.org/all/20211105083308.392156-1-jay...@rock-chips.com/

Another problem is that the drm_gem_remove_prime_handles() now only
remove handle to the exported dmabuf (gem_obj->dma_buf), so the imported
ones would leak:
WARNING: CPU: 2 PID: 236 at drivers/gpu/drm/drm_prime.c:228 
drm_prime_destroy_file_private+0x18/0x24


Let's fix these by using handle to find the exact map to remove.

Signed-off-by: Jeffy Chen 
---

  drivers/gpu/drm/drm_gem.c  | 17 +
  drivers/gpu/drm/drm_internal.h |  4 ++--
  drivers/gpu/drm/drm_prime.c    | 16 ++--
  3 files changed, 13 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index eb0c2d041f13..ed39da383570 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -168,21 +168,6 @@ void drm_gem_private_object_init(struct 
drm_device *dev,

  }
  EXPORT_SYMBOL(drm_gem_private_object_init);
-static void
-drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct 
drm_file *filp)

-{
-    /*
- * Note: obj->dma_buf can't disappear as long as we still hold a
- * handle reference in obj->handle_count.
- */
-    mutex_lock(>prime.lock);
-    if (obj->dma_buf) {
-    drm_prime_remove_buf_handle_locked(>prime,
-   obj->dma_buf);
-    }
-    mutex_unlock(>prime.lock);
-}
-
  /**
   * drm_gem_object_handle_free - release resources bound to userspace 
handles

   * @obj: GEM object to clean up.
@@ -253,7 +238,7 @@ drm_gem_object_release_handle(int id, void *ptr, 
void *data)

  if (obj->funcs->close)
  obj->funcs->close(obj, file_priv);
-    drm_gem_remove_prime_handles(obj, file_priv);
+    drm_prime_remove_buf_handle(_priv->prime, id);
  drm_vma_node_revoke(>vma_node, file_priv);
  drm_gem_object_handle_put_unlocked(obj);
diff --git a/drivers/gpu/drm/drm_internal.h 
b/drivers/gpu/drm/drm_internal.h

index 1fbbc19f1ac0..7bb98e6a446d 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -74,8 +74,8 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device 
*dev, void *data,
  void drm_prime_init_file_private(struct drm_prime_file_private 
*prime_fpriv);
  void drm_prime_destroy_file_private(struct drm_prime_file_private 
*prime_fpriv);
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private 
*prime_fpriv,

-    struct dma_buf *dma_buf);
+void drm_prime_remove_buf_handle(struct drm_prime_file_private 
*prime_fpriv,

+ uint32_t handle);
  /* drm_drv.c */
  struct drm_minor *drm_minor_acquire(unsigned int minor_id);
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index e3f09f18110c..c28518ab62d0 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -190,29 +190,33 @@ static int drm_prime_lookup_buf_handle(struct 
drm_prime_file_private *prime_fpri

  return -ENOENT;
  }
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private 
*prime_fpriv,

-    struct dma_buf *dma_buf)
+void drm_prime_remove_buf_handle(struct drm_prime_file_private 
*prime_fpriv,

+ uint32_t handle)
  {
  struct rb_node *rb;
+    mutex_lock(_fpriv->lock);
+
  rb = prime_fpriv->dmabufs.rb_node;
  while (rb) {
  struct drm_prime_member *member;
  member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
-    if (member->dma_buf == dma_buf) {
+    if (member->handle == handle) {
  rb_erase(>handle_rb, _fpriv->handles);
  rb_erase(>dmabuf_rb, _fpriv->dmabufs);
-    dma_buf_put(dma_buf);
+    dma_buf_put(member->dma_buf);
  kfree(member);
-    return;
-    } else if (member->dma_buf < dma_buf) {
+    break;
+    } else if (member->handle < handle) {


Just to make it clear once more. That change here is completely broken.

The rb is indexed by the dma_buf object, not the handle.

Regards,
Christian.


  rb = rb->rb_right;
  } else {
  rb = rb->rb_left;
  }
  }
+
+    mutex_unlock(_fpriv->lock);
  }
  void drm_prime_init_file_private(struct drm_prime_file_private 
*prime_fpriv)







[RFC] drm/bridge: adv7533: remove dynamic lane switching from adv7533 bridge

2022-08-08 Thread Abhinav Kumar
adv7533 bridge tries to dynamically switch lanes based on the
mode by detaching and attaching the mipi dsi device.

This approach is incorrect because as per the DSI spec the
number of lanes is fixed at the time of system design or initial
configuration and may not change dynamically.

In addition this method of dynamic switch of detaching and
attaching the mipi dsi device also results in removing
and adding the component which is not necessary.

This approach is also prone to deadlocks. So for example, on the
db410c whenever this path is executed with lockdep enabled,
this results in a deadlock due to below ordering of locks.

-> #1 (crtc_ww_class_acquire){+.+.}-{0:0}:
lock_acquire+0x6c/0x90
drm_modeset_acquire_init+0xf4/0x150
drmm_mode_config_init+0x220/0x770
msm_drm_bind+0x13c/0x654
try_to_bring_up_aggregate_device+0x164/0x1d0
__component_add+0xa8/0x174
component_add+0x18/0x2c
dsi_dev_attach+0x24/0x30
dsi_host_attach+0x98/0x14c
devm_mipi_dsi_attach+0x38/0xb0
adv7533_attach_dsi+0x8c/0x110
adv7511_probe+0x5a0/0x930
i2c_device_probe+0x30c/0x350
really_probe.part.0+0x9c/0x2b0
__driver_probe_device+0x98/0x144
driver_probe_device+0xac/0x14c
__device_attach_driver+0xbc/0x124
bus_for_each_drv+0x78/0xd0
__device_attach+0xa8/0x1c0
device_initial_probe+0x18/0x24
bus_probe_device+0xa0/0xac
deferred_probe_work_func+0x90/0xd0
process_one_work+0x28c/0x6b0
worker_thread+0x240/0x444
kthread+0x110/0x114
ret_from_fork+0x10/0x20

-> #0 (component_mutex){+.+.}-{3:3}:
__lock_acquire+0x1280/0x20ac
lock_acquire.part.0+0xe0/0x230
lock_acquire+0x6c/0x90
__mutex_lock+0x84/0x400
mutex_lock_nested+0x3c/0x70
component_del+0x34/0x170
dsi_dev_detach+0x24/0x30
dsi_host_detach+0x20/0x64
mipi_dsi_detach+0x2c/0x40
adv7533_mode_set+0x64/0x90
adv7511_bridge_mode_set+0x210/0x214
drm_bridge_chain_mode_set+0x5c/0x84
crtc_set_mode+0x18c/0x1dc
drm_atomic_helper_commit_modeset_disables+0x40/0x50
msm_atomic_commit_tail+0x1d0/0x6e0
commit_tail+0xa4/0x180
drm_atomic_helper_commit+0x178/0x3b0
drm_atomic_commit+0xa4/0xe0
drm_client_modeset_commit_atomic+0x228/0x284
drm_client_modeset_commit_locked+0x64/0x1d0
drm_client_modeset_commit+0x34/0x60
drm_fb_helper_lastclose+0x74/0xcc
drm_lastclose+0x3c/0x80
drm_release+0xfc/0x114
__fput+0x70/0x224
fput+0x14/0x20
task_work_run+0x88/0x1a0
do_exit+0x350/0xa50
do_group_exit+0x38/0xa4
__wake_up_parent+0x0/0x34
invoke_syscall+0x48/0x114
el0_svc_common.constprop.0+0x60/0x11c
do_el0_svc+0x30/0xc0
el0_svc+0x58/0x100
el0t_64_sync_handler+0x1b0/0x1bc
el0t_64_sync+0x18c/0x190

Due to above reasons, remove the dynamic lane switching
code from adv7533 bridge chip and filter out the modes
which would need different number of lanes as compared
to the initialization time using the mode_valid callback.

Suggested-by: Dmitry Baryshkov 
Signed-off-by: Abhinav Kumar 
---
 drivers/gpu/drm/bridge/adv7511/adv7511.h |  3 ++-
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 18 ++
 drivers/gpu/drm/bridge/adv7511/adv7533.c | 25 +
 3 files changed, 29 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h 
b/drivers/gpu/drm/bridge/adv7511/adv7511.h
index 9e3bb8a8ee40..0a7cec80b75d 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h
@@ -417,7 +417,8 @@ static inline int adv7511_cec_init(struct device *dev, 
struct adv7511 *adv7511)
 
 void adv7533_dsi_power_on(struct adv7511 *adv);
 void adv7533_dsi_power_off(struct adv7511 *adv);
-void adv7533_mode_set(struct adv7511 *adv, const struct drm_display_mode 
*mode);
+enum drm_mode_status adv7533_mode_valid(struct adv7511 *adv,
+   const struct drm_display_mode *mode);
 int adv7533_patch_registers(struct adv7511 *adv);
 int adv7533_patch_cec_registers(struct adv7511 *adv);
 int adv7533_attach_dsi(struct adv7511 *adv);
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c 
b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index 5bb9300040dd..1115ef9be83c 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -697,7 +697,7 @@ adv7511_detect(struct adv7511 *adv7511, struct 
drm_connector *connector)
 }
 
 static enum drm_mode_status adv7511_mode_valid(struct adv7511 *adv7511,
- struct drm_display_mode *mode)
+ const struct drm_display_mode *mode)
 {
if (mode->clock > 165000)
return MODE_CLOCK_HIGH;
@@ -791,9 +791,6 @@ static void 

Re: [Intel-gfx] [PATCH v3 1/3] drm/i915: pass a pointer for tlb seqno at vma_invalidate_tlb()

2022-08-08 Thread Vivi, Rodrigo
On Tue, 2022-08-09 at 01:09 +0200, Andi Shyti wrote:
> Hi Rodrigo,
> 
> On Mon, Aug 08, 2022 at 03:04:13PM -0400, Rodrigo Vivi wrote:
> > On Mon, Aug 08, 2022 at 06:37:58PM +0200, Andi Shyti wrote:
> > > Hi Mauro,
> > > 
> > > On Thu, Aug 04, 2022 at 09:37:22AM +0200, Mauro Carvalho Chehab
> > > wrote:
> > > > WRITE_ONCE() should happen at the original var, not on a local
> > > > copy of it.
> > > > 
> > > > Fixes: 5d36acb7198b ("drm/i915/gt: Batch TLB invalidations")
> > > > Signed-off-by: Mauro Carvalho Chehab 
> > > 
> > > Reviewed-by: Andi Shyti 
> > 
> > Thanks and pushed...
> 
> Thanks!
> 
> > > 
> > > Are you going to send it to the stable mailing list?
> > 
> > I added cc stable while pushing and the cherry-pick to drm-intel-
> > next-fixes
> > has the right sha, so I'd assume this would be automagically now.
> > But yeap, it would be good if Mauro can follow up whenever this
> > gets
> > to Linus tree and Greg's script start to pop up the heads-up
> > messages.
> 
> That's what I meant... does Mauro now need to send the e-mail
> again for the stable?
> 
> I thought there was some suspicion towards e-mails pushed without
> being first sent to both stable and upstream mailing lists
> because they can get lost or forgotten... maybe I'm wrong.

It doesn't help to send now to stable ml because it can only be merged
there after it reaches the Linus' master tree.
Right now with the right fixes and cc:stable it should be automatically
and he shouldn't worry.
But in case he notices that the first patch got in but the second
didn't then it is when we send the patch directly to the stable ml.


> 
> Andi
> 
> > Thanks,
> > Rodrigo.
> > 
> > > 
> > > Andi



[RFC v2 18/18] drm/display/dp_mst: Move all payload info into the atomic state

2022-08-08 Thread Lyude Paul
Now that we've finally gotten rid of the non-atomic MST users leftover in
the kernel, we can finally get rid of all of the legacy payload code we
have and move as much as possible into the MST atomic state structs. The
main purpose of this is to make the MST code a lot less confusing to work
on, as there's a lot of duplicated logic that doesn't really need to be
here. As well, this should make introducing features like fallback link
retraining and DSC support far easier.

Since the old payload code was pretty gnarly and there's a Lot of changes
here, I expect this might be a bit difficult to review. So to make things
as easy as possible for reviewers, I'll sum up how both the old and new
code worked here (it took me a while to figure this out too!).

The old MST code basically worked by maintaining two different payload
tables - proposed_vcpis, and payloads. proposed_vcpis would hold the
modified payload we wanted to push to the topology, while payloads held the
payload table that was currently programmed in hardware. Modifications to
proposed_vcpis would be handled through drm_dp_allocate_vcpi(),
drm_dp_mst_deallocate_vcpi(), and drm_dp_mst_reset_vcpi_slots(). Then, they
would be pushed via drm_dp_mst_update_payload_step1() and
drm_dp_mst_update_payload_step2().

Furthermore, it's important to note how adding and removing VC payloads
actually worked with drm_dp_mst_update_payload_step1(). When a VC payload
is removed from the VC table, all VC payloads which come after the removed
VC payload's slots must have their time slots shifted towards the start of
the table. The old code handles this by looping through the entire payload
table and recomputing the start slot for every payload in the topology from
scratch. While very much overkill, this ends up doing the right thing
because we always order the VCPIs for payloads from first to last starting
timeslot.

It's important to also note that drm_dp_mst_update_payload_step2() isn't
actually limited to updating a single payload - the driver can use it to
queue up multiple payload changes so that as many of them can be sent as
possible before waiting for the ACT. This is -technically- not against
spec, but as Wayne Lin has pointed out it's not consistently implemented
correctly in hubs - so it might as well be.

drm_dp_mst_update_payload_step2() is pretty self explanatory and basically
the same between the old and new code, save for the fact we don't have a
second step for deleting payloads anymore -and thus rename it to
drm_dp_mst_add_payload_step2().

The new payload code stores all of the current payload info within the MST
atomic state and computes as much of the state as possible ahead of time.
This has the one exception of the starting timeslots for payloads, which
can't be determined at atomic check time since the starting time slots will
vary depending on what order CRTCs are enabled in the atomic state - which
varies from driver to driver. These are still stored in the atomic MST
state, but are only copied from the old MST state during atomic commit
time. Likewise, this is when new start slots are determined.

Adding/removing payloads now works much more closely to how things are
described in the spec. When we delete a payload, we loop through the
current list of payloads and update the start slots for any payloads whose
time slots came after the payload we just deleted. Determining the starting
time slots for new payloads being added is done by simply keeping track of
where the end of the VC table is in
drm_dp_mst_topology_mgr->next_start_slot. Additionally, it's worth noting
that we no longer have a single update_payload() function. Instead, we now
have drm_dp_mst_add_payload_step1|2() and drm_dp_mst_remove_payload(). As
such, it's now left it up to the driver to figure out when to add or remove
payloads. The driver already knows when it's disabling/enabling CRTCs, so
it also already knows when payloads should be added or removed.

Changes since v1:
* Refactor around all of the completely dead code changes that are
  happening in amdgpu for some reason when they really shouldn't even be
  there in the first place… :\
* Remove mention of sending one ACT per series of payload updates. As Wayne
  Lin pointed out, there are apparently hubs on the market that don't work
  correctly with this scheme and require a separate ACT per payload update.
* Fix accidental drop of mst_mgr.lock - Wayne Lin
* Remove mentions of allowing multiple ACT updates per payload change,
  mention that this is a result of vendors not consistently supporting this
  part of the spec and requiring a unique ACT for each payload change.
* Get rid of reference to drm_dp_mst_port in DC - turns out I just got
  myself confused by DC and we don't actually need this.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
Acked-by: Jani Nikula 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  56 +-

[RFC v2 16/18] drm/display/dp_mst: Maintain time slot allocations when deleting payloads

2022-08-08 Thread Lyude Paul
Currently, we set drm_dp_atomic_payload->time_slots to 0 in order to
indicate that we're about to delete a payload in the current atomic state.
Since we're going to be dropping all of the legacy code for handling the
payload table however, we need to be able to ensure that we still keep
track of the current time slot allocations for each payload so we can reuse
this info when asking the root MST hub to delete payloads. We'll also be
using it to recalculate the start slots of each VC.

So, let's keep track of the intent of a payload in drm_dp_atomic_payload by
adding ->delete, which we set whenever we're planning on deleting a payload
during the current atomic commit.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
Acked-by: Jani Nikula 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 14 +++---
 include/drm/display/drm_dp_mst_helper.h   |  5 -
 2 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index e9cf09a4b2a4..3fce1ed8d5e8 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4399,7 +4399,7 @@ int drm_dp_atomic_find_time_slots(struct drm_atomic_state 
*state,
 * releasing and allocating the same timeslot allocation,
 * which is an error
 */
-   if (WARN_ON(!prev_slots)) {
+   if (drm_WARN_ON(mgr->dev, payload->delete)) {
drm_err(mgr->dev,
"cannot allocate and release time slots on [MST 
PORT:%p] in the same state\n",
port);
@@ -4504,10 +4504,10 @@ int drm_dp_atomic_release_time_slots(struct 
drm_atomic_state *state,
}
 
drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, 
payload->time_slots);
-   if (payload->time_slots) {
+   if (!payload->delete) {
drm_dp_mst_put_port_malloc(port);
-   payload->time_slots = 0;
payload->pbn = 0;
+   payload->delete = true;
}
 
return 0;
@@ -5222,7 +5222,7 @@ drm_dp_mst_duplicate_state(struct drm_private_obj *obj)
 
list_for_each_entry(pos, _state->payloads, next) {
/* Prune leftover freed timeslot allocations */
-   if (!pos->time_slots)
+   if (pos->delete)
continue;
 
payload = kmemdup(pos, sizeof(*payload), GFP_KERNEL);
@@ -5254,8 +5254,8 @@ static void drm_dp_mst_destroy_state(struct 
drm_private_obj *obj,
int i;
 
list_for_each_entry_safe(pos, tmp, _state->payloads, next) {
-   /* We only keep references to ports with non-zero VCPIs */
-   if (pos->time_slots)
+   /* We only keep references to ports with active payloads */
+   if (!pos->delete)
drm_dp_mst_put_port_malloc(pos->port);
kfree(pos);
}
@@ -5383,7 +5383,7 @@ drm_dp_mst_atomic_check_payload_alloc_limits(struct 
drm_dp_mst_topology_mgr *mgr
 
list_for_each_entry(payload, _state->payloads, next) {
/* Releasing payloads is always OK-even if the port is gone */
-   if (!payload->time_slots) {
+   if (payload->delete) {
drm_dbg_atomic(mgr->dev, "[MST PORT:%p] releases all 
time slots\n",
   payload->port);
continue;
diff --git a/include/drm/display/drm_dp_mst_helper.h 
b/include/drm/display/drm_dp_mst_helper.h
index b9c361b242ea..8b847836a0b4 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -560,8 +560,11 @@ struct drm_dp_mst_atomic_payload {
int time_slots;
/** @pbn: The payload bandwidth for this payload */
int pbn;
+
+   /** @delete: Whether or not we intend to delete this payload during 
this atomic commit */
+   bool delete : 1;
/** @dsc_enabled: Whether or not this payload has DSC enabled */
-   bool dsc_enabled;
+   bool dsc_enabled : 1;
 
/** @next: The list node for this payload */
struct list_head next;
-- 
2.37.1



[RFC v2 17/18] drm/radeon: Drop legacy MST support

2022-08-08 Thread Lyude Paul
Right now, radeon is technically the only non-atomic driver still making
use of the MST helpers - and thus the final user of all of the legacy MST
helpers. Originally I was going to look into seeing if we could move legacy
MST into the radeon driver itself, however:

* SI and CIK both can use amdgpu, which still supports MST
* It currently doesn't work according to my own testing. I'm sure with some
  troubleshooting we could likely fix it, but that brings me to point #2:
* It was never actually enabled by default, and is still marked as
  experimental in the module parameter description
* If people were using it, someone probably would have probably seen a bug
  report about how it is currently not functional by now. That certainly
  doesn't appear to be the case, since before getting access to my own
  hardware I had to go out of my way to try finding someone to help test
  whether this legacy MST code even works - even amongst AMD employees.
* Getting rid of this code and only having atomic versions of the MST
  helpers to maintain is likely going to be a lot easier in the long run,
  and will make it a lot easier for others contributing to this code to
  follow along with what's happening.

FWIW - if anyone still wants this code to be in the tree and has a good
idea of how to support this without needing to maintain the legacy MST
helpers (trying to move them would probably be acceptable), I'm happy to
suggestions. But my hope is that we can just drop this code and forget
about it. I've already run this idea by Harry Wentland and Alex Deucher a
few times as well.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
Acked-by: Alex Deucher 
Acked-by: Jani Nikula 
---
 drivers/gpu/drm/radeon/Makefile|   2 +-
 drivers/gpu/drm/radeon/atombios_crtc.c |  11 +-
 drivers/gpu/drm/radeon/atombios_encoders.c |  59 --
 drivers/gpu/drm/radeon/radeon_atombios.c   |   2 -
 drivers/gpu/drm/radeon/radeon_connectors.c |  61 +-
 drivers/gpu/drm/radeon/radeon_device.c |   1 -
 drivers/gpu/drm/radeon/radeon_dp_mst.c | 778 -
 drivers/gpu/drm/radeon/radeon_drv.c|   4 -
 drivers/gpu/drm/radeon/radeon_encoders.c   |  14 +-
 drivers/gpu/drm/radeon/radeon_irq_kms.c|  10 +-
 drivers/gpu/drm/radeon/radeon_mode.h   |  40 --
 11 files changed, 7 insertions(+), 975 deletions(-)
 delete mode 100644 drivers/gpu/drm/radeon/radeon_dp_mst.c

diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index e3ab3aca1396..bb4e56f2f170 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -49,7 +49,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o 
\
trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \
ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o \
-   radeon_sync.o radeon_audio.o radeon_dp_auxch.o radeon_dp_mst.o
+   radeon_sync.o radeon_audio.o radeon_dp_auxch.o
 
 radeon-$(CONFIG_MMU_NOTIFIER) += radeon_mn.o
 
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c 
b/drivers/gpu/drm/radeon/atombios_crtc.c
index 69f1bc073902..d28d3acb3ba1 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -617,13 +617,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
}
}
 
-   if (radeon_encoder->is_mst_encoder) {
-   struct radeon_encoder_mst *mst_enc = radeon_encoder->enc_priv;
-   struct radeon_connector_atom_dig *dig_connector = 
mst_enc->connector->con_priv;
-
-   dp_clock = dig_connector->dp_clock;
-   }
-
/* use recommended ref_div for ss */
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
if (radeon_crtc->ss_enabled) {
@@ -972,9 +965,7 @@ static bool atombios_crtc_prepare_pll(struct drm_crtc 
*crtc, struct drm_display_
radeon_crtc->bpc = 8;
radeon_crtc->ss_enabled = false;
 
-   if (radeon_encoder->is_mst_encoder) {
-   radeon_dp_mst_prepare_pll(crtc, mode);
-   } else if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | 
ATOM_DEVICE_DFP_SUPPORT)) ||
+   if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | 
ATOM_DEVICE_DFP_SUPPORT)) ||
(radeon_encoder_get_dp_bridge_encoder_id(radeon_crtc->encoder) != 
ENCODER_OBJECT_ID_NONE)) {
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
struct drm_connector *connector =
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c 
b/drivers/gpu/drm/radeon/atombios_encoders.c
index c93040e60d04..0eae05dfb385 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -667,15 +667,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
 

[RFC v2 13/18] drm/display/dp_mst: Add helpers for serializing SST <-> MST transitions

2022-08-08 Thread Lyude Paul
There's another kind of situation where we could potentially race with
nonblocking modesets and MST, especially if we were to only use the locking
provided by atomic modesetting:

* Display 1 begins as enabled on DP-1 in SST mode
* Display 1 switches to MST mode, exposes one sink in MST mode
* Userspace does non-blocking modeset to disable the SST display
* Userspace does non-blocking modeset to enable the MST display with a
  different CRTC, but the SST display hasn't been fully taken down yet
* Execution order between the last two commits isn't guaranteed since they
  share no drm resources

We can fix this however, by ensuring that we always pull in the atomic
topology state whenever a connector capable of driving an MST display
performs its atomic check - and then tracking CRTC commits happening on the
SST connector in the MST topology state. So, let's add some simple helpers
for doing that and hook them up in various drivers.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
Acked-by: Jani Nikula 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  7 +++
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 59 +++
 drivers/gpu/drm/i915/display/intel_dp.c   |  9 +++
 drivers/gpu/drm/nouveau/dispnv50/disp.c   |  2 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.h   |  2 +
 drivers/gpu/drm/nouveau/nouveau_connector.c   | 14 +
 include/drm/display/drm_dp_mst_helper.h   |  2 +
 7 files changed, 94 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 1739710003a4..51732bd603a9 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6318,10 +6318,17 @@ amdgpu_dm_connector_atomic_check(struct drm_connector 
*conn,
drm_atomic_get_old_connector_state(state, conn);
struct drm_crtc *crtc = new_con_state->crtc;
struct drm_crtc_state *new_crtc_state;
+   struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(conn);
int ret;
 
trace_amdgpu_dm_connector_atomic_check(new_con_state);
 
+   if (conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
+   ret = drm_dp_mst_root_conn_atomic_check(new_con_state, 
>mst_mgr);
+   if (ret < 0)
+   return ret;
+   }
+
if (!crtc)
return 0;
 
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 2f7c43f88d74..97e8f8a83ed4 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4597,6 +4597,65 @@ void drm_dp_mst_atomic_wait_for_dependencies(struct 
drm_atomic_state *state)
 }
 EXPORT_SYMBOL(drm_dp_mst_atomic_wait_for_dependencies);
 
+/**
+ * drm_dp_mst_root_conn_atomic_check() - Serialize CRTC commits on MST-capable 
connectors operating
+ * in SST mode
+ * @new_conn_state: The new connector state of the _connector
+ * @mgr: The MST topology manager for the _connector
+ *
+ * Since MST uses fake _encoder structs, the generic atomic modesetting 
code isn't able to
+ * serialize non-blocking commits happening on the real DP connector of an MST 
topology switching
+ * into/away from MST mode - as the CRTC on the real DP connector and the 
CRTCs on the connector's
+ * MST topology will never share the same _encoder.
+ *
+ * This function takes care of this serialization issue, by checking a root 
MST connector's atomic
+ * state to determine if it is about to have a modeset - and then pulling in 
the MST topology state
+ * if so, along with adding any relevant CRTCs to 
_dp_mst_topology_state.pending_crtc_mask.
+ *
+ * Drivers implementing MST must call this function from the
+ * _connector_helper_funcs.atomic_check hook of any physical DP 
_connector capable of
+ * driving MST sinks.
+ *
+ * Returns:
+ * 0 on success, negative error code otherwise
+ */
+int drm_dp_mst_root_conn_atomic_check(struct drm_connector_state 
*new_conn_state,
+ struct drm_dp_mst_topology_mgr *mgr)
+{
+   struct drm_atomic_state *state = new_conn_state->state;
+   struct drm_connector_state *old_conn_state =
+   drm_atomic_get_old_connector_state(state, 
new_conn_state->connector);
+   struct drm_crtc_state *crtc_state;
+   struct drm_dp_mst_topology_state *mst_state = NULL;
+
+   if (new_conn_state->crtc) {
+   crtc_state = drm_atomic_get_new_crtc_state(state, 
new_conn_state->crtc);
+   if (crtc_state && drm_atomic_crtc_needs_modeset(crtc_state)) {
+   mst_state = drm_atomic_get_mst_topology_state(state, 
mgr);
+   if (IS_ERR(mst_state))
+   return PTR_ERR(mst_state);
+
+   

[RFC v2 14/18] drm/display/dp_mst: Drop all ports from topology on CSNs before queueing link address work

2022-08-08 Thread Lyude Paul
We want to start cutting down on all of the places that we use port
validation, so that ports may be removed from the topology as quickly as
possible to minimize the number of errors we run into as a result of being
out of sync with the current topology status. This isn't a very typical
scenario and I don't think I've ever even run into it - but since the next
commit is going to make some changes to payload updates depending on their
hotplug status I think it's a probably good idea to take precautions.

Let's do this with CSNs by moving some code around so that we only queue
link address probing work at the end of handling all CSNs - allowing us to
make sure we drop as many topology references as we can beforehand.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
Acked-by: Jani Nikula 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 97e8f8a83ed4..a5460cadf2c8 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -2509,7 +2509,7 @@ drm_dp_mst_handle_link_address_port(struct 
drm_dp_mst_branch *mstb,
return ret;
 }
 
-static void
+static int
 drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb,
struct drm_dp_connection_status_notify *conn_stat)
 {
@@ -2522,7 +2522,7 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch 
*mstb,
 
port = drm_dp_get_port(mstb, conn_stat->port_number);
if (!port)
-   return;
+   return 0;
 
if (port->connector) {
if (!port->input && conn_stat->input_port) {
@@ -2575,8 +2575,7 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch 
*mstb,
 
 out:
drm_dp_mst_topology_put_port(port);
-   if (dowork)
-   queue_work(system_long_wq, >mgr->work);
+   return dowork;
 }
 
 static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct 
drm_dp_mst_topology_mgr *mgr,
@@ -4060,7 +4059,7 @@ drm_dp_mst_process_up_req(struct drm_dp_mst_topology_mgr 
*mgr,
struct drm_dp_mst_branch *mstb = NULL;
struct drm_dp_sideband_msg_req_body *msg = _req->msg;
struct drm_dp_sideband_msg_hdr *hdr = _req->hdr;
-   bool hotplug = false;
+   bool hotplug = false, dowork = false;
 
if (hdr->broadcast) {
const u8 *guid = NULL;
@@ -4083,11 +4082,14 @@ drm_dp_mst_process_up_req(struct 
drm_dp_mst_topology_mgr *mgr,
 
/* TODO: Add missing handler for DP_RESOURCE_STATUS_NOTIFY events */
if (msg->req_type == DP_CONNECTION_STATUS_NOTIFY) {
-   drm_dp_mst_handle_conn_stat(mstb, >u.conn_stat);
+   dowork = drm_dp_mst_handle_conn_stat(mstb, >u.conn_stat);
hotplug = true;
}
 
drm_dp_mst_topology_put_mstb(mstb);
+
+   if (dowork)
+   queue_work(system_long_wq, >work);
return hotplug;
 }
 
-- 
2.37.1



[RFC v2 15/18] drm/display/dp_mst: Skip releasing payloads if last connected port isn't connected

2022-08-08 Thread Lyude Paul
In the past, we've ran into strange issues regarding errors in response to
trying to destroy payloads after a port has been unplugged. We fixed this
back in:

This is intended to replace the workaround that was added here:

commit 3769e4c0af5b ("drm/dp_mst: Avoid to mess up payload table by ports in 
stale topology")

which was intended fix to some of the payload leaks that were observed
before, where we would attempt to determine if the port was still connected
to the topology before updating payloads using
drm_dp_mst_port_downstream_of_branch. This wasn't a particularly good
solution, since one of the points of still having port and mstb validation
is to avoid sending messages to newly disconnected branches wherever
possible - thus the required use of drm_dp_mst_port_downstream_of_branch
would indicate something may be wrong with said validation.

It seems like it may have just been races and luck that made
drm_dp_mst_port_downstream_of_branch work however, as while I was trying to
figure out the true cause of this issue when removing the legacy MST code -
I discovered an important excerpt in section 2.14.2.3.3.6 of the DP 2.0
specs:

"BAD_PARAM - This reply is transmitted when a Message Transaction parameter
is in error; for example, the next port number is invalid or /no device is
connected/ to the port associated with the port number."

Sure enough - removing the calls to drm_dp_mst_port_downstream_of_branch()
and instead checking the ->ddps field of the parent port to see whether we
should release a given payload or not seems to totally fix the issue. This
does actually make sense to me, as it seems the implication is that given a
topology where an MSTB is removed, the payload for the MST parent's port
will be released automatically if that port is also marked as disconnected.
However, if there's another parent in the chain after that which is
connected - payloads must be released there with an ALLOCATE_PAYLOAD
message.

So, let's do that!

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
Acked-by: Jani Nikula 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 51 +++
 1 file changed, 17 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index a5460cadf2c8..e9cf09a4b2a4 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -3128,7 +3128,7 @@ static struct drm_dp_mst_port 
*drm_dp_get_last_connected_port_to_mstb(struct drm
 static struct drm_dp_mst_branch *
 drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_branch *mstb,
-   int *port_num)
+   struct drm_dp_mst_port **last_port)
 {
struct drm_dp_mst_branch *rmstb = NULL;
struct drm_dp_mst_port *found_port;
@@ -3144,7 +3144,8 @@ drm_dp_get_last_connected_port_and_mstb(struct 
drm_dp_mst_topology_mgr *mgr,
 
if (drm_dp_mst_topology_try_get_mstb(found_port->parent)) {
rmstb = found_port->parent;
-   *port_num = found_port->port_num;
+   *last_port = found_port;
+   drm_dp_mst_get_port_malloc(found_port);
} else {
/* Search again, starting from this parent */
mstb = found_port->parent;
@@ -3161,7 +3162,7 @@ static int drm_dp_payload_send_msg(struct 
drm_dp_mst_topology_mgr *mgr,
   int pbn)
 {
struct drm_dp_sideband_msg_tx *txmsg;
-   struct drm_dp_mst_branch *mstb;
+   struct drm_dp_mst_branch *mstb = NULL;
int ret, port_num;
u8 sinks[DRM_DP_MAX_SDP_STREAMS];
int i;
@@ -3169,12 +3170,22 @@ static int drm_dp_payload_send_msg(struct 
drm_dp_mst_topology_mgr *mgr,
port_num = port->port_num;
mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent);
if (!mstb) {
-   mstb = drm_dp_get_last_connected_port_and_mstb(mgr,
-  port->parent,
-  _num);
+   struct drm_dp_mst_port *rport = NULL;
+   bool ddps;
 
+   mstb = drm_dp_get_last_connected_port_and_mstb(mgr, 
port->parent, );
if (!mstb)
return -EINVAL;
+
+   ddps = rport->ddps;
+   port_num = rport->port_num;
+   drm_dp_mst_put_port_malloc(rport);
+
+   /* If the port is currently marked as disconnected, don't send 
a payload message */
+   if (!ddps) {
+   ret = -EINVAL;
+   goto fail_put;
+   }
}
 

[RFC v2 12/18] drm/nouveau/kms: Pull mst state in for all modesets

2022-08-08 Thread Lyude Paul
Since we're going to be relying on atomic locking for payloads now (and the
MST mgr needs to track CRTCs), pull in the topology state for all modesets
in nv50_msto_atomic_check().

Signed-off-by: Lyude Paul 
Acked-by: Jani Nikula 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 5669c8d747d7..24807aa9da5f 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -1049,7 +1049,7 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
if (ret)
return ret;
 
-   if (!crtc_state->mode_changed && !crtc_state->connectors_changed)
+   if (!drm_atomic_crtc_needs_modeset(crtc_state))
return 0;
 
/*
-- 
2.37.1



[RFC v2 11/18] drm/nouveau/kms: Cache DP encoders in nouveau_connector

2022-08-08 Thread Lyude Paul
Post-NV50, the only kind of encoder you'll find for DP connectors on Nvidia
GPUs are SORs (serial output resources). Because SORs have fixed
associations with their connectors, we can correctly assume that any DP
connector on a nvidia GPU will have exactly one SOR encoder routed to it
for DisplayPort.

Since we're going to need to be able to retrieve this fixed SOR DP encoder
much more often as a result of hooking up MST helpers for tracking
SST<->MST transitions in atomic states, let's simply cache this encoder in
nouveau_connector for any DP connectors on the system to avoid looking it
up each time. This isn't safe for NV50 since PIORs then come into play,
however there's no code pre-NV50 that would need to look this up anyhow -
so it's not really an issue.

Signed-off-by: Lyude Paul 
Acked-by: Jani Nikula 
---
 drivers/gpu/drm/nouveau/nouveau_connector.c | 4 +++-
 drivers/gpu/drm/nouveau/nouveau_connector.h | 3 +++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c 
b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 43a9d1e1cf71..bdaec3427f14 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -1367,7 +1367,7 @@ nouveau_connector_create(struct drm_device *dev,
return ERR_PTR(-ENOMEM);
}
drm_dp_aux_init(_connector->aux);
-   fallthrough;
+   break;
default:
funcs = _connector_funcs;
break;
@@ -1430,6 +1430,8 @@ nouveau_connector_create(struct drm_device *dev,
 
switch (type) {
case DRM_MODE_CONNECTOR_DisplayPort:
+   nv_connector->dp_encoder = find_encoder(_connector->base, 
DCB_OUTPUT_DP);
+   fallthrough;
case DRM_MODE_CONNECTOR_eDP:
drm_dp_cec_register_connector(_connector->aux, connector);
break;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h 
b/drivers/gpu/drm/nouveau/nouveau_connector.h
index 4bf0c703eee7..f4e17ff68bf9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -128,6 +128,9 @@ struct nouveau_connector {
 
struct drm_dp_aux aux;
 
+   /* The fixed DP encoder for this connector, if there is one */
+   struct nouveau_encoder *dp_encoder;
+
int dithering_mode;
int scaling_mode;
 
-- 
2.37.1



[RFC v2 10/18] drm/display/dp_mst: Fix modeset tracking in drm_dp_atomic_release_vcpi_slots()

2022-08-08 Thread Lyude Paul
Currently with the MST helpers we avoid releasing payloads _and_ avoid
pulling in the MST state if there aren't any actual payload changes. While
we want to keep the first step, we need to now make sure that we're always
pulling in the MST state on all modesets that can modify payloads - even if
the resulting payloads in the atomic state are identical to the previous
ones.

This is mainly to make it so that if a CRTC is still assigned to a
connector but is set to DPMS off, the CRTC still holds it's payload
allocation in the atomic state and still appropriately pulls in the MST
state for commit tracking. Otherwise, we'll occasionally forget to update
MST payloads from changes caused by non-atomic DPMS changes. Doing this
also allows us to track bandwidth limitations in a state correctly even
between DPMS changes, so that there's no chance of a simple ->active change
being rejected by the atomic check.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
Acked-by: Jani Nikula 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index aa6dcd9ff6a5..2f7c43f88d74 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4474,6 +4474,7 @@ int drm_dp_atomic_release_time_slots(struct 
drm_atomic_state *state,
struct drm_dp_mst_topology_state *topology_state;
struct drm_dp_mst_atomic_payload *payload;
struct drm_connector_state *old_conn_state, *new_conn_state;
+   bool update_payload = true;
 
old_conn_state = drm_atomic_get_old_connector_state(state, 
port->connector);
if (!old_conn_state->crtc)
@@ -4485,10 +4486,12 @@ int drm_dp_atomic_release_time_slots(struct 
drm_atomic_state *state,
struct drm_crtc_state *crtc_state =
drm_atomic_get_new_crtc_state(state, 
new_conn_state->crtc);
 
-   if (!crtc_state ||
-   !drm_atomic_crtc_needs_modeset(crtc_state) ||
-   crtc_state->enable)
+   /* No modeset means no payload changes, so it's safe to not 
pull in the MST state */
+   if (!crtc_state || !drm_atomic_crtc_needs_modeset(crtc_state))
return 0;
+
+   if (!crtc_state->mode_changed && 
!crtc_state->connectors_changed)
+   update_payload = false;
}
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
@@ -4496,6 +4499,8 @@ int drm_dp_atomic_release_time_slots(struct 
drm_atomic_state *state,
return PTR_ERR(topology_state);
 
topology_state->pending_crtc_mask |= 
drm_crtc_mask(old_conn_state->crtc);
+   if (!update_payload)
+   return 0;
 
payload = drm_atomic_get_mst_payload_state(topology_state, port);
if (WARN_ON(!payload)) {
-- 
2.37.1



[RFC v2 09/18] drm/display/dp_mst: Don't open code modeset checks for releasing time slots

2022-08-08 Thread Lyude Paul
I'm not sure why, but at the time I originally wrote the find/release time
slot helpers I thought we should avoid keeping modeset tracking out of the
MST helpers. In retrospect though there's no actual good reason to do
this, and the logic has ended up being identical across all the drivers
using the helpers. Also, it needs to be fixed anyway so we don't break
things when going atomic-only with MST.

So, let's just move this code into drm_dp_atomic_release_time_slots() and
stop open coding it.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
Acked-by: Jani Nikula 
---
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 29 +++
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 21 --
 drivers/gpu/drm/i915/display/intel_dp_mst.c   | 24 +--
 drivers/gpu/drm/nouveau/dispnv50/disp.c   | 21 --
 4 files changed, 23 insertions(+), 72 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 655d63b20b33..7a0d6cfa77f5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -447,34 +447,13 @@ dm_dp_mst_detect(struct drm_connector *connector,
 }
 
 static int dm_dp_mst_atomic_check(struct drm_connector *connector,
-   struct drm_atomic_state *state)
+ struct drm_atomic_state *state)
 {
-   struct drm_connector_state *new_conn_state =
-   drm_atomic_get_new_connector_state(state, connector);
-   struct drm_connector_state *old_conn_state =
-   drm_atomic_get_old_connector_state(state, connector);
struct amdgpu_dm_connector *aconnector = 
to_amdgpu_dm_connector(connector);
-   struct drm_crtc_state *new_crtc_state;
-   struct drm_dp_mst_topology_mgr *mst_mgr;
-   struct drm_dp_mst_port *mst_port;
+   struct drm_dp_mst_topology_mgr *mst_mgr = 
>mst_port->mst_mgr;
+   struct drm_dp_mst_port *mst_port = aconnector->port;
 
-   mst_port = aconnector->port;
-   mst_mgr = >mst_port->mst_mgr;
-
-   if (!old_conn_state->crtc)
-   return 0;
-
-   if (new_conn_state->crtc) {
-   new_crtc_state = drm_atomic_get_new_crtc_state(state, 
new_conn_state->crtc);
-   if (!new_crtc_state ||
-   !drm_atomic_crtc_needs_modeset(new_crtc_state) ||
-   new_crtc_state->enable)
-   return 0;
-   }
-
-   return drm_dp_atomic_release_time_slots(state,
-   mst_mgr,
-   mst_port);
+   return drm_dp_atomic_release_time_slots(state, mst_mgr, mst_port);
 }
 
 static const struct drm_connector_helper_funcs 
dm_dp_mst_connector_helper_funcs = {
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index d701e5b819b8..aa6dcd9ff6a5 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4473,14 +4473,29 @@ int drm_dp_atomic_release_time_slots(struct 
drm_atomic_state *state,
 {
struct drm_dp_mst_topology_state *topology_state;
struct drm_dp_mst_atomic_payload *payload;
-   struct drm_connector_state *conn_state;
+   struct drm_connector_state *old_conn_state, *new_conn_state;
+
+   old_conn_state = drm_atomic_get_old_connector_state(state, 
port->connector);
+   if (!old_conn_state->crtc)
+   return 0;
+
+   /* If the CRTC isn't disabled by this state, don't release it's payload 
*/
+   new_conn_state = drm_atomic_get_new_connector_state(state, 
port->connector);
+   if (new_conn_state->crtc) {
+   struct drm_crtc_state *crtc_state =
+   drm_atomic_get_new_crtc_state(state, 
new_conn_state->crtc);
+
+   if (!crtc_state ||
+   !drm_atomic_crtc_needs_modeset(crtc_state) ||
+   crtc_state->enable)
+   return 0;
+   }
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(topology_state))
return PTR_ERR(topology_state);
 
-   conn_state = drm_atomic_get_old_connector_state(state, port->connector);
-   topology_state->pending_crtc_mask |= drm_crtc_mask(conn_state->crtc);
+   topology_state->pending_crtc_mask |= 
drm_crtc_mask(old_conn_state->crtc);
 
payload = drm_atomic_get_mst_payload_state(topology_state, port);
if (WARN_ON(!payload)) {
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 1cebbc51d8fa..1b067cd73261 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ 

[RFC v2 08/18] drm/display/dp_mst: Add nonblocking helpers for DP MST

2022-08-08 Thread Lyude Paul
As Daniel Vetter pointed out, if we only use the atomic modesetting locks
with MST it's technically possible for a driver with non-blocking modesets
to race when it comes to MST displays - as we make the mistake of not doing
our own CRTC commit tracking in the topology_state object.

This could potentially cause problems if something like this happens:

* User starts non-blocking commit to disable CRTC-1 on MST topology 1
* User starts non-blocking commit to enable CRTC-2 on MST topology 1

There's no guarantee here that the commit for disabling CRTC-2 will only
occur after CRTC-1 has finished, since neither commit shares a CRTC - only
the private modesetting object for MST. Keep in mind this likely isn't a
problem for blocking modesets, only non-blocking.

So, begin fixing this by keeping track of which CRTCs on a topology have
changed by keeping track of which CRTCs we release or allocate timeslots
on. As well, add some helpers for:

* Setting up the drm_crtc_commit structs in the ->commit_setup hook
* Waiting for any CRTC dependencies from the previous topology state

v2:
* Use drm_dp_mst_atomic_setup_commit() directly - Jani

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
Acked-by: Jani Nikula 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  5 +-
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 93 +++
 drivers/gpu/drm/i915/display/intel_display.c  |  6 ++
 drivers/gpu/drm/nouveau/dispnv50/disp.c   |  7 ++
 include/drm/display/drm_dp_mst_helper.h   | 15 +++
 5 files changed, 124 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 34f0d2f056bb..1739710003a4 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -2808,7 +2808,8 @@ static const struct drm_mode_config_funcs 
amdgpu_dm_mode_funcs = {
 };
 
 static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = 
{
-   .atomic_commit_tail = amdgpu_dm_atomic_commit_tail
+   .atomic_commit_tail = amdgpu_dm_atomic_commit_tail,
+   .atomic_commit_setup = drm_dp_mst_atomic_setup_commit,
 };
 
 static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
@@ -7986,6 +7987,7 @@ static void amdgpu_dm_atomic_commit_tail(struct 
drm_atomic_state *state)
DRM_ERROR("Waiting for fences timed out!");
 
drm_atomic_helper_update_legacy_modeset_state(dev, state);
+   drm_dp_mst_atomic_wait_for_dependencies(state);
 
dm_state = dm_atomic_get_new_state(state);
if (dm_state && dm_state->context) {
@@ -8384,7 +8386,6 @@ static void amdgpu_dm_atomic_commit_tail(struct 
drm_atomic_state *state)
dc_release_state(dc_state_temp);
 }
 
-
 static int dm_force_atomic_commit(struct drm_connector *connector)
 {
int ret = 0;
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 1c054a5e2e77..d701e5b819b8 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4384,12 +4384,16 @@ int drm_dp_atomic_find_time_slots(struct 
drm_atomic_state *state,
 {
struct drm_dp_mst_topology_state *topology_state;
struct drm_dp_mst_atomic_payload *payload = NULL;
+   struct drm_connector_state *conn_state;
int prev_slots = 0, prev_bw = 0, req_slots;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(topology_state))
return PTR_ERR(topology_state);
 
+   conn_state = drm_atomic_get_new_connector_state(state, port->connector);
+   topology_state->pending_crtc_mask |= drm_crtc_mask(conn_state->crtc);
+
/* Find the current allocation for this port, if any */
payload = drm_atomic_get_mst_payload_state(topology_state, port);
if (payload) {
@@ -4469,11 +4473,15 @@ int drm_dp_atomic_release_time_slots(struct 
drm_atomic_state *state,
 {
struct drm_dp_mst_topology_state *topology_state;
struct drm_dp_mst_atomic_payload *payload;
+   struct drm_connector_state *conn_state;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(topology_state))
return PTR_ERR(topology_state);
 
+   conn_state = drm_atomic_get_old_connector_state(state, port->connector);
+   topology_state->pending_crtc_mask |= drm_crtc_mask(conn_state->crtc);
+
payload = drm_atomic_get_mst_payload_state(topology_state, port);
if (WARN_ON(!payload)) {
drm_err(mgr->dev, "No payload for [MST PORT:%p] found in mst 
state %p\n",
@@ -4492,6 +4500,83 @@ int drm_dp_atomic_release_time_slots(struct 
drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_dp_atomic_release_time_slots);
 
+/**
+ * 

[RFC v2 07/18] drm/display/dp_mst: Add helper for finding payloads in atomic MST state

2022-08-08 Thread Lyude Paul
We already open-code this quite often, and will be iterating through
payloads even more once we've moved all of the payload tracking into the
atomic state. So, let's add a helper for doing this.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
Acked-by: Jani Nikula 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 109 --
 1 file changed, 45 insertions(+), 64 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 8a2ddfde594a..1c054a5e2e77 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -1738,6 +1738,19 @@ drm_dp_mst_dump_port_topology_history(struct 
drm_dp_mst_port *port) {}
 #define save_port_topology_ref(port, type)
 #endif
 
+static struct drm_dp_mst_atomic_payload *
+drm_atomic_get_mst_payload_state(struct drm_dp_mst_topology_state *state,
+struct drm_dp_mst_port *port)
+{
+   struct drm_dp_mst_atomic_payload *payload;
+
+   list_for_each_entry(payload, >payloads, next)
+   if (payload->port == port)
+   return payload;
+
+   return NULL;
+}
+
 static void drm_dp_destroy_mst_branch_device(struct kref *kref)
 {
struct drm_dp_mst_branch *mstb =
@@ -4370,39 +4383,31 @@ int drm_dp_atomic_find_time_slots(struct 
drm_atomic_state *state,
  int pbn_div)
 {
struct drm_dp_mst_topology_state *topology_state;
-   struct drm_dp_mst_atomic_payload *pos, *payload = NULL;
-   int prev_slots, prev_bw, req_slots;
+   struct drm_dp_mst_atomic_payload *payload = NULL;
+   int prev_slots = 0, prev_bw = 0, req_slots;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(topology_state))
return PTR_ERR(topology_state);
 
/* Find the current allocation for this port, if any */
-   list_for_each_entry(pos, _state->payloads, next) {
-   if (pos->port == port) {
-   payload = pos;
-   prev_slots = payload->time_slots;
-   prev_bw = payload->pbn;
-
-   /*
-* This should never happen, unless the driver tries
-* releasing and allocating the same timeslot 
allocation,
-* which is an error
-*/
-   if (WARN_ON(!prev_slots)) {
-   drm_err(mgr->dev,
-   "cannot allocate and release time slots 
on [MST PORT:%p] in the same state\n",
-   port);
-   return -EINVAL;
-   }
+   payload = drm_atomic_get_mst_payload_state(topology_state, port);
+   if (payload) {
+   prev_slots = payload->time_slots;
+   prev_bw = payload->pbn;
 
-   break;
+   /*
+* This should never happen, unless the driver tries
+* releasing and allocating the same timeslot allocation,
+* which is an error
+*/
+   if (WARN_ON(!prev_slots)) {
+   drm_err(mgr->dev,
+   "cannot allocate and release time slots on [MST 
PORT:%p] in the same state\n",
+   port);
+   return -EINVAL;
}
}
-   if (!payload) {
-   prev_slots = 0;
-   prev_bw = 0;
-   }
 
if (pbn_div <= 0)
pbn_div = mgr->pbn_div;
@@ -4463,30 +4468,24 @@ int drm_dp_atomic_release_time_slots(struct 
drm_atomic_state *state,
 struct drm_dp_mst_port *port)
 {
struct drm_dp_mst_topology_state *topology_state;
-   struct drm_dp_mst_atomic_payload *pos;
-   bool found = false;
+   struct drm_dp_mst_atomic_payload *payload;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(topology_state))
return PTR_ERR(topology_state);
 
-   list_for_each_entry(pos, _state->payloads, next) {
-   if (pos->port == port) {
-   found = true;
-   break;
-   }
-   }
-   if (WARN_ON(!found)) {
+   payload = drm_atomic_get_mst_payload_state(topology_state, port);
+   if (WARN_ON(!payload)) {
drm_err(mgr->dev, "No payload for [MST PORT:%p] found in mst 
state %p\n",
port, _state->base);
return -EINVAL;
}
 
-   drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, 
pos->time_slots);
-   if (pos->time_slots) {
+   drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d 

[RFC v2 05/18] drm/display/dp_mst: Fix confusing docs for drm_dp_atomic_release_time_slots()

2022-08-08 Thread Lyude Paul
For some reason we mention returning 0 if "slots have been added back to
drm_dp_mst_topology_state->avail_slots". This is totally misleading,
avail_slots is simply for figuring out the total number of slots available
in total on the topology and has no relation to the current payload
allocations.

So, let's get rid of that comment.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
Acked-by: Jani Nikula 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index fad80ab2b9db..8a2ddfde594a 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4456,8 +4456,7 @@ EXPORT_SYMBOL(drm_dp_atomic_find_time_slots);
  * drm_dp_mst_atomic_check()
  *
  * Returns:
- * 0 if all slots for this port were added back to
- * _dp_mst_topology_state.avail_slots or negative error code
+ * 0 on success, negative error code otherwise
  */
 int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state,
 struct drm_dp_mst_topology_mgr *mgr,
-- 
2.37.1



[RFC v2 04/18] drm/display/dp_mst: Call them time slots, not VCPI slots

2022-08-08 Thread Lyude Paul
VCPI is only sort of the correct term here, originally the majority of this
code simply referred to timeslots vaguely as "slots" - and since I started
working on it and adding atomic functionality, the name "VCPI slots" has
been used to represent time slots.

Now that we actually have consistent access to the DisplayPort spec thanks
to VESA, I now know this isn't actually the proper term - as the
specification refers to these as time slots.

Since we're trying to make this code as easy to figure out as possible,
let's take this opportunity to correct this nomenclature and call them by
their proper name - timeslots. Likewise, we rename various functions
appropriately, along with replacing references in the kernel documentation
and various debugging messages.

It's important to note that this patch series leaves the legacy MST code
untouched for the most part, which is fine since we'll be removing it soon
anyhow. There should be no functional changes in this series.

v2:
* Add note that Wayne Lin from AMD suggested regarding slots being between
  the source DP Tx and the immediate downstream DP Rx

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
Acked-by: Jani Nikula 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   2 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |  28 ++---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 106 +-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |   5 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c   |   4 +-
 include/drm/display/drm_dp_mst_helper.h   |  12 +-
 6 files changed, 81 insertions(+), 76 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 8a3e25d35099..34f0d2f056bb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6428,7 +6428,7 @@ static int dm_encoder_helper_atomic_check(struct 
drm_encoder *encoder,
clock = adjusted_mode->clock;
dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp, 
false);
}
-   dm_new_connector_state->vcpi_slots = 
drm_dp_atomic_find_vcpi_slots(state,
+   dm_new_connector_state->vcpi_slots = 
drm_dp_atomic_find_time_slots(state,
   
mst_mgr,
   
mst_port,
   
dm_new_connector_state->pbn,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 2e74ccf7df5b..655d63b20b33 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -472,7 +472,7 @@ static int dm_dp_mst_atomic_check(struct drm_connector 
*connector,
return 0;
}
 
-   return drm_dp_atomic_release_vcpi_slots(state,
+   return drm_dp_atomic_release_time_slots(state,
mst_mgr,
mst_port);
 }
@@ -785,7 +785,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
 
if (initial_slack[next_index] > fair_pbn_alloc) {
vars[next_index].pbn += fair_pbn_alloc;
-   if (drm_dp_atomic_find_vcpi_slots(state,
+   if (drm_dp_atomic_find_time_slots(state,
  
params[next_index].port->mgr,
  
params[next_index].port,
  vars[next_index].pbn,
@@ -795,7 +795,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
vars[next_index].bpp_x16 = 
bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
} else {
vars[next_index].pbn -= fair_pbn_alloc;
-   if (drm_dp_atomic_find_vcpi_slots(state,
+   if (drm_dp_atomic_find_time_slots(state,
  
params[next_index].port->mgr,
  
params[next_index].port,
  
vars[next_index].pbn,
@@ -804,7 +804,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
}
} else {
vars[next_index].pbn += initial_slack[next_index];
-   if (drm_dp_atomic_find_vcpi_slots(state,
+   if (drm_dp_atomic_find_time_slots(state,

[RFC v2 06/18] drm/display/dp_mst: Add some missing kdocs for atomic MST structs

2022-08-08 Thread Lyude Paul
Since we're about to start adding some stuff here, we may as well fill in
any missing documentation that we forgot to write.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
Acked-by: Jani Nikula 
---
 include/drm/display/drm_dp_mst_helper.h | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/include/drm/display/drm_dp_mst_helper.h 
b/include/drm/display/drm_dp_mst_helper.h
index 9cdd2def56a1..3b155ad3eee4 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -542,7 +542,14 @@ struct drm_dp_payload {
 
 #define to_dp_mst_topology_state(x) container_of(x, struct 
drm_dp_mst_topology_state, base)
 
+/**
+ * struct drm_dp_mst_atomic_payload - Atomic state struct for an MST payload
+ *
+ * The primary atomic state structure for a given MST payload. Stores 
information like current
+ * bandwidth allocation, intended action for this payload, etc.
+ */
 struct drm_dp_mst_atomic_payload {
+   /** @port: The MST port assigned to this payload */
struct drm_dp_mst_port *port;
 
/**
@@ -551,16 +558,32 @@ struct drm_dp_mst_atomic_payload {
 * the immediate downstream DP Rx
 */
int time_slots;
+   /** @pbn: The payload bandwidth for this payload */
int pbn;
+   /** @dsc_enabled: Whether or not this payload has DSC enabled */
bool dsc_enabled;
+
+   /** @next: The list node for this payload */
struct list_head next;
 };
 
+/**
+ * struct drm_dp_mst_topology_state - DisplayPort MST topology atomic state
+ *
+ * This struct represents the atomic state of the toplevel DisplayPort MST 
manager
+ */
 struct drm_dp_mst_topology_state {
+   /** @base: Base private state for atomic */
struct drm_private_state base;
+
+   /** @payloads: The list of payloads being created/destroyed in this 
state */
struct list_head payloads;
+   /** @mgr: The topology manager */
struct drm_dp_mst_topology_mgr *mgr;
+
+   /** @total_avail_slots: The total number of slots this topology can 
handle (63 or 64) */
u8 total_avail_slots;
+   /** @start_slot: The first usable time slot in this topology (1 or 0) */
u8 start_slot;
 };
 
-- 
2.37.1



[RFC v2 03/18] drm/display/dp_mst: Rename drm_dp_mst_vcpi_allocation

2022-08-08 Thread Lyude Paul
In retrospect, the name I chose for this originally is confusing, as
there's a lot more info in here then just the VCPI. This really should be
called a payload. Let's make it more obvious that this is meant to be
related to the atomic state and is about payloads by renaming it to
drm_dp_mst_atomic_payload. Also, rename various variables throughout the
code that use atomic payloads.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 
Acked-by: Jani Nikula 
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 96 +--
 include/drm/display/drm_dp_mst_helper.h   |  4 +-
 2 files changed, 50 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 7a94a5288e8d..f448e3e5ec6e 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4370,7 +4370,7 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state 
*state,
  int pbn_div)
 {
struct drm_dp_mst_topology_state *topology_state;
-   struct drm_dp_vcpi_allocation *pos, *vcpi = NULL;
+   struct drm_dp_mst_atomic_payload *pos, *payload = NULL;
int prev_slots, prev_bw, req_slots;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
@@ -4378,11 +4378,11 @@ int drm_dp_atomic_find_vcpi_slots(struct 
drm_atomic_state *state,
return PTR_ERR(topology_state);
 
/* Find the current allocation for this port, if any */
-   list_for_each_entry(pos, _state->vcpis, next) {
+   list_for_each_entry(pos, _state->payloads, next) {
if (pos->port == port) {
-   vcpi = pos;
-   prev_slots = vcpi->vcpi;
-   prev_bw = vcpi->pbn;
+   payload = pos;
+   prev_slots = payload->vcpi;
+   prev_bw = payload->pbn;
 
/*
 * This should never happen, unless the driver tries
@@ -4399,7 +4399,7 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state 
*state,
break;
}
}
-   if (!vcpi) {
+   if (!payload) {
prev_slots = 0;
prev_bw = 0;
}
@@ -4417,17 +4417,17 @@ int drm_dp_atomic_find_vcpi_slots(struct 
drm_atomic_state *state,
   port, prev_bw, pbn);
 
/* Add the new allocation to the state */
-   if (!vcpi) {
-   vcpi = kzalloc(sizeof(*vcpi), GFP_KERNEL);
-   if (!vcpi)
+   if (!payload) {
+   payload = kzalloc(sizeof(*payload), GFP_KERNEL);
+   if (!payload)
return -ENOMEM;
 
drm_dp_mst_get_port_malloc(port);
-   vcpi->port = port;
-   list_add(>next, _state->vcpis);
+   payload->port = port;
+   list_add(>next, _state->payloads);
}
-   vcpi->vcpi = req_slots;
-   vcpi->pbn = pbn;
+   payload->vcpi = req_slots;
+   payload->pbn = pbn;
 
return req_slots;
 }
@@ -4464,21 +4464,21 @@ int drm_dp_atomic_release_vcpi_slots(struct 
drm_atomic_state *state,
 struct drm_dp_mst_port *port)
 {
struct drm_dp_mst_topology_state *topology_state;
-   struct drm_dp_vcpi_allocation *pos;
+   struct drm_dp_mst_atomic_payload *pos;
bool found = false;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(topology_state))
return PTR_ERR(topology_state);
 
-   list_for_each_entry(pos, _state->vcpis, next) {
+   list_for_each_entry(pos, _state->payloads, next) {
if (pos->port == port) {
found = true;
break;
}
}
if (WARN_ON(!found)) {
-   drm_err(mgr->dev, "no VCPI for [MST PORT:%p] found in mst state 
%p\n",
+   drm_err(mgr->dev, "No payload for [MST PORT:%p] found in mst 
state %p\n",
port, _state->base);
return -EINVAL;
}
@@ -5060,7 +5060,7 @@ drm_dp_mst_duplicate_state(struct drm_private_obj *obj)
 {
struct drm_dp_mst_topology_state *state, *old_state =
to_dp_mst_topology_state(obj->state);
-   struct drm_dp_vcpi_allocation *pos, *vcpi;
+   struct drm_dp_mst_atomic_payload *pos, *payload;
 
state = kmemdup(old_state, sizeof(*state), GFP_KERNEL);
if (!state)
@@ -5068,25 +5068,25 @@ drm_dp_mst_duplicate_state(struct drm_private_obj *obj)
 
__drm_atomic_helper_private_obj_duplicate_state(obj, >base);
 
-   INIT_LIST_HEAD(>vcpis);
+   INIT_LIST_HEAD(>payloads);
 
-   list_for_each_entry(pos, _state->vcpis, next) {
+   

[RFC v2 02/18] drm/amdgpu/dm/mst: Rename get_payload_table()

2022-08-08 Thread Lyude Paul
This function isn't too confusing if you see the comment around the
call-site for it, but if you don't then it's not at all obvious this is
meant to copy DRM's payload table over to DC's internal state structs.
Seeing this function before finding that comment definitely threw me into a
loop a few times.

So, let's rename this to make it's purpose more obvious regardless of where
in the code you are.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Fangzhi Zuo 
Acked-by: Jani Nikula 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 3aa385860eea..77c545e670d5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -153,8 +153,9 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
return result;
 }
 
-static void get_payload_table(struct amdgpu_dm_connector *aconnector,
- struct dc_dp_mst_stream_allocation_table 
*proposed_table)
+static void
+fill_dc_mst_payload_table_from_drm(struct amdgpu_dm_connector *aconnector,
+  struct dc_dp_mst_stream_allocation_table 
*proposed_table)
 {
int i;
struct drm_dp_mst_topology_mgr *mst_mgr =
@@ -252,7 +253,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
 * stream. AMD ASIC stream slot allocation should follow the same
 * sequence. copy DRM MST allocation to dc */
 
-   get_payload_table(aconnector, proposed_table);
+   fill_dc_mst_payload_table_from_drm(aconnector, proposed_table);
 
return true;
 }
-- 
2.37.1



[RFC v2 01/18] drm/amdgpu/dc/mst: Rename dp_mst_stream_allocation(_table)

2022-08-08 Thread Lyude Paul
Just to make this more clear to outside contributors that these are
DC-specific structs, as this also threw me into a loop a number of times
before I figured out the purpose of this.

Signed-off-by: Lyude Paul 
Cc: Wayne Lin 
Cc: Fangzhi Zuo 
Acked-by: Jani Nikula 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  9 -
 drivers/gpu/drm/amd/display/dc/core/dc_link.c | 10 +-
 drivers/gpu/drm/amd/display/dc/dm_helpers.h   |  4 ++--
 .../gpu/drm/amd/display/include/link_service_types.h  | 11 ---
 4 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index a0154a5f7183..3aa385860eea 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -153,9 +153,8 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
return result;
 }
 
-static void get_payload_table(
-   struct amdgpu_dm_connector *aconnector,
-   struct dp_mst_stream_allocation_table *proposed_table)
+static void get_payload_table(struct amdgpu_dm_connector *aconnector,
+ struct dc_dp_mst_stream_allocation_table 
*proposed_table)
 {
int i;
struct drm_dp_mst_topology_mgr *mst_mgr =
@@ -177,7 +176,7 @@ static void get_payload_table(
mst_mgr->payloads[i].payload_state ==
DP_PAYLOAD_REMOTE) {
 
-   struct dp_mst_stream_allocation *sa =
+   struct dc_dp_mst_stream_allocation *sa =
_table->stream_allocations[
proposed_table->stream_count];
 
@@ -201,7 +200,7 @@ void dm_helpers_dp_update_branch_info(
 bool dm_helpers_dp_mst_write_payload_allocation_table(
struct dc_context *ctx,
const struct dc_stream_state *stream,
-   struct dp_mst_stream_allocation_table *proposed_table,
+   struct dc_dp_mst_stream_allocation_table *proposed_table,
bool enable)
 {
struct amdgpu_dm_connector *aconnector;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index 9e51338441d0..e01424fb02ba 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -3516,7 +3516,7 @@ static void update_mst_stream_alloc_table(
struct dc_link *link,
struct stream_encoder *stream_enc,
struct hpo_dp_stream_encoder *hpo_dp_stream_enc, // TODO: Rename 
stream_enc to dio_stream_enc?
-   const struct dp_mst_stream_allocation_table *proposed_table)
+   const struct dc_dp_mst_stream_allocation_table *proposed_table)
 {
struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = { 0 
};
struct link_mst_stream_allocation *dc_alloc;
@@ -3679,7 +3679,7 @@ enum dc_status dc_link_allocate_mst_payload(struct 
pipe_ctx *pipe_ctx)
 {
struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->link;
-   struct dp_mst_stream_allocation_table proposed_table = {0};
+   struct dc_dp_mst_stream_allocation_table proposed_table = {0};
struct fixed31_32 avg_time_slots_per_mtp;
struct fixed31_32 pbn;
struct fixed31_32 pbn_per_slot;
@@ -3784,7 +3784,7 @@ enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx 
*pipe_ctx, uint32_t bw
struct fixed31_32 avg_time_slots_per_mtp;
struct fixed31_32 pbn;
struct fixed31_32 pbn_per_slot;
-   struct dp_mst_stream_allocation_table proposed_table = {0};
+   struct dc_dp_mst_stream_allocation_table proposed_table = {0};
uint8_t i;
const struct link_hwss *link_hwss = get_link_hwss(link, 
_ctx->link_res);
DC_LOGGER_INIT(link->ctx->logger);
@@ -3873,7 +3873,7 @@ enum dc_status dc_link_increase_mst_payload(struct 
pipe_ctx *pipe_ctx, uint32_t
struct fixed31_32 avg_time_slots_per_mtp;
struct fixed31_32 pbn;
struct fixed31_32 pbn_per_slot;
-   struct dp_mst_stream_allocation_table proposed_table = {0};
+   struct dc_dp_mst_stream_allocation_table proposed_table = {0};
uint8_t i;
enum act_return_status ret;
const struct link_hwss *link_hwss = get_link_hwss(link, 
_ctx->link_res);
@@ -3957,7 +3957,7 @@ static enum dc_status deallocate_mst_payload(struct 
pipe_ctx *pipe_ctx)
 {
struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->link;
-   struct dp_mst_stream_allocation_table proposed_table = {0};
+   struct dc_dp_mst_stream_allocation_table proposed_table = {0};
struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0);
int i;
bool mst_mode = (link->type == 

[RFC v2 00/18] drm/display/dp_mst: Drop Radeon MST support, make MST atomic-only

2022-08-08 Thread Lyude Paul
For quite a while we've been carrying around a lot of legacy modesetting
code in the MST helpers that has been rather annoying to keep around,
and very often gets in the way of trying to implement additional
functionality in MST such as fallback link rate retraining, dynamic BPC
management and DSC support, etc. because of the fact that we can't rely
on atomic for everything.

Luckily, we only actually have one user of the legacy MST code in the
kernel - radeon. Originally I was thinking of trying to maintain this
code and keep it around in some form, but I'm pretty unconvinced anyone
is actually using this. My reasoning for that is because I've seen
nearly no issues regarding MST on radeon for quite a while now - despite
the fact my local testing seems to indicate it's quite broken. This
isn't too surprising either, as MST support in radeon.ko is gated behind
a module parameter that isn't enabled by default. This isn't to say I
wouldn't be open to alternative suggestions, but I'd rather not be the
one to have to spend time on that if at all possible! Plus, I already
floated the idea of dropping this code by AMD folks a few times and
didn't get much resistance.

As well, this series has some basic refactoring that I did along the way
and some bugs I had to fix in order to get my atomic-only MST code
working. Most of this is pretty straight forward and simply renaming
things to more closely match the DisplayPort specification, as I think
this will also make maintaining this code a lot easier in the long run
(I've gotten myself confused way too many times because of this).

So far I've tested this on all three MST drivers: amdgpu, i915 and
nouveau, along with making sure that removing the radeon MST code
doesn't break anything else. The one thing I very much could use help
with regarding testing though is making sure that this works with
amdgpu's DSC support on MST.

So, with this we should be using the atomic state as much as possible
with MST modesetting, hooray!

Cc: Wayne Lin 
Cc: Ville Syrjälä 
Cc: Fangzhi Zuo 
Cc: Jani Nikula 
Cc: Imre Deak 
Cc: Daniel Vetter 
Cc: Sean Paul 

Lyude Paul (18):
  drm/amdgpu/dc/mst: Rename dp_mst_stream_allocation(_table)
  drm/amdgpu/dm/mst: Rename get_payload_table()
  drm/display/dp_mst: Rename drm_dp_mst_vcpi_allocation
  drm/display/dp_mst: Call them time slots, not VCPI slots
  drm/display/dp_mst: Fix confusing docs for
drm_dp_atomic_release_time_slots()
  drm/display/dp_mst: Add some missing kdocs for atomic MST structs
  drm/display/dp_mst: Add helper for finding payloads in atomic MST
state
  drm/display/dp_mst: Add nonblocking helpers for DP MST
  drm/display/dp_mst: Don't open code modeset checks for releasing time
slots
  drm/display/dp_mst: Fix modeset tracking in
drm_dp_atomic_release_vcpi_slots()
  drm/nouveau/kms: Cache DP encoders in nouveau_connector
  drm/nouveau/kms: Pull mst state in for all modesets
  drm/display/dp_mst: Add helpers for serializing SST <-> MST
transitions
  drm/display/dp_mst: Drop all ports from topology on CSNs before
queueing link address work
  drm/display/dp_mst: Skip releasing payloads if last connected port
isn't connected
  drm/display/dp_mst: Maintain time slot allocations when deleting
payloads
  drm/radeon: Drop legacy MST support
  drm/display/dp_mst: Move all payload info into the atomic state

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   68 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  108 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |  125 +-
 drivers/gpu/drm/amd/display/dc/core/dc_link.c |   10 +-
 drivers/gpu/drm/amd/display/dc/dm_helpers.h   |4 +-
 .../amd/display/include/link_service_types.h  |   14 +-
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 1154 -
 drivers/gpu/drm/i915/display/intel_display.c  |6 +
 drivers/gpu/drm/i915/display/intel_dp.c   |9 +
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |   91 +-
 drivers/gpu/drm/i915/display/intel_hdcp.c |   24 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c   |  197 ++-
 drivers/gpu/drm/nouveau/dispnv50/disp.h   |2 +
 drivers/gpu/drm/nouveau/nouveau_connector.c   |   18 +-
 drivers/gpu/drm/nouveau/nouveau_connector.h   |3 +
 drivers/gpu/drm/radeon/Makefile   |2 +-
 drivers/gpu/drm/radeon/atombios_crtc.c|   11 +-
 drivers/gpu/drm/radeon/atombios_encoders.c|   59 -
 drivers/gpu/drm/radeon/radeon_atombios.c  |2 -
 drivers/gpu/drm/radeon/radeon_connectors.c|   61 +-
 drivers/gpu/drm/radeon/radeon_device.c|1 -
 drivers/gpu/drm/radeon/radeon_dp_mst.c|  778 ---
 drivers/gpu/drm/radeon/radeon_drv.c   |4 -
 drivers/gpu/drm/radeon/radeon_encoders.c  |   14 +-
 drivers/gpu/drm/radeon/radeon_irq_kms.c   |   10 +-
 drivers/gpu/drm/radeon/radeon_mode.h  |   40 -
 include/drm/display/drm_dp_mst_helper.h   |  234 ++--
 27 files changed, 964 insertions(+), 2085 deletions(-)
 delete mode 

Re: [Intel-gfx] [PATCH v3 1/3] drm/i915: pass a pointer for tlb seqno at vma_invalidate_tlb()

2022-08-08 Thread Andi Shyti
Hi Rodrigo,

On Mon, Aug 08, 2022 at 03:04:13PM -0400, Rodrigo Vivi wrote:
> On Mon, Aug 08, 2022 at 06:37:58PM +0200, Andi Shyti wrote:
> > Hi Mauro,
> > 
> > On Thu, Aug 04, 2022 at 09:37:22AM +0200, Mauro Carvalho Chehab wrote:
> > > WRITE_ONCE() should happen at the original var, not on a local
> > > copy of it.
> > > 
> > > Fixes: 5d36acb7198b ("drm/i915/gt: Batch TLB invalidations")
> > > Signed-off-by: Mauro Carvalho Chehab 
> > 
> > Reviewed-by: Andi Shyti 
> 
> Thanks and pushed...

Thanks!

> > 
> > Are you going to send it to the stable mailing list?
> 
> I added cc stable while pushing and the cherry-pick to drm-intel-next-fixes
> has the right sha, so I'd assume this would be automagically now.
> But yeap, it would be good if Mauro can follow up whenever this gets
> to Linus tree and Greg's script start to pop up the heads-up messages.

That's what I meant... does Mauro now need to send the e-mail
again for the stable?

I thought there was some suspicion towards e-mails pushed without
being first sent to both stable and upstream mailing lists
because they can get lost or forgotten... maybe I'm wrong.

Andi

> Thanks,
> Rodrigo.
> 
> > 
> > Andi


Re: [RESEND RFC 06/18] drm/display/dp_mst: Add some missing kdocs for atomic MST structs

2022-08-08 Thread Lyude Paul
Also JFYI - I did see this comment but didn't address it in my respin, but
only because I figured this might be better for a followup patch considering
how much work is already in here

On Wed, 2022-06-15 at 04:43 +, Lin, Wayne wrote:
> I would prefer not using the term "available" which is a bit conflicting with
> the idea in the reply of ENUM_PATH_RESOURCES - full PBN & available PBN.
> Maybe better to change to use "full_slots"?
> 
> Not yet finish all the patches. Will try to go through all the patches 
> recently : )

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



Re: [RESEND RFC 18/18] drm/display/dp_mst: Move all payload info into the atomic state

2022-08-08 Thread Lyude Paul
On Mon, 2022-08-08 at 10:02 +, Lin, Wayne wrote:
> [Public]
> 
> 
> 
> > -Original Message-
> > From: Lyude Paul 
> > Sent: Thursday, August 4, 2022 4:28 AM
> > To: Lin, Wayne ; dri-devel@lists.freedesktop.org;
> > nouv...@lists.freedesktop.org; amd-...@lists.freedesktop.org
> > Cc: Ville Syrjälä ; Zuo, Jerry
> > ; Jani Nikula ; Imre Deak
> > ; Daniel Vetter ; Sean Paul
> > ; Wentland, Harry ; Li, Sun
> > peng (Leo) ; Siqueira, Rodrigo
> > ; Deucher, Alexander
> > ; Koenig, Christian
> > ; Pan, Xinhui ; David
> > Airlie ; Daniel Vetter ; Jani Nikula
> > ; Joonas Lahtinen
> > ; Rodrigo Vivi ;
> > Tvrtko Ursulin ; Ben Skeggs
> > ; Karol Herbst ; Kazlauskas,
> > Nicholas ; Li, Roman
> > ; Shih, Jude ; Simon Ser
> > ; Lakha, Bhawanpreet
> > ; Mikita Lipski ;
> > Claudio Suarez ; Chen, Ian ; Colin Ian
> > King ; Wu, Hersen ; Liu,
> > Wenjing ; Lei, Jun ; Strauss,
> > Michael ; Ma, Leo ;
> > Thomas Zimmermann ; José Roberto de Souza
> > ; He Ying ; Anshuman
> > Gupta ; Andi Shyti
> > ; Ashutosh Dixit ;
> > Juston Li ; Sean Paul ;
> > Fernando Ramos ; Luo Jiaxing
> > ; Javier Martinez Canillas ;
> > open list ; open list:INTEL DRM DRIVERS
> > 
> > Subject: Re: [RESEND RFC 18/18] drm/display/dp_mst: Move all payload info
> > into the atomic state
> > 
> > On Tue, 2022-07-05 at 09:10 +, Lin, Wayne wrote:
> > > > +struct drm_dp_mst_port;
> > > > +
> > > >   /* DP MST stream allocation (payload bandwidth number) */
> > > >   struct dc_dp_mst_stream_allocation {
> > > >    uint8_t vcp_id;
> > > >    /* number of slots required for the DP stream in
> > > >    * transport packet */
> > > >    uint8_t slot_count;
> > > > + /* The MST port this is on, this is used to associate DC MST
> > > > + payloads
> > > > with their
> > > > + * respective DRM payloads allocations, and can be ignored on non-
> > > > Linux.
> > > > + */
> > > 
> > > Is it necessary for adding this new member? Since this is for setting
> > > the DC HW and not relating to drm.
> > 
> > I don't entirely know, honestly. The reasons I did it:
> > 
> >  * Mapping things from DRM to DC and from DC to DRM is really confusing for
> >outside contributors like myself, so it wasn't even really clear to me if
> >there was another way to reconstruct the DRM context from the spots
> > where
> >we call from DC up to DM (not a typo, see next point).
> >  * These DC structs for MST are already layer mixing as far as I can tell,
> >just not in an immediately obvious way. While this struct itself is for 
> > DC,
> >there's multiple spots where we pass the DC payload structs down from
> > DM to
> >DC, then pass them back up from DC to DM and have to figure out how to
> >reconstruct the DRM context that we actually need to use the MST helpers
> >from that. So, that kind of further complicates the confusion of where
> >layers should be separated.
> >  * As far as I'm aware with C there shouldn't be any issue with adding a
> >pointer to a struct whose contents are undefined. IMHO, this is also
> >preferable to just using void* because then at least you get some hint as
> >to the actual type of the data and avoid the possibility of casting it to
> >the wrong type. So tl;dr, on any platform even outside of Linux with a
> >reasonably compliant compiler this should still build just fine. It'll 
> > even
> >give you the added bonus of warning people if they try to access the
> >contents of this member in DC on non-Linux platforms. If void* is 
> > preferred
> >though I'm fine with switching it to that.
> > 
> > --
> > Cheers, Lyude Paul (she/her) Software Engineer at Red Hat
> 
> Hi Lyude,
> 
> Thanks for your time!
> I was thinking that our DC just mainly takes care of HW related programming. 
> Struct dc_dp_mst_stream_allocation is only used to construct a copy of the 
> virtual 
> channel payload ID and slots count of payload allocation table determined by
> dm/drm. ID and slots are only things required for programming HW registers.
> I think there shouldn't be any spots to try to construct the DRM context from
> this dc struct since there is no such concept in HW level. Our HW should only 
> take care of local DP link and it doesn't have overall topology info.

Looking at the code I wrote again and realizing I slightly misspoke, looking
at the code again I think I probably can drop this. It's likely I just got
totally lost with the DC codebase and thought this was necessary when it
wasn't. Will drop in the respin

> 
> Thanks!
> 
> Regards,
> Wayne

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



[Bug 100871] radeon fails to initialize one DisplayPort monitor

2022-08-08 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=100871

--- Comment #18 from Charles R. Anderson (c...@fea.st) ---
I believe the PCI ID is 1002:68f1:

01:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc.
[AMD/ATI] Cedar GL [FirePro 2460] [1002:68f1] (prog-if 00 [VGA controller])

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are watching the assignee of the bug.

[PATCH] drm/amd/display: include soc._clock_tmp[] into DC's scratch region

2022-08-08 Thread Hamza Mahfooz
Currently, we are using soc._clock_tmp[] to temporarily store and modify
data from soc.clock_limits[] before copying it back into
soc.clock_limits[] (because modifying data directly in
soc.clock_limits[] causes unintended behavior). However, this approch
has a number of downsides, such as:

1. struct _vcs_dpi_soc_bounding_box_st's creation/destruction
   aren't well defined (which could mean more unintended
   behavior).
2. Throwing temp varibles in structs everywhere doesn't make
   for a particularly readable codebase.

For these reasons, we should get rid of soc._clock_tmp[] by defining a
struct scratch within struct dc that, contains within it all of the
temporary varibles (including _clock_tmp[]) such that it is obvious how
they are intended to be used.

Co-authored-by: Leo Li 
Signed-off-by: Hamza Mahfooz 
---
 drivers/gpu/drm/amd/display/dc/dc.h   | 11 +++
 .../drm/amd/display/dc/dml/dcn20/dcn20_fpu.c  | 34 
 .../amd/display/dc/dml/dcn301/dcn301_fpu.c| 40 +-
 .../drm/amd/display/dc/dml/dcn31/dcn31_fpu.c  | 77 ++-
 .../amd/display/dc/dml/display_mode_structs.h |  6 --
 5 files changed, 91 insertions(+), 77 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dc.h 
b/drivers/gpu/drm/amd/display/dc/dc.h
index 77f327569b8f..61879f36379b 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -898,6 +898,17 @@ struct dc {
 
uint32_t *dcn_reg_offsets;
uint32_t *nbio_reg_offsets;
+
+   /* Scratch memory */
+   struct {
+   struct {
+   /*
+* For matching clock_limits table in driver with table
+* from PMFW.
+*/
+   struct _vcs_dpi_voltage_scaling_st 
clock_limits[DC__VOLTAGE_STATES];
+   } update_bw_bounding_box;
+   } scratch;
 };
 
 enum frame_buffer_mode {
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c 
b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
index d34e0f1314d9..d680f1c5b69f 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
@@ -2234,6 +2234,7 @@ static struct _vcs_dpi_voltage_scaling_st 
construct_low_pstate_lvl(struct clk_li
 
 void dcn21_update_bw_bounding_box(struct dc *dc, struct clk_bw_params 
*bw_params)
 {
+   struct _vcs_dpi_voltage_scaling_st *s = 
dc->scratch.update_bw_bounding_box.clock_limits;
struct dcn21_resource_pool *pool = TO_DCN21_RES_POOL(dc->res_pool);
struct clk_limit_table *clk_table = _params->clk_table;
unsigned int i, closest_clk_lvl = 0, k = 0;
@@ -2247,8 +2248,7 @@ void dcn21_update_bw_bounding_box(struct dc *dc, struct 
clk_bw_params *bw_params
 
ASSERT(clk_table->num_entries);
/* Copy dcn2_1_soc.clock_limits to clock_limits to avoid copying over 
null states later */
-   memcpy(_1_soc._clock_tmp, _1_soc.clock_limits,
-  sizeof(dcn2_1_soc.clock_limits));
+   memcpy(s, dcn2_1_soc.clock_limits, sizeof(dcn2_1_soc.clock_limits));
 
for (i = 0; i < clk_table->num_entries; i++) {
/* loop backwards*/
@@ -2263,25 +2263,25 @@ void dcn21_update_bw_bounding_box(struct dc *dc, struct 
clk_bw_params *bw_params
if (i == 1)
k++;
 
-   dcn2_1_soc._clock_tmp[k].state = k;
-   dcn2_1_soc._clock_tmp[k].dcfclk_mhz = 
clk_table->entries[i].dcfclk_mhz;
-   dcn2_1_soc._clock_tmp[k].fabricclk_mhz = 
clk_table->entries[i].fclk_mhz;
-   dcn2_1_soc._clock_tmp[k].socclk_mhz = 
clk_table->entries[i].socclk_mhz;
-   dcn2_1_soc._clock_tmp[k].dram_speed_mts = 
clk_table->entries[i].memclk_mhz * 2;
-
-   dcn2_1_soc._clock_tmp[k].dispclk_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
-   dcn2_1_soc._clock_tmp[k].dppclk_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
-   dcn2_1_soc._clock_tmp[k].dram_bw_per_chan_gbps = 
dcn2_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
-   dcn2_1_soc._clock_tmp[k].dscclk_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
-   dcn2_1_soc._clock_tmp[k].dtbclk_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
-   dcn2_1_soc._clock_tmp[k].phyclk_d18_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
-   dcn2_1_soc._clock_tmp[k].phyclk_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
+   s[k].state = k;
+   s[k].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
+   s[k].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
+   s[k].socclk_mhz = clk_table->entries[i].socclk_mhz;
+   s[k].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2;
+
+   s[k].dispclk_mhz = 

[Bug 100871] radeon fails to initialize one DisplayPort monitor

2022-08-08 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=100871

--- Comment #17 from Charles R. Anderson (c...@fea.st) ---
Still a problem on Fedora 36 / Linux kernel 5.18.16-200.fc36.x86_64.  I'm now
using two newer monitors (DELL U3219Q) connected via DP instead of the previous
four monitors (2 DP, 2 DVI) and neither monitor turns on unless radeon.audio=0
is passed.

Maybe there needs to be a quirk added to the driver to keep audio turned off
for this card?

Advanced Micro Devices, Inc. [AMD/ATI] Cedar GL [FirePro 2460] (prog-if 00 [VGA
controller])

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are watching the assignee of the bug.

[PATCH v3 2/2] drm/panel/tianma-tl057fvxp01: add panel for Motorola Moto G6

2022-08-08 Thread Julian Braha
This is a 5.7" 2160x1080 panel found on the Motorola Moto G6.
There may be other smartphones using it, as well.

Signed-off-by: Julian Braha 
---
v3:
Fixed kconfig dependencies.

v2:
Fixed accidental whitespace deletion.
---
 drivers/gpu/drm/panel/Kconfig |   9 +
 drivers/gpu/drm/panel/Makefile|   1 +
 .../gpu/drm/panel/panel-tianma-tl057fvxp01.c  | 262 ++
 3 files changed, 272 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-tianma-tl057fvxp01.c

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index a9043eacce97..f7d637084d96 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -658,6 +658,15 @@ config DRM_PANEL_TDO_TL070WSH30
  24 bit RGB per pixel. It provides a MIPI DSI interface to
  the host, a built-in LED backlight and touch controller.

+config DRM_PANEL_TIANMA_TL057FVXP01
+   tristate "Tianma TL057FVXP01 panel"
+   depends on OF
+   depends on DRM_MIPI_DSI
+   depends on BACKLIGHT_CLASS_DEVICE
+   help
+ Say Y here if you want to enable support for the Tianma TL057FVXP01
+ 2160x1080 5.7" panel (found on the Motorola Moto G6)
+
 config DRM_PANEL_TPO_TD028TTEC1
tristate "Toppoly (TPO) TD028TTEC1 panel driver"
depends on OF && SPI
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 34e717382dbb..8f9228082c32 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += 
panel-sitronix-st7789v.o
 obj-$(CONFIG_DRM_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o
 obj-$(CONFIG_DRM_PANEL_SONY_TULIP_TRULY_NT35521) += 
panel-sony-tulip-truly-nt35521.o
 obj-$(CONFIG_DRM_PANEL_TDO_TL070WSH30) += panel-tdo-tl070wsh30.o
+obj-$(CONFIG_DRM_PANEL_TIANMA-TL057FVXP01) += panel-tianma-tl057fvxp01.o
 obj-$(CONFIG_DRM_PANEL_TPO_TD028TTEC1) += panel-tpo-td028ttec1.o
 obj-$(CONFIG_DRM_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
 obj-$(CONFIG_DRM_PANEL_TPO_TPG110) += panel-tpo-tpg110.o
diff --git a/drivers/gpu/drm/panel/panel-tianma-tl057fvxp01.c 
b/drivers/gpu/drm/panel/panel-tianma-tl057fvxp01.c
new file mode 100644
index ..92238defa9ad
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-tianma-tl057fvxp01.c
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021 Julian Braha 
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+
+struct tianma_tl057fvxp01 {
+   struct drm_panel panel;
+   struct mipi_dsi_device *dsi;
+   struct gpio_desc *reset_gpio;
+   bool prepared;
+};
+
+static inline struct tianma_tl057fvxp01 *to_tianma_tl057fvxp01(struct 
drm_panel *panel)
+{
+   return container_of(panel, struct tianma_tl057fvxp01, panel);
+}
+
+#define dsi_dcs_write_seq(dsi, seq...) do {\
+   static const u8 d[] = { seq };  \
+   int ret;\
+   ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
+   if (ret < 0)\
+   return ret; \
+   } while (0)
+
+static void tianma_tl057fvxp01_reset(struct tianma_tl057fvxp01 *ctx)
+{
+   gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+   usleep_range(5000, 6000);
+   gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+   usleep_range(1000, 2000);
+   gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+   usleep_range(1, 11000);
+}
+
+static int tianma_tl057fvxp01_on(struct tianma_tl057fvxp01 *ctx)
+{
+   struct mipi_dsi_device *dsi = ctx->dsi;
+   struct device *dev = >dev;
+   int ret;
+
+   dsi_dcs_write_seq(dsi, 0x00, 0x00);
+   dsi_dcs_write_seq(dsi, 0xff, 0x19, 0x11, 0x01);
+   dsi_dcs_write_seq(dsi, 0x00, 0x80);
+   dsi_dcs_write_seq(dsi, 0xff, 0x19, 0x11);
+   dsi_dcs_write_seq(dsi, 0x00, 0xb0);
+   dsi_dcs_write_seq(dsi, 0xb3, 0x04, 0x38, 0x08, 0x70);
+   dsi_dcs_write_seq(dsi, 0x00, 0x00);
+   dsi_dcs_write_seq(dsi, 0xff, 0xff, 0xff, 0xff);
+   dsi_dcs_write_seq(dsi, 0x35, 0x00);
+   dsi_dcs_write_seq(dsi, 0x51, 0xcc, 0x08);
+   dsi_dcs_write_seq(dsi, 0x53, 0x2c);
+   dsi_dcs_write_seq(dsi, 0x55, 0x01);
+
+   ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+   if (ret < 0) {
+   dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+   return ret;
+   }
+   msleep(120);
+
+   ret = mipi_dsi_dcs_set_display_on(dsi);
+   if (ret < 0) {
+   dev_err(dev, "Failed to set display on: %d\n", ret);
+   return ret;
+   }
+   usleep_range(1, 

[PATCH v3 1/2] dt-bindings: panel-simple-dsi: add Tianma TL057FVXP01

2022-08-08 Thread Julian Braha
Adds the bindings for the Tianma TL057FVXP01 DSI panel,
found on the Motorola Moto G6.

Signed-off-by: Julian Braha 
---
v3:
Fixed kconfig dependencies.

v2:
Fixed accidental whitespace deletion.
---
 .../devicetree/bindings/display/panel/panel-simple-dsi.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml 
b/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml
index 2c00813f5d20..1b3d5e5acefd 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml
@@ -57,6 +57,8 @@ properties:
   - samsung,sofef00
 # Shangai Top Display Optoelectronics 7" TL070WSH30 1024x600 TFT LCD 
panel
   - tdo,tl070wsh30
+# Tianma Micro-electronics TL057FVXP01 5.7" 2160x1080 LCD panel
+  - tianma,tl057fvxp01

   reg:
 maxItems: 1
--
2.34.1


Re: FYI: misc: visconti: Toshiba Visconti DSP accelerator driver sample

2022-08-08 Thread Oded Gabbay
On Fri, Aug 5, 2022 at 1:41 PM Yuji Ishikawa
 wrote:
>
> Hello Odded
>
> This is a sample (wip) driver for a DSP found on Toshiba Visconti SoC.
> The DSP typically accepts some images, apply an algorithm on them and yields 
> resulting one.
> Therefore (image-in, image-out), they say this driver should be classified to 
> media driver category.
> However, it can handle various data format (wider than v4l2 officially 
> supports)
> if userland provide firmware (=algorithm) for its own.
>
> Yes, this rough implementation is the first step only our staff could go.
> I'm not for sure whether we could carry out experiments earlier if we chose 
> to use existing frameworks,
> instead of writing our own routine for handling DMA-BUFs and interrupts.
> I hope this post will help your case-study.
>
> Regards
> Yuji Ishikawa
>
Thanks Yuji.

I've gone over the IOCTLs and they seem fairly straightforward. I
think that we will be able to accommodate at least part of them in the
common code of an accel subsystem.
Oded


Re: [PATCH v9 1/3] i915/gvt: Separate the MMIO tracking table from GVT-g

2022-08-08 Thread Alex Williamson
On Thu,  7 Apr 2022 03:19:43 -0400
Zhi Wang  wrote:

> From: Zhi Wang 
> 
> To support the new mdev interfaces and the re-factor patches from
> Christoph, which moves the GVT-g code into a dedicated module, the GVT-g
> MMIO tracking table needs to be separated from GVT-g.
> 

Since this commit I'm unable to make use of GVT-g on a Xeon W-1290 IGD.
The following in dmesg is the first sign of trouble:

[ cut here ]
assign a handler to a non-tracked mmio 4ab8
WARNING: CPU: 16 PID: 504 at drivers/gpu/drm/i915/gvt/handlers.c:123 
setup_mmio_info.constprop.0+0xd1/0xf0 [i915]
ixgbe :02:00.0: 31.504 Gb/s available PCIe bandwidth (8.0 GT/s PCIe x4 link)
Modules linked in: nouveau(+) i915(+) mdev vfio_iommu_type1 vfio prime_numbers 
intel_gtt ast drm_buddy mxm_wmi drm_dp_helper drm_vram_helper drm_ttm_helper 
drm_kms_helper sd_mod t10_pi syscopyarea sysfillrect sysimgblt sg fb_sys_fops 
cec ttm crct10dif_pclmul drm ixgbe(+) crc32_pclmul igb crc32c_intel ahci e1000e 
libahci mdio libata ghash_clmulni_intel i2c_algo_bit dca wmi video 
pinctrl_cannonlake rndis_host cdc_ether usbnet mii dm_mirror dm_region_hash 
dm_log dm_mod fuse
ixgbe :02:00.0: MAC: 4, PHY: 0, PBA No: 020C08-0F8
CPU: 16 PID: 504 Comm: systemd-udevd Not tainted 5.18.0-rc1+ #16
ixgbe :02:00.0: 3c:ec:ef:27:ef:0e
Hardware name: Supermicro Super Server/X12SCZ-F, BIOS 1.0 06/16/2020
RIP: 0010:setup_mmio_info.constprop.0+0xd1/0xf0 [i915]
Code: 83 c6 04 81 ef e4 e6 dd 78 39 f5 77 a2 31 c0 48 83 c4 08 5b 5d 41 5c 41 
5d 41 5e 41 5f c3 48 c7 c7 d8 c1 07 c1 e8 fe 83 cc c9 <0f> 0b 48 83 c4 08 b8 ed 
ff ff ff 5b 5d 41 5c 41 5d 41 5e 41 5f c3
RSP: 0018:a2014090fa28 EFLAGS: 00010282
RAX:  RBX: 934754a38000 RCX: 
RDX: 9346ce42c740 RSI: 9346ce41fca0 RDI: 9346ce41fca0
RBP: 4abc R08:  R09: 7fff
R10: a2014090f868 R11: 8bfe65e8 R12: 
R13:  R14: 0008 R15: 
FS:  7f345634d540() GS:9346ce40() knlGS:
CS:  0010 DS:  ES:  CR0: 80050033
CR2: 562eacfa8980 CR3: 002058ac0001 CR4: 007706e0
PKRU: 5554
Call Trace:
 
 init_skl_mmio_info+0x1532/0x15a0 [i915]
 intel_gvt_setup_mmio_info+0x1aa/0x240 [i915]
 ? gen9_dbuf_ctl_mmio_write+0x40/0x40 [i915]
 intel_gvt_init_device+0x106/0x300 [i915]
 intel_gvt_init+0x41/0xa0 [i915]
 i915_driver_hw_probe+0x2b2/0x340 [i915]
 i915_driver_probe+0x1fd/0x570 [i915]
 ? drm_privacy_screen_get+0x15f/0x190 [drm]
 i915_pci_probe+0x56/0x1e0 [i915]
 local_pci_probe+0x42/0x80
 pci_call_probe+0x56/0x160
 pci_device_probe+0x75/0xf0
 ? driver_sysfs_add+0x6f/0xd0
 really_probe+0x199/0x380
ixgbe :02:00.0: Intel(R) 10 Gigabit Network Connection
 __driver_probe_device+0xfe/0x180
 driver_probe_device+0x1e/0x90
 __driver_attach+0xc0/0x1c0
 ? __device_attach_driver+0xe0/0xe0
 ? __device_attach_driver+0xe0/0xe0
 bus_for_each_dev+0x75/0xc0
 bus_add_driver+0x149/0x1e0
 driver_register+0x8f/0xe0
 i915_init+0x1d/0x7c [i915]
 ? 0xc0768000
 do_one_initcall+0x41/0x200
 ? kmem_cache_alloc_trace+0x174/0x2f0
 do_init_module+0x4c/0x250
 __do_sys_finit_module+0xb4/0x120
 do_syscall_64+0x59/0x80
 ? syscall_exit_to_user_mode+0x12/0x30
 ? do_syscall_64+0x69/0x80
 ? do_syscall_64+0x69/0x80
 ? do_syscall_64+0x69/0x80
 ? sysvec_call_function+0x3c/0x90
 entry_SYSCALL_64_after_hwframe+0x44/0xae
RIP: 0033:0x7f3456e5a3ed
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 
89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 
c3 48 8b 0d 03 aa 1b 00 f7 d8 64 89 01 48
RSP: 002b:7fff4df686b8 EFLAGS: 0246 ORIG_RAX: 0139
RAX: ffda RBX: 562eacf62920 RCX: 7f3456e5a3ed
RDX:  RSI: 562eacf886b0 RDI: 001a
RBP: 0002 R08:  R09: 0002
R10: 001a R11: 0246 R12: 562eacf886b0
R13: 562eacf627c0 R14:  R15: 562eacf8d2d0
 
---[ end trace  ]---


> diff --git a/drivers/gpu/drm/i915/gvt/handlers.c 
> b/drivers/gpu/drm/i915/gvt/handlers.c
> index 520a7e1942f3..9bd3c15bfab6 100644
> --- a/drivers/gpu/drm/i915/gvt/handlers.c
> +++ b/drivers/gpu/drm/i915/gvt/handlers.c
...
> @@ -3440,7 +2729,6 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)
>NULL, NULL);
>  
>   MMIO_DFH(GAMT_CHKN_BIT_REG, D_KBL | D_CFL, F_CMD_ACCESS, NULL, NULL);
> - MMIO_D(GEN9_CTX_PREEMPT_REG, D_SKL_PLUS & ~D_BXT);
>   MMIO_DFH(_MMIO(0xe4cc), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
>  
>   return 0;

I tracked this to the above code segment, where the untouched line
provides this mmio address:

#define GAMT_CHKN_BIT_REG   _MMIO(0x4ab8)

If I comment out setup of this register, GVT-g appears to initialize
and I can list available mdev types.  I haven't tried assignment of the
resulting 

Re: New subsystem for acceleration devices

2022-08-08 Thread Oded Gabbay
On Mon, Aug 8, 2022 at 8:46 PM Jason Gunthorpe  wrote:
>
> On Sun, Aug 07, 2022 at 09:43:40AM +0300, Oded Gabbay wrote:
>
> > 1. If there is a subsystem which is responsible for creating and
> > exposing the device character files, then there should be some code
> > that connects between each device driver to that subsystem.
> > i.e. There should be functions that each driver should call from its
> > probe and release callback functions.
> >
> > Those functions should take care of the following:
> > - Create metadata for the device, the device's minor(s) and the
> > driver's ioctls table and driver's callback for file operations (both
> > are common for all the driver's devices). Save all that metadata with
> > proper locking.
> > - Create the device char files themselves and supply file operations
> > that will be called per each open/close/mmap/etc.
> > - Keep track of all these objects' lifetime in regard to the device
> > driver's lifetime, with proper handling for release.
> > - Add common handling and entries of sysfs/debugfs for these devices
> > with the ability for each device driver to add their own unique
> > entries.
> >
> > 2. I think that you underestimate (due to your experience) the "using
> > it properly" part... It is not so easy to do this properly for
> > inexperienced kernel people. If we provide all the code I mentioned
> > above, the device driver writer doesn't need to be aware of all these
> > kernel APIs.
>
> This may be, but it still seems weird to me to justify a subsystem as
> "making existing APIs simpler so drivers don't mess them up". It
> suggests perhaps we need additional core API helpers?
>
I'm sorry, but my original argument was poorly phrased. I'll try to
phrase it better.

What I'm trying to say is that imo one of the end goals of doing a
common subsystem is to provide a common uAPI for all the drivers that
belong to that subsystem.
I wrote this argument in a previous email as a criteria whether a
driver should join a subsystem.

So if you want a common uAPI and a common userspace library to use it,
you need to expose the same device character files for every device,
regardless of the driver. e.g. you need all devices to be called
/dev/accelX and not /dev/habanaX or /dev/nvidiaX

This means that the whole device character creation/removal/open/close
is done in the common subsystem, not in each driver individually.
So even if it is a simple code as you said, it still must reside in
the subsystem common code.

Once you put that code there, you need to add meta-data as different
drivers attach to the subsystem and ask to create devices and minors
when their probe function is called. In addition, you need to remove
all this code from each individual driver.

That's what I mean by abstracting all this kernel API from the
drivers. Not because it is an API that is hard to use, but because the
drivers should *not* use it at all.

I think drm did that pretty well. Their code defines objects for
driver, device and minors, with resource manager that will take care
of releasing the objects automatically (it is based on devres.c).

> > > It would be nice to at least identify something that could obviously
> > > be common, like some kind of enumeration and metadata kind of stuff
> > > (think like ethtool, devlink, rdma tool, nvemctl etc)
> > Definitely. I think we can have at least one ioctl that will be common
> > to all drivers from the start.
>
> Generally you don't want that as an ioctl because you have to open the
> device to execute it, there may be permissions issues for instance -
> or if you have a single-open-at-a-time model like VFIO, then it
> doesn't work well together.
>
> Usually this would be sysfs or netlink.
So actually I do want an ioctl but as you said, not for the main
device char, but to an accompanied control device char.

In habana we define two device char per device. One is the compute
which behaves like VFIO, and one is a control device which has no
limitation on the number of applications that can access it. However,
an application only has access to the information ioctl through this
device char (so it can't submit anything, allocate memory, etc.) and
can only retrieve metrics which do not leak information about the
compute application.

The reason I want an ioctl is because it is much more flexible than
sysfs and allows writing proper software to monitor the device in the
data-center. At least, that's my experience from the deployment we had
so far.

>
> > > This makes sense to me, all accelerators need a way to set a memory
> > > map, but on the other hand we are doing some very nifty stuff in this
> > > area with iommufd and it might be very interesting to just have the
> > > accelerator driver link to that API instead of building yet another
> > > copy of pin_user_pages() code.. Especially with PASID likely becoming
> > > part of any accelerator toolkit.
> >
> > Here I disagree with you. First of all, there are many relatively
> > simple 

Re: [PATCH v2 00/14] drm/format-helper: Move to struct iosys_map

2022-08-08 Thread Noralf Trønnes



Den 08.08.2022 14.53, skrev Thomas Zimmermann:
> Change format-conversion helpers to use struct iosys_map for source
> and destination buffers. Update all users. Also prepare interface for
> multi-plane color formats.
> 
> The format-conversion helpers mostly used to convert to I/O memory
> or system memory. To actual memory type depended on the usecase. We
> now have drivers upcomming that do the conversion entirely in system
> memory. It's a good opportunity to stream-line the interface of the
> conversion helpers to use struct iosys_map. Source and destination
> buffers can now be either in system or in I/O memory. Note that the
> implementation still only supports source buffers in system memory.
> 
> This patchset also changes the interface to support multi-plane
> color formats, where the values for each component are stored in
> distinct memory locations. Converting from RGBRGBRGB to RRRGGGBBB
> would require a single source buffer with RGB values and 3 destination
> buffers for the R, G and B values. Conversion-helper interfaces now
> support this.
> 
> v2:
>   * add IOSYS_MAP_INIT_VADDR_IOMEM (Sam)
>   * use drm_format_info_bpp() (Sam)
>   * update documentation (Sam)
>   * rename 'vmap' to 'src' (Sam)
>   * many smaller cleanups and fixes (Sam, Jose)
> 
> Thomas Zimmermann (14):
>   iosys-map: Add IOSYS_MAP_INIT_VADDR_IOMEM()
>   drm/format-helper: Provide drm_fb_blit()
>   drm/format-helper: Merge drm_fb_memcpy() and drm_fb_memcpy_toio()
>   drm/format-helper: Convert drm_fb_swab() to struct iosys_map
>   drm/format-helper: Rework XRGB-to-RGBG332 conversion
>   drm/format-helper: Rework XRGB-to-RGBG565 conversion
>   drm/format-helper: Rework XRGB-to-RGB888 conversion
>   drm/format-helper: Rework RGB565-to-XRGB conversion
>   drm/format-helper: Rework RGB888-to-XRGB conversion
>   drm/format-helper: Rework XRGB-to-XRGB2101010 conversion
>   drm/format-helper: Rework XRGB-to-GRAY8 conversion
>   drm/format-helper: Rework XRGB-to-MONO conversion
>   drm/format-helper: Move destination-buffer handling into internal
> helper
>   drm/format-helper: Rename parameter vmap to src
> 

Tested-by: Noralf Trønnes 

* gud: XRGB-to-{MONO,GRAY8,RGB332,RGB565}
* mi0283qt (drm_mipi_dbi): XRGB-to-RGB565 with swap=true,
drm_fb_memcpy, drm_fb_swab

>  drivers/gpu/drm/drm_format_helper.c   | 509 ++
>  drivers/gpu/drm/drm_mipi_dbi.c|   9 +-
>  drivers/gpu/drm/gud/gud_pipe.c|  20 +-
>  drivers/gpu/drm/hyperv/hyperv_drm_modeset.c   |   9 +-
>  drivers/gpu/drm/mgag200/mgag200_mode.c|   9 +-
>  drivers/gpu/drm/solomon/ssd130x.c |   7 +-
>  .../gpu/drm/tests/drm_format_helper_test.c|  45 +-
>  drivers/gpu/drm/tiny/cirrus.c |  19 +-
>  drivers/gpu/drm/tiny/repaper.c|   6 +-
>  drivers/gpu/drm/tiny/simpledrm.c  |   8 +-
>  drivers/gpu/drm/tiny/st7586.c |   5 +-
>  include/drm/drm_format_helper.h   |  56 +-
>  include/linux/iosys-map.h |  15 +-
>  13 files changed, 416 insertions(+), 301 deletions(-)
> 
> 
> base-commit: 2bdae66c9988dd0f07633629c0a85383cfc05940
> prerequisite-patch-id: c2b2f08f0eccc9f5df0c0da49fa1d36267deb11d
> prerequisite-patch-id: c67e5d886a47b7d0266d81100837557fda34cb24
> prerequisite-patch-id: 3f204510fcbf9530d6540bd8e6128cce598988b6


Re: [PATCH RFC] dma-buf: To check DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT status on debug

2022-08-08 Thread Christian König




Am 04.08.22 um 14:19 schrieb Arvind Yadav:

If core DMA-buf framework forgets to call dma_fence_enable_signaling()
before calling the dma_fence_is_signaled(). To handle this scenario on
debug kernel the DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT needs to be checked
before checking the actual signaling status.

Signed-off-by: Arvind Yadav 
---
  include/linux/dma-fence.h | 4 
  1 file changed, 4 insertions(+)

diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h
index 775cdc0b4f24..7c95c8d5e5f5 100644
--- a/include/linux/dma-fence.h
+++ b/include/linux/dma-fence.h
@@ -428,6 +428,10 @@ dma_fence_is_signaled_locked(struct dma_fence *fence)
  static inline bool
  dma_fence_is_signaled(struct dma_fence *fence)
  {
+#ifdef CONFIG_DEBUG_FS
+   if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, >flags))
+   return true;


The logic is just inverted. The test should be !test_bit(...) return false;

And please give that some testing as well.

Regards,
Christian.


+#endif
if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, >flags))
return true;
  




Re: [Intel-gfx] [PATCH v3 1/3] drm/i915: pass a pointer for tlb seqno at vma_invalidate_tlb()

2022-08-08 Thread Rodrigo Vivi
On Mon, Aug 08, 2022 at 06:37:58PM +0200, Andi Shyti wrote:
> Hi Mauro,
> 
> On Thu, Aug 04, 2022 at 09:37:22AM +0200, Mauro Carvalho Chehab wrote:
> > WRITE_ONCE() should happen at the original var, not on a local
> > copy of it.
> > 
> > Fixes: 5d36acb7198b ("drm/i915/gt: Batch TLB invalidations")
> > Signed-off-by: Mauro Carvalho Chehab 
> 
> Reviewed-by: Andi Shyti 

Thanks and pushed...

> 
> Are you going to send it to the stable mailing list?

I added cc stable while pushing and the cherry-pick to drm-intel-next-fixes
has the right sha, so I'd assume this would be automagically now.
But yeap, it would be good if Mauro can follow up whenever this gets
to Linus tree and Greg's script start to pop up the heads-up messages.

Thanks,
Rodrigo.

> 
> Andi


Re: [PATCH v2 14/14] drm/format-helper: Rename parameter vmap to src

2022-08-08 Thread Sam Ravnborg
Hi Thomas,

On Mon, Aug 08, 2022 at 02:54:06PM +0200, Thomas Zimmermann wrote:
> The name the parameter vmap to src in all functions. The parameter
> contains the locations of the source data and the new name says that.
> 
> Signed-off-by: Thomas Zimmermann 

Thanks, this helped in readability!
Reviewed-by: Sam Ravnborg 


Re: [PATCH v2 00/14] drm/format-helper: Move to struct iosys_map

2022-08-08 Thread Sam Ravnborg
Hi Thomas,

On Mon, Aug 08, 2022 at 02:53:52PM +0200, Thomas Zimmermann wrote:
> Change format-conversion helpers to use struct iosys_map for source
> and destination buffers. Update all users. Also prepare interface for
> multi-plane color formats.
> 
> The format-conversion helpers mostly used to convert to I/O memory
> or system memory. To actual memory type depended on the usecase. We
> now have drivers upcomming that do the conversion entirely in system
> memory. It's a good opportunity to stream-line the interface of the
> conversion helpers to use struct iosys_map. Source and destination
> buffers can now be either in system or in I/O memory. Note that the
> implementation still only supports source buffers in system memory.
> 
> This patchset also changes the interface to support multi-plane
> color formats, where the values for each component are stored in
> distinct memory locations. Converting from RGBRGBRGB to RRRGGGBBB
> would require a single source buffer with RGB values and 3 destination
> buffers for the R, G and B values. Conversion-helper interfaces now
> support this.
> 
> v2:
>   * add IOSYS_MAP_INIT_VADDR_IOMEM (Sam)
>   * use drm_format_info_bpp() (Sam)
>   * update documentation (Sam)
>   * rename 'vmap' to 'src' (Sam)
>   * many smaller cleanups and fixes (Sam, Jose)
Thanks for the quick respin - I reviewed the remaining patches and looks
good. Nice cleanup of the API and it makes is easier to add more
conversions.

Sam


Re: [PATCH v1 0/7] New DRM driver for Intel VPU

2022-08-08 Thread Sam Ravnborg
Hi Stanislaw,

> I'm not sure what we can add to TODO file, from driver perspective
> I think it's pretty much ready for merging (except renaming), just
> other components: F/W and user-space are not yet released.
> 
> > I think I'd like Christian/Maarten to maybe review the fencing/uapi,
> > to make sure nothing too much is wrong there. The submit/waitbo model
> > is getting a bit old, and using syncobjs might be useful to make it
> > more modern. Is this device meant to be used by multiple users at
> > once? Maybe we'd want scheduler integration for it as well (which I
> > think I saw mentioned somewhere in passing).
> 
> In the future we are planning to add support for
> HW based scheduling (we are also looking at SW scheduler) and we will
> likely revisit submit/sync APIs at that time.

This is already two entries in the TODO file.

Sam


Re: [PATCH v2 13/14] drm/format-helper: Move destination-buffer handling into internal helper

2022-08-08 Thread Sam Ravnborg
Hi Thomas,

On Mon, Aug 08, 2022 at 02:54:05PM +0200, Thomas Zimmermann wrote:
> The format-convertion helpers handle several cases for different
> values of destination buffer and pitch. Move that code into the
> internal helper drm_fb_xfrm() and avoid quite a bit of duplication.
> 
> v2:
>   * remove a duplicated blank line (Jose)
>   * use drm_format_info_bpp() (Sam)
>   * fix vaddr_cached_hint bug (Sam)
>   * add TODO on vaddr location (Sam)
> 
> Signed-off-by: Thomas Zimmermann 
Reviewed-by: Sam Ravnborg 


Re: [Intel-gfx] [PATCH 3/7] drm/i915/guc: Add GuC <-> kernel time stamp translation information

2022-08-08 Thread John Harrison

On 8/4/2022 17:40, Teres Alexis, Alan Previn wrote:

I have a question on below code. Everything else looked good.
Will r-b as soon as we can close on below question
...alan


On Wed, 2022-07-27 at 19:20 -0700, john.c.harri...@intel.com wrote:

From: John Harrison 

It is useful to be able to match GuC events to kernel events when
looking at the GuC log. That requires being able to convert GuC
timestamps to kernel time. So, when dumping error captures and/or GuC
logs, include a stamp in both time zones plus the clock frequency.

Signed-off-by: John Harrison 
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1675,6 +1678,13 @@ gt_record_uc(struct intel_gt_coredump *gt,
 */
error_uc->guc_fw.path = kstrdup(uc->guc.fw.path, ALLOW_FAIL);
error_uc->huc_fw.path = kstrdup(uc->huc.fw.path, ALLOW_FAIL);
+
+   /*
+* Save the GuC log and include a timestamp reference for converting the
+* log times to system times (in conjunction with the error->boottime 
and
+* gt->clock_frequency fields saved elsewhere).
+*/
+   error_uc->timestamp = intel_uncore_read(gt->_gt->uncore, 
GUCPMTIMESTAMP);

Alan:this register is in the GUC-SHIM domain and so unless i am mistaken u 
might need to ensure we hold a wakeref so
that are getting a live value of the real timestamp register that this register 
is mirror-ing and not a stale snapshot.
Or was this already done farther up the stack? Or are we doing the opposite - 
in which case we should ensure we drop al
  wakeref prior to this point. (which i am not sure is a reliable method since 
we wouldnt know what GuC ref was at).

The intel_uncore_read() does a forcewake acquire implicitly.

Not sure what you mean about dropping all wakerefs prior to this point?

John.


error_uc->guc_log = create_vma_coredump(gt->_gt, uc->guc.log.vma,
"GuC log buffer", compress);
  




Re: [PATCH v2 04/14] drm/format-helper: Convert drm_fb_swab() to struct iosys_map

2022-08-08 Thread Sam Ravnborg
Hi Thomas,

On Mon, Aug 08, 2022 at 02:53:56PM +0200, Thomas Zimmermann wrote:
> Convert drm_fb_swab() to use struct iosys_map() and convert users. The
> new interface supports multi-plane color formats, but implementation
> only supports a single plane for now.
> 
> v2:
>   * use drm_format_info_bpp() (Sam)
>   * update documentation (Sam)
>   * add TODO on vaddr location (Sam)
> 
> Signed-off-by: Thomas Zimmermann 
Reviewed-by: Sam Ravnborg 



Re: [PATCH v2 03/14] drm/format-helper: Merge drm_fb_memcpy() and drm_fb_memcpy_toio()

2022-08-08 Thread Sam Ravnborg
Hi Thomas,

On Mon, Aug 08, 2022 at 02:53:55PM +0200, Thomas Zimmermann wrote:
> Merge drm_fb_memcpy() and drm_fb_memcpy_toio() into a drm_fb_memcpy()
> that uses struct iosys_map for buffers. The new function also supports
> multi-plane color formats. Convert all users of the original helpers.
> 
> v2:
>   * rebase onto refactored mgag200
>   * use drm_formap_info_bpp() (Sam)
>   * do static init in hyperv and mgag200 (Sam)
>   * update documentation (Sam)
>   * add TODO on vaddr location (Sam)
> 
> Signed-off-by: Thomas Zimmermann 
Reviewed-by: Sam Ravnborg 


Re: [PATCH v2 01/14] iosys-map: Add IOSYS_MAP_INIT_VADDR_IOMEM()

2022-08-08 Thread Sam Ravnborg
On Mon, Aug 08, 2022 at 02:53:53PM +0200, Thomas Zimmermann wrote:
> Add IOSYS_MAP_INIT_VADDR_IOMEM() for static init of variables of type
> struct iosys_map.
> 
> Signed-off-by: Thomas Zimmermann 
Reviewed-by: Sam Ravnborg 
> ---
>  include/linux/iosys-map.h | 15 ++-
>  1 file changed, 14 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/iosys-map.h b/include/linux/iosys-map.h
> index a533cae189d7..cb71aa616bd3 100644
> --- a/include/linux/iosys-map.h
> +++ b/include/linux/iosys-map.h
> @@ -46,10 +46,13 @@
>   *
>   *   iosys_map_set_vaddr(, 0xdeadbeaf);
>   *
> - * To set an address in I/O memory, use iosys_map_set_vaddr_iomem().
> + * To set an address in I/O memory, use IOSYS_MAP_INIT_VADDR_IOMEM() or
> + * iosys_map_set_vaddr_iomem().
>   *
>   * .. code-block:: c
>   *
> + *   struct iosys_map map = IOSYS_MAP_INIT_VADDR_IOMEM(0xdeadbeaf);
> + *
>   *   iosys_map_set_vaddr_iomem(, 0xdeadbeaf);
>   *
>   * Instances of struct iosys_map do not have to be cleaned up, but
> @@ -121,6 +124,16 @@ struct iosys_map {
>   .is_iomem = false,  \
>   }
>  
> +/**
> + * IOSYS_MAP_INIT_VADDR_IOMEM - Initializes struct iosys_map to an address 
> in I/O memory
> + * @vaddr_iomem_:An I/O-memory address
> + */
> +#define IOSYS_MAP_INIT_VADDR_IOMEM(vaddr_iomem_) \
> + {   \
> + .vaddr_iomem = (vaddr_iomem_),  \
> + .is_iomem = true,   \
> + }
> +
>  /**
>   * IOSYS_MAP_INIT_OFFSET - Initializes struct iosys_map from another 
> iosys_map
>   * @map_:The dma-buf mapping structure to copy from
> -- 
> 2.37.1


[Bug 216092] rn_vbios_smu_send_msg_with_param+0xf9/0x100 - amdgpu

2022-08-08 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=216092

Mario Limonciello (AMD) (mario.limoncie...@amd.com) changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 CC||mario.limoncie...@amd.com
 Resolution|--- |CODE_FIX

--- Comment #7 from Mario Limonciello (AMD) (mario.limoncie...@amd.com) ---
As pointed out in the linked #2110, it's fixed in Linus' tree by this:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=149f6d1a6035a7aa6595ac6eeb9c8f566b2103cd

Which will be part of 6.0-rc1.

-- 
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 12/12] drm/format-helper: Move destination-buffer handling into internal helper

2022-08-08 Thread Sam Ravnborg
Hi Thomas,

> > > - static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
> > > - 0, 0, 0, 0
> > > - };
> > >   const struct drm_format_info *format = fb->format;
> > > - u8 cpp = format->cpp[0];
> > >   void (*swab_line)(void *dbuf, const void *sbuf, unsigned int 
> > > npixels);
> > > - switch (cpp) {
> > > + switch (format->cpp[0]) {
> > >   case 4:
> > >   swab_line = drm_fb_swab32_line;
> > >   break;
> > > @@ -230,21 +249,10 @@ void drm_fb_swab(struct iosys_map *dst, const 
> > > unsigned int *dst_pitch,
> > >   default:
> > >   drm_warn_once(fb->dev, "Format %p4cc has unsupported 
> > > pixel size.\n",
> > > >format);
> > > - swab_line = NULL;
> > > - break;
> > > - }
> > > - if (!swab_line)
> > >   return;
> > > + }
> > > - if (!dst_pitch)
> > > - dst_pitch = default_dst_pitch;
> > > -
> > > - if (dst->is_iomem)
> > > - drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], cpp,
> > > -  vmap[0].vaddr, fb, clip, cached, swab_line);
> > > - else
> > > - drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], cpp, vmap[0].vaddr, fb,
> > > - clip, cached, swab_line);
> > > + drm_fb_xfrm(dst, dst_pitch, format->cpp, vmap, fb, clip, cached, 
> > > swab_line);
> > 
> > In this case we pass fb->format-cpp as dst_pitch - so we could retreive
> > is via the fb pointer.
> 
> I don't understand this comment. We're passing format->cpp as dst_pixsize.
> I've meanwhile updated the code to compute the value from
> drm_format_info_bpp().

I wanted to ask if we could drop the format->cpp argument and in
drm_fb_xfrm() use fb->format to retrieve the char per pixel.
So we move this part down in drm_fb_xfrm(), rather than finding
the char per pixel in all callers.

Maybe some of the other callers do not allow this and then this comment
can be ignored.

I have not yet looked at the updated patch-set.

Sam


Re: [PATCH] drm/gem: Fix GEM handle release errors

2022-08-08 Thread Christian König




Am 02.08.22 um 13:33 schrieb Jeffy Chen:

Currently we are assuming a one to one mapping between dmabuf and handle
when releasing GEM handles.

But that is not always true, since we would create extra handles for the
GEM obj in cases like gem_open() and getfb{,2}().

A similar issue was reported at:
https://lore.kernel.org/all/20211105083308.392156-1-jay...@rock-chips.com/

Another problem is that the drm_gem_remove_prime_handles() now only
remove handle to the exported dmabuf (gem_obj->dma_buf), so the imported
ones would leak:
WARNING: CPU: 2 PID: 236 at drivers/gpu/drm/drm_prime.c:228 
drm_prime_destroy_file_private+0x18/0x24

Let's fix these by using handle to find the exact map to remove.

Signed-off-by: Jeffy Chen 
---

  drivers/gpu/drm/drm_gem.c  | 17 +
  drivers/gpu/drm/drm_internal.h |  4 ++--
  drivers/gpu/drm/drm_prime.c| 16 ++--
  3 files changed, 13 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index eb0c2d041f13..ed39da383570 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -168,21 +168,6 @@ void drm_gem_private_object_init(struct drm_device *dev,
  }
  EXPORT_SYMBOL(drm_gem_private_object_init);
  
-static void

-drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp)
-{
-   /*
-* Note: obj->dma_buf can't disappear as long as we still hold a
-* handle reference in obj->handle_count.
-*/
-   mutex_lock(>prime.lock);
-   if (obj->dma_buf) {
-   drm_prime_remove_buf_handle_locked(>prime,
-  obj->dma_buf);
-   }
-   mutex_unlock(>prime.lock);
-}
-
  /**
   * drm_gem_object_handle_free - release resources bound to userspace handles
   * @obj: GEM object to clean up.
@@ -253,7 +238,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
if (obj->funcs->close)
obj->funcs->close(obj, file_priv);
  
-	drm_gem_remove_prime_handles(obj, file_priv);

+   drm_prime_remove_buf_handle(_priv->prime, id);
drm_vma_node_revoke(>vma_node, file_priv);
  
  	drm_gem_object_handle_put_unlocked(obj);

diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index 1fbbc19f1ac0..7bb98e6a446d 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -74,8 +74,8 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void 
*data,
  
  void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);

  void drm_prime_destroy_file_private(struct drm_prime_file_private 
*prime_fpriv);
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private 
*prime_fpriv,
-   struct dma_buf *dma_buf);
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
+uint32_t handle);
  
  /* drm_drv.c */

  struct drm_minor *drm_minor_acquire(unsigned int minor_id);
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index e3f09f18110c..c28518ab62d0 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -190,29 +190,33 @@ static int drm_prime_lookup_buf_handle(struct 
drm_prime_file_private *prime_fpri
return -ENOENT;
  }
  
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv,

-   struct dma_buf *dma_buf)
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
+uint32_t handle)
  {
struct rb_node *rb;
  
+	mutex_lock(_fpriv->lock);

+
rb = prime_fpriv->dmabufs.rb_node;
while (rb) {
struct drm_prime_member *member;
  
  		member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);

-   if (member->dma_buf == dma_buf) {
+   if (member->handle == handle) {
rb_erase(>handle_rb, _fpriv->handles);
rb_erase(>dmabuf_rb, _fpriv->dmabufs);
  
-			dma_buf_put(dma_buf);

+   dma_buf_put(member->dma_buf);
kfree(member);
-   return;
-   } else if (member->dma_buf < dma_buf) {
+   break;
+   } else if (member->handle < handle) {


Just to make it clear once more. That change here is completely broken.

The rb is indexed by the dma_buf object, not the handle.

Regards,
Christian.


rb = rb->rb_right;
} else {
rb = rb->rb_left;
}
}
+
+   mutex_unlock(_fpriv->lock);
  }
  
  void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)




Re: [PATCH v2] drm/gem: Fix GEM handle release errors

2022-08-08 Thread Christian König

Hi Jeffy,

Am 08.08.22 um 05:51 schrieb Chen Jeffy:

Hi Christian,

Thanks for your reply, and sorry i didn't make it clear.

On 8/8 星期一 0:52, Christian König wrote:

Am 03.08.22 um 10:32 schrieb Jeffy Chen:
Currently we are assuming a one to one mapping between dmabuf and 
handle

when releasing GEM handles.

But that is not always true, since we would create extra handles for 
the

GEM obj in cases like gem_open() and getfb{,2}().

A similar issue was reported at:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fall%2F20211105083308.392156-1-jay.xu%40rock-chips.com%2Fdata=05%7C01%7Cchristian.koenig%40amd.com%7Cd7488e9f235041f7e84408da78f14882%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637955274964656400%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7Csdata=9G2YbHcYUs1VQYyvjXwLzYawNw%2BP8i%2BjjPBSHx3r2yg%3Dreserved=0 



Another problem is that the drm_gem_remove_prime_handles() now only
remove handle to the exported dmabuf (gem_obj->dma_buf), so the 
imported

ones would leak:
WARNING: CPU: 2 PID: 236 at drivers/gpu/drm/drm_prime.c:228 
drm_prime_destroy_file_private+0x18/0x24


Let's fix these by using handle to find the exact map to remove.


Well we are clearly something missing here. As far as I can see the 
current code is correct.


Creating multiple GEM handles for the same DMA-buf is possible, but 
illegal. >
In other words when a GEM handle is exported as DMA-buf and imported 
again you should intentionally always get the same handle.


These issue are not about having handles for importing an exported 
dma-buf case, but for having multiple handles to a GEM object(which 
means having multiple handles to a dma-buf).


I know the drm-prime is trying to make dma-buf and handle maps one to 
one, but the drm-gem is allowing to create extra handles for a GEM 
object, for example:

drm_gem_open_ioctl -> drm_gem_handle_create_tail
drm_mode_getfb2_ioctl -> drm_gem_handle_create
drm_mode_getfb -> fb->funcs->create_handle


Yes, so far that's correct.




So we are allowing GEM object to have multiple handles, and GEM object 
could have at most one dma-buf, doesn't that means that dma-buf could 
map to multiple handles?


No, at least not for the same GEM file private. That's the reason why 
the rb is indexed by the dma_buf object and not the handle.


In other words the rb is so that you have exactly one handle for each 
dma_buf in each file private.




Or should we rewrite the GEM framework to limit GEM object with uniq 
handle?


No, the extra handles are expected because when you call 
drm_mode_getfb*() and drm_gem_open_ioctl() the caller now owns the 
returned GEM handle.




The other issue is that we are leaking dma-buf <-> handle map for the 
imported dma-buf, since the drm_gem_remove_prime_handles doesn't take 
care of obj->import_attach->dmabuf.


No, that's correct as well. obj->dma_buf is set even for imported 
DMA-buf objects. See drm_gem_prime_fd_to_handle().


Regards,
Christian.



But of cause this can be fixed in other way:
+++ b/drivers/gpu/drm/drm_gem.c
@@ -180,6 +180,9 @@ drm_gem_remove_prime_handles(struct drm_gem_object 
*obj, struct drm_file *filp)

drm_prime_remove_buf_handle_locked(>prime,
obj->dma_buf);
    }
+   if (obj->import_attach)
+ drm_prime_remove_buf_handle_locked(>prime,
+ obj->import_attach->dmabuf);
    mutex_unlock(>prime.lock);
 }


So this is pretty much a clear NAK to this patch since it shouldn't 
be necessary or something is seriously broken somewhere else.


Regards,
Christian.



Signed-off-by: Jeffy Chen 
---

Changes in v2:
Fix a typo of rbtree.

  drivers/gpu/drm/drm_gem.c  | 17 +
  drivers/gpu/drm/drm_internal.h |  4 ++--
  drivers/gpu/drm/drm_prime.c    | 20 
  3 files changed, 15 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index eb0c2d041f13..ed39da383570 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -168,21 +168,6 @@ void drm_gem_private_object_init(struct 
drm_device *dev,

  }
  EXPORT_SYMBOL(drm_gem_private_object_init);
-static void
-drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct 
drm_file *filp)

-{
-    /*
- * Note: obj->dma_buf can't disappear as long as we still hold a
- * handle reference in obj->handle_count.
- */
-    mutex_lock(>prime.lock);
-    if (obj->dma_buf) {
- drm_prime_remove_buf_handle_locked(>prime,
-   obj->dma_buf);
-    }
-    mutex_unlock(>prime.lock);
-}
-
  /**
   * drm_gem_object_handle_free - release resources bound to 
userspace handles

   * @obj: GEM object to clean up.
@@ -253,7 +238,7 @@ drm_gem_object_release_handle(int id, void *ptr, 
void *data)

  if (obj->funcs->close)
  obj->funcs->close(obj, file_priv);
-    drm_gem_remove_prime_handles(obj, file_priv);
+    drm_prime_remove_buf_handle(_priv->prime, id);
  

Re: New subsystem for acceleration devices

2022-08-08 Thread Jason Gunthorpe
On Mon, Aug 08, 2022 at 08:10:22AM +0200, Greg Kroah-Hartman wrote:
> On Sun, Aug 07, 2022 at 02:25:33PM +0300, Oded Gabbay wrote:
> > 2. Common code to handle drivers that want to allow a single user at a
> > time to run open the device char file.
> 
> Note, that's an impossible request, and one that the kernel should never
> worry about, so don't even try it.  Think about userspace doing an call
> to dup() on an open char file descriptor and then passing that off
> somewhere else.

Oded is talking about a model like VFIO has where the HW has a limited
number of concurrent state registers - lets say in this case the ASID
translation mapping the accelerator into DMA.

Each 'struct file' that is created owns one of those HW state
registers, and each struct file is completely isolated from all
others. eg someone controlling the accelerator through struct file A
cannot access memory mapped into the accelerator through struct file
B.

So, the number of struct files that can be created is capped at the
number of HW state registers the device can support (eg one for
Habana).

This is different from the number of FDs pointing at the struct file.
Userpsace can open a HW state and point a lot of FDs at it, that is
userspace's problem. From a kernel view they all share one struct file
and thus one HW state.

Jason


Re: [PATCH v1 0/7] New DRM driver for Intel VPU

2022-08-08 Thread Stanislaw Gruszka
On Mon, Aug 08, 2022 at 12:34:59PM +1000, Dave Airlie wrote:
> On Thu, 28 Jul 2022 at 23:17, Jacek Lawrynowicz
>  wrote:
> >
> > Hi,
> >
> > This patchset contains a new Linux* Kernel Driver for Intel® VPUs.
> >
> > VPU stands for Versatile Processing Unit and it is an AI inference 
> > accelerator
> > integrated with Intel non-server CPUs starting from 14th generation.
> > VPU enables efficient execution of Deep Learning applications
> > like object detection, classification etc.
> >
> > Driver is part of gpu/drm subsystem because VPU is similar in operation to
> > an integrated GPU. Reusing drm driver init, ioctl handling, gem and prime
> > helpers and drm_mm allows to minimize code duplication in the kernel.
> >
> > The whole driver is licensed under GPL-2.0-only except for two headers 
> > imported
> > from the firmware that are MIT licensed.
> >
> > User mode driver stack consists of Level Zero API driver and OpenVINO 
> > plugin.
> > Both should be open-sourced by the end of Q3.
> > The firmware for the VPU will be distributed as a closed source binary.
> 
> 
> Thanks for the submission, this looks pretty good and well layed out,
> 
> just a few higher level things, I think I'd like this name intel-vpu
> or ivpu or something, VPU is a pretty generic namespace usage.

Thanks for the comments, we will consider renaming. 

> I think adding some sort of TODO file with what is missing and what
> future things need to happen would be useful to know when merging this
> might be a good idea.
> 
> I'm kinda thinking with a rename we could merge this sooner into a
> staging-lite model.

I'm not sure what we can add to TODO file, from driver perspective
I think it's pretty much ready for merging (except renaming), just
other components: F/W and user-space are not yet released.

> I think I'd like Christian/Maarten to maybe review the fencing/uapi,
> to make sure nothing too much is wrong there. The submit/waitbo model
> is getting a bit old, and using syncobjs might be useful to make it
> more modern. Is this device meant to be used by multiple users at
> once? Maybe we'd want scheduler integration for it as well (which I
> think I saw mentioned somewhere in passing).

The current approach with submit/wait_bo is simplistic but sufficient
for basic use case. In the future we are planning to add support for
HW based scheduling (we are also looking at SW scheduler) and we will
likely revisit submit/sync APIs at that time.

Regards
Stanislaw


Re: [PATCH] dma-buf: Use dma_fence_unwrap_for_each when importing fences

2022-08-08 Thread Jason Ekstrand
On Sun, 2022-08-07 at 18:35 +0200, Christian König wrote:
> Am 02.08.22 um 23:01 schrieb Jason Ekstrand:
> > Ever since 68129f431faa ("dma-buf: warn about containers in
> > dma_resv object"),
> > dma_resv_add_shared_fence will warn if you attempt to add a
> > container fence.
> > While most drivers were fine, fences can also be added to a
> > dma_resv via the
> > recently added DMA_BUF_IOCTL_IMPORT_SYNC_FILE.  Use
> > dma_fence_unwrap_for_each
> > to add each fence one at a time.
> > 
> > Fixes: 594740497e99 ("dma-buf: Add an API for importing sync files
> > (v10)")
> > Signed-off-by: Jason Ekstrand 
> > Reported-by: Sarah Walker 
> > Cc: Christian König 
> > ---
> >   drivers/dma-buf/dma-buf.c | 23 +--
> >   1 file changed, 17 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> > index 630133284e2b..8d5d45112f52 100644
> > --- a/drivers/dma-buf/dma-buf.c
> > +++ b/drivers/dma-buf/dma-buf.c
> > @@ -15,6 +15,7 @@
> >   #include 
> >   #include 
> >   #include 
> > +#include 
> >   #include 
> >   #include 
> >   #include 
> > @@ -391,8 +392,10 @@ static long dma_buf_import_sync_file(struct
> > dma_buf *dmabuf,
> >  const void __user *user_data)
> >   {
> > struct dma_buf_import_sync_file arg;
> > -   struct dma_fence *fence;
> > +   struct dma_fence *fence, *f;
> > enum dma_resv_usage usage;
> > +   struct dma_fence_unwrap iter;
> > +   unsigned int num_fences;
> > int ret = 0;
> >   
> > if (copy_from_user(, user_data, sizeof(arg)))
> > @@ -411,13 +414,21 @@ static long dma_buf_import_sync_file(struct
> > dma_buf *dmabuf,
> > usage = (arg.flags & DMA_BUF_SYNC_WRITE) ?
> > DMA_RESV_USAGE_WRITE :
> >   
> > DMA_RESV_USAGE_READ;
> >   
> > -   dma_resv_lock(dmabuf->resv, NULL);
> > +   num_fences = 0;
> > +   dma_fence_unwrap_for_each(f, , fence)
> > +   ++num_fences;
> >   
> > -   ret = dma_resv_reserve_fences(dmabuf->resv, 1);
> > -   if (!ret)
> > -   dma_resv_add_fence(dmabuf->resv, fence, usage);
> > +   if (num_fences > 0) {
> > +   dma_resv_lock(dmabuf->resv, NULL);
> >   
> > -   dma_resv_unlock(dmabuf->resv);
> > +   ret = dma_resv_reserve_fences(dmabuf->resv,
> > num_fences);
> 
> That looks like it is misplaced.
> 
> You *must* only lock the reservation object once and then add all
> fences 
> in one go.

That's what I'm doing.  Lock, reserve, add a bunch, unlock.  I am
assuming that the iterator won't suddenly want to iterate more fences
between my initial count and when I go to add them but I think that
assumption is ok.

--Jason


> Thinking now about it we probably had a bug around that before as
> well. 
> Going to double check tomorrow.
> 
> Regards,
> Christian.
> 
> > +   if (!ret) {
> > +   dma_fence_unwrap_for_each(f, , fence)
> > +   dma_resv_add_fence(dmabuf->resv, f,
> > usage);
> > +   }
> > +
> > +   dma_resv_unlock(dmabuf->resv);
> > +   }
> >   
> > dma_fence_put(fence);
> >   
> 



Re: [PATCH] i2c: qcom-geni: Fix GPI DMA buffer sync-back

2022-08-08 Thread Robin Reckmann




On Mon, 8 Aug 2022, Wolfram Sang wrote:


On Sun, Aug 07, 2022 at 11:04:54PM +0900, Robin Reckmann wrote:

Fix i2c transfers using GPI DMA mode for all message types that do not set
the I2C_M_DMA_SAFE flag (e.g. SMBus "read byte").

In this case a bounce buffer is returned by i2c_get_dma_safe_msg_buf(),
and it has to synced back to the message after the transfer is done.

Add missing assignment of dma buffer in geni_i2c_gpi().

Set xferred in i2c_put_dma_safe_msg_buf() to true in case of no error to
ensure the sync-back of this dma buffer to the message.

Signed-off-by: Robin Reckmann 


Thank you! What would be a Fixes tag for this?



Thanks for having a look!

Fixes: d8703554f4de ("i2c: qcom-geni: Add support for GPI DMA")


Re: New subsystem for acceleration devices

2022-08-08 Thread Jason Gunthorpe
On Sun, Aug 07, 2022 at 09:43:40AM +0300, Oded Gabbay wrote:

> 1. If there is a subsystem which is responsible for creating and
> exposing the device character files, then there should be some code
> that connects between each device driver to that subsystem.
> i.e. There should be functions that each driver should call from its
> probe and release callback functions.
> 
> Those functions should take care of the following:
> - Create metadata for the device, the device's minor(s) and the
> driver's ioctls table and driver's callback for file operations (both
> are common for all the driver's devices). Save all that metadata with
> proper locking.
> - Create the device char files themselves and supply file operations
> that will be called per each open/close/mmap/etc.
> - Keep track of all these objects' lifetime in regard to the device
> driver's lifetime, with proper handling for release.
> - Add common handling and entries of sysfs/debugfs for these devices
> with the ability for each device driver to add their own unique
> entries.
> 
> 2. I think that you underestimate (due to your experience) the "using
> it properly" part... It is not so easy to do this properly for
> inexperienced kernel people. If we provide all the code I mentioned
> above, the device driver writer doesn't need to be aware of all these
> kernel APIs.

This may be, but it still seems weird to me to justify a subsystem as
"making existing APIs simpler so drivers don't mess them up". It
suggests perhaps we need additional core API helpers?

> > It would be nice to at least identify something that could obviously
> > be common, like some kind of enumeration and metadata kind of stuff
> > (think like ethtool, devlink, rdma tool, nvemctl etc)
> Definitely. I think we can have at least one ioctl that will be common
> to all drivers from the start.

Generally you don't want that as an ioctl because you have to open the
device to execute it, there may be permissions issues for instance -
or if you have a single-open-at-a-time model like VFIO, then it
doesn't work well together.

Usually this would be sysfs or netlink.

> > This makes sense to me, all accelerators need a way to set a memory
> > map, but on the other hand we are doing some very nifty stuff in this
> > area with iommufd and it might be very interesting to just have the
> > accelerator driver link to that API instead of building yet another
> > copy of pin_user_pages() code.. Especially with PASID likely becoming
> > part of any accelerator toolkit.
>
> Here I disagree with you. First of all, there are many relatively
> simple accelerators, especially in edge, where PASID is really not
> relevant.
> Second, even for the more sophisticated PCIe/CXL-based ones, PASID is
> not mandatory and I suspect that it won't be in 100% of those devices.
> But definitely that should be an alternative to the "classic" way of
> handling dma'able memory (pin_user_pages()).

My point was that iommufd can do the pinning for you and dump that
result into a iommu based PASID, or it can do the pinning for you and
allow the driver to translate it into its own page table format eg the
ASID in the habana device.

We don't need to have map/unmap APIs to manage address spaces in every
subsystem.

> Maybe this is something that should be discussed in the kernel summit ?

Maybe, I expect to be at LPC at least

Jason 


Re: [PATCH] drm: Fix EDID firmware load on resume

2022-08-08 Thread Jani Nikula
On Mon, 08 Aug 2022, Matthieu CHARETTE  wrote:
> Sorry, What do you mean?

You cache with one name at connector init time, but the name specified
using drm.edid_firmware may be changed whenever, to cause the next EDID
read to use a different EDID firmware.

BR,
Jani.


>
> Matthieu
>
> On Tue, Aug 2 2022 at 05:29:12 PM +0300, Jani Nikula 
>  wrote:
>> On Wed, 27 Jul 2022, Matthieu CHARETTE > > wrote:
>>>  Loading an EDID using drm.edid_firmware parameter makes resume to 
>>> fail
>>>  after firmware cache is being cleaned. This is because edid_load() 
>>> use a
>>>  temporary device to request the firmware. This cause the EDID 
>>> firmware
>>>  not to be cached from suspend. And, requesting the EDID firmware 
>>> return
>>>  an error during resume.
>>>  So the request_firmware() call should use a permanent device for 
>>> each
>>>  connector. Also, we should cache the EDID even if no monitor is
>>>  connected, in case it's plugged while suspended.
>> 
>> AFAICT this breaks changing drm.edid_firmware runtime.
>> 
>> BR,
>> Jani.
>> 
>>> 
>>>  Link: 
>>>  Signed-off-by: Matthieu CHARETTE >> >
>>>  ---
>>>   drivers/gpu/drm/drm_connector.c |  9 
>>>   drivers/gpu/drm/drm_edid_load.c | 81 
>>> -
>>>   include/drm/drm_connector.h | 12 +
>>>   include/drm/drm_edid.h  |  3 ++
>>>   4 files changed, 94 insertions(+), 11 deletions(-)
>>> 
>>>  diff --git a/drivers/gpu/drm/drm_connector.c 
>>> b/drivers/gpu/drm/drm_connector.c
>>>  index 1c48d162c77e..e8819ebf1c4b 100644
>>>  --- a/drivers/gpu/drm/drm_connector.c
>>>  +++ b/drivers/gpu/drm/drm_connector.c
>>>  @@ -31,6 +31,7 @@
>>>   #include 
>>>   #include 
>>> 
>>>  +#include 
>>>   #include 
>>> 
>>>   #include "drm_crtc_internal.h"
>>>  @@ -289,6 +290,9 @@ int drm_connector_init(struct drm_device *dev,
>>> 
>>> drm_connector_get_cmdline_mode(connector);
>>> 
>>>  +  connector->edid_load_pdev = NULL;
>>>  +  drm_cache_edid_firmware(connector);
>>>  +
>>> /* We should add connectors at the end to avoid upsetting the 
>>> connector
>>>  * index too much.
>>>  */
>>>  @@ -473,6 +477,11 @@ void drm_connector_cleanup(struct 
>>> drm_connector *connector)
>>> connector->tile_group = NULL;
>>> }
>>> 
>>>  +  if (connector->edid_load_pdev) {
>>>  +  platform_device_unregister(connector->edid_load_pdev);
>>>  +  connector->edid_load_pdev = NULL;
>>>  +  }
>>>  +
>>> list_for_each_entry_safe(mode, t, >probed_modes, head)
>>> drm_mode_remove(connector, mode);
>>> 
>>>  diff --git a/drivers/gpu/drm/drm_edid_load.c 
>>> b/drivers/gpu/drm/drm_edid_load.c
>>>  index 37d8ba3ddb46..5a82be9917ec 100644
>>>  --- a/drivers/gpu/drm/drm_edid_load.c
>>>  +++ b/drivers/gpu/drm/drm_edid_load.c
>>>  @@ -167,6 +167,19 @@ static int edid_size(const u8 *edid, int 
>>> data_size)
>>> return (edid[0x7e] + 1) * EDID_LENGTH;
>>>   }
>>> 
>>>  +static struct platform_device *edid_pdev(const char 
>>> *connector_name)
>>>  +{
>>>  +  struct platform_device *pdev = 
>>> platform_device_register_simple(connector_name, -1, NULL, 0);
>>>  +
>>>  +  if (IS_ERR(pdev)) {
>>>  +  DRM_ERROR("Failed to register EDID firmware platform device "
>>>  +  "for connector \"%s\"\n", connector_name);
>>>  +  return ERR_CAST(pdev);
>>>  +  }
>>>  +
>>>  +  return pdev;
>>>  +}
>>>  +
>>>   static void *edid_load(struct drm_connector *connector, const char 
>>> *name,
>>> const char *connector_name)
>>>   {
>>>  @@ -182,18 +195,17 @@ static void *edid_load(struct drm_connector 
>>> *connector, const char *name,
>>> fwdata = generic_edid[builtin];
>>> fwsize = sizeof(generic_edid[builtin]);
>>> } else {
>>>  -  struct platform_device *pdev;
>>>  +  struct platform_device *pdev = connector->edid_load_pdev;
>>> int err;
>>> 
>>>  -  pdev = platform_device_register_simple(connector_name, -1, 
>>> NULL, 
>>> 0);
>>>  -  if (IS_ERR(pdev)) {
>>>  -  DRM_ERROR("Failed to register EDID firmware platform 
>>> device "
>>>  -"for connector \"%s\"\n", connector_name);
>>>  -  return ERR_CAST(pdev);
>>>  +  if (WARN_ON(!pdev)) {
>>>  +  pdev = edid_pdev(connector_name);
>>>  +  if (IS_ERR(pdev))
>>>  +  return ERR_CAST(pdev);
>>>  +  connector->edid_load_pdev = pdev;
>>> }
>>> 
>>> err = request_firmware(, name, >dev);
>>>  -  platform_device_unregister(pdev);
>>> if (err) {
>>> DRM_ERROR("Requesting EDID firmware \"%s\" failed 
>>> (err=%d)\n",
>>>   name, err);
>>>  @@ -263,11 +275,9 @@ static void *edid_load(struct drm_connector 
>>> 

Re: [PATCH v3 3/3] drm/i915/gt: document TLB cache invalidation functions

2022-08-08 Thread Andi Shyti
Hi Mauro,

On Thu, Aug 04, 2022 at 09:37:24AM +0200, Mauro Carvalho Chehab wrote:
> Add a description for the TLB cache invalidation algorithm and for
> the related kAPI functions.
> 
> Signed-off-by: Mauro Carvalho Chehab 

Reviewed-by: Andi Shyti 

Andi


[Bug 216092] rn_vbios_smu_send_msg_with_param+0xf9/0x100 - amdgpu

2022-08-08 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=216092

--- Comment #6 from Alex Deucher (alexdeuc...@gmail.com) ---
See also:
https://gitlab.freedesktop.org/drm/amd/-/issues/2110

-- 
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 v3 1/3] drm/i915: pass a pointer for tlb seqno at vma_invalidate_tlb()

2022-08-08 Thread Andi Shyti
Hi Mauro,

On Thu, Aug 04, 2022 at 09:37:22AM +0200, Mauro Carvalho Chehab wrote:
> WRITE_ONCE() should happen at the original var, not on a local
> copy of it.
> 
> Fixes: 5d36acb7198b ("drm/i915/gt: Batch TLB invalidations")
> Signed-off-by: Mauro Carvalho Chehab 

Reviewed-by: Andi Shyti 

Are you going to send it to the stable mailing list?

Andi


Re: [Linaro-mm-sig] [PATCH 1/3] dma-buf: Add ioctl to query mmap info

2022-08-08 Thread Rob Clark
On Mon, Aug 8, 2022 at 7:56 AM Christian König  wrote:
>
> Am 08.08.22 um 15:26 schrieb Rob Clark:
> > On Mon, Aug 8, 2022 at 4:22 AM Christian König  
> > wrote:
> >
> > [SNIP]
>  If the virtio/virtgpu UAPI was build around the idea that this is
>  possible then it is most likely fundamental broken.
> >>> How else can you envision mmap'ing to guest userspace working?
> >> Well long story short: You can't.
> >>
> >> See userspace mappings are not persistent, but rather faulted in on
> >> demand. The exporter is responsible for setting those up to be able to
> >> add reverse tracking and so can invalidate those mappings when the
> >> backing store changes.
> > I think that is not actually a problem.  At least for how it works on
> > arm64 but I'm almost positive x86 is similar.. I'm not sure how else
> > you could virtualize mmu/iommu/etc in a way that didn't have horrible
> > performance.
> >
> > There are two levels of pagetable translation, the first controlled by
> > the host kernel, the second by the guest.  From the PoV of host
> > kernel, it is just memory mapped to userspace, getting faulted in on
> > demand, just as normal.  First the guest controlled translation
> > triggers a fault in the guest which sets up guest mapping.  And then
> > the second level of translation to translate from what guest sees as
> > PA (but host sees as VA) to actual PA triggers a fault in the host.
>
> Ok, that's calming.
>
> At least that's not the approach talked about the last time this came up
> and it doesn't rip a massive security hole somewhere.

Hmm, tbh I'm not sure which thread/discussion this was.. it could have
been before I was paying much attention to the vm use-case

> The question is why is the guest then not using the caching attributes
> setup by the host page tables when the translation is forwarded anyway?

The guest kernel itself doesn't know.  AFAICT, at least on arm, the hw
will combine the attributes of the mapping in S1 and S2 pagetables and
use the most restrictive.  So if S1 (host) is cached but S2 (guest) is
WC, you'll end up w/ WC.

That said, at least on aarch64, it seems like we could always tell the
guest it is cached, and if mapped WC in S1 you'll end up with WC
access.  But this seems to depend on an optional feature, FWB, which
allows S2 to override S1 attributes, not being enabled.  And not
entirely sure how it works on x86.

BR,
-R

> > [SNIP]
> > This is basically what happens, although via the two levels of pgtable
> > translation.  This patch provides the missing piece, the caching
> > attributes.
>
> Yeah, but that won't work like this. See the backing store migrates all
> the time and when it is backed by PCIe/VRAM/local memory you need to use
> write combine while system memory is usually cached.
>
> >>   Because otherwise you can't accommodate that the exporter is
> >> changing those caching attributes.
> > Changing the attributes dynamically isn't going to work.. or at least
> > not easily.  If you had some sort of synchronous notification to host
> > userspace, it could trigger an irq to the guest, I suppose.  But it
> > would mean host kernel has to block waiting for host userspace to
> > interrupt the guest, then wait for guest vgpu process to be scheduled
> > and handle the irq.
>
> We basically change that on every page flip on APUs and that doesn't
> sound like something fast.
>
> Thanks for the explanation how this works,
> Christian.
>
> >
> > At least in the case of msm, the cache attributes are static for the
> > life of the buffer, so this scenario isn't a problem.  AFAICT this
> > should work fine for at least all UMA hw.. I'm a bit less sure when it
> > comes to TTM, but shouldn't you at least be able to use worst-cache
> > cache attributes for buffers that are allowed to be mapped to guest?
> >
> > BR,
> > -R
> >
> >>> But more seriously, let's take a step back here.. what scenarios are
> >>> you seeing this being problematic for?  Then we can see how to come up
> >>> with solutions.  The current situation of host userspace VMM just
> >>> guessing isn't great.
> >> Well "isn't great" is a complete understatement. When KVM/virtio/virtgpu
> >> is doing what I guess they are doing here then that is a really major
> >> security hole.
> >>
> >>> And sticking our heads in the sand and
> >>> pretending VMs don't exist isn't great.  So what can we do?  I can
> >>> instead add a msm ioctl to return this info and solve the problem even
> >>> more narrowly for a single platform.  But then the problem still
> >>> remains on other platforms.
> >> Well once more: This is *not* MSM specific, you just absolutely *can't
> >> do that* for any driver!
> >>
> >> I'm just really wondering what the heck is going on here, because all of
> >> this was discussed in lengthy before on the mailing list and very
> >> bluntly rejected.
> >>
> >> Either I'm missing something (that's certainly possible) or we have a
> >> strong case of somebody implementing something without 

[PATCH 1/2] drm/fourcc: Add Synaptics VideoSmart tiled modifiers

2022-08-08 Thread Hsia-Jun Li
From: "Hsia-Jun(Randy) Li" 

Memory Traffic Reduction(MTR) is a module in Synaptics
VideoSmart platform could process lossless compression image
and cache the tile memory line.

Those modifiers only record the parameters would effort pixel
layout or memory layout. Whether physical memory page mapping
is used is not a part of format.

We would allocate the same size of memory for uncompressed
and compressed luma and chroma data, while the compressed buffer
would request two extra planes holding the metadata for
the decompression.

The reason why we need to allocate the same size of memory for
the compressed frame:
1. The compression ratio is not fixed and differnt platforms could
use a different compression protocol. These protocols are complete
vendor proprietaries, the other device won't be able to use them.
It is not necessary to define the version of them here.

2. Video codec could discard the compression attribute when the
intra block copy applied to this frame. It would waste lots of
time on re-allocation.

I am wondering if it is better to add an addtional plane property to
describe whether the current framebuffer is compressed?
While the compression flag is still a part of format modifier,
because it would have two extra meta data planes in the compression
version.

Signed-off-by: Hsia-Jun(Randy) Li 
---
 include/uapi/drm/drm_fourcc.h | 49 +++
 1 file changed, 49 insertions(+)

diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index 0206f812c569..b67884e8bc69 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -381,6 +381,7 @@ extern "C" {
 #define DRM_FORMAT_MOD_VENDOR_ARM 0x08
 #define DRM_FORMAT_MOD_VENDOR_ALLWINNER 0x09
 #define DRM_FORMAT_MOD_VENDOR_AMLOGIC 0x0a
+#define DRM_FORMAT_MOD_VENDOR_SYNAPTICS 0x0b
 
 /* add more to the end as needed */
 
@@ -1452,6 +1453,54 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier)
 #define AMD_FMT_MOD_CLEAR(field) \
(~((__u64)AMD_FMT_MOD_##field##_MASK << AMD_FMT_MOD_##field##_SHIFT))
 
+/*
+ * Synaptics VideoSmart modifiers
+ *
+ *   Macro
+ * Bits  Param Description
+ *   - 
-
+ *
+ *  7:0  f Scan direction description.
+ *
+ *   0 = Invalid
+ *   1 = V4, the scan would always start from vertical for 4 pixel
+ *   then move back to the start pixel of the next horizontal
+ *   direction.
+ *   2 = Reserved for future use.
+ *
+ * 15:8  m The times of pattern repeat in the right angle direction from
+ * the first scan direction.
+ *
+ * 19:16 p The padding bits after the whole scan, could be zero.
+ *
+ * 35:20 - Reserved for future use.  Must be zero.
+ *
+ * 36:36 c Compression flag.
+ *
+ * 55:37 - Reserved for future use.  Must be zero.
+ *
+ */
+
+#define DRM_FORMAT_MOD_SYNA_V4_TILED   fourcc_mod_code(SYNAPTICS, 1)
+
+#define DRM_FORMAT_MOD_SYNA_MTR_LINEAR_2D(f, m, p, c) \
+   fourcc_mod_code(SYNAPTICS, (((f) & 0xff) | \
+(((m) & 0xff) << 8) | \
+(((p) & 0xf) << 16) | \
+(((c) & 0x1) << 36)))
+
+#define DRM_FORMAT_MOD_SYNA_V4H1 \
+   DRM_FORMAT_MOD_SYNA_MTR_LINEAR_2D(1, 1, 0, 0)
+
+#define DRM_FORMAT_MOD_SYNA_V4H3P8 \
+   DRM_FORMAT_MOD_SYNA_MTR_LINEAR_2D(1, 3, 8, 0)
+
+#define DRM_FORMAT_MOD_SYNA_V4H1_COMPRESSED \
+   DRM_FORMAT_MOD_SYNA_MTR_LINEAR_2D(1, 1, 0, 1)
+
+#define DRM_FORMAT_MOD_SYNA_V4H3P8_COMPRESSED \
+   DRM_FORMAT_MOD_SYNA_MTR_LINEAR_2D(1, 3, 8, 1)
+
 #if defined(__cplusplus)
 }
 #endif
-- 
2.17.1



[PATCH 2/2] [WIP]: media: Add Synaptics compressed tiled format

2022-08-08 Thread Hsia-Jun Li
From: "Hsia-Jun(Randy) Li" 

The most of detail has been written in the drm.
Please notice that the tiled formats here request
one more plane for storing the motion vector metadata.
This buffer won't be compressed, so you can't append
it to luma or chroma plane.

Signed-off-by: Hsia-Jun(Randy) Li 
---
 drivers/media/v4l2-core/v4l2-common.c | 1 +
 drivers/media/v4l2-core/v4l2-ioctl.c  | 2 ++
 include/uapi/linux/videodev2.h| 2 ++
 3 files changed, 5 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-common.c 
b/drivers/media/v4l2-core/v4l2-common.c
index e0fbe6ba4b6c..f645278b3055 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -314,6 +314,7 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
{ .format = V4L2_PIX_FMT_SGBRG12,   .pixel_enc = 
V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, 
.hdiv = 1, .vdiv = 1 },
{ .format = V4L2_PIX_FMT_SGRBG12,   .pixel_enc = 
V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, 
.hdiv = 1, .vdiv = 1 },
{ .format = V4L2_PIX_FMT_SRGGB12,   .pixel_enc = 
V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, 
.hdiv = 1, .vdiv = 1 },
+   { .format = V4L2_PIX_FMT_NV12M_V4H1C, .pixel_enc = 
V4L2_PIXEL_ENC_YUV, .mem_planes = 5, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, 
.hdiv = 2, .vdiv = 2, .block_w = { 128, 128 }, .block_h = { 128, 128 } },
};
unsigned int i;
 
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index e6fd355a2e92..8f65964aff08 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1497,6 +1497,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_PIX_FMT_MT21C:descr = "Mediatek Compressed 
Format"; break;
case V4L2_PIX_FMT_QC08C:descr = "QCOM Compressed 8-bit 
Format"; break;
case V4L2_PIX_FMT_QC10C:descr = "QCOM Compressed 10-bit 
Format"; break;
+   case V4L2_PIX_FMT_NV12M_V4H1C:  descr = "Synaptics Compressed 
8-bit tiled Format";break;
+   case V4L2_PIX_FMT_NV12M_10_V4H3P8C: descr = "Synaptics 
Compressed 10-bit tiled Format";break;
default:
if (fmt->description[0])
return;
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 01e630f2ec78..7e928cb69e7c 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -661,6 +661,8 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2') /* 12  
Y/CbCr 4:2:0 16x16 tiles */
 #define V4L2_PIX_FMT_NV12M_8L128  v4l2_fourcc('N', 'A', '1', '2') /* 
Y/CbCr 4:2:0 8x128 tiles */
 #define V4L2_PIX_FMT_NV12M_10BE_8L128 v4l2_fourcc_be('N', 'T', '1', '2') /* 
Y/CbCr 4:2:0 10-bit 8x128 tiles */
+#define V4L2_PIX_FMT_NV12M_V4H1C v4l2_fourcc('S', 'Y', '1', '2')   /* 12  
Y/CbCr 4:2:0 tiles */
+#define V4L2_PIX_FMT_NV12M_10_V4H3P8C v4l2_fourcc('S', 'Y', '1', '0')   /* 12  
Y/CbCr 4:2:0 10-bits tiles */
 
 /* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */
 #define V4L2_PIX_FMT_SBGGR8  v4l2_fourcc('B', 'A', '8', '1') /*  8  BGBG.. 
GRGR.. */
-- 
2.17.1



[PATCH 0/2] Add pixel formats used in Synatpics SoC

2022-08-08 Thread Hsia-Jun Li
From: "Hsia-Jun(Randy) Li" 

Those pixel formats are used in Synaptics's VideoSmart series SoCs,
likes VS640, VS680.  I just disclose the pixel formats used in the video
codecs and display pipeline this time. Actually any device with a MTR
module could support those tiled and compressed pixel formats. The more
detail about MTR module could be found in the first patch of this serial
of mail.

We may not be able to post any drivers here in a short time, the most of
work in this platform is done in the Trusted Execution Environment and
we didn't use the optee framework.

Please notice that, the memory planes used for video codecs would be 5
when the compression is invoked while it would be 4 for display, the
extra planes in the video codecs is for the decoding internally usage,
it can't append the luma or chroma buffer as many other drivers do,
because this buffer could be only accessed by the video codecs itself,
it requests a different memory security attributes. Any other reason is
described in the v4l pixel formats's patch. I don't know whether a
different numbers of memory planes between drm and v4l2 is acceptable.

I only posted the compression fourcc for the v4l2, because it is really
hard to put the uncompression version of pixel formats under the fourcc.
I would be better that we could have something likes format modifers in
drm here.

https://synaptics.com/products/multimedia-solutions

Hsia-Jun(Randy) Li (2):
  drm/fourcc: Add Synaptics VideoSmart tiled modifiers
  [WIP]: media: Add Synaptics compressed tiled format

 drivers/media/v4l2-core/v4l2-common.c |  1 +
 drivers/media/v4l2-core/v4l2-ioctl.c  |  2 ++
 include/uapi/drm/drm_fourcc.h | 49 +++
 include/uapi/linux/videodev2.h|  2 ++
 4 files changed, 54 insertions(+)

-- 
2.17.1



Re: [PATCH v2 1/3] drivers: serial: earlycon: Correct argument name

2022-08-08 Thread Rob Herring
On Sat, Aug 6, 2022 at 10:34 AM Markuss Broks  wrote:
>
> The "node" argument is actually an offset,

It's an offset to a node in the FDT. The fact that it is an offset is
an internal implementation detail of the FDT format. So really, it's a
handle to a node. 'node' is more descriptive to its purpose.

> and it's also an "int", and not "unsigned long".

Uh, no it's not. of_flat_dt_*() functions all take an unsigned long.

Rob


Re: [PATCH v5] drm/i915: stop using swiotlb

2022-08-08 Thread Hellstrom, Thomas
Hi, [back from vacation]

On Tue, 2022-07-26 at 16:39 +0100, Robert Beckett wrote:
> Calling swiotlb functions directly is nowadays considered harmful.
> See
> https://lore.kernel.org/intel-gfx/20220711082614.ga29...@lst.de/
> 
> Replace swiotlb_max_segment() calls with dma_max_mapping_size().
> In i915_gem_object_get_pages_internal() no longer consider
> max_segment
> only if CONFIG_SWIOTLB is enabled. There can be other (iommu related)
> causes of specific max segment sizes.
> 
> Cc: Christoph Hellwig 
> Cc: Tvrtko Ursulin 
> Cc: Thomas Hellstrom 
> Cc: Matthew Auld 
> 
> v2: - restore UINT_MAX clamp in i915_sg_segment_size()
>     - drop PAGE_SIZE check as it will always be >= PAGE_SIZE
> v3: - actually clamp to UINT_MAX in i915_sg_segment_size()
> v4: - round down max segment size to PAGE_SIZE
> v5: - fix checkpatch whitespace issue
> 
> Reviewed-by: Christoph Hellwig 
> Reviewed-by: Tvrtko Ursulin 
> Signed-off-by: Robert Beckett 

Hmm,

This whole thing looks a bit strange to me since with SWIOTLB actually
used for i915, the driver should malfunction anyway as it doesn't do
any dma_sync_sg_for_cpu() or dma_sync_sg_for_device(), and the driver
assumes all coherent dma. Is that SWIOTLB=force kernel option still
available?

Also, correct me if I'm wrong, but the original driver segment size
appears to mean "the largest contiguous area that can be handled either
by the device or the dma mapping layer" rather than the total space
available for dma mappings? Not completely sure what
dma_max_mapping_size() is returning, though?

/Thomas




Re: [PATCH] drm: Fix EDID firmware load on resume

2022-08-08 Thread Matthieu CHARETTE

Sorry, What do you mean?

Matthieu

On Tue, Aug 2 2022 at 05:29:12 PM +0300, Jani Nikula 
 wrote:
On Wed, 27 Jul 2022, Matthieu CHARETTE  
wrote:
 Loading an EDID using drm.edid_firmware parameter makes resume to 
fail
 after firmware cache is being cleaned. This is because edid_load() 
use a
 temporary device to request the firmware. This cause the EDID 
firmware
 not to be cached from suspend. And, requesting the EDID firmware 
return

 an error during resume.
 So the request_firmware() call should use a permanent device for 
each

 connector. Also, we should cache the EDID even if no monitor is
 connected, in case it's plugged while suspended.


AFAICT this breaks changing drm.edid_firmware runtime.

BR,
Jani.



 Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2061
 Signed-off-by: Matthieu CHARETTE 
 ---
  drivers/gpu/drm/drm_connector.c |  9 
  drivers/gpu/drm/drm_edid_load.c | 81 
-

  include/drm/drm_connector.h | 12 +
  include/drm/drm_edid.h  |  3 ++
  4 files changed, 94 insertions(+), 11 deletions(-)

 diff --git a/drivers/gpu/drm/drm_connector.c 
b/drivers/gpu/drm/drm_connector.c

 index 1c48d162c77e..e8819ebf1c4b 100644
 --- a/drivers/gpu/drm/drm_connector.c
 +++ b/drivers/gpu/drm/drm_connector.c
 @@ -31,6 +31,7 @@
  #include 
  #include 

 +#include 
  #include 

  #include "drm_crtc_internal.h"
 @@ -289,6 +290,9 @@ int drm_connector_init(struct drm_device *dev,

drm_connector_get_cmdline_mode(connector);

 +  connector->edid_load_pdev = NULL;
 +  drm_cache_edid_firmware(connector);
 +
  	/* We should add connectors at the end to avoid upsetting the 
connector

 * index too much.
 */
 @@ -473,6 +477,11 @@ void drm_connector_cleanup(struct 
drm_connector *connector)

connector->tile_group = NULL;
}

 +  if (connector->edid_load_pdev) {
 +  platform_device_unregister(connector->edid_load_pdev);
 +  connector->edid_load_pdev = NULL;
 +  }
 +
list_for_each_entry_safe(mode, t, >probed_modes, head)
drm_mode_remove(connector, mode);

 diff --git a/drivers/gpu/drm/drm_edid_load.c 
b/drivers/gpu/drm/drm_edid_load.c

 index 37d8ba3ddb46..5a82be9917ec 100644
 --- a/drivers/gpu/drm/drm_edid_load.c
 +++ b/drivers/gpu/drm/drm_edid_load.c
 @@ -167,6 +167,19 @@ static int edid_size(const u8 *edid, int 
data_size)

return (edid[0x7e] + 1) * EDID_LENGTH;
  }

 +static struct platform_device *edid_pdev(const char 
*connector_name)

 +{
 +	struct platform_device *pdev = 
platform_device_register_simple(connector_name, -1, NULL, 0);

 +
 +  if (IS_ERR(pdev)) {
 +  DRM_ERROR("Failed to register EDID firmware platform device "
 +  "for connector \"%s\"\n", connector_name);
 +  return ERR_CAST(pdev);
 +  }
 +
 +  return pdev;
 +}
 +
  static void *edid_load(struct drm_connector *connector, const char 
*name,

const char *connector_name)
  {
 @@ -182,18 +195,17 @@ static void *edid_load(struct drm_connector 
*connector, const char *name,

fwdata = generic_edid[builtin];
fwsize = sizeof(generic_edid[builtin]);
} else {
 -  struct platform_device *pdev;
 +  struct platform_device *pdev = connector->edid_load_pdev;
int err;

 -		pdev = platform_device_register_simple(connector_name, -1, NULL, 
0);

 -  if (IS_ERR(pdev)) {
 -  DRM_ERROR("Failed to register EDID firmware platform device 
"
 -"for connector \"%s\"\n", connector_name);
 -  return ERR_CAST(pdev);
 +  if (WARN_ON(!pdev)) {
 +  pdev = edid_pdev(connector_name);
 +  if (IS_ERR(pdev))
 +  return ERR_CAST(pdev);
 +  connector->edid_load_pdev = pdev;
}

err = request_firmware(, name, >dev);
 -  platform_device_unregister(pdev);
if (err) {
DRM_ERROR("Requesting EDID firmware \"%s\" failed 
(err=%d)\n",
  name, err);
 @@ -263,11 +275,9 @@ static void *edid_load(struct drm_connector 
*connector, const char *name,

return edid;
  }

 -struct edid *drm_load_edid_firmware(struct drm_connector 
*connector)

 +static char *edid_name(const char *connector_name)
  {
 -  const char *connector_name = connector->name;
char *edidname, *last, *colon, *fwstr, *edidstr, *fallback = NULL;
 -  struct edid *edid;

if (edid_firmware[0] == '\0')
return ERR_PTR(-ENOENT);
 @@ -310,8 +320,57 @@ struct edid *drm_load_edid_firmware(struct 
drm_connector *connector)

if (*last == '\n')
*last = '\0';

 -  edid = edid_load(connector, edidname, connector_name);
 +  edidname = 

Re: [PATCH] drm: Fix EDID firmware load on resume

2022-08-08 Thread Matthieu CHARETTE

Sorry, What do you mean?

Matthieu

On Tue, Aug 2 2022 at 05:29:12 PM +0300, Jani Nikula 
 wrote:
On Wed, 27 Jul 2022, Matthieu CHARETTE > wrote:
 Loading an EDID using drm.edid_firmware parameter makes resume to 
fail
 after firmware cache is being cleaned. This is because edid_load() 
use a
 temporary device to request the firmware. This cause the EDID 
firmware
 not to be cached from suspend. And, requesting the EDID firmware 
return

 an error during resume.
 So the request_firmware() call should use a permanent device for 
each

 connector. Also, we should cache the EDID even if no monitor is
 connected, in case it's plugged while suspended.


AFAICT this breaks changing drm.edid_firmware runtime.

BR,
Jani.



 Link: 
 Signed-off-by: Matthieu CHARETTE >

 ---
  drivers/gpu/drm/drm_connector.c |  9 
  drivers/gpu/drm/drm_edid_load.c | 81 
-

  include/drm/drm_connector.h | 12 +
  include/drm/drm_edid.h  |  3 ++
  4 files changed, 94 insertions(+), 11 deletions(-)

 diff --git a/drivers/gpu/drm/drm_connector.c 
b/drivers/gpu/drm/drm_connector.c

 index 1c48d162c77e..e8819ebf1c4b 100644
 --- a/drivers/gpu/drm/drm_connector.c
 +++ b/drivers/gpu/drm/drm_connector.c
 @@ -31,6 +31,7 @@
  #include 
  #include 

 +#include 
  #include 

  #include "drm_crtc_internal.h"
 @@ -289,6 +290,9 @@ int drm_connector_init(struct drm_device *dev,

drm_connector_get_cmdline_mode(connector);

 +  connector->edid_load_pdev = NULL;
 +  drm_cache_edid_firmware(connector);
 +
  	/* We should add connectors at the end to avoid upsetting the 
connector

 * index too much.
 */
 @@ -473,6 +477,11 @@ void drm_connector_cleanup(struct 
drm_connector *connector)

connector->tile_group = NULL;
}

 +  if (connector->edid_load_pdev) {
 +  platform_device_unregister(connector->edid_load_pdev);
 +  connector->edid_load_pdev = NULL;
 +  }
 +
list_for_each_entry_safe(mode, t, >probed_modes, head)
drm_mode_remove(connector, mode);

 diff --git a/drivers/gpu/drm/drm_edid_load.c 
b/drivers/gpu/drm/drm_edid_load.c

 index 37d8ba3ddb46..5a82be9917ec 100644
 --- a/drivers/gpu/drm/drm_edid_load.c
 +++ b/drivers/gpu/drm/drm_edid_load.c
 @@ -167,6 +167,19 @@ static int edid_size(const u8 *edid, int 
data_size)

return (edid[0x7e] + 1) * EDID_LENGTH;
  }

 +static struct platform_device *edid_pdev(const char 
*connector_name)

 +{
 +	struct platform_device *pdev = 
platform_device_register_simple(connector_name, -1, NULL, 0);

 +
 +  if (IS_ERR(pdev)) {
 +  DRM_ERROR("Failed to register EDID firmware platform device "
 +  "for connector \"%s\"\n", connector_name);
 +  return ERR_CAST(pdev);
 +  }
 +
 +  return pdev;
 +}
 +
  static void *edid_load(struct drm_connector *connector, const char 
*name,

const char *connector_name)
  {
 @@ -182,18 +195,17 @@ static void *edid_load(struct drm_connector 
*connector, const char *name,

fwdata = generic_edid[builtin];
fwsize = sizeof(generic_edid[builtin]);
} else {
 -  struct platform_device *pdev;
 +  struct platform_device *pdev = connector->edid_load_pdev;
int err;

 -		pdev = platform_device_register_simple(connector_name, -1, NULL, 
0);

 -  if (IS_ERR(pdev)) {
 -  DRM_ERROR("Failed to register EDID firmware platform device 
"
 -"for connector \"%s\"\n", connector_name);
 -  return ERR_CAST(pdev);
 +  if (WARN_ON(!pdev)) {
 +  pdev = edid_pdev(connector_name);
 +  if (IS_ERR(pdev))
 +  return ERR_CAST(pdev);
 +  connector->edid_load_pdev = pdev;
}

err = request_firmware(, name, >dev);
 -  platform_device_unregister(pdev);
if (err) {
DRM_ERROR("Requesting EDID firmware \"%s\" failed 
(err=%d)\n",
  name, err);
 @@ -263,11 +275,9 @@ static void *edid_load(struct drm_connector 
*connector, const char *name,

return edid;
  }

 -struct edid *drm_load_edid_firmware(struct drm_connector 
*connector)

 +static char *edid_name(const char *connector_name)
  {
 -  const char *connector_name = connector->name;
char *edidname, *last, *colon, *fwstr, *edidstr, *fallback = NULL;
 -  struct edid *edid;

if (edid_firmware[0] == '\0')
return ERR_PTR(-ENOENT);
 @@ -310,8 +320,57 @@ struct edid *drm_load_edid_firmware(struct 
drm_connector *connector)

if (*last == '\n')
*last = '\0';

 -  edid = 

Re: [PATCH 5/5] drm/vkms: Support registering configfs devices

2022-08-08 Thread Sean Paul
On Fri, Jul 22, 2022 at 05:32:13PM -0400, Jim Shargo wrote:
> VKMS now supports creating virtual cards and registering them to create
> real drm devices.
> 
> In addition to the registration logic, this commit also prevents users
> from adding new objects once a card is registered.
> 
> Signed-off-by: Jim Shargo 
> ---
>  drivers/gpu/drm/vkms/vkms_configfs.c |  27 +++-
>  drivers/gpu/drm/vkms/vkms_drv.c  |  21 ++-
>  drivers/gpu/drm/vkms/vkms_drv.h  |   3 +
>  drivers/gpu/drm/vkms/vkms_output.c   | 227 ---
>  4 files changed, 251 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c 
> b/drivers/gpu/drm/vkms/vkms_configfs.c
> index fa0d8700258e..6f0f4e39864a 100644
> --- a/drivers/gpu/drm/vkms/vkms_configfs.c
> +++ b/drivers/gpu/drm/vkms/vkms_configfs.c
> @@ -326,8 +326,15 @@ static struct config_item_type plane_type = {
>  static struct config_group *connectors_group_make(struct config_group *group,
> const char *name)
>  {
> - struct vkms_config_connector *connector =
> - kzalloc(sizeof(struct vkms_config_connector), GFP_KERNEL);
> + struct vkms_configfs *configfs =
> + container_of(group, struct vkms_configfs, connectors_group);
> + struct vkms_config_connector *connector;
> +
> + if (configfs->card) {

I think it would be better to assign configfs->card in
card_is_registered_store() after successful call to vkms_card_init(). My
reasoning is that the functions in this file care about configfs->card, and not
vkms_drv.c. As a bonus, you can also eliminate the if (configfs) check before
the assignment which is necessary in vkms_card_init() but not
card_is_registered_store().

> + return ERR_PTR(EBUSY);

Nit: Negative errno please (applies elsewhere through the patch as well).

> + }

Nit: remove braces

> +
> + connector = kzalloc(sizeof(struct vkms_config_connector), GFP_KERNEL);

Nit: sizeof(*connector) could be handy here and elsewhere below.

It's a bit awkward to make use of devres elsewhere and not here. I guess the
devres group doesn't exist at this point and perhaps card destruction and
config_group destruction aren't strictly ordered. ¯\_(ツ)_/¯

>   if (!connector)
>   return ERR_PTR(ENOMEM);
>  
> @@ -368,6 +375,9 @@ static struct config_group *crtcs_group_make(struct 
> config_group *group,
>VKMS_MAX_OUTPUT_OBJECTS);
>   struct vkms_config_crtc *crtc;
>  
> + if (configfs->card)

It really feels like we should have some locking protecting us from races
between adding new components and registration.

> + return ERR_PTR(EBUSY);
> +
>   if (next_idx == VKMS_MAX_OUTPUT_OBJECTS) {
>   DRM_ERROR("Unable to allocate another CRTC.");
>   return ERR_PTR(ENOMEM);
> @@ -413,6 +423,9 @@ static struct config_group *encoders_group_make(struct 
> config_group *group,
>   >allocated_encoders, VKMS_MAX_OUTPUT_OBJECTS);
>   struct vkms_config_encoder *encoder;
>  
> + if (configfs->card)
> + return ERR_PTR(EBUSY);
> +
>   if (next_idx == VKMS_MAX_OUTPUT_OBJECTS) {
>   DRM_ERROR("Unable to allocate another encoder.");
>   return ERR_PTR(ENOMEM);
> @@ -454,8 +467,14 @@ static struct config_item_type encoders_group_type = {
>  static struct config_group *make_plane_group(struct config_group *group,
>const char *name)
>  {
> - struct vkms_config_plane *plane =
> - kzalloc(sizeof(struct vkms_config_plane), GFP_KERNEL);
> + struct vkms_configfs *configfs =
> + container_of(group, struct vkms_configfs, planes_group);
> + struct vkms_config_plane *plane;
> +
> + if (configfs->card)
> + return ERR_PTR(EBUSY);
> +
> + plane = kzalloc(sizeof(struct vkms_config_plane), GFP_KERNEL);
>   if (!plane)
>   return ERR_PTR(ENOMEM);
>  
> diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
> index 37b95ca28672..4e00f3b0de7d 100644
> --- a/drivers/gpu/drm/vkms/vkms_drv.c
> +++ b/drivers/gpu/drm/vkms/vkms_drv.c
> @@ -216,7 +216,7 @@ struct vkms_card *vkms_card_init(const char *name, struct 
> vkms_configfs *configf
>   goto out_release_group;
>   }
>  
> - ret = drm_vblank_init(>drm, 1);
> + ret = drm_vblank_init(>drm, vkms_card_crtc_count(card));

I wonder if you could re-order this below vkms_modeset_init() and use
card->output.num_crtcs instead of the new function?

>   if (ret) {
>   DRM_ERROR("Failed to vblank\n");
>   goto out_release_group;
> @@ -231,7 +231,7 @@ struct vkms_card *vkms_card_init(const char *name, struct 
> vkms_configfs *configf
>   ret = drm_dev_register(>drm, 0);
>   if (ret) {
>   DRM_ERROR("Unable to register card");
> - return ERR_PTR(ret);

[PATCH 1/3] dma-buf: heaps: add Linaro secure dmabuf heap support

2022-08-08 Thread Olivier Masse
add Linaro secure heap compatible reserved mem: linaro,secure-heap
use genalloc to allocate/free buffer from buffer pool.
buffer pool info is defined from a dts reserved memory.

Signed-off-by: Olivier Masse 
---
 drivers/dma-buf/heaps/Kconfig   |   9 +
 drivers/dma-buf/heaps/Makefile  |   1 +
 drivers/dma-buf/heaps/secure_heap.c | 339 
 3 files changed, 349 insertions(+)
 create mode 100644 drivers/dma-buf/heaps/secure_heap.c

diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
index 3782eeeb91c0..c9070c728b9a 100644
--- a/drivers/dma-buf/heaps/Kconfig
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -20,3 +20,12 @@ config DMABUF_HEAPS_DSP
   Choose this option to enable the dsp dmabuf heap. The dsp heap
   is allocated by gen allocater. it's allocated according the dts.
   If in doubt, say Y.
+
+config DMABUF_HEAPS_SECURE
+   tristate "DMA-BUF Secure Heap"
+   depends on DMABUF_HEAPS
+   help
+ Choose this option to enable the secure dmabuf heap. The secure heap
+ pools are defined according to the DT. Heaps are allocated
+ in the pools using gen allocater.
+ If in doubt, say Y.
diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
index 29733f84c354..863ef10056a3 100644
--- a/drivers/dma-buf/heaps/Makefile
+++ b/drivers/dma-buf/heaps/Makefile
@@ -2,3 +2,4 @@
 obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)  += system_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_DSP)  += dsp_heap.o
+obj-$(CONFIG_DMABUF_HEAPS_SECURE)  += secure_heap.o
diff --git a/drivers/dma-buf/heaps/secure_heap.c 
b/drivers/dma-buf/heaps/secure_heap.c
new file mode 100644
index ..a3023bf8d457
--- /dev/null
+++ b/drivers/dma-buf/heaps/secure_heap.c
@@ -0,0 +1,339 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DMABUF secure heap exporter
+ *
+ * Copyright 2022 NXP.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_SECURE_HEAP 2
+#define MAX_HEAP_NAME_LEN 32
+
+struct secure_heap_buffer {
+   struct dma_heap *heap;
+   struct list_head attachments;
+   struct mutex lock;
+   unsigned long len;
+   struct sg_table sg_table;
+   int vmap_cnt;
+   void *vaddr;
+};
+
+struct secure_heap_attachment {
+   struct device *dev;
+   struct sg_table *table;
+   struct list_head list;
+};
+
+struct secure_heap_info {
+   struct gen_pool *pool;
+};
+
+struct rmem_secure {
+   phys_addr_t base;
+   phys_addr_t size;
+
+   char name[MAX_HEAP_NAME_LEN];
+};
+
+static struct rmem_secure secure_data[MAX_SECURE_HEAP] = {0};
+static unsigned int secure_data_count;
+
+static struct sg_table *dup_sg_table(struct sg_table *table)
+{
+   struct sg_table *new_table;
+   int ret, i;
+   struct scatterlist *sg, *new_sg;
+
+   new_table = kzalloc(sizeof(*new_table), GFP_KERNEL);
+   if (!new_table)
+   return ERR_PTR(-ENOMEM);
+
+   ret = sg_alloc_table(new_table, table->orig_nents, GFP_KERNEL);
+   if (ret) {
+   kfree(new_table);
+   return ERR_PTR(-ENOMEM);
+   }
+
+   new_sg = new_table->sgl;
+   for_each_sgtable_sg(table, sg, i) {
+   sg_set_page(new_sg, sg_page(sg), sg->length, sg->offset);
+   new_sg->dma_address = sg->dma_address;
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
+   new_sg->dma_length = sg->dma_length;
+#endif
+   new_sg = sg_next(new_sg);
+   }
+
+   return new_table;
+}
+
+static int secure_heap_attach(struct dma_buf *dmabuf,
+ struct dma_buf_attachment *attachment)
+{
+   struct secure_heap_buffer *buffer = dmabuf->priv;
+   struct secure_heap_attachment *a;
+   struct sg_table *table;
+
+   a = kzalloc(sizeof(*a), GFP_KERNEL);
+   if (!a)
+   return -ENOMEM;
+
+   table = dup_sg_table(>sg_table);
+   if (IS_ERR(table)) {
+   kfree(a);
+   return PTR_ERR(table);
+   }
+
+   a->table = table;
+   a->dev = attachment->dev;
+   INIT_LIST_HEAD(>list);
+   attachment->priv = a;
+
+   mutex_lock(>lock);
+   list_add(>list, >attachments);
+   mutex_unlock(>lock);
+
+   return 0;
+}
+
+static void secure_heap_detach(struct dma_buf *dmabuf,
+  struct dma_buf_attachment *attachment)
+{
+   struct secure_heap_buffer *buffer = dmabuf->priv;
+   struct secure_heap_attachment *a = attachment->priv;
+
+   mutex_lock(>lock);
+   list_del(>list);
+   mutex_unlock(>lock);
+
+   sg_free_table(a->table);
+   kfree(a->table);
+   kfree(a);
+}
+
+static struct sg_table *secure_heap_map_dma_buf(struct dma_buf_attachment 
*attachment,
+   enum 

Re: [Linaro-mm-sig] [PATCH 1/3] dma-buf: Add ioctl to query mmap info

2022-08-08 Thread Christian König

Am 08.08.22 um 15:26 schrieb Rob Clark:

On Mon, Aug 8, 2022 at 4:22 AM Christian König  wrote:

[SNIP]

If the virtio/virtgpu UAPI was build around the idea that this is
possible then it is most likely fundamental broken.

How else can you envision mmap'ing to guest userspace working?

Well long story short: You can't.

See userspace mappings are not persistent, but rather faulted in on
demand. The exporter is responsible for setting those up to be able to
add reverse tracking and so can invalidate those mappings when the
backing store changes.

I think that is not actually a problem.  At least for how it works on
arm64 but I'm almost positive x86 is similar.. I'm not sure how else
you could virtualize mmu/iommu/etc in a way that didn't have horrible
performance.

There are two levels of pagetable translation, the first controlled by
the host kernel, the second by the guest.  From the PoV of host
kernel, it is just memory mapped to userspace, getting faulted in on
demand, just as normal.  First the guest controlled translation
triggers a fault in the guest which sets up guest mapping.  And then
the second level of translation to translate from what guest sees as
PA (but host sees as VA) to actual PA triggers a fault in the host.


Ok, that's calming.

At least that's not the approach talked about the last time this came up 
and it doesn't rip a massive security hole somewhere.


The question is why is the guest then not using the caching attributes 
setup by the host page tables when the translation is forwarded anyway?



[SNIP]
This is basically what happens, although via the two levels of pgtable
translation.  This patch provides the missing piece, the caching
attributes.


Yeah, but that won't work like this. See the backing store migrates all 
the time and when it is backed by PCIe/VRAM/local memory you need to use 
write combine while system memory is usually cached.



  Because otherwise you can't accommodate that the exporter is
changing those caching attributes.

Changing the attributes dynamically isn't going to work.. or at least
not easily.  If you had some sort of synchronous notification to host
userspace, it could trigger an irq to the guest, I suppose.  But it
would mean host kernel has to block waiting for host userspace to
interrupt the guest, then wait for guest vgpu process to be scheduled
and handle the irq.


We basically change that on every page flip on APUs and that doesn't 
sound like something fast.


Thanks for the explanation how this works,
Christian.



At least in the case of msm, the cache attributes are static for the
life of the buffer, so this scenario isn't a problem.  AFAICT this
should work fine for at least all UMA hw.. I'm a bit less sure when it
comes to TTM, but shouldn't you at least be able to use worst-cache
cache attributes for buffers that are allowed to be mapped to guest?

BR,
-R


But more seriously, let's take a step back here.. what scenarios are
you seeing this being problematic for?  Then we can see how to come up
with solutions.  The current situation of host userspace VMM just
guessing isn't great.

Well "isn't great" is a complete understatement. When KVM/virtio/virtgpu
is doing what I guess they are doing here then that is a really major
security hole.


And sticking our heads in the sand and
pretending VMs don't exist isn't great.  So what can we do?  I can
instead add a msm ioctl to return this info and solve the problem even
more narrowly for a single platform.  But then the problem still
remains on other platforms.

Well once more: This is *not* MSM specific, you just absolutely *can't
do that* for any driver!

I'm just really wondering what the heck is going on here, because all of
this was discussed in lengthy before on the mailing list and very
bluntly rejected.

Either I'm missing something (that's certainly possible) or we have a
strong case of somebody implementing something without thinking about
all the consequences.

Regards,
Christian.



Slightly implicit in this is that mapping dma-bufs to the guest won't
work for anything that requires DMA_BUF_IOCTL_SYNC for coherency.. we
could add a possible return value for DMA_BUF_INFO_VM_PROT indicating
that the buffer does not support mapping to guest or CPU access
without DMA_BUF_IOCTL_SYNC.  Then at least the VMM can fail gracefully
instead of subtly.

BR,
-R




[Bug 216338] New: Null Pointer Dereference in rockchip_drm_vop2.c

2022-08-08 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=216338

Bug ID: 216338
   Summary: Null Pointer Dereference in rockchip_drm_vop2.c
   Product: Drivers
   Version: 2.5
Kernel Version: 5.19.0
  Hardware: ARM
OS: Linux
  Tree: Mainline
Status: NEW
  Severity: normal
  Priority: P1
 Component: Video(DRI - non Intel)
  Assignee: drivers_video-...@kernel-bugs.osdl.org
  Reporter: macromor...@hotmail.com
Regression: No

When you use more than 1 video port (VP0 and VP1, for instance) on a Rockchip
RK3566 with the VOP2 driver, the driver issues a null pointer dereference when
it gets to the drm_crtc_init_with_planes function here:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c?h=v5.19#n2333

This appears to be because the function above it assigns primary planes to all
active video ports, but since it has special logic for the RK3566 it only ends
up with 1 primary plane to assign to a video port. When it encounters a second
video port it assigns it nothing, and then triggers a null pointer dereference
when it gets to the drm_crtc_init_with_planes function because plane is null.

-- 
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: [EXT] Re: [PATCH 1/3] dma-buf: heaps: add Linaro secure dmabuf heap support

2022-08-08 Thread Olivier Masse
Hi Brian,

On ven., 2022-08-05 at 16:41 +0100, Brian Starkey wrote:
> Caution: EXT Email
> 
> Hi Olivier,
> 
> Thanks, I think this is looking much better.
> 
> I'd like to know how others feel about landing this heap; there's
> been
> push-back in the past about heaps in device-tree and discussions
> around how "custom" heaps should be treated (though IMO this is quite
> a generic one).
> 
> On Fri, Aug 05, 2022 at 03:53:28PM +0200, Olivier Masse wrote:
> > add Linaro secure heap bindings: linaro,secure-heap
> > use genalloc to allocate/free buffer from buffer pool.
> > buffer pool info is from dts.
> > use sg_table instore the allocated memory info, the length of
> > sg_table is 1.
> > implement secure_heap_buf_ops to implement buffer share in
> > difference device:
> > 1. Userspace passes this fd to all drivers it wants this buffer
> > to share with: First the filedescriptor is converted to a _buf
> > using
> > dma_buf_get(). Then the buffer is attached to the device using
> > dma_buf_attach().
> > 2. Once the buffer is attached to all devices userspace can
> > initiate DMA
> > access to the shared buffer. In the kernel this is done by calling
> > dma_buf_map_attachment()
> > 3. get sg_table with dma_buf_map_attachment in difference device.
> > 
> 
> I think this commit message could use a little rework. A few
> thoughts:
> 
> * The bindings are in a separate commit, so seems strange to mention
>   here.

what about:
"add Linaro secure heap compatible reserved memory: linaro,secure-heap"

> * "buffer pool info is from dts" --> I think you should mention that
>   this uses a reserved-memory region.
ok

> * sg_table nents and genalloc seem like low-level implementation
>   details, so probably not needed in the commit message
> * The usage steps 1, 2, 3 aren't specific to this heap - that's how
>   all dma-buf sharing works.
ok, let's cleanup and removed this.

> 
> > Signed-off-by: Olivier Masse 
> > ---
> >  drivers/dma-buf/heaps/Kconfig   |   9 +
> >  drivers/dma-buf/heaps/Makefile  |   1 +
> >  drivers/dma-buf/heaps/secure_heap.c | 357
> > 
> >  3 files changed, 367 insertions(+)
> >  create mode 100644 drivers/dma-buf/heaps/secure_heap.c
> > 
> > diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-
> > buf/heaps/Kconfig
> > index 3782eeeb91c0..c9070c728b9a 100644
> > --- a/drivers/dma-buf/heaps/Kconfig
> > +++ b/drivers/dma-buf/heaps/Kconfig
> > @@ -20,3 +20,12 @@ config DMABUF_HEAPS_DSP
> >Choose this option to enable the dsp dmabuf heap. The
> > dsp heap
> >is allocated by gen allocater. it's allocated according
> > the dts.
> >If in doubt, say Y.
> > +
> > +config DMABUF_HEAPS_SECURE
> > + tristate "DMA-BUF Secure Heap"
> > + depends on DMABUF_HEAPS
> > + help
> > +   Choose this option to enable the secure dmabuf heap. The
> > secure heap
> > +   pools are defined according to the DT. Heaps are allocated
> > +   in the pools using gen allocater.
> > +   If in doubt, say Y.
> > diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-
> > buf/heaps/Makefile
> > index 29733f84c354..863ef10056a3 100644
> > --- a/drivers/dma-buf/heaps/Makefile
> > +++ b/drivers/dma-buf/heaps/Makefile
> > @@ -2,3 +2,4 @@
> >  obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)+= system_heap.o
> >  obj-$(CONFIG_DMABUF_HEAPS_CMA)   += cma_heap.o
> >  obj-$(CONFIG_DMABUF_HEAPS_DSP)  += dsp_heap.o
> > +obj-$(CONFIG_DMABUF_HEAPS_SECURE)+= secure_heap.o
> > diff --git a/drivers/dma-buf/heaps/secure_heap.c b/drivers/dma-
> > buf/heaps/secure_heap.c
> > new file mode 100644
> > index ..25b3629613f3
> > --- /dev/null
> > +++ b/drivers/dma-buf/heaps/secure_heap.c
> > @@ -0,0 +1,357 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * DMABUF secure heap exporter
> > + *
> > + * Copyright 2021 NXP.
> 
> It's 2022 :-)
> 
> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#define MAX_SECURE_HEAP 2
> > +#define MAX_HEAP_NAME_LEN 32
> > +
> > +struct secure_heap_buffer {
> > + struct dma_heap *heap;
> > + struct list_head attachments;
> > + struct mutex lock;
> > + unsigned long len;
> > + struct sg_table sg_table;
> > + int vmap_cnt;
> > + void *vaddr;
> > +};
> > +
> > +struct secure_heap_attachment {
> > + struct device *dev;
> > + struct sg_table *table;
> > + struct list_head list;
> > +};
> > +
> > +struct secure_heap_info {
> > + struct gen_pool *pool;
> > +};
> > +
> > +struct rmem_secure {
> > + phys_addr_t base;
> > + phys_addr_t size;
> > +
> > + char name[MAX_HEAP_NAME_LEN];
> > +};
> > +
> > +static struct rmem_secure secure_data[MAX_SECURE_HEAP] = {0};
> > +static unsigned int secure_data_count;
> > +
> > +static struct sg_table *dup_sg_table(struct 

Re: [v1] drm/msm/disp/dpu1: add support for hierarchical flush for dspp in sc7280

2022-08-08 Thread Doug Anderson
Hi,

On Mon, Aug 8, 2022 at 3:44 AM Kalyan Thota  wrote:
>
> >I'd like to land at least patches 6-8 from [1] next cycle. They clean up the 
> >CTL
> >interface. Could you please rebase your patch on top of them?
> >
>
> Sure I'll wait for the series to rebase. @Doug can you comment if this is 
> okay and this patch is not needed immediately ?
>
> >[1] https://patchwork.freedesktop.org/series/99909/

I don't personally see a problem basing them atop a cleanup. If the
patches Dmitry points at are targeted for the next cycle then that
seems like a pretty reasonable timeframe to me.

-Doug


Re: [PATCH v2 01/14] iosys-map: Add IOSYS_MAP_INIT_VADDR_IOMEM()

2022-08-08 Thread Lucas De Marchi

On Mon, Aug 08, 2022 at 02:53:53PM +0200, Thomas Zimmermann wrote:

Add IOSYS_MAP_INIT_VADDR_IOMEM() for static init of variables of type
struct iosys_map.

Signed-off-by: Thomas Zimmermann 



Reviewed-by: Lucas De Marchi 

Lucas De Marchi


---
include/linux/iosys-map.h | 15 ++-
1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/include/linux/iosys-map.h b/include/linux/iosys-map.h
index a533cae189d7..cb71aa616bd3 100644
--- a/include/linux/iosys-map.h
+++ b/include/linux/iosys-map.h
@@ -46,10 +46,13 @@
 *
 *  iosys_map_set_vaddr(, 0xdeadbeaf);
 *
- * To set an address in I/O memory, use iosys_map_set_vaddr_iomem().
+ * To set an address in I/O memory, use IOSYS_MAP_INIT_VADDR_IOMEM() or
+ * iosys_map_set_vaddr_iomem().
 *
 * .. code-block:: c
 *
+ * struct iosys_map map = IOSYS_MAP_INIT_VADDR_IOMEM(0xdeadbeaf);
+ *
 *  iosys_map_set_vaddr_iomem(, 0xdeadbeaf);
 *
 * Instances of struct iosys_map do not have to be cleaned up, but
@@ -121,6 +124,16 @@ struct iosys_map {
.is_iomem = false,  \
}

+/**
+ * IOSYS_MAP_INIT_VADDR_IOMEM - Initializes struct iosys_map to an address in 
I/O memory
+ * @vaddr_iomem_:  An I/O-memory address
+ */
+#define IOSYS_MAP_INIT_VADDR_IOMEM(vaddr_iomem_)   \
+   {   \
+   .vaddr_iomem = (vaddr_iomem_),  \
+   .is_iomem = true,   \
+   }
+
/**
 * IOSYS_MAP_INIT_OFFSET - Initializes struct iosys_map from another iosys_map
 * @map_:   The dma-buf mapping structure to copy from
--
2.37.1



Re: [PATCH v3 4/4] drm/panel: simple: add bus-format support for panel-dpi

2022-08-08 Thread Max Krummenacher
Hi Aradhya

Thanks for the review.

Rob's comment requires changes to panel-common.yaml in order for this to get in.
I think I know what needs to be done.

However, as there is no agreement on bus-format in the first place there is no
point in sorting that out now.

Regards
Max

On Wed, Aug 3, 2022 at 8:45 AM Aradhya Bhatia  wrote:
>
>
>
> On 28-Jun-22 23:48, Max Krummenacher wrote:
> > From: Max Krummenacher 
> >
> > Evaluate the device tree bus-format property to set bus_format for
> > a 'panel-dpi' panel. Additionally infer the bpc value from the
> > given bus-format.
> >
> > Valid values for bus-format are found in:
> > 
> >
> > This completes the addition of panel-dpi to completely specify
> > a panel-simple panel from the device tree.
> >
> > Signed-off-by: Max Krummenacher 
> >
> > ---
> >
> > Changes in v3:
> > - Moved the bus-format property under the port/endpoint node as
> >suggested by Rob Herring
> >
> > Changes in v2:
> > - Fix errors found by dt_binding_check
> >
> >   drivers/gpu/drm/panel/panel-simple.c | 49 
> >   1 file changed, 49 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/panel/panel-simple.c 
> > b/drivers/gpu/drm/panel/panel-simple.c
> > index 4a2e580a2f7b..f1a457f1069e 100644
> > --- a/drivers/gpu/drm/panel/panel-simple.c
> > +++ b/drivers/gpu/drm/panel/panel-simple.c
> > @@ -21,9 +21,11 @@
> >* DEALINGS IN THE SOFTWARE.
> >*/
> >
> > +#include 
> >   #include 
> >   #include 
> >   #include 
> > +#include 
> >   #include 
> >   #include 
> >   #include 
> > @@ -449,10 +451,12 @@ static int panel_dpi_probe(struct device *dev,
> >  struct panel_simple *panel)
> >   {
> >   struct display_timing *timing;
> > + struct device_node *endpoint;
> >   const struct device_node *np;
> >   struct panel_desc *desc;
> >   unsigned int bus_flags;
> >   struct videomode vm;
> > + u32 bus_format;
> >   int ret;
> >
> >   np = dev->of_node;
> > @@ -477,6 +481,51 @@ static int panel_dpi_probe(struct device *dev,
> >   of_property_read_u32(np, "width-mm", >size.width);
> >   of_property_read_u32(np, "height-mm", >size.height);
> >
> > + endpoint = of_graph_get_endpoint_by_regs(np, -1, -1);
> > + if (endpoint &&
> > + !of_property_read_u32(endpoint, "bus-format", _format)) {
> > + /* infer bpc from bus-format */
> > + switch (bus_format) {
> > + case DT_MEDIA_BUS_FMT_RGB565_1X16:
> > + desc->bus_format = MEDIA_BUS_FMT_RGB565_1X16;
> > + desc->bpc = 6;
> > + break;
> > + case DT_MEDIA_BUS_FMT_RGB666_1X18:
> > + desc->bus_format = MEDIA_BUS_FMT_RGB666_1X18;
> > + desc->bpc = 6;
> > + break;
> > + case DT_MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
> > + desc->bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI;
> > + desc->bpc = 6;
> > + break;
> > + case DT_MEDIA_BUS_FMT_BGR888_1X24:
> > + desc->bus_format = MEDIA_BUS_FMT_BGR888_1X24;
> > + desc->bpc = 8;
> > + break;
> > + case DT_MEDIA_BUS_FMT_GBR888_1X24:
> > + desc->bus_format = MEDIA_BUS_FMT_GBR888_1X24;
> > + desc->bpc = 8;
> > + break;
> > + case DT_MEDIA_BUS_FMT_RBG888_1X24:
> > + desc->bus_format = MEDIA_BUS_FMT_RBG888_1X24;
> > + desc->bpc = 8;
> > + break;
> > + case DT_MEDIA_BUS_FMT_RGB888_1X24:
> > + desc->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
> > + desc->bpc = 8;
> > + break;
> > + case DT_MEDIA_BUS_FMT_RGB888_1X32_PADHI:
> > + desc->bus_format = MEDIA_BUS_FMT_RGB888_1X32_PADHI;
> > + desc->bpc = 8;
> > + break;
> > + default:
> > + dev_err(dev, "%pOF: unknown bus-format property\n", 
> > np);
> > + return -EINVAL;
> > + }
> > + }
> > +
> > + of_node_put(endpoint);
> > +
> >   /* Extract bus_flags from display_timing */
> >   bus_flags = 0;
> >   vm.flags = timing->flags;
>
> I understand that it is important to add a bus-format property for dumb
> dpi-panels, and I agree with the implementation in the patch-set.
>
> However,
> I do not yet fully understand Rob's comments on the dt-bindings side of
> patch set (patch 1/4) and what consequences it may cause if that remains
> unresolved.
>
> Given that the bus-format property gets added, I do not see any concern
> with the panel-simple driver patch.
>
>
> Reviewed-by: Aradhya Bhatia 
>
>
> Regards
> Aradhya


Re: [PATCH v3 2/4] dt-bindings: display: add new bus-format property for panel-dpi

2022-08-08 Thread Max Krummenacher
Hi Marek

On Wed, Aug 3, 2022 at 10:21 AM Marek Vasut  wrote:
>
> On 6/28/22 20:18, Max Krummenacher wrote:
>
> Hello Max,
>
> [...]
>
> > diff --git a/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml 
> > b/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml
> > index dae0676b5c6e..52f5db03b6a8 100644
> > --- a/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml
> > +++ b/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml
> > @@ -26,7 +26,28 @@ properties:
> > height-mm: true
> > label: true
> > panel-timing: true
> > -  port: true
> > +
> > +  port:
> > +$ref: /schemas/graph.yaml#/$defs/port-base
> > +description:
> > +  Input port node, receives the panel data.
> > +
> > +properties:
> > +  endpoint:
> > +$ref: /schemas/graph.yaml#/$defs/endpoint-base
> > +
> > +properties:
> > +  bus-format:
> > +$ref: /schemas/types.yaml#/definitions/uint32
> > +minimum: 0x1001
> > +maximum: 0x1fff
> > +description: |
> > +  Describes how the display panel is connected to the display 
> > interface.
> > +  Valid values are defined in 
> > .
> > +  The mapping between the color/significance of the panel 
> > lines to the
> > +  parallel data lines are defined in:
> > +  
> > https://www.kernel.org/doc/html/v5.17/userspace-api/media/v4l/subdev-formats.html#packed-rgb-formats
>
> I am not sure whether I should re-open this discussion, but I still
> wonder, wouldn't it be better to describe the DPI bus color channel
> ordering (RGB, BGR, ...), width of each color channel in bits, pixel
> format (RGB, YUV, ...) instead of using specific constants for the
> entire format ?

>From a system view it would be hard to define that structure which
will catch any and all future requirements. Assume that there will be
3D panels and they will need an additional depth field. Or in
in addition to RGB data there will be a fourth color component. Or
whatever the panel manufacturers might come up with...
Or consider the Tegra 30 example I brought up in this thread. Tegras can
output RGB666 for 18bit panels, and then use the next 8 bits to extend
to 24bit (Maybe RGB666RGB222 ?).
https://lore.kernel.org/all/71ef1b35301330d0bbb64844247b6c4c2237ad1c.ca...@gmail.com/
If such requirements pop up the enumeration can be extended with a new
value without changing the binding in any way, with a structured
approach this will require changed bindings, maybe even with issues
in backward compatibility.

>From an implementation perspective for Linux the busformat in code is
currently an enumeration. So one would have to take the device tree
structured busformat and run it through a potentially complicated
function to get to the Linux busformat enumeration value. The final
consumer has no advantage over what is there today.

IMHO a change away from one enumeration value to a structured approach
creates some drawbacks without any obvious advantages.

Comments, other views on that?

Regards
Max


Re: [Linaro-mm-sig] [PATCH 1/3] dma-buf: Add ioctl to query mmap info

2022-08-08 Thread Rob Clark
On Mon, Aug 8, 2022 at 4:22 AM Christian König  wrote:
>
> Am 07.08.22 um 21:10 schrieb Rob Clark:
> > On Sun, Aug 7, 2022 at 11:05 AM Christian König
> >  wrote:
> >> Am 07.08.22 um 19:56 schrieb Rob Clark:
> >>> On Sun, Aug 7, 2022 at 10:38 AM Christian König
> >>>  wrote:
>  [SNIP]
>  And exactly that was declared completely illegal the last time it came
>  up on the mailing list.
> 
>  Daniel implemented a whole bunch of patches into the DMA-buf layer to
>  make it impossible for KVM to do this.
> >>> This issue isn't really with KVM, it is not making any CPU mappings
> >>> itself.  KVM is just making the pages available to the guest.
> >> Well I can only repeat myself: This is strictly illegal.
> >>
> >> Please try this approach with CONFIG_DMABUF_DEBUG set. I'm pretty sure
> >> you will immediately run into a crash.
> >>
> >> See this here as well
> >> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Felixir.bootlin.com%2Flinux%2Fv5.19%2Fsource%2Fdrivers%2Fdma-buf%2Fdma-buf.c%23L653data=05%7C01%7Cchristian.koenig%40amd.com%7Cc1392f76994f4fef7c7f08da78a86283%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637954961892996770%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7Csdata=T3g9ICZizCWXkIn5vEnhFYs38Uj37jCwHjMb1s3UtOw%3Dreserved=0
> >>
> >> Daniel intentionally added code to mangle the page pointers to make it
> >> impossible for KVM to do this.
> > I don't believe KVM is using the sg table, so this isn't going to stop
> > anything ;-)
>
> Then I have no idea how KVM actually works. Can you please briefly
> describe that?
>
> >> If the virtio/virtgpu UAPI was build around the idea that this is
> >> possible then it is most likely fundamental broken.
> > How else can you envision mmap'ing to guest userspace working?
>
> Well long story short: You can't.
>
> See userspace mappings are not persistent, but rather faulted in on
> demand. The exporter is responsible for setting those up to be able to
> add reverse tracking and so can invalidate those mappings when the
> backing store changes.

I think that is not actually a problem.  At least for how it works on
arm64 but I'm almost positive x86 is similar.. I'm not sure how else
you could virtualize mmu/iommu/etc in a way that didn't have horrible
performance.

There are two levels of pagetable translation, the first controlled by
the host kernel, the second by the guest.  From the PoV of host
kernel, it is just memory mapped to userspace, getting faulted in on
demand, just as normal.  First the guest controlled translation
triggers a fault in the guest which sets up guest mapping.  And then
the second level of translation to translate from what guest sees as
PA (but host sees as VA) to actual PA triggers a fault in the host.

>
> > The guest kernel is the one that controls the guest userspace pagetables,
> > not the host kernel.  I guess your complaint is about VMs in general,
> > but unfortunately I don't think you'll convince the rest of the
> > industry to abandon VMs ;-)
>
> I'm not arguing against the usefulness of VM, it's just that what you
> describe here technically is just utterly nonsense as far as I can tell.
>
> I have to confess that I'm totally lacking how this KVM mapping works,
> but when the struct pages pointers from the sg_table are not used I see
> two possibilities what was implemented here:
>
> 1. KVM is somehow walking the page tables to figure out what to map into
> the guest VM.

it is just mapping host VA to the guest.. the guest kernel sees this
as the PA and uses the level of pgtable translation that it controls
to map to guest userspace.  *All* that is needed (which this patch
provides) is the correct cache attributes.

>  This would be *HIGHLY* illegal and not just with DMA-buf, but with
> pretty much a whole bunch of other drivers/subsystems as well.
>  In other words it would be trivial for the guest to take over the
> host with that because it doesn't take into account that the underlying
> backing store of DMA-buf and other mmaped() areas can change at any time.
>
> 2. The guest VM triggers the fault handler for the mappings to fill in
> their page tables on demand.
>
>  That would actually work with DMA-buf, but then the guest needs to
> somehow use the caching attributes from the host side and not use it's own.

This is basically what happens, although via the two levels of pgtable
translation.  This patch provides the missing piece, the caching
attributes.

>  Because otherwise you can't accommodate that the exporter is
> changing those caching attributes.

Changing the attributes dynamically isn't going to work.. or at least
not easily.  If you had some sort of synchronous notification to host
userspace, it could trigger an irq to the guest, I suppose.  But it
would mean host kernel has to block waiting for host userspace to
interrupt the guest, then wait for guest vgpu process to be scheduled
and handle 

Nested AVIC design (was:Re: [RFC PATCH v3 04/19] KVM: x86: mmu: allow to enable write tracking externally)

2022-08-08 Thread Maxim Levitsky
On Mon, 2022-08-01 at 17:20 +, Sean Christopherson wrote:
> On Thu, Jul 28, 2022, Maxim Levitsky wrote:
> > On Mon, 2022-07-25 at 16:08 +, Sean Christopherson wrote:
> > > On Wed, Jul 20, 2022, Maxim Levitsky wrote:
> > > And on that topic, do you have performance numbers to justify using a 
> > > single
> > > shared node?  E.g. if every table instance has its own notifier, then no 
> > > additional
> > > refcounting is needed. 
> > 
> > The thing is that KVM goes over the list of notifiers and calls them for
> > every write from the emulator in fact even just for mmio write, and when you
> > enable write tracking on a page, you just write protect the page and add a
> > mark in the page track array, which is roughly 
> > 
> > 'don't install spte, don't install mmio spte, but just emulate the page 
> > fault if it hits this page'
> > 
> > So adding more than a bare minimum to this list, seems just a bit wrong.
> 
> Hmm, I see what you're saying.  To some extent, having a minimal page tracker
> implementation is just that, an implementation detail.  But for better or 
> worse,
> the existing API effectively pushes range checking to the callers.  I agree 
> that
> breaking from that pattern would be odd.
> 
> > >  It's not obvious that a shared node will provide better performance, e.g.
> > >  if there are only a handful of AVIC tables being shadowed, then a linear
> > >  walk of all nodes is likely fast enough, and doesn't bring the risk of a
> > >  write potentially being stalled due to having to acquire a VM-scoped
> > >  mutex.
> > 
> > The thing is that if I register multiple notifiers, they all will be called 
> > anyway,
> > but yes I can use container_of, and discover which table the notifier 
> > belongs to,
> > instead of having a hash table where I lookup the GFN of the fault.
> > 
> > The above means practically that all the shadow physid tables will be in a 
> > linear
> > list of notifiers, so I could indeed avoid per vm mutex on the write 
> > tracking,
> > however for simplicity I probably will still need it because I do modify 
> > the page,
> > and having per physid table mutex complicates things.
> > 
> > Currently in my code the locking is very simple and somewhat dumb, but the 
> > performance
> > is very good because the code isn't executed often, most of the time the 
> > AVIC hardware
> > works alone without any VM exits.
> 
> Yes, but because the code isn't executed often, pretty much any solution will
> provide good performance.
> 
> > Once the code is accepted upstream, it's one of the things that can be 
> > improved.
> > 
> > Note though that I still need a hash table and a mutex because on each VM 
> > entry,
> > the guest can use a different physid table, so I need to lookup it, and 
> > create it,
> > if not found, which would require read/write of the hash table and thus a 
> > mutex.
> 
> One of the points I'm trying to make is that a hash table isn't strictly 
> required.
> E.g. if I understand the update rules correctly, I believe tables can be 
> tracked
> via an RCU-protected list, with vCPUs taking a spinlock and doing 
> synchronize_rcu()
> when adding/removing a table.  That would avoid having to take any "real" 
> locks in
> the page track notifier.
> 
> The VM-scoped mutex worries me as it will be a bottleneck if L1 is running 
> multiple
> L2 VMs.  E.g. if L1 is frequently switching vmcs12 and thus avic_physical_id, 
> then
> nested VMRUN will effectively get serialized.  That is mitigated to some 
> extent by
> an RCU-protected list, as a sane L1 will use a single table for each L2, and 
> so a
> vCPU will need to add/remove a table if and only if it's the first/last vCPU 
> to
> start/stop running an L2 VM.

Hi Sean, Paolo, and everyone else who wants to review my nested AVIC work.
 
I would like to explain the design choices for locking, and life cycle of the 
shadow physid tables, and I hope
that this will make it easier for you to review my code and/or make some 
suggestions on how to improve it.
 
=
Explanation of the AVIC physid page (AVIC physical ID table)
=
 
This table gives a vCPU enough knowledge of its peers to send them IPIs without 
VM exit.
 
A vCPU doesn’t use this table to send IPIs to itself and or to process its own 
interrupts from its own
IRR/ISR. It accesses its APIC backing page directly.
 
This table contains an entry for each vCPU, and each entry contains 2 things:
 
1. A physical address of a peer’s vCPU APIC backing page, so that when sending 
IPIs to this vCPU
   It can set them in the IRR location in this page (this differs from APICv, 
which uses PIR bitmaps).
 
   NOTE1: There is also a ‘V’(valid) bit attached to the address - when clear, 
then whole entry is invalid
   and trying to use it will 

Re: [Freedreno] [PATCH 1/3] dma-buf: Add ioctl to query mmap info

2022-08-08 Thread Rob Clark
On Sun, Aug 7, 2022 at 1:25 PM Akhil P Oommen  wrote:
>
> On 7/29/2022 10:37 PM, Rob Clark wrote:
> > From: Rob Clark 
> >
> > This is a fairly narrowly focused interface, providing a way for a VMM
> > in userspace to tell the guest kernel what pgprot settings to use when
> > mapping a buffer to guest userspace.
> >
> > For buffers that get mapped into guest userspace, virglrenderer returns
> > a dma-buf fd to the VMM (crosvm or qemu).  In addition to mapping the
> > pages into the guest VM, it needs to report to drm/virtio in the guest
> > the cache settings to use for guest userspace.  In particular, on some
> > architectures, creating aliased mappings with different cache attributes
> > is frowned upon, so it is important that the guest mappings have the
> > same cache attributes as any potential host mappings.
> >
> > Signed-off-by: Rob Clark 
> > ---
> >   drivers/dma-buf/dma-buf.c| 26 ++
> >   include/linux/dma-buf.h  |  7 +++
> >   include/uapi/linux/dma-buf.h | 28 
> >   3 files changed, 61 insertions(+)
> >
> > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> > index 32f55640890c..d02d6c2a3b49 100644
> > --- a/drivers/dma-buf/dma-buf.c
> > +++ b/drivers/dma-buf/dma-buf.c
> > @@ -326,6 +326,29 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, 
> > const char __user *buf)
> >   return 0;
> >   }
> >
> > +static long dma_buf_info(struct dma_buf *dmabuf, const void __user *uarg)
> > +{
> > + struct dma_buf_info arg;
> > +
> > + if (copy_from_user(, uarg, sizeof(arg)))
> > + return -EFAULT;
> > +
> > + switch (arg.param) {
> > + case DMA_BUF_INFO_VM_PROT:
> > + if (!dmabuf->ops->mmap_info)
> > + return -ENOSYS;
> > + arg.value = dmabuf->ops->mmap_info(dmabuf);
> > + break;
> > + default:
> > + return -EINVAL;
> > + }
> > +
> > + if (copy_to_user(uarg, , sizeof(arg)))
> > + return -EFAULT;
> > +
> > + return 0;
> > +}
> > +
> >   static long dma_buf_ioctl(struct file *file,
> > unsigned int cmd, unsigned long arg)
> >   {
> > @@ -369,6 +392,9 @@ static long dma_buf_ioctl(struct file *file,
> >   case DMA_BUF_SET_NAME_B:
> >   return dma_buf_set_name(dmabuf, (const char __user *)arg);
> >
> > + case DMA_BUF_IOCTL_INFO:
> > + return dma_buf_info(dmabuf, (const void __user *)arg);
> > +
> >   default:
> >   return -ENOTTY;
> >   }
> > diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
> > index 71731796c8c3..6f4de64a5937 100644
> > --- a/include/linux/dma-buf.h
> > +++ b/include/linux/dma-buf.h
> > @@ -283,6 +283,13 @@ struct dma_buf_ops {
> >*/
> >   int (*mmap)(struct dma_buf *, struct vm_area_struct *vma);
> >
> > + /**
> > +  * @mmap_info:
> > +  *
> > +  * Return mmapping info for the buffer.  See DMA_BUF_INFO_VM_PROT.
> > +  */
> > + int (*mmap_info)(struct dma_buf *);
> > +
> >   int (*vmap)(struct dma_buf *dmabuf, struct iosys_map *map);
> >   void (*vunmap)(struct dma_buf *dmabuf, struct iosys_map *map);
> >   };
> > diff --git a/include/uapi/linux/dma-buf.h b/include/uapi/linux/dma-buf.h
> > index b1523cb8ab30..a41adac0f46a 100644
> > --- a/include/uapi/linux/dma-buf.h
> > +++ b/include/uapi/linux/dma-buf.h
> > @@ -85,6 +85,32 @@ struct dma_buf_sync {
> >
> >   #define DMA_BUF_NAME_LEN32
> >
> > +
> > +/**
> > + * struct dma_buf_info - Query info about the buffer.
> > + */
> > +struct dma_buf_info {
> > +
> > +#define DMA_BUF_INFO_VM_PROT  1
> > +#  define DMA_BUF_VM_PROT_WC  0
> > +#  define DMA_BUF_VM_PROT_CACHED  1
> > +
> > + /**
> > +  * @param: Which param to query
> > +  *
> > +  * DMA_BUF_INFO_BM_PROT:
> Is there a typo here? BM -> VM ?

yes, fixed locally

>
> -Akhil.
> > +  * Query the access permissions of userspace mmap's of this 
> > buffer.
> > +  * Returns one of DMA_BUF_VM_PROT_x
> > +  */
> > + __u32 param;
> > + __u32 pad;
> > +
> > + /**
> > +  * @value: Return value of the query.
> > +  */
> > + __u64 value;
> > +};
> > +
> >   #define DMA_BUF_BASE'b'
> >   #define DMA_BUF_IOCTL_SYNC  _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync)
> >
> > @@ -95,4 +121,6 @@ struct dma_buf_sync {
> >   #define DMA_BUF_SET_NAME_A  _IOW(DMA_BUF_BASE, 1, __u32)
> >   #define DMA_BUF_SET_NAME_B  _IOW(DMA_BUF_BASE, 1, __u64)
> >
> > +#define DMA_BUF_IOCTL_INFO   _IOWR(DMA_BUF_BASE, 2, struct dma_buf_info)
> > +
> >   #endif
>


Re: [PATCH v1 00/35] drm: Analog TV Improvements

2022-08-08 Thread Noralf Trønnes



Den 29.07.2022 18.34, skrev Maxime Ripard:
> Hi,
> 
> Here's a series aiming at improving the command line named modes support,
> and more importantly how we deal with all the analog TV variants.
> 
> The named modes support were initially introduced to allow to specify the
> analog TV mode to be used.
> 
> However, this was causing multiple issues:
> 
>   * The mode name parsed on the command line was passed directly to the
> driver, which had to figure out which mode it was suppose to match;
> 
>   * Figuring that out wasn't really easy, since the video= argument or what
> the userspace might not even have a name in the first place, but
> instead could have passed a mode with the same timings;
> 
>   * The fallback to matching on the timings was mostly working as long as
> we were supporting one 525 lines (most likely NSTC) and one 625 lines
> (PAL), but couldn't differentiate between two modes with the same
> timings (NTSC vs PAL-M vs NSTC-J for example); 
> 
>   * There was also some overlap with the tv mode property registered by 
> drm_mode_create_tv_properties(), but named modes weren't interacting
> with that property at all.
> 
>   * Even though that property was generic, its possible values were
> specific to each drivers, which made some generic support difficult.
> 
> Thus, I chose to tackle in multiple steps:
> 
>   * A new TV norm property was introduced, with generic values, each driver
> reporting through a bitmask what standard it supports to the userspace;
> 
>   * This option was added to the command line parsing code to be able to
> specify it on the kernel command line, and new atomic_check and reset
> helpers were created to integrate properly into atomic KMS;
> 
>   * The named mode parsing code is now creating a proper display mode for
> the given named mode, and the TV standard will thus be part of the
> connector state;
> 
>   * Two drivers were converted and tested for now (vc4 and sun4i), with
> some backward compatibility code to translate the old TV mode to the
> new TV mode;
> 
> Unit tests were created along the way. Nouveau, ch7006 and gud are
> currently broken for now since I expect that work to be reworked fairly
> significantly. I'm also not entirely sure about how to migrate GUD to the
> new property.
> 

I have looked at gud and I think the future proof solution is to add a
new TV_NORM property to the GUD protocol and add backwards compatibility
for the GUD_TV_MODE property (just for the modes that Raspberry Pi
supports since the gadget driver is out of tree). I don't bother
supporting the tv.mode property in userspace (I haven't seen anything
that uses the property).

I have written up most of the host driver changes but I have to do the
gadget side as well to make sure it works. I'll post some patches when
I'm done. In hindsight I should have used a bitmask for the TV standards
in the first place ;)

Noralf.


[PATCH v2 13/14] drm/format-helper: Move destination-buffer handling into internal helper

2022-08-08 Thread Thomas Zimmermann
The format-convertion helpers handle several cases for different
values of destination buffer and pitch. Move that code into the
internal helper drm_fb_xfrm() and avoid quite a bit of duplication.

v2:
* remove a duplicated blank line (Jose)
* use drm_format_info_bpp() (Sam)
* fix vaddr_cached_hint bug (Sam)
* add TODO on vaddr location (Sam)

Signed-off-by: Thomas Zimmermann 
---
 drivers/gpu/drm/drm_format_helper.c | 174 ++--
 1 file changed, 63 insertions(+), 111 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index 53a313f83dc2..0fec3b68db95 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -41,11 +41,11 @@ unsigned int drm_fb_clip_offset(unsigned int pitch, const 
struct drm_format_info
 }
 EXPORT_SYMBOL(drm_fb_clip_offset);
 
-/* TODO: Make this functon work with multi-plane formats. */
-static int drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long 
dst_pixsize,
-  const void *vaddr, const struct drm_framebuffer *fb,
-  const struct drm_rect *clip, bool vaddr_cached_hint,
-  void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned 
int npixels))
+/* TODO: Make this function work with multi-plane formats. */
+static int __drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long 
dst_pixsize,
+const void *vaddr, const struct drm_framebuffer *fb,
+const struct drm_rect *clip, bool vaddr_cached_hint,
+void (*xfrm_line)(void *dbuf, const void *sbuf, 
unsigned int npixels))
 {
unsigned long linepixels = drm_rect_width(clip);
unsigned long lines = drm_rect_height(clip);
@@ -84,11 +84,11 @@ static int drm_fb_xfrm(void *dst, unsigned long dst_pitch, 
unsigned long dst_pix
return 0;
 }
 
-/* TODO: Make this functon work with multi-plane formats. */
-static int drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, 
unsigned long dst_pixsize,
-   const void *vaddr, const struct drm_framebuffer *fb,
-   const struct drm_rect *clip, bool vaddr_cached_hint,
-   void (*xfrm_line)(void *dbuf, const void *sbuf, 
unsigned int npixels))
+/* TODO: Make this function work with multi-plane formats. */
+static int __drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, 
unsigned long dst_pixsize,
+ const void *vaddr, const struct drm_framebuffer 
*fb,
+ const struct drm_rect *clip, bool 
vaddr_cached_hint,
+ void (*xfrm_line)(void *dbuf, const void *sbuf, 
unsigned int npixels))
 {
unsigned long linepixels = drm_rect_width(clip);
unsigned long lines = drm_rect_height(clip);
@@ -129,6 +129,29 @@ static int drm_fb_xfrm_toio(void __iomem *dst, unsigned 
long dst_pitch, unsigned
return 0;
 }
 
+/* TODO: Make this function work with multi-plane formats. */
+static int drm_fb_xfrm(struct iosys_map *dst,
+  const unsigned int *dst_pitch, const u8 *dst_pixsize,
+  const struct iosys_map *vmap, const struct 
drm_framebuffer *fb,
+  const struct drm_rect *clip, bool vaddr_cached_hint,
+  void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned 
int npixels))
+{
+   static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
+   0, 0, 0, 0
+   };
+
+   if (!dst_pitch)
+   dst_pitch = default_dst_pitch;
+
+   /* TODO: handle vmap in I/O memory here */
+   if (dst[0].is_iomem)
+   return __drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 
dst_pixsize[0],
+ vmap[0].vaddr, fb, clip, 
vaddr_cached_hint, xfrm_line);
+   else
+   return __drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], dst_pixsize[0],
+vmap[0].vaddr, fb, clip, 
vaddr_cached_hint, xfrm_line);
+}
+
 /**
  * drm_fb_memcpy - Copy clip buffer
  * @dst: Array of destination buffers
@@ -228,9 +251,6 @@ void drm_fb_swab(struct iosys_map *dst, const unsigned int 
*dst_pitch,
 const struct iosys_map *vmap, const struct drm_framebuffer *fb,
 const struct drm_rect *clip, bool cached)
 {
-   static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
-   0, 0, 0, 0
-   };
const struct drm_format_info *format = fb->format;
u8 cpp = DIV_ROUND_UP(drm_format_info_bpp(format, 0), 8);
void (*swab_line)(void *dbuf, const void *sbuf, unsigned int npixels);
@@ -245,22 +265,10 @@ void drm_fb_swab(struct iosys_map *dst, const unsigned 
int *dst_pitch,
default:
drm_warn_once(fb->dev, "Format %p4cc has unsupported pixel 
size.\n",
  

[PATCH v2 00/14] drm/format-helper: Move to struct iosys_map

2022-08-08 Thread Thomas Zimmermann
Change format-conversion helpers to use struct iosys_map for source
and destination buffers. Update all users. Also prepare interface for
multi-plane color formats.

The format-conversion helpers mostly used to convert to I/O memory
or system memory. To actual memory type depended on the usecase. We
now have drivers upcomming that do the conversion entirely in system
memory. It's a good opportunity to stream-line the interface of the
conversion helpers to use struct iosys_map. Source and destination
buffers can now be either in system or in I/O memory. Note that the
implementation still only supports source buffers in system memory.

This patchset also changes the interface to support multi-plane
color formats, where the values for each component are stored in
distinct memory locations. Converting from RGBRGBRGB to RRRGGGBBB
would require a single source buffer with RGB values and 3 destination
buffers for the R, G and B values. Conversion-helper interfaces now
support this.

v2:
* add IOSYS_MAP_INIT_VADDR_IOMEM (Sam)
* use drm_format_info_bpp() (Sam)
* update documentation (Sam)
* rename 'vmap' to 'src' (Sam)
* many smaller cleanups and fixes (Sam, Jose)

Thomas Zimmermann (14):
  iosys-map: Add IOSYS_MAP_INIT_VADDR_IOMEM()
  drm/format-helper: Provide drm_fb_blit()
  drm/format-helper: Merge drm_fb_memcpy() and drm_fb_memcpy_toio()
  drm/format-helper: Convert drm_fb_swab() to struct iosys_map
  drm/format-helper: Rework XRGB-to-RGBG332 conversion
  drm/format-helper: Rework XRGB-to-RGBG565 conversion
  drm/format-helper: Rework XRGB-to-RGB888 conversion
  drm/format-helper: Rework RGB565-to-XRGB conversion
  drm/format-helper: Rework RGB888-to-XRGB conversion
  drm/format-helper: Rework XRGB-to-XRGB2101010 conversion
  drm/format-helper: Rework XRGB-to-GRAY8 conversion
  drm/format-helper: Rework XRGB-to-MONO conversion
  drm/format-helper: Move destination-buffer handling into internal
helper
  drm/format-helper: Rename parameter vmap to src

 drivers/gpu/drm/drm_format_helper.c   | 509 ++
 drivers/gpu/drm/drm_mipi_dbi.c|   9 +-
 drivers/gpu/drm/gud/gud_pipe.c|  20 +-
 drivers/gpu/drm/hyperv/hyperv_drm_modeset.c   |   9 +-
 drivers/gpu/drm/mgag200/mgag200_mode.c|   9 +-
 drivers/gpu/drm/solomon/ssd130x.c |   7 +-
 .../gpu/drm/tests/drm_format_helper_test.c|  45 +-
 drivers/gpu/drm/tiny/cirrus.c |  19 +-
 drivers/gpu/drm/tiny/repaper.c|   6 +-
 drivers/gpu/drm/tiny/simpledrm.c  |   8 +-
 drivers/gpu/drm/tiny/st7586.c |   5 +-
 include/drm/drm_format_helper.h   |  56 +-
 include/linux/iosys-map.h |  15 +-
 13 files changed, 416 insertions(+), 301 deletions(-)


base-commit: 2bdae66c9988dd0f07633629c0a85383cfc05940
prerequisite-patch-id: c2b2f08f0eccc9f5df0c0da49fa1d36267deb11d
prerequisite-patch-id: c67e5d886a47b7d0266d81100837557fda34cb24
prerequisite-patch-id: 3f204510fcbf9530d6540bd8e6128cce598988b6
-- 
2.37.1



[PATCH v2 04/14] drm/format-helper: Convert drm_fb_swab() to struct iosys_map

2022-08-08 Thread Thomas Zimmermann
Convert drm_fb_swab() to use struct iosys_map() and convert users. The
new interface supports multi-plane color formats, but implementation
only supports a single plane for now.

v2:
* use drm_format_info_bpp() (Sam)
* update documentation (Sam)
* add TODO on vaddr location (Sam)

Signed-off-by: Thomas Zimmermann 
---
 drivers/gpu/drm/drm_format_helper.c | 53 +
 drivers/gpu/drm/drm_mipi_dbi.c  |  2 +-
 drivers/gpu/drm/gud/gud_pipe.c  |  2 +-
 include/drm/drm_format_helper.h |  6 ++--
 4 files changed, 44 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index 7489c665a47c..b5ed058984ae 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -205,37 +205,62 @@ static void drm_fb_swab32_line(void *dbuf, const void 
*sbuf, unsigned int pixels
 
 /**
  * drm_fb_swab - Swap bytes into clip buffer
- * @dst: Destination buffer
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @src: Source buffer
+ * @dst: Array of destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive 
scanlines
+ * within @dst; can be NULL if scanlines are stored next to each 
other.
+ * @vmap: Array of source buffers
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  * @cached: Source buffer is mapped cached (eg. not write-combined)
  *
- * If @cached is false a temporary buffer is used to cache one pixel line at a
- * time to speed up slow uncached reads.
+ * This function copies parts of a framebuffer to display memory and swaps 
per-pixel
+ * bytes during the process. Destination and framebuffer formats must match. 
The
+ * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have 
at
+ * least as many entries as there are planes in @fb's format. Each entry 
stores the
+ * value for the format's respective color plane at the same index. If @cached 
is
+ * false a temporary buffer is used to cache one pixel line at a time to speed 
up
+ * slow uncached reads.
  *
- * This function does not apply clipping on dst, i.e. the destination
- * is at the top-left corner.
+ * This function does not apply clipping on @dst (i.e. the destination is at 
the
+ * top-left corner).
  */
-void drm_fb_swab(void *dst, unsigned int dst_pitch, const void *src,
-const struct drm_framebuffer *fb, const struct drm_rect *clip,
-bool cached)
+void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch,
+const struct iosys_map *vmap, const struct drm_framebuffer *fb,
+const struct drm_rect *clip, bool cached)
 {
-   u8 cpp = fb->format->cpp[0];
+   static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
+   0, 0, 0, 0
+   };
+   const struct drm_format_info *format = fb->format;
+   u8 cpp = DIV_ROUND_UP(drm_format_info_bpp(format, 0), 8);
+   void (*swab_line)(void *dbuf, const void *sbuf, unsigned int npixels);
 
switch (cpp) {
case 4:
-   drm_fb_xfrm(dst, dst_pitch, cpp, src, fb, clip, cached, 
drm_fb_swab32_line);
+   swab_line = drm_fb_swab32_line;
break;
case 2:
-   drm_fb_xfrm(dst, dst_pitch, cpp, src, fb, clip, cached, 
drm_fb_swab16_line);
+   swab_line = drm_fb_swab16_line;
break;
default:
drm_warn_once(fb->dev, "Format %p4cc has unsupported pixel 
size.\n",
- >format->format);
+ >format);
+   swab_line = NULL;
break;
}
+   if (!swab_line)
+   return;
+
+   if (!dst_pitch)
+   dst_pitch = default_dst_pitch;
+
+   /* TODO: handle vmap in I/O memory here */
+   if (dst->is_iomem)
+   drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], cpp,
+vmap[0].vaddr, fb, clip, cached, swab_line);
+   else
+   drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], cpp, vmap[0].vaddr, fb,
+   clip, cached, swab_line);
 }
 EXPORT_SYMBOL(drm_fb_swab);
 
diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index 1ba506ca83e1..a44b7d6ae06c 100644
--- a/drivers/gpu/drm/drm_mipi_dbi.c
+++ b/drivers/gpu/drm/drm_mipi_dbi.c
@@ -221,7 +221,7 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
switch (fb->format->format) {
case DRM_FORMAT_RGB565:
if (swap)
-   drm_fb_swab(dst, 0, src, fb, clip, !gem->import_attach);
+   drm_fb_swab(_map, NULL, data, fb, clip, 
!gem->import_attach);
else
drm_fb_memcpy(_map, NULL, data, fb, clip);
break;
diff --git a/drivers/gpu/drm/gud/gud_pipe.c 

[PATCH v2 14/14] drm/format-helper: Rename parameter vmap to src

2022-08-08 Thread Thomas Zimmermann
The name the parameter vmap to src in all functions. The parameter
contains the locations of the source data and the new name says that.

Signed-off-by: Thomas Zimmermann 
---
 drivers/gpu/drm/drm_format_helper.c | 106 ++--
 include/drm/drm_format_helper.h |  18 ++---
 2 files changed, 62 insertions(+), 62 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index 0fec3b68db95..56642816fdff 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -132,7 +132,7 @@ static int __drm_fb_xfrm_toio(void __iomem *dst, unsigned 
long dst_pitch, unsign
 /* TODO: Make this function work with multi-plane formats. */
 static int drm_fb_xfrm(struct iosys_map *dst,
   const unsigned int *dst_pitch, const u8 *dst_pixsize,
-  const struct iosys_map *vmap, const struct 
drm_framebuffer *fb,
+  const struct iosys_map *src, const struct 
drm_framebuffer *fb,
   const struct drm_rect *clip, bool vaddr_cached_hint,
   void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned 
int npixels))
 {
@@ -143,13 +143,13 @@ static int drm_fb_xfrm(struct iosys_map *dst,
if (!dst_pitch)
dst_pitch = default_dst_pitch;
 
-   /* TODO: handle vmap in I/O memory here */
+   /* TODO: handle src in I/O memory here */
if (dst[0].is_iomem)
return __drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 
dst_pixsize[0],
- vmap[0].vaddr, fb, clip, 
vaddr_cached_hint, xfrm_line);
+ src[0].vaddr, fb, clip, 
vaddr_cached_hint, xfrm_line);
else
return __drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], dst_pixsize[0],
-vmap[0].vaddr, fb, clip, 
vaddr_cached_hint, xfrm_line);
+src[0].vaddr, fb, clip, vaddr_cached_hint, 
xfrm_line);
 }
 
 /**
@@ -157,13 +157,13 @@ static int drm_fb_xfrm(struct iosys_map *dst,
  * @dst: Array of destination buffers
  * @dst_pitch: Array of numbers of bytes between the start of two consecutive 
scanlines
  * within @dst; can be NULL if scanlines are stored next to each 
other.
- * @vmap: Array of source buffers
+ * @src: Array of source buffers
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  *
  * This function copies parts of a framebuffer to display memory. Destination 
and
  * framebuffer formats must match. No conversion takes place. The parameters 
@dst,
- * @dst_pitch and @vmap refer to arrays. Each array must have at least as many 
entries
+ * @dst_pitch and @src refer to arrays. Each array must have at least as many 
entries
  * as there are planes in @fb's format. Each entry stores the value for the 
format's
  * respective color plane at the same index.
  *
@@ -171,7 +171,7 @@ static int drm_fb_xfrm(struct iosys_map *dst,
  * top-left corner).
  */
 void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch,
-  const struct iosys_map *vmap, const struct drm_framebuffer 
*fb,
+  const struct iosys_map *src, const struct drm_framebuffer 
*fb,
   const struct drm_rect *clip)
 {
static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
@@ -190,16 +190,16 @@ void drm_fb_memcpy(struct iosys_map *dst, const unsigned 
int *dst_pitch,
size_t len_i = DIV_ROUND_UP(drm_rect_width(clip) * bpp_i, 8);
unsigned int dst_pitch_i = dst_pitch[i];
struct iosys_map dst_i = dst[i];
-   struct iosys_map vmap_i = vmap[i];
+   struct iosys_map src_i = src[i];
 
if (!dst_pitch_i)
dst_pitch_i = len_i;
 
-   iosys_map_incr(_i, clip_offset(clip, fb->pitches[i], 
cpp_i));
+   iosys_map_incr(_i, clip_offset(clip, fb->pitches[i], 
cpp_i));
for (y = 0; y < lines; y++) {
-   /* TODO: handle vmap_i in I/O memory here */
-   iosys_map_memcpy_to(_i, 0, vmap_i.vaddr, len_i);
-   iosys_map_incr(_i, fb->pitches[i]);
+   /* TODO: handle src_i in I/O memory here */
+   iosys_map_memcpy_to(_i, 0, src_i.vaddr, len_i);
+   iosys_map_incr(_i, fb->pitches[i]);
iosys_map_incr(_i, dst_pitch_i);
}
}
@@ -231,14 +231,14 @@ static void drm_fb_swab32_line(void *dbuf, const void 
*sbuf, unsigned int pixels
  * @dst: Array of destination buffers
  * @dst_pitch: Array of numbers of bytes between the start of two consecutive 
scanlines
  * within @dst; can be NULL if scanlines are stored next to each 
other.
- * @vmap: Array of source buffers
+ * @src: Array of source buffers
  * @fb: DRM framebuffer
  * @clip: 

[PATCH v2 10/14] drm/format-helper: Rework XRGB8888-to-XRGB2101010 conversion

2022-08-08 Thread Thomas Zimmermann
Update XRGB-to-XRGB2101010 conversion to support struct iosys_map
and convert all users. Although these are single-plane color formats,
the new interface supports multi-plane formats for consistency with
drm_fb_blit().

v2:
* update documentation (Sam)
* add TODO on vaddr location (Sam)

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Sam Ravnborg 
---
 drivers/gpu/drm/drm_format_helper.c | 50 -
 include/drm/drm_format_helper.h |  6 ++--
 2 files changed, 37 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index 8083f5b85b3a..795d845c7e53 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -554,26 +554,45 @@ static void drm_fb_xrgb_to_xrgb2101010_line(void 
*dbuf, const void *sbuf, un
 }
 
 /**
- * drm_fb_xrgb_to_xrgb2101010_toio - Convert XRGB to XRGB2101010 clip
- * buffer
- * @dst: XRGB2101010 destination buffer (iomem)
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @vaddr: XRGB source buffer
+ * drm_fb_xrgb_to_xrgb2101010 - Convert XRGB to XRGB2101010 clip buffer
+ * @dst: Array of XRGB2101010 destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive 
scanlines
+ * within @dst; can be NULL if scanlines are stored next to each 
other.
+ * @vmap: Array of XRGB source buffers
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  *
- * Drivers can use this function for XRGB2101010 devices that don't natively
- * support XRGB.
+ * This function copies parts of a framebuffer to display memory and converts 
the
+ * color format during the process. Destination and framebuffer formats must 
match. The
+ * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have 
at
+ * least as many entries as there are planes in @fb's format. Each entry 
stores the
+ * value for the format's respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at 
the
+ * top-left corner).
+ *
+ * Drivers can use this function for XRGB2101010 devices that don't support 
XRGB
+ * natively.
  */
-void drm_fb_xrgb_to_xrgb2101010_toio(void __iomem *dst,
-unsigned int dst_pitch, const void 
*vaddr,
-const struct drm_framebuffer *fb,
-const struct drm_rect *clip)
+void drm_fb_xrgb_to_xrgb2101010(struct iosys_map *dst, const unsigned int 
*dst_pitch,
+   const struct iosys_map *vmap, const struct 
drm_framebuffer *fb,
+   const struct drm_rect *clip)
 {
-   drm_fb_xfrm_toio(dst, dst_pitch, 4, vaddr, fb, clip, false,
-drm_fb_xrgb_to_xrgb2101010_line);
+   static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
+   0, 0, 0, 0
+   };
+
+   if (!dst_pitch)
+   dst_pitch = default_dst_pitch;
+
+   /* TODO: handle vmap in I/O memory here */
+   if (dst[0].is_iomem)
+   drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 4, 
vmap[0].vaddr, fb,
+clip, false, 
drm_fb_xrgb_to_xrgb2101010_line);
+   else
+   drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 4, vmap[0].vaddr, fb,
+   clip, false, drm_fb_xrgb_to_xrgb2101010_line);
 }
-EXPORT_SYMBOL(drm_fb_xrgb_to_xrgb2101010_toio);
 
 static void drm_fb_xrgb_to_gray8_line(void *dbuf, const void *sbuf, 
unsigned int pixels)
 {
@@ -681,8 +700,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int 
*dst_pitch, uint32_t d
}
} else if (dst_format == DRM_FORMAT_XRGB2101010) {
if (fb_format == DRM_FORMAT_XRGB) {
-   drm_fb_xrgb_to_xrgb2101010_toio(dst[0].vaddr_iomem, 
dst_pitch[0],
-   vmap[0].vaddr, fb, 
clip);
+   drm_fb_xrgb_to_xrgb2101010(dst, dst_pitch, vmap, 
fb, clip);
return 0;
}
}
diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h
index 8c633dbab5d6..6807440ce29c 100644
--- a/include/drm/drm_format_helper.h
+++ b/include/drm/drm_format_helper.h
@@ -29,9 +29,9 @@ void drm_fb_xrgb_to_rgb565(struct iosys_map *dst, const 
unsigned int *dst_pi
 void drm_fb_xrgb_to_rgb888(struct iosys_map *dst, const unsigned int 
*dst_pitch,
   const struct iosys_map *vmap, const struct 
drm_framebuffer *fb,
   const struct drm_rect *clip);
-void drm_fb_xrgb_to_xrgb2101010_toio(void __iomem *dst, unsigned int 
dst_pitch,
-const void *vaddr, const struct 

[PATCH v2 11/14] drm/format-helper: Rework XRGB8888-to-GRAY8 conversion

2022-08-08 Thread Thomas Zimmermann
Update XRGB-to-GRAY8 conversion to support struct iosys_map
and convert all users. Although these are single-plane color formats,
the new interface supports multi-plane formats for consistency with
drm_fb_blit().

v2:
* update documentation (Sam)
* add TODO on vaddr location (Sam)

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Sam Ravnborg 
---
 drivers/gpu/drm/drm_format_helper.c | 46 +
 drivers/gpu/drm/gud/gud_pipe.c  |  7 +++--
 drivers/gpu/drm/tiny/st7586.c   |  5 +++-
 include/drm/drm_format_helper.h |  5 ++--
 4 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index 795d845c7e53..890370c0424f 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -613,25 +613,47 @@ static void drm_fb_xrgb_to_gray8_line(void *dbuf, 
const void *sbuf, unsigned
 
 /**
  * drm_fb_xrgb_to_gray8 - Convert XRGB to grayscale
- * @dst: 8-bit grayscale destination buffer
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @vaddr: XRGB source buffer
+ * @dst: Array of 8-bit grayscale destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive 
scanlines
+ * within @dst; can be NULL if scanlines are stored next to each 
other.
+ * @vmap: Array of XRGB source buffers
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  *
- * Drm doesn't have native monochrome or grayscale support.
- * Such drivers can announce the commonly supported XR24 format to userspace
- * and use this function to convert to the native format.
+ * This function copies parts of a framebuffer to display memory and converts 
the
+ * color format during the process. Destination and framebuffer formats must 
match. The
+ * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have 
at
+ * least as many entries as there are planes in @fb's format. Each entry 
stores the
+ * value for the format's respective color plane at the same index.
  *
- * Monochrome drivers will use the most significant bit,
- * where 1 means foreground color and 0 background color.
+ * This function does not apply clipping on @dst (i.e. the destination is at 
the
+ * top-left corner).
  *
- * ITU BT.601 is used for the RGB -> luma (brightness) conversion.
+ * DRM doesn't have native monochrome or grayscale support. Drivers can use 
this
+ * function for grayscale devices that don't support XRGB natively.Such
+ * drivers can announce the commonly supported XR24 format to userspace and use
+ * this function to convert to the native format. Monochrome drivers will use 
the
+ * most significant bit, where 1 means foreground color and 0 background color.
+ * ITU BT.601 is being used for the RGB -> luma (brightness) conversion.
  */
-void drm_fb_xrgb_to_gray8(void *dst, unsigned int dst_pitch, const void 
*vaddr,
- const struct drm_framebuffer *fb, const struct 
drm_rect *clip)
+void drm_fb_xrgb_to_gray8(struct iosys_map *dst, const unsigned int 
*dst_pitch,
+ const struct iosys_map *vmap, const struct 
drm_framebuffer *fb,
+ const struct drm_rect *clip)
 {
-   drm_fb_xfrm(dst, dst_pitch, 1, vaddr, fb, clip, false, 
drm_fb_xrgb_to_gray8_line);
+   static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
+   0, 0, 0, 0
+   };
+
+   if (!dst_pitch)
+   dst_pitch = default_dst_pitch;
+
+   /* TODO: handle vmap in I/O memory here */
+   if (dst[0].is_iomem)
+   drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 1, 
vmap[0].vaddr, fb,
+clip, false, drm_fb_xrgb_to_gray8_line);
+   else
+   drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 1, vmap[0].vaddr, fb,
+   clip, false, drm_fb_xrgb_to_gray8_line);
 }
 EXPORT_SYMBOL(drm_fb_xrgb_to_gray8);
 
diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c
index 0caa228f736d..7c6dc2bcd14a 100644
--- a/drivers/gpu/drm/gud/gud_pipe.c
+++ b/drivers/gpu/drm/gud/gud_pipe.c
@@ -59,6 +59,7 @@ static size_t gud_xrgb_to_r124(u8 *dst, const struct 
drm_format_info *format
unsigned int bits_per_pixel = 8 / block_width;
unsigned int x, y, width, height;
u8 pix, *pix8, *block = dst; /* Assign to silence compiler warning */
+   struct iosys_map dst_map, vmap;
size_t len;
void *buf;
 
@@ -74,7 +75,9 @@ static size_t gud_xrgb_to_r124(u8 *dst, const struct 
drm_format_info *format
if (!buf)
return 0;
 
-   drm_fb_xrgb_to_gray8(buf, 0, src, fb, rect);
+   iosys_map_set_vaddr(_map, buf);
+   iosys_map_set_vaddr(, src);
+   drm_fb_xrgb_to_gray8(_map, NULL, , fb, rect);
pix8 = buf;
 

[PATCH v2 05/14] drm/format-helper: Rework XRGB8888-to-RGBG332 conversion

2022-08-08 Thread Thomas Zimmermann
Update XRGB-to-RGB332 conversion to support struct iosys_map
and convert all users. Although these are single-plane color formats,
the new interface supports multi-plane formats for consistency with
drm_fb_blit().

v2:
* rebase onto refactored Kunit tests
* update documentation (Sam)
* add TODO on vaddr location (Sam)

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Sam Ravnborg 
---
 drivers/gpu/drm/drm_format_helper.c   | 38 +++
 drivers/gpu/drm/gud/gud_pipe.c|  2 +-
 .../gpu/drm/tests/drm_format_helper_test.c| 20 +-
 include/drm/drm_format_helper.h   |  5 ++-
 4 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index b5ed058984ae..248fd87f0a36 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -281,18 +281,42 @@ static void drm_fb_xrgb_to_rgb332_line(void *dbuf, 
const void *sbuf, unsigne
 
 /**
  * drm_fb_xrgb_to_rgb332 - Convert XRGB to RGB332 clip buffer
- * @dst: RGB332 destination buffer
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @src: XRGB source buffer
+ * @dst: Array of RGB332 destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive 
scanlines
+ * within @dst; can be NULL if scanlines are stored next to each 
other.
+ * @vmap: Array of XRGB source buffers
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  *
- * Drivers can use this function for RGB332 devices that don't natively 
support XRGB.
+ * This function copies parts of a framebuffer to display memory and converts 
the
+ * color format during the process. Destination and framebuffer formats must 
match. The
+ * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have 
at
+ * least as many entries as there are planes in @fb's format. Each entry 
stores the
+ * value for the format's respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at 
the
+ * top-left corner).
+ *
+ * Drivers can use this function for RGB332 devices that don't support 
XRGB natively.
  */
-void drm_fb_xrgb_to_rgb332(void *dst, unsigned int dst_pitch, const void 
*src,
-  const struct drm_framebuffer *fb, const struct 
drm_rect *clip)
+void drm_fb_xrgb_to_rgb332(struct iosys_map *dst, const unsigned int 
*dst_pitch,
+  const struct iosys_map *vmap, const struct 
drm_framebuffer *fb,
+  const struct drm_rect *clip)
 {
-   drm_fb_xfrm(dst, dst_pitch, 1, src, fb, clip, false, 
drm_fb_xrgb_to_rgb332_line);
+   static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
+   0, 0, 0, 0
+   };
+
+   if (!dst_pitch)
+   dst_pitch = default_dst_pitch;
+
+   /* TODO: handle vmap in I/O memory here */
+   if (dst[0].is_iomem)
+   drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 1, 
vmap[0].vaddr, fb, clip,
+false, drm_fb_xrgb_to_rgb332_line);
+   else
+   drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 1, vmap[0].vaddr, fb, 
clip,
+   false, drm_fb_xrgb_to_rgb332_line);
 }
 EXPORT_SYMBOL(drm_fb_xrgb_to_rgb332);
 
diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c
index a15cda9ba058..426a3ae6cc50 100644
--- a/drivers/gpu/drm/gud/gud_pipe.c
+++ b/drivers/gpu/drm/gud/gud_pipe.c
@@ -196,7 +196,7 @@ static int gud_prep_flush(struct gud_device *gdrm, struct 
drm_framebuffer *fb,
} else if (format->format == DRM_FORMAT_R8) {
drm_fb_xrgb_to_gray8(buf, 0, vaddr, fb, rect);
} else if (format->format == DRM_FORMAT_RGB332) {
-   drm_fb_xrgb_to_rgb332(buf, 0, vaddr, fb, rect);
+   drm_fb_xrgb_to_rgb332(, NULL, map_data, fb, 
rect);
} else if (format->format == DRM_FORMAT_RGB565) {
drm_fb_xrgb_to_rgb565(buf, 0, vaddr, fb, rect, 
gud_is_big_endian());
} else if (format->format == DRM_FORMAT_RGB888) {
diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c 
b/drivers/gpu/drm/tests/drm_format_helper_test.c
index 26ecf3b4b137..7b14694ead59 100644
--- a/drivers/gpu/drm/tests/drm_format_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_format_helper_test.c
@@ -197,8 +197,9 @@ static void xrgb_to_rgb332_test(struct kunit *test)
const struct convert_xrgb_case *params = test->param_value;
const struct convert_to_rgb332_result *result = >rgb332_result;
size_t dst_size;
-   __u8 *dst = NULL;
-   __u32 *src = NULL;
+   __u8 *buf = NULL;
+   __u32 *xrgb = NULL;
+   struct iosys_map 

[PATCH v2 02/14] drm/format-helper: Provide drm_fb_blit()

2022-08-08 Thread Thomas Zimmermann
Provide drm_fb_blit() that works with struct iosys_map. Update all
users of drm_fb_blit_toio(), which required a destination buffer in
I/O memory.

This patch only updates the function's interface. The implementation
still relies on the destination buffer to be located in  I/O memory.
See the follow-up patches for implementational changes. The new
function's interface works with multi-plane color formats, but again
implementation only supports a single plane for now.

v2:
* rebase onto refactored simpledrm
* use IOSYS_MAP_INIT_VADDR() (Sam)
* update the commit message on the use of I/O memory (Sam)

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Sam Ravnborg 
---
 drivers/gpu/drm/drm_format_helper.c | 44 ++---
 drivers/gpu/drm/tiny/simpledrm.c|  8 +++---
 include/drm/drm_format_helper.h |  7 +++--
 3 files changed, 36 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index 400b16d9147d..07f329f607a3 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -8,9 +8,10 @@
  * (at your option) any later version.
  */
 
+#include 
+#include 
 #include 
 #include 
-#include 
 
 #include 
 #include 
@@ -545,9 +546,10 @@ void drm_fb_xrgb_to_gray8(void *dst, unsigned int 
dst_pitch, const void *vad
 EXPORT_SYMBOL(drm_fb_xrgb_to_gray8);
 
 /**
- * drm_fb_blit_toio - Copy parts of a framebuffer to display memory
- * @dst:   The display memory to copy to
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
+ * drm_fb_blit - Copy parts of a framebuffer to display memory
+ * @dst:   Array of display-memory addresses to copy to
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive 
scanlines
+ * within @dst; can be NULL if scanlines are stored next to each 
other.
  * @dst_format:FOURCC code of the display's color format
  * @vmap:  The framebuffer memory to copy from
  * @fb:The framebuffer to copy from
@@ -555,16 +557,22 @@ EXPORT_SYMBOL(drm_fb_xrgb_to_gray8);
  *
  * This function copies parts of a framebuffer to display memory. If the
  * formats of the display and the framebuffer mismatch, the blit function
- * will attempt to convert between them.
+ * will attempt to convert between them during the process. The parameters 
@dst,
+ * @dst_pitch and @vmap refer to arrays. Each array must have at least as many
+ * entries as there are planes in @dst_format's format. Each entry stores the
+ * value for the format's respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at 
the
+ * top-left corner).
  *
  * Returns:
  * 0 on success, or
  * -EINVAL if the color-format conversion failed, or
  * a negative error code otherwise.
  */
-int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t 
dst_format,
-const void *vmap, const struct drm_framebuffer *fb,
-const struct drm_rect *clip)
+int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t 
dst_format,
+   const struct iosys_map *vmap, const struct drm_framebuffer *fb,
+   const struct drm_rect *clip)
 {
uint32_t fb_format = fb->format->format;
 
@@ -579,30 +587,35 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int 
dst_pitch, uint32_t dst_for
dst_format = DRM_FORMAT_XRGB2101010;
 
if (dst_format == fb_format) {
-   drm_fb_memcpy_toio(dst, dst_pitch, vmap, fb, clip);
+   drm_fb_memcpy_toio(dst[0].vaddr_iomem, dst_pitch[0], 
vmap[0].vaddr, fb, clip);
return 0;
 
} else if (dst_format == DRM_FORMAT_RGB565) {
if (fb_format == DRM_FORMAT_XRGB) {
-   drm_fb_xrgb_to_rgb565_toio(dst, dst_pitch, vmap, 
fb, clip, false);
+   drm_fb_xrgb_to_rgb565_toio(dst[0].vaddr_iomem, 
dst_pitch[0],
+  vmap[0].vaddr, fb, clip, 
false);
return 0;
}
} else if (dst_format == DRM_FORMAT_RGB888) {
if (fb_format == DRM_FORMAT_XRGB) {
-   drm_fb_xrgb_to_rgb888_toio(dst, dst_pitch, vmap, 
fb, clip);
+   drm_fb_xrgb_to_rgb888_toio(dst[0].vaddr_iomem, 
dst_pitch[0],
+  vmap[0].vaddr, fb, clip);
return 0;
}
} else if (dst_format == DRM_FORMAT_XRGB) {
if (fb_format == DRM_FORMAT_RGB888) {
-   drm_fb_rgb888_to_xrgb_toio(dst, dst_pitch, vmap, 
fb, clip);
+   drm_fb_rgb888_to_xrgb_toio(dst[0].vaddr_iomem, 
dst_pitch[0],
+  vmap[0].vaddr, fb, 

[PATCH v2 12/14] drm/format-helper: Rework XRGB8888-to-MONO conversion

2022-08-08 Thread Thomas Zimmermann
Update XRGB-to-MONO conversion to support struct iosys_map
and convert all users. Although these are single-plane color formats,
the new interface supports multi-plane formats for consistency with
drm_fb_blit().

v2:
* rebase after renaming CMA helpers to DMA helpers
* update documentation (Sam)

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Sam Ravnborg 
---
 drivers/gpu/drm/drm_format_helper.c | 56 +++--
 drivers/gpu/drm/solomon/ssd130x.c   |  7 ++--
 drivers/gpu/drm/tiny/repaper.c  |  6 +++-
 include/drm/drm_format_helper.h |  5 +--
 4 files changed, 49 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index 890370c0424f..53a313f83dc2 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -753,46 +753,64 @@ static void drm_fb_gray8_to_mono_line(void *dbuf, const 
void *sbuf, unsigned int
 
 /**
  * drm_fb_xrgb_to_mono - Convert XRGB to monochrome
- * @dst: monochrome destination buffer (0=black, 1=white)
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @vaddr: XRGB source buffer
+ * @dst: Array of monochrome destination buffers (0=black, 1=white)
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive 
scanlines
+ * within @dst; can be NULL if scanlines are stored next to each 
other.
+ * @vmap: Array of XRGB source buffers
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  *
- * DRM doesn't have native monochrome support.
- * Such drivers can announce the commonly supported XR24 format to userspace
- * and use this function to convert to the native format.
+ * This function copies parts of a framebuffer to display memory and converts 
the
+ * color format during the process. Destination and framebuffer formats must 
match. The
+ * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have 
at
+ * least as many entries as there are planes in @fb's format. Each entry 
stores the
+ * value for the format's respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at 
the
+ * top-left corner). The first pixel (upper left corner of the clip rectangle) 
will
+ * be converted and copied to the first bit (LSB) in the first byte of the 
monochrome
+ * destination buffer. If the caller requires that the first pixel in a byte 
must
+ * be located at an x-coordinate that is a multiple of 8, then the caller must 
take
+ * care itself of supplying a suitable clip rectangle.
+ *
+ * DRM doesn't have native monochrome support. Drivers can use this function 
for
+ * monochrome devices that don't support XRGB natively. Such drivers can
+ * announce the commonly supported XR24 format to userspace and use this 
function
+ * to convert to the native format.
  *
  * This function uses drm_fb_xrgb_to_gray8() to convert to grayscale and
  * then the result is converted from grayscale to monochrome.
- *
- * The first pixel (upper left corner of the clip rectangle) will be converted
- * and copied to the first bit (LSB) in the first byte of the monochrome
- * destination buffer.
- * If the caller requires that the first pixel in a byte must be located at an
- * x-coordinate that is a multiple of 8, then the caller must take care itself
- * of supplying a suitable clip rectangle.
  */
-void drm_fb_xrgb_to_mono(void *dst, unsigned int dst_pitch, const void 
*vaddr,
-const struct drm_framebuffer *fb, const struct 
drm_rect *clip)
+void drm_fb_xrgb_to_mono(struct iosys_map *dst, const unsigned int 
*dst_pitch,
+const struct iosys_map *vmap, const struct 
drm_framebuffer *fb,
+const struct drm_rect *clip)
 {
+   static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
+   0, 0, 0, 0
+   };
unsigned int linepixels = drm_rect_width(clip);
unsigned int lines = drm_rect_height(clip);
unsigned int cpp = fb->format->cpp[0];
unsigned int len_src32 = linepixels * cpp;
struct drm_device *dev = fb->dev;
+   void *vaddr = vmap[0].vaddr;
+   unsigned int dst_pitch_0;
unsigned int y;
-   u8 *mono = dst, *gray8;
+   u8 *mono = dst[0].vaddr, *gray8;
u32 *src32;
 
if (drm_WARN_ON(dev, fb->format->format != DRM_FORMAT_XRGB))
return;
 
+   if (!dst_pitch)
+   dst_pitch = default_dst_pitch;
+   dst_pitch_0 = dst_pitch[0];
+
/*
 * The mono destination buffer contains 1 bit per pixel
 */
-   if (!dst_pitch)
-   dst_pitch = DIV_ROUND_UP(linepixels, 8);
+   if (!dst_pitch_0)
+   dst_pitch_0 = DIV_ROUND_UP(linepixels, 8);
 
/*
 * The dma memory is write-combined so reads are uncached.
@@ -817,7 +835,7 

[PATCH v2 08/14] drm/format-helper: Rework RGB565-to-XRGB8888 conversion

2022-08-08 Thread Thomas Zimmermann
Update RGB565-to-XRGB conversion to support struct iosys_map
and convert all users. Although these are single-plane color formats,
the new interface supports multi-plane formats for consistency with
drm_fb_blit().

v2:
* add TODO on vaddr location (Sam)

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Sam Ravnborg 
---
 drivers/gpu/drm/drm_format_helper.c | 26 +++---
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index 3ee57dc8bcc5..b390d529afeb 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -478,12 +478,25 @@ static void drm_fb_rgb565_to_xrgb_line(void *dbuf, 
const void *sbuf, unsigne
}
 }
 
-static void drm_fb_rgb565_to_xrgb_toio(void __iomem *dst, unsigned int 
dst_pitch,
-  const void *vaddr, const struct 
drm_framebuffer *fb,
-  const struct drm_rect *clip)
+static void drm_fb_rgb565_to_xrgb(struct iosys_map *dst, const unsigned 
int *dst_pitch,
+ const struct iosys_map *vmap,
+ const struct drm_framebuffer *fb,
+ const struct drm_rect *clip)
 {
-   drm_fb_xfrm_toio(dst, dst_pitch, 4, vaddr, fb, clip, false,
-drm_fb_rgb565_to_xrgb_line);
+   static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
+   0, 0, 0, 0
+   };
+
+   if (!dst_pitch)
+   dst_pitch = default_dst_pitch;
+
+   /* TODO: handle vmap in I/O memory here */
+   if (dst[0].is_iomem)
+   drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 4, 
vmap[0].vaddr, fb,
+clip, false, drm_fb_rgb565_to_xrgb_line);
+   else
+   drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 4, vmap[0].vaddr, fb,
+   clip, false, drm_fb_rgb565_to_xrgb_line);
 }
 
 static void drm_fb_rgb888_to_xrgb_line(void *dbuf, const void *sbuf, 
unsigned int pixels)
@@ -651,8 +664,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int 
*dst_pitch, uint32_t d
   vmap[0].vaddr, fb, clip);
return 0;
} else if (fb_format == DRM_FORMAT_RGB565) {
-   drm_fb_rgb565_to_xrgb_toio(dst[0].vaddr_iomem, 
dst_pitch[0],
-  vmap[0].vaddr, fb, clip);
+   drm_fb_rgb565_to_xrgb(dst, dst_pitch, vmap, fb, 
clip);
return 0;
}
} else if (dst_format == DRM_FORMAT_XRGB2101010) {
-- 
2.37.1



[PATCH v2 06/14] drm/format-helper: Rework XRGB8888-to-RGBG565 conversion

2022-08-08 Thread Thomas Zimmermann
Update XRGB-to-RGB565 conversion to support struct iosys_map
and convert all users. Although these are single-plane color formats,
the new interface supports multi-plane formats for consistency with
drm_fb_blit().

v2:
* update new Kunit tests
* update documentation (Sam)
* add TODO on vaddr location (Sam)

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Sam Ravnborg 
---
 drivers/gpu/drm/drm_format_helper.c   | 73 +--
 drivers/gpu/drm/drm_mipi_dbi.c|  4 +-
 drivers/gpu/drm/gud/gud_pipe.c|  3 +-
 .../gpu/drm/tests/drm_format_helper_test.c| 25 ---
 drivers/gpu/drm/tiny/cirrus.c |  3 +-
 include/drm/drm_format_helper.h   |  9 +--
 6 files changed, 55 insertions(+), 62 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index 248fd87f0a36..a77291d2f9b9 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -357,53 +357,51 @@ static void drm_fb_xrgb_to_rgb565_swab_line(void 
*dbuf, const void *sbuf,
 
 /**
  * drm_fb_xrgb_to_rgb565 - Convert XRGB to RGB565 clip buffer
- * @dst: RGB565 destination buffer
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @vaddr: XRGB source buffer
+ * @dst: Array of RGB565 destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive 
scanlines
+ * within @dst; can be NULL if scanlines are stored next to each 
other.
+ * @vmap: Array of XRGB source buffer
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  * @swab: Swap bytes
  *
- * Drivers can use this function for RGB565 devices that don't natively
- * support XRGB.
+ * This function copies parts of a framebuffer to display memory and converts 
the
+ * color format during the process. Destination and framebuffer formats must 
match. The
+ * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have 
at
+ * least as many entries as there are planes in @fb's format. Each entry 
stores the
+ * value for the format's respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at 
the
+ * top-left corner).
+ *
+ * Drivers can use this function for RGB565 devices that don't support 
XRGB natively.
  */
-void drm_fb_xrgb_to_rgb565(void *dst, unsigned int dst_pitch, const void 
*vaddr,
-  const struct drm_framebuffer *fb, const struct 
drm_rect *clip,
-  bool swab)
+void drm_fb_xrgb_to_rgb565(struct iosys_map *dst, const unsigned int 
*dst_pitch,
+  const struct iosys_map *vmap, const struct 
drm_framebuffer *fb,
+  const struct drm_rect *clip, bool swab)
 {
+   static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
+   0, 0, 0, 0
+   };
+   void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels);
+
if (swab)
-   drm_fb_xfrm(dst, dst_pitch, 2, vaddr, fb, clip, false,
-   drm_fb_xrgb_to_rgb565_swab_line);
+   xfrm_line = drm_fb_xrgb_to_rgb565_swab_line;
else
-   drm_fb_xfrm(dst, dst_pitch, 2, vaddr, fb, clip, false,
-   drm_fb_xrgb_to_rgb565_line);
-}
-EXPORT_SYMBOL(drm_fb_xrgb_to_rgb565);
+   xfrm_line = drm_fb_xrgb_to_rgb565_line;
 
-/**
- * drm_fb_xrgb_to_rgb565_toio - Convert XRGB to RGB565 clip buffer
- * @dst: RGB565 destination buffer (iomem)
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @vaddr: XRGB source buffer
- * @fb: DRM framebuffer
- * @clip: Clip rectangle area to copy
- * @swab: Swap bytes
- *
- * Drivers can use this function for RGB565 devices that don't natively
- * support XRGB.
- */
-void drm_fb_xrgb_to_rgb565_toio(void __iomem *dst, unsigned int dst_pitch,
-   const void *vaddr, const struct 
drm_framebuffer *fb,
-   const struct drm_rect *clip, bool swab)
-{
-   if (swab)
-   drm_fb_xfrm_toio(dst, dst_pitch, 2, vaddr, fb, clip, false,
-drm_fb_xrgb_to_rgb565_swab_line);
+   if (!dst_pitch)
+   dst_pitch = default_dst_pitch;
+
+   /* TODO: handle vmap in I/O memory here */
+   if (dst[0].is_iomem)
+   drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 2, 
vmap[0].vaddr, fb, clip,
+false, xfrm_line);
else
-   drm_fb_xfrm_toio(dst, dst_pitch, 2, vaddr, fb, clip, false,
-drm_fb_xrgb_to_rgb565_line);
+   drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 2, vmap[0].vaddr, fb, 
clip,
+   false, 

[PATCH v2 09/14] drm/format-helper: Rework RGB888-to-XRGB8888 conversion

2022-08-08 Thread Thomas Zimmermann
Update RGB888-to-XRGB conversion to support struct iosys_map
and convert all users. Although these are single-plane color formats,
the new interface supports multi-plane formats for consistency with
drm_fb_blit().

v2:
* add TODO on vaddr location (Sam)

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Sam Ravnborg 
---
 drivers/gpu/drm/drm_format_helper.c | 26 +++---
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index b390d529afeb..8083f5b85b3a 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -514,12 +514,25 @@ static void drm_fb_rgb888_to_xrgb_line(void *dbuf, 
const void *sbuf, unsigne
}
 }
 
-static void drm_fb_rgb888_to_xrgb_toio(void __iomem *dst, unsigned int 
dst_pitch,
-  const void *vaddr, const struct 
drm_framebuffer *fb,
-  const struct drm_rect *clip)
+static void drm_fb_rgb888_to_xrgb(struct iosys_map *dst, const unsigned 
int *dst_pitch,
+ const struct iosys_map *vmap,
+ const struct drm_framebuffer *fb,
+ const struct drm_rect *clip)
 {
-   drm_fb_xfrm_toio(dst, dst_pitch, 4, vaddr, fb, clip, false,
-drm_fb_rgb888_to_xrgb_line);
+   static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
+   0, 0, 0, 0
+   };
+
+   if (!dst_pitch)
+   dst_pitch = default_dst_pitch;
+
+   /* TODO: handle vmap in I/O memory here */
+   if (dst[0].is_iomem)
+   drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 4, 
vmap[0].vaddr, fb,
+clip, false, drm_fb_rgb888_to_xrgb_line);
+   else
+   drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 4, vmap[0].vaddr, fb,
+   clip, false, drm_fb_rgb888_to_xrgb_line);
 }
 
 static void drm_fb_xrgb_to_xrgb2101010_line(void *dbuf, const void *sbuf, 
unsigned int pixels)
@@ -660,8 +673,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int 
*dst_pitch, uint32_t d
}
} else if (dst_format == DRM_FORMAT_XRGB) {
if (fb_format == DRM_FORMAT_RGB888) {
-   drm_fb_rgb888_to_xrgb_toio(dst[0].vaddr_iomem, 
dst_pitch[0],
-  vmap[0].vaddr, fb, clip);
+   drm_fb_rgb888_to_xrgb(dst, dst_pitch, vmap, fb, 
clip);
return 0;
} else if (fb_format == DRM_FORMAT_RGB565) {
drm_fb_rgb565_to_xrgb(dst, dst_pitch, vmap, fb, 
clip);
-- 
2.37.1



[PATCH v2 07/14] drm/format-helper: Rework XRGB8888-to-RGB888 conversion

2022-08-08 Thread Thomas Zimmermann
Update XRGB-to-RGB888 conversion to support struct iosys_map
and convert all users. Although these are single-plane color formats,
the new interface supports multi-plane formats for consistency with
drm_fb_blit().

v2:
* update documentation (Sam)
* add TODO on vaddr location (Sam)

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Sam Ravnborg 
---
 drivers/gpu/drm/drm_format_helper.c | 59 +++--
 drivers/gpu/drm/gud/gud_pipe.c  |  2 +-
 drivers/gpu/drm/tiny/cirrus.c   |  3 +-
 include/drm/drm_format_helper.h |  8 ++--
 4 files changed, 36 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index a77291d2f9b9..3ee57dc8bcc5 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -420,41 +420,45 @@ static void drm_fb_xrgb_to_rgb888_line(void *dbuf, 
const void *sbuf, unsigne
 
 /**
  * drm_fb_xrgb_to_rgb888 - Convert XRGB to RGB888 clip buffer
- * @dst: RGB888 destination buffer
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @src: XRGB source buffer
+ * @dst: Array of RGB888 destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive 
scanlines
+ * within @dst; can be NULL if scanlines are stored next to each 
other.
+ * @vmap: Array of XRGB source buffers
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  *
- * Drivers can use this function for RGB888 devices that don't natively
- * support XRGB.
- */
-void drm_fb_xrgb_to_rgb888(void *dst, unsigned int dst_pitch, const void 
*src,
-  const struct drm_framebuffer *fb, const struct 
drm_rect *clip)
-{
-   drm_fb_xfrm(dst, dst_pitch, 3, src, fb, clip, false, 
drm_fb_xrgb_to_rgb888_line);
-}
-EXPORT_SYMBOL(drm_fb_xrgb_to_rgb888);
-
-/**
- * drm_fb_xrgb_to_rgb888_toio - Convert XRGB to RGB888 clip buffer
- * @dst: RGB565 destination buffer (iomem)
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @vaddr: XRGB source buffer
- * @fb: DRM framebuffer
- * @clip: Clip rectangle area to copy
+ * This function copies parts of a framebuffer to display memory and converts 
the
+ * color format during the process. Destination and framebuffer formats must 
match. The
+ * parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must have 
at
+ * least as many entries as there are planes in @fb's format. Each entry 
stores the
+ * value for the format's respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at 
the
+ * top-left corner).
  *
  * Drivers can use this function for RGB888 devices that don't natively
  * support XRGB.
  */
-void drm_fb_xrgb_to_rgb888_toio(void __iomem *dst, unsigned int dst_pitch,
-   const void *vaddr, const struct 
drm_framebuffer *fb,
-   const struct drm_rect *clip)
+void drm_fb_xrgb_to_rgb888(struct iosys_map *dst, const unsigned int 
*dst_pitch,
+  const struct iosys_map *vmap, const struct 
drm_framebuffer *fb,
+  const struct drm_rect *clip)
 {
-   drm_fb_xfrm_toio(dst, dst_pitch, 3, vaddr, fb, clip, false,
-drm_fb_xrgb_to_rgb888_line);
+   static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
+   0, 0, 0, 0
+   };
+
+   if (!dst_pitch)
+   dst_pitch = default_dst_pitch;
+
+   /* TODO: handle vmap in I/O memory here */
+   if (dst[0].is_iomem)
+   drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 3, 
vmap[0].vaddr, fb,
+clip, false, drm_fb_xrgb_to_rgb888_line);
+   else
+   drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 3, vmap[0].vaddr, fb,
+   clip, false, drm_fb_xrgb_to_rgb888_line);
 }
-EXPORT_SYMBOL(drm_fb_xrgb_to_rgb888_toio);
+EXPORT_SYMBOL(drm_fb_xrgb_to_rgb888);
 
 static void drm_fb_rgb565_to_xrgb_line(void *dbuf, const void *sbuf, 
unsigned int pixels)
 {
@@ -638,8 +642,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int 
*dst_pitch, uint32_t d
}
} else if (dst_format == DRM_FORMAT_RGB888) {
if (fb_format == DRM_FORMAT_XRGB) {
-   drm_fb_xrgb_to_rgb888_toio(dst[0].vaddr_iomem, 
dst_pitch[0],
-  vmap[0].vaddr, fb, clip);
+   drm_fb_xrgb_to_rgb888(dst, dst_pitch, vmap, fb, 
clip);
return 0;
}
} else if (dst_format == DRM_FORMAT_XRGB) {
diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c
index a43eb6645352..0caa228f736d 100644
--- 

[PATCH v2 03/14] drm/format-helper: Merge drm_fb_memcpy() and drm_fb_memcpy_toio()

2022-08-08 Thread Thomas Zimmermann
Merge drm_fb_memcpy() and drm_fb_memcpy_toio() into a drm_fb_memcpy()
that uses struct iosys_map for buffers. The new function also supports
multi-plane color formats. Convert all users of the original helpers.

v2:
* rebase onto refactored mgag200
* use drm_formap_info_bpp() (Sam)
* do static init in hyperv and mgag200 (Sam)
* update documentation (Sam)
* add TODO on vaddr location (Sam)

Signed-off-by: Thomas Zimmermann 
---
 drivers/gpu/drm/drm_format_helper.c | 90 ++---
 drivers/gpu/drm/drm_mipi_dbi.c  |  3 +-
 drivers/gpu/drm/gud/gud_pipe.c  |  4 +-
 drivers/gpu/drm/hyperv/hyperv_drm_modeset.c |  9 +--
 drivers/gpu/drm/mgag200/mgag200_mode.c  |  9 +--
 drivers/gpu/drm/tiny/cirrus.c   | 21 ++---
 include/drm/drm_format_helper.h |  7 +-
 7 files changed, 70 insertions(+), 73 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index 07f329f607a3..7489c665a47c 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -131,63 +131,57 @@ static int drm_fb_xfrm_toio(void __iomem *dst, unsigned 
long dst_pitch, unsigned
 
 /**
  * drm_fb_memcpy - Copy clip buffer
- * @dst: Destination buffer
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @vaddr: Source buffer
+ * @dst: Array of destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive 
scanlines
+ * within @dst; can be NULL if scanlines are stored next to each 
other.
+ * @vmap: Array of source buffers
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  *
- * This function does not apply clipping on dst, i.e. the destination
- * is at the top-left corner.
- */
-void drm_fb_memcpy(void *dst, unsigned int dst_pitch, const void *vaddr,
-  const struct drm_framebuffer *fb, const struct drm_rect 
*clip)
-{
-   unsigned int cpp = fb->format->cpp[0];
-   size_t len = (clip->x2 - clip->x1) * cpp;
-   unsigned int y, lines = clip->y2 - clip->y1;
-
-   if (!dst_pitch)
-   dst_pitch = len;
-
-   vaddr += clip_offset(clip, fb->pitches[0], cpp);
-   for (y = 0; y < lines; y++) {
-   memcpy(dst, vaddr, len);
-   vaddr += fb->pitches[0];
-   dst += dst_pitch;
-   }
-}
-EXPORT_SYMBOL(drm_fb_memcpy);
-
-/**
- * drm_fb_memcpy_toio - Copy clip buffer
- * @dst: Destination buffer (iomem)
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @vaddr: Source buffer
- * @fb: DRM framebuffer
- * @clip: Clip rectangle area to copy
+ * This function copies parts of a framebuffer to display memory. Destination 
and
+ * framebuffer formats must match. No conversion takes place. The parameters 
@dst,
+ * @dst_pitch and @vmap refer to arrays. Each array must have at least as many 
entries
+ * as there are planes in @fb's format. Each entry stores the value for the 
format's
+ * respective color plane at the same index.
  *
- * This function does not apply clipping on dst, i.e. the destination
- * is at the top-left corner.
+ * This function does not apply clipping on @dst (i.e. the destination is at 
the
+ * top-left corner).
  */
-void drm_fb_memcpy_toio(void __iomem *dst, unsigned int dst_pitch, const void 
*vaddr,
-   const struct drm_framebuffer *fb, const struct drm_rect 
*clip)
+void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch,
+  const struct iosys_map *vmap, const struct drm_framebuffer 
*fb,
+  const struct drm_rect *clip)
 {
-   unsigned int cpp = fb->format->cpp[0];
-   size_t len = (clip->x2 - clip->x1) * cpp;
-   unsigned int y, lines = clip->y2 - clip->y1;
+   static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
+   0, 0, 0, 0
+   };
 
-   if (!dst_pitch)
-   dst_pitch = len;
+   const struct drm_format_info *format = fb->format;
+   unsigned int i, y, lines = drm_rect_height(clip);
 
-   vaddr += clip_offset(clip, fb->pitches[0], cpp);
-   for (y = 0; y < lines; y++) {
-   memcpy_toio(dst, vaddr, len);
-   vaddr += fb->pitches[0];
-   dst += dst_pitch;
+   if (!dst_pitch)
+   dst_pitch = default_dst_pitch;
+
+   for (i = 0; i < format->num_planes; ++i) {
+   unsigned int bpp_i = drm_format_info_bpp(format, i);
+   unsigned int cpp_i = DIV_ROUND_UP(bpp_i, 8);
+   size_t len_i = DIV_ROUND_UP(drm_rect_width(clip) * bpp_i, 8);
+   unsigned int dst_pitch_i = dst_pitch[i];
+   struct iosys_map dst_i = dst[i];
+   struct iosys_map vmap_i = vmap[i];
+
+   if (!dst_pitch_i)
+   dst_pitch_i = len_i;
+
+   iosys_map_incr(_i, clip_offset(clip, 

[PATCH v2 01/14] iosys-map: Add IOSYS_MAP_INIT_VADDR_IOMEM()

2022-08-08 Thread Thomas Zimmermann
Add IOSYS_MAP_INIT_VADDR_IOMEM() for static init of variables of type
struct iosys_map.

Signed-off-by: Thomas Zimmermann 
---
 include/linux/iosys-map.h | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/include/linux/iosys-map.h b/include/linux/iosys-map.h
index a533cae189d7..cb71aa616bd3 100644
--- a/include/linux/iosys-map.h
+++ b/include/linux/iosys-map.h
@@ -46,10 +46,13 @@
  *
  * iosys_map_set_vaddr(, 0xdeadbeaf);
  *
- * To set an address in I/O memory, use iosys_map_set_vaddr_iomem().
+ * To set an address in I/O memory, use IOSYS_MAP_INIT_VADDR_IOMEM() or
+ * iosys_map_set_vaddr_iomem().
  *
  * .. code-block:: c
  *
+ * struct iosys_map map = IOSYS_MAP_INIT_VADDR_IOMEM(0xdeadbeaf);
+ *
  * iosys_map_set_vaddr_iomem(, 0xdeadbeaf);
  *
  * Instances of struct iosys_map do not have to be cleaned up, but
@@ -121,6 +124,16 @@ struct iosys_map {
.is_iomem = false,  \
}
 
+/**
+ * IOSYS_MAP_INIT_VADDR_IOMEM - Initializes struct iosys_map to an address in 
I/O memory
+ * @vaddr_iomem_:  An I/O-memory address
+ */
+#define IOSYS_MAP_INIT_VADDR_IOMEM(vaddr_iomem_)   \
+   {   \
+   .vaddr_iomem = (vaddr_iomem_),  \
+   .is_iomem = true,   \
+   }
+
 /**
  * IOSYS_MAP_INIT_OFFSET - Initializes struct iosys_map from another iosys_map
  * @map_:  The dma-buf mapping structure to copy from
-- 
2.37.1



Re: [PATCH v1 06/35] drm/connector: Only register TV mode property if present

2022-08-08 Thread Noralf Trønnes



Den 29.07.2022 18.34, skrev Maxime Ripard:
> The drm_create_tv_properties() will create the TV mode property
> unconditionally.
> 
> However, since we'll gradually phase it out, let's register it only if we
> have a list passed as an argument. This will make the transition easier.
> 
> Signed-off-by: Maxime Ripard 
> 

I don't understand why this makes the transition easier, but if you
think so:

Acked-by: Noralf Trønnes 

> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 68a4e47f85a9..d73a68764b6e 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -1684,7 +1684,6 @@ int drm_mode_create_tv_properties(struct drm_device 
> *dev,
>   struct drm_property *tv_selector;
>   struct drm_property *tv_subconnector;
>   struct drm_property *tv_norm;
> - unsigned int i;
>  
>   if (dev->mode_config.tv_select_subconnector_property)
>   return 0;
> @@ -1723,15 +1722,19 @@ int drm_mode_create_tv_properties(struct drm_device 
> *dev,
>   goto nomem;
>   dev->mode_config.tv_norm_property = tv_norm;
>  
> - dev->mode_config.tv_mode_property =
> - drm_property_create(dev, DRM_MODE_PROP_ENUM,
> - "mode", num_modes);
> - if (!dev->mode_config.tv_mode_property)
> - goto nomem;
> + if (num_modes) {
> + unsigned int i;
>  
> - for (i = 0; i < num_modes; i++)
> - drm_property_add_enum(dev->mode_config.tv_mode_property,
> -   i, modes[i]);
> + dev->mode_config.tv_mode_property =
> + drm_property_create(dev, DRM_MODE_PROP_ENUM,
> + "mode", num_modes);
> + if (!dev->mode_config.tv_mode_property)
> + goto nomem;
> +
> + for (i = 0; i < num_modes; i++)
> + drm_property_add_enum(dev->mode_config.tv_mode_property,
> +   i, modes[i]);
> + }
>  
>   dev->mode_config.tv_brightness_property =
>   drm_property_create_range(dev, 0, "brightness", 0, 100);
> 


Re: [PATCH v1 05/35] drm/connector: Add TV standard property

2022-08-08 Thread Noralf Trønnes



Den 29.07.2022 18.34, skrev Maxime Ripard:
> The TV mode property has been around for a while now to select and get the
> current TV mode output on an analog TV connector.
> 
> Despite that property name being generic, its content isn't and has been
> driver-specific which makes it hard to build any generic behaviour on top
> of it, both in kernel and user-space.
> 
> Let's create a new bitmask tv norm property, that can contain any of the
> analog TV standards currently supported by kernel drivers. Each driver can
> then pass in a bitmask of the modes it supports.
> 
> We'll then be able to phase out the older tv mode property.
> 
> Signed-off-by: Maxime Ripard 
> 

Please also update Documentation/gpu/kms-properties.csv

Requirements for adding a new property is found in
Documentation/gpu/drm-kms.rst

> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
> b/drivers/gpu/drm/drm_atomic_uapi.c
> index c06d0639d552..d7ff6c644c2f 100644
> --- a/drivers/gpu/drm/drm_atomic_uapi.c
> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> @@ -700,6 +700,8 @@ static int drm_atomic_connector_set_property(struct 
> drm_connector *connector,
>   state->tv.margins.bottom = val;
>   } else if (property == config->tv_mode_property) {
>   state->tv.mode = val;
> + } else if (property == config->tv_norm_property) {
> + state->tv.norm = val;
>   } else if (property == config->tv_brightness_property) {
>   state->tv.brightness = val;
>   } else if (property == config->tv_contrast_property) {
> @@ -810,6 +812,8 @@ drm_atomic_connector_get_property(struct drm_connector 
> *connector,
>   *val = state->tv.margins.bottom;
>   } else if (property == config->tv_mode_property) {
>   *val = state->tv.mode;
> + } else if (property == config->tv_norm_property) {
> + *val = state->tv.norm;
>   } else if (property == config->tv_brightness_property) {
>   *val = state->tv.brightness;
>   } else if (property == config->tv_contrast_property) {
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index e3142c8142b3..68a4e47f85a9 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -1637,6 +1637,7 @@ EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
>  /**
>   * drm_mode_create_tv_properties - create TV specific connector properties
>   * @dev: DRM device
> + * @supported_tv_norms: Bitmask of TV norms supported (See 
> DRM_MODE_TV_NORM_*)
>   * @num_modes: number of different TV formats (modes) supported
>   * @modes: array of pointers to strings containing name of each format
>   *
> @@ -1649,11 +1650,40 @@ EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
>   * 0 on success or a negative error code on failure.
>   */
>  int drm_mode_create_tv_properties(struct drm_device *dev,
> +   unsigned int supported_tv_norms,
> unsigned int num_modes,
> const char * const modes[])
>  {
> + static const struct drm_prop_enum_list tv_norm_values[] = {
> + { __builtin_ffs(DRM_MODE_TV_NORM_NTSC_443) - 1, "NTSC-443" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_NTSC_J) - 1, "NTSC-J" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_NTSC_M) - 1, "NTSC-M" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_PAL_60) - 1, "PAL-60" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_PAL_B) - 1, "PAL-B" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_PAL_D) - 1, "PAL-D" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_PAL_G) - 1, "PAL-G" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_PAL_H) - 1, "PAL-H" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_PAL_I) - 1, "PAL-I" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_PAL_M) - 1, "PAL-M" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_PAL_N) - 1, "PAL-N" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_PAL_NC) - 1, "PAL-Nc" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_SECAM_60) - 1, "SECAM-60" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_SECAM_B) - 1, "SECAM-B" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_SECAM_D) - 1, "SECAM-D" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_SECAM_G) - 1, "SECAM-G" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_SECAM_K) - 1, "SECAM-K" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_SECAM_K1) - 1, "SECAM-K1" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_SECAM_L) - 1, "SECAM-L" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_HD480I) - 1, "hd480i" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_HD480P) - 1, "hd480p" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_HD576I) - 1, "hd576i" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_HD576P) - 1, "hd576p" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_HD720P) - 1, "hd720p" },
> + { __builtin_ffs(DRM_MODE_TV_NORM_HD1080I) - 1, "hd1080i" 

RE: [v1] drm/msm/disp/dpu1: add support for hierarchical flush for dspp in sc7280

2022-08-08 Thread Kalyan Thota


>-Original Message-
>From: Dmitry Baryshkov 
>Sent: Thursday, August 4, 2022 9:29 PM
>To: Kalyan Thota (QUIC) 
>Cc: dri-devel@lists.freedesktop.org; linux-arm-...@vger.kernel.org;
>freedr...@lists.freedesktop.org; devicet...@vger.kernel.org; linux-
>ker...@vger.kernel.org; robdcl...@gmail.com; diand...@chromium.org;
>swb...@chromium.org; Vinod Polimera (QUIC) ;
>Abhinav Kumar (QUIC) 
>Subject: Re: [v1] drm/msm/disp/dpu1: add support for hierarchical flush for 
>dspp
>in sc7280
>
>WARNING: This email originated from outside of Qualcomm. Please be wary of
>any links or attachments, and do not enable macros.
>
>On Thu, 4 Aug 2022 at 13:29, Kalyan Thota  wrote:
>>
>> Flush mechanism for DSPP blocks has changed in sc7280 family, it
>> allows individual sub blocks to be flushed in coordination with master
>> flush control.
>>
>> representation: master_flush && (PCC_flush | IGC_flush .. etc )
>>
>> This change adds necessary support for the above design.
>>
>> Signed-off-by: Kalyan Thota 
>
>I'd like to land at least patches 6-8 from [1] next cycle. They clean up the 
>CTL
>interface. Could you please rebase your patch on top of them?
>

Sure I'll wait for the series to rebase. @Doug can you comment if this is okay 
and this patch is not needed immediately ?

>[1] https://patchwork.freedesktop.org/series/99909/
>
>> ---
>>  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c   |  4 +++
>>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c |  5 +++-
>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h |  2 ++
>>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 40
>+-
>>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h |  3 ++
>>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h|  7 +
>>  6 files changed, 59 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> index 7763558..4eca317 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> @@ -703,6 +703,10 @@ static void _dpu_crtc_setup_cp_blocks(struct
>drm_crtc *crtc)
>> mixer[i].flush_mask |= ctl->ops.get_bitmask_dspp(ctl,
>> mixer[i].hw_dspp->idx);
>>
>> +   if(ctl->ops.set_dspp_hierarchical_flush)
>> +   ctl->ops.set_dspp_hierarchical_flush(ctl,
>> +   mixer[i].hw_dspp->idx,
>> + DSPP_SUB_PCC);
>> +
>> /* stage config flush mask */
>> ctl->ops.update_pending_flush(ctl,
>> mixer[i].flush_mask);
>>
>> 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 021eb2f..3b27a87 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>> @@ -58,7 +58,10 @@
>> (PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2))
>>
>>  #define CTL_SC7280_MASK \
>> -   (BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_FETCH_ACTIVE) |
>BIT(DPU_CTL_VM_CFG))
>> +   (BIT(DPU_CTL_ACTIVE_CFG) | \
>> +BIT(DPU_CTL_FETCH_ACTIVE) | \
>> +BIT(DPU_CTL_VM_CFG) | \
>> +BIT(DPU_CTL_HIERARCHICAL_FLUSH))
>>
>>  #define MERGE_3D_SM8150_MASK (0)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>> index b85b24b..7922f6c 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>> @@ -185,6 +185,7 @@ enum {
>>   * @DPU_CTL_SPLIT_DISPLAY: CTL supports video mode split display
>>   * @DPU_CTL_FETCH_ACTIVE:  Active CTL for fetch HW (SSPPs)
>>   * @DPU_CTL_VM_CFG:CTL config to support multiple VMs
>> + * @DPU_CTL_HIERARCHICAL_FLUSH: CTL config to support hierarchical
>> + flush
>>   * @DPU_CTL_MAX
>>   */
>>  enum {
>> @@ -192,6 +193,7 @@ enum {
>> DPU_CTL_ACTIVE_CFG,
>> DPU_CTL_FETCH_ACTIVE,
>> DPU_CTL_VM_CFG,
>> +   DPU_CTL_HIERARCHICAL_FLUSH,
>> DPU_CTL_MAX
>>  };
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>> index 3584f5e..b34fc30 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>> @@ -28,6 +28,8 @@
>>  #define   CTL_INTF_FLUSH0x110
>>  #define   CTL_INTF_MASTER   0x134
>>  #define   CTL_FETCH_PIPE_ACTIVE 0x0FC
>> +#define   CTL_DSPP_0_FLUSH 0x13C
>
>Please change to CTL_DSPP_n_FLUSH(n).
>
>> +
>>
>>  #define CTL_MIXER_BORDER_OUTBIT(24)
>>  #define CTL_FLUSH_MASK_CTL  BIT(17)
>> @@ -292,6 +294,36 @@ static uint32_t dpu_hw_ctl_get_bitmask_dspp(struct
>dpu_hw_ctl *ctx,
>> return flushbits;
>>  }
>>
>> +static uint32_t dpu_hw_ctl_get_bitmask_dspp_v1(struct dpu_hw_ctl *ctx,
>> +   enum dpu_dspp dspp)
>> +{
>> +   return BIT(29);
>> +}
>> +
>> +static void 

  1   2   >