[PATCH v4 09/20] gpu: nova-core: increase BAR0 size to 16MB

2025-05-21 Thread Alexandre Courbot
The Turing+ register address space spans over that range, so increase it
as future patches will access more registers.

Signed-off-by: Alexandre Courbot 
---
 drivers/gpu/nova-core/driver.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver.rs
index 
8c86101c26cb5fe5eb9a3d03268338c6b58baef7..b13d0b7399e56ed36b4ee5b77a0408299d69d9dd
 100644
--- a/drivers/gpu/nova-core/driver.rs
+++ b/drivers/gpu/nova-core/driver.rs
@@ -11,7 +11,7 @@ pub(crate) struct NovaCore {
 _reg: auxiliary::Registration,
 }
 
-const BAR0_SIZE: usize = 8;
+const BAR0_SIZE: usize = 0x100;
 pub(crate) type Bar0 = pci::Bar;
 
 kernel::pci_device_table!(

-- 
2.49.0



Re: [PATCH v9 2/9] dma-buf: dma-heap: export declared functions

2025-05-21 Thread Christian König
On 5/20/25 17:16, Jens Wiklander wrote:
> Export the dma-buf heap functions declared in .

That is what this patch does and that should be obvious by looking at it. You 
need to explain why you do this.

Looking at the rest of the series it's most likely ok, but this commit message 
should really be improved.

Regards,
Christian.

> 
> Signed-off-by: Jens Wiklander 
> ---
>  drivers/dma-buf/dma-heap.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
> index 3cbe87d4a464..cdddf0e24dce 100644
> --- a/drivers/dma-buf/dma-heap.c
> +++ b/drivers/dma-buf/dma-heap.c
> @@ -202,6 +202,7 @@ void *dma_heap_get_drvdata(struct dma_heap *heap)
>  {
>   return heap->priv;
>  }
> +EXPORT_SYMBOL(dma_heap_get_drvdata);
>  
>  /**
>   * dma_heap_get_name - get heap name
> @@ -214,6 +215,7 @@ const char *dma_heap_get_name(struct dma_heap *heap)
>  {
>   return heap->name;
>  }
> +EXPORT_SYMBOL(dma_heap_get_name);
>  
>  /**
>   * dma_heap_add - adds a heap to dmabuf heaps
> @@ -303,6 +305,7 @@ struct dma_heap *dma_heap_add(const struct 
> dma_heap_export_info *exp_info)
>   kfree(heap);
>   return err_ret;
>  }
> +EXPORT_SYMBOL(dma_heap_add);
>  
>  static char *dma_heap_devnode(const struct device *dev, umode_t *mode)
>  {



[PATCH v4 12/20] gpu: nova-core: add DMA object struct

2025-05-21 Thread Alexandre Courbot
Since we will need to allocate lots of distinct memory chunks to be
shared between GPU and CPU, introduce a type dedicated to that. It is a
light wrapper around CoherentAllocation.

Signed-off-by: Alexandre Courbot 
---
 drivers/gpu/nova-core/dma.rs   | 61 ++
 drivers/gpu/nova-core/nova_core.rs |  1 +
 2 files changed, 62 insertions(+)

diff --git a/drivers/gpu/nova-core/dma.rs b/drivers/gpu/nova-core/dma.rs
new file mode 100644
index 
..4b063aaef65ec4e2f476fc5ce9dc25341b6660ca
--- /dev/null
+++ b/drivers/gpu/nova-core/dma.rs
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Simple DMA object wrapper.
+
+// To be removed when all code is used.
+#![expect(dead_code)]
+
+use core::ops::{Deref, DerefMut};
+
+use kernel::device;
+use kernel::dma::CoherentAllocation;
+use kernel::page::PAGE_SIZE;
+use kernel::prelude::*;
+
+pub(crate) struct DmaObject {
+dma: CoherentAllocation,
+}
+
+impl DmaObject {
+pub(crate) fn new(dev: &device::Device, len: usize) -> 
Result {
+let len = core::alloc::Layout::from_size_align(len, PAGE_SIZE)
+.map_err(|_| EINVAL)?
+.pad_to_align()
+.size();
+let dma = CoherentAllocation::alloc_coherent(dev, len, GFP_KERNEL | 
__GFP_ZERO)?;
+
+Ok(Self { dma })
+}
+
+pub(crate) fn from_data(dev: &device::Device, data: &[u8]) 
-> Result {
+Self::new(dev, data.len()).map(|mut dma_obj| {
+// TODO: replace with `CoherentAllocation::write()` once available.
+// SAFETY:
+// - `dma_obj`'s size is at least `data.len()`.
+// - We have just created this object and there is no other user 
at this stage.
+unsafe {
+core::ptr::copy_nonoverlapping(
+data.as_ptr(),
+dma_obj.dma.start_ptr_mut(),
+data.len(),
+);
+}
+
+dma_obj
+})
+}
+}
+
+impl Deref for DmaObject {
+type Target = CoherentAllocation;
+
+fn deref(&self) -> &Self::Target {
+&self.dma
+}
+}
+
+impl DerefMut for DmaObject {
+fn deref_mut(&mut self) -> &mut Self::Target {
+&mut self.dma
+}
+}
diff --git a/drivers/gpu/nova-core/nova_core.rs 
b/drivers/gpu/nova-core/nova_core.rs
index 
c3fde3e132ea65851137ab47fcb7b3637577..121fe5c11044a192212d0a64353b7acad58c796a
 100644
--- a/drivers/gpu/nova-core/nova_core.rs
+++ b/drivers/gpu/nova-core/nova_core.rs
@@ -2,6 +2,7 @@
 
 //! Nova Core GPU Driver
 
+mod dma;
 mod driver;
 mod firmware;
 mod gfw;

-- 
2.49.0



[PATCH v4 11/20] gpu: nova-core: wait for GFW_BOOT completion

2025-05-21 Thread Alexandre Courbot
Upon reset, the GPU executes the GFW (GPU Firmware) in order to
initialize its base parameters such as clocks. The driver must ensure
that this step is completed before using the hardware.

Signed-off-by: Alexandre Courbot 
---
 drivers/gpu/nova-core/gfw.rs   | 37 +
 drivers/gpu/nova-core/gpu.rs   |  5 +
 drivers/gpu/nova-core/nova_core.rs |  1 +
 drivers/gpu/nova-core/regs.rs  | 25 +
 drivers/gpu/nova-core/util.rs  |  1 -
 5 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/nova-core/gfw.rs b/drivers/gpu/nova-core/gfw.rs
new file mode 100644
index 
..11ad480e1da826555e264101ef56ff0f69db8f95
--- /dev/null
+++ b/drivers/gpu/nova-core/gfw.rs
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! GPU Firmware (GFW) support.
+//!
+//! Upon reset, the GPU runs some firmware code from the BIOS to setup its 
core parameters. Most of
+//! the GPU is considered unusable until this step is completed, so we must 
wait on it before
+//! performing driver initialization.
+
+use core::time::Duration;
+
+use kernel::bindings;
+use kernel::prelude::*;
+
+use crate::driver::Bar0;
+use crate::regs;
+use crate::util;
+
+/// Wait until GFW (GPU Firmware) completes, or a 4 seconds timeout elapses.
+pub(crate) fn wait_gfw_boot_completion(bar: &Bar0) -> Result<()> {
+util::wait_on(Duration::from_secs(4), || {
+// Check that FWSEC has lowered its protection level before reading 
the GFW_BOOT
+// status.
+let gfw_booted = 
regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK::read(bar)
+.read_protection_level0()
+&& 
regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT::read(bar).completed();
+
+if gfw_booted {
+Some(())
+} else {
+// Avoid busy-looping.
+// SAFETY: msleep should be safe to call with any parameter.
+unsafe { bindings::msleep(1) };
+
+None
+}
+})
+}
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index 
99c6796e73e924cb5fd2b6f49d84589c1ce5f627..50417f608dc7b445958ae43444a13c7593204fcf
 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -4,6 +4,7 @@
 
 use crate::driver::Bar0;
 use crate::firmware::{Firmware, FIRMWARE_VERSION};
+use crate::gfw;
 use crate::regs;
 use crate::util;
 use core::fmt;
@@ -182,6 +183,10 @@ pub(crate) fn new(
 spec.revision
 );
 
+// We must wait for GFW_BOOT completion before doing any significant 
setup on the GPU.
+gfw::wait_gfw_boot_completion(bar)
+.inspect_err(|_| dev_err!(pdev.as_ref(), "GFW boot did not 
complete"))?;
+
 Ok(pin_init!(Self {
 spec,
 bar: devres_bar,
diff --git a/drivers/gpu/nova-core/nova_core.rs 
b/drivers/gpu/nova-core/nova_core.rs
index 
618632f0abcc8f5ef6945a04fc084acc4ecbf20b..c3fde3e132ea65851137ab47fcb7b3637577
 100644
--- a/drivers/gpu/nova-core/nova_core.rs
+++ b/drivers/gpu/nova-core/nova_core.rs
@@ -4,6 +4,7 @@
 
 mod driver;
 mod firmware;
+mod gfw;
 mod gpu;
 mod regs;
 mod util;
diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs
index 
5a12732303066f78b8ec5745096cef632ff3bfba..cba442da51181971f209b338249307c11ac481e3
 100644
--- a/drivers/gpu/nova-core/regs.rs
+++ b/drivers/gpu/nova-core/regs.rs
@@ -37,3 +37,28 @@ pub(crate) fn chipset(self) -> Result {
 .and_then(Chipset::try_from)
 }
 }
+
+/* PGC6 */
+
+register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK @ 0x00118128 {
+0:0 read_protection_level0 as bool, "Set after FWSEC lowers its 
protection level";
+});
+
+// TODO: This is an array of registers.
+register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_05 @ 0x00118234 {
+31:0value as u32;
+});
+
+register!(
+NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT => 
NV_PGC6_AON_SECURE_SCRATCH_GROUP_05,
+"Scratch group 05 register 0 used as GFW boot progress indicator" {
+7:0progress as u8, "Progress of GFW boot (0xff means completed)";
+}
+);
+
+impl NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT {
+/// Returns `true` if GFW boot is completed.
+pub(crate) fn completed(self) -> bool {
+self.progress() == 0xff
+}
+}
diff --git a/drivers/gpu/nova-core/util.rs b/drivers/gpu/nova-core/util.rs
index 
afb525228431a2645afe7bb34988e9537757b1d7..81fcfff1f6f437d2f6a2130ce2249fbf4c1501be
 100644
--- a/drivers/gpu/nova-core/util.rs
+++ b/drivers/gpu/nova-core/util.rs
@@ -34,7 +34,6 @@ pub(crate) const fn const_bytes_to_str(bytes: &[u8]) -> &str {
 ///
 /// TODO: replace with `read_poll_timeout` once it is available.
 /// 
(https://lore.kernel.org/lkml/20250220070611.214262-8-fujita.tomon...@gmail.com/)
-#[expect(dead_code)]
 pub(crate) fn wait_on Option>(timeout: Duration, cond: F) -> 
Result {
 let start_time = Ktime::ktime_get();
 

-- 
2.49.0

[PATCH v4 06/20] gpu: nova-core: add delimiter for helper rules in register!() macro

2025-05-21 Thread Alexandre Courbot
This macro is pretty complex, and most rules are just helper, so add a
delimiter to indicate when users only interested in using it can stop
reading.

Signed-off-by: Alexandre Courbot 
---
 drivers/gpu/nova-core/regs/macros.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/nova-core/regs/macros.rs 
b/drivers/gpu/nova-core/regs/macros.rs
index 
40bf9346cd0699ede05cfddff5d39822c696c164..d7f09026390b4ccb1c969f2b29caf07fa9204a77
 100644
--- a/drivers/gpu/nova-core/regs/macros.rs
+++ b/drivers/gpu/nova-core/regs/macros.rs
@@ -94,6 +94,8 @@ macro_rules! register {
 register!(@io$name @ + $offset);
 };
 
+// All rules below are helpers.
+
 // Defines the wrapper `$name` type, as well as its relevant 
implementations (`Debug`, `BitOr`,
 // and conversion to regular `u32`).
 (@common $name:ident $(, $comment:literal)?) => {

-- 
2.49.0



Re: [PATCH v5 15/24] drm/msm/dsi/phy: Define PHY_CMN_CTRL_0 bitfields

2025-05-21 Thread Krzysztof Kozlowski
On 20/05/2025 23:23, Dmitry Baryshkov wrote:
>>
>> There is no checkpatch --strict warning here exactly for the reason I
>> was saying. For readability there should be no empty line after because
>> such statements are expected to be together. I don't mind of course
>> adding one, so I will implement the change.
> 
> I'd prefer this:
> 
> u32 data;
> 
> data = readl();
> data &= foo;;

Ah, ok, I understand now.

Best regards,
Krzysztof


Re: [PATCH v3 2/5] drm/panfrost: Internally label some BOs

2025-05-21 Thread Boris Brezillon
On Tue, 20 May 2025 18:43:59 +0100
Adrián Larumbe  wrote:

> Perfcnt samples buffer is not exposed to UM, but we would like to keep
> a tag on it as a potential debug aid.
> 
> PRIME imported GEM buffers are UM exposed, but since the usual Panfrost
> UM driver code path is not followed in their creation, they might remain
> unlabelled for their entire lifetime, so a generic tag was deemed
> preferable. The tag is assigned before a UM handle is created so it
> doesn't contradict the logic about labelling internal BOs.
> 
> Signed-off-by: Adrián Larumbe 

Reviewed-by: Boris Brezillon 

> ---
>  drivers/gpu/drm/panfrost/panfrost_gem.c | 10 ++
>  drivers/gpu/drm/panfrost/panfrost_perfcnt.c |  2 ++
>  2 files changed, 12 insertions(+)
> 
> diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c 
> b/drivers/gpu/drm/panfrost/panfrost_gem.c
> index 4c5be7ccc9cc..04483d5fb45d 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_gem.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c
> @@ -305,6 +305,16 @@ panfrost_gem_prime_import_sg_table(struct drm_device 
> *dev,
>   bo = to_panfrost_bo(obj);
>   bo->noexec = true;
>  
> + /*
> +  * We assign this generic label because this function cannot
> +  * be reached through any of the Panfrost UM driver-specific
> +  * code paths, unless one is given by explicitly calling the
> +  * SET_LABEL_BO ioctl. It is therefore preferable to have a
> +  * blanket BO tag that tells us the object was imported from
> +  * another driver than nothing at all.
> +  */
> + panfrost_gem_internal_set_label(obj, "GEM PRIME buffer");
> +
>   return obj;
>  }
>  
> diff --git a/drivers/gpu/drm/panfrost/panfrost_perfcnt.c 
> b/drivers/gpu/drm/panfrost/panfrost_perfcnt.c
> index 52befead08c6..563f16bae543 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_perfcnt.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_perfcnt.c
> @@ -111,6 +111,8 @@ static int panfrost_perfcnt_enable_locked(struct 
> panfrost_device *pfdev,
>   goto err_put_mapping;
>   perfcnt->buf = map.vaddr;
>  
> + panfrost_gem_internal_set_label(&bo->base, "Perfcnt sample buffer");
> +
>   /*
>* Invalidate the cache and clear the counters to start from a fresh
>* state.



[PATCH v3 30/30] panel/orisetech-ota5601a: Use refcounted allocation in place of devm_kzalloc()

2025-05-21 Thread Anusha Srivatsa
Move to using the new API devm_drm_panel_alloc() to allocate the
panel.

Reviewed-by: Neil Armstrong 
Signed-off-by: Anusha Srivatsa 
---
v3: none.
v2: none.
---
 drivers/gpu/drm/panel/panel-orisetech-ota5601a.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-orisetech-ota5601a.c 
b/drivers/gpu/drm/panel/panel-orisetech-ota5601a.c
index 
fc87f61d4400d49814953d7f453a7c6e84004f29..3231e84dc66c2bf319f5287fd53bc437e24e0d5b
 100644
--- a/drivers/gpu/drm/panel/panel-orisetech-ota5601a.c
+++ b/drivers/gpu/drm/panel/panel-orisetech-ota5601a.c
@@ -237,9 +237,11 @@ static int ota5601a_probe(struct spi_device *spi)
struct ota5601a *panel;
int err;
 
-   panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
-   if (!panel)
-   return -ENOMEM;
+   panel = devm_drm_panel_alloc(dev, struct ota5601a, drm_panel,
+&ota5601a_funcs,
+DRM_MODE_CONNECTOR_DPI);
+   if (IS_ERR(panel))
+   return PTR_ERR(panel);
 
spi_set_drvdata(spi, panel);
 
@@ -273,9 +275,6 @@ static int ota5601a_probe(struct spi_device *spi)
return PTR_ERR(panel->map);
}
 
-   drm_panel_init(&panel->drm_panel, dev, &ota5601a_funcs,
-  DRM_MODE_CONNECTOR_DPI);
-
err = drm_panel_of_backlight(&panel->drm_panel);
if (err) {
if (err != -EPROBE_DEFER)

-- 
2.48.1



Re: [PATCH v3 23/30] panel/novatek-nt35510: Use refcounted allocation in place of devm_kzalloc()

2025-05-21 Thread Linus Walleij
On Wed, May 21, 2025 at 6:11 AM Anusha Srivatsa  wrote:

> Move to using the new API devm_drm_panel_alloc() to allocate the
> panel.
>
> Reviewed-by: Neil Armstrong 
> Signed-off-by: Anusha Srivatsa 

Reviewed-by: Linus Walleij 

Yours,
Linus Walleij


Re:[RFC PATCH v2 1/3] drm/bridge: cadence: cdns-mhdp8546-core: Remove legacy support for connector initialisation in bridge

2025-05-21 Thread Andy Yan


Hello Javesh,

At 2025-05-21 15:32:35, "Jayesh Choudhary"  wrote:
>Now that we have DBANC framework, remove the connector initialisation code
>as that piece of code is not called if DRM_BRIDGE_ATTACH_NO_CONNECTOR flag
>is used. Only TI K3 platforms consume this driver and tidss (their display
>controller) has this flag set. So this legacy support can be dropped.
>
>Signed-off-by: Jayesh Choudhary 
>---
> .../drm/bridge/cadence/cdns-mhdp8546-core.c   | 186 +++---
> 1 file changed, 25 insertions(+), 161 deletions(-)
>
>diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c 
>b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
>index b431e7efd1f0..66bd916c2fe9 100644
>--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
>+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
>@@ -1444,56 +1444,6 @@ static const struct drm_edid 
>*cdns_mhdp_edid_read(struct cdns_mhdp_device *mhdp,
>   return drm_edid_read_custom(connector, cdns_mhdp_get_edid_block, mhdp);
> }
> 
>-static int cdns_mhdp_get_modes(struct drm_connector *connector)
>-{
>-  struct cdns_mhdp_device *mhdp = connector_to_mhdp(connector);
>-  const struct drm_edid *drm_edid;
>-  int num_modes;
>-
>-  if (!mhdp->plugged)
>-  return 0;
>-
>-  drm_edid = cdns_mhdp_edid_read(mhdp, connector);
>-
>-  drm_edid_connector_update(connector, drm_edid);
>-
>-  if (!drm_edid) {
>-  dev_err(mhdp->dev, "Failed to read EDID\n");
>-  return 0;
>-  }
>-
>-  num_modes = drm_edid_connector_add_modes(connector);
>-  drm_edid_free(drm_edid);
>-
>-  /*
>-   * HACK: Warn about unsupported display formats until we deal
>-   *   with them correctly.
>-   */
>-  if (connector->display_info.color_formats &&
>-  !(connector->display_info.color_formats &
>-mhdp->display_fmt.color_format))
>-  dev_warn(mhdp->dev,
>-   "%s: No supported color_format found (0x%08x)\n",
>-  __func__, connector->display_info.color_formats);
>-
>-  if (connector->display_info.bpc &&
>-  connector->display_info.bpc < mhdp->display_fmt.bpc)
>-  dev_warn(mhdp->dev, "%s: Display bpc only %d < %d\n",
>-   __func__, connector->display_info.bpc,
>-   mhdp->display_fmt.bpc);
>-
>-  return num_modes;
>-}
>-
>-static int cdns_mhdp_connector_detect(struct drm_connector *conn,
>-struct drm_modeset_acquire_ctx *ctx,
>-bool force)
>-{
>-  struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn);
>-
>-  return cdns_mhdp_detect(mhdp);
>-}
>-
> static u32 cdns_mhdp_get_bpp(struct cdns_mhdp_display_fmt *fmt)
> {
>   u32 bpp;
>@@ -1547,114 +1497,6 @@ bool cdns_mhdp_bandwidth_ok(struct cdns_mhdp_device 
>*mhdp,
>   return true;
> }
> 
>-static
>-enum drm_mode_status cdns_mhdp_mode_valid(struct drm_connector *conn,
>-const struct drm_display_mode *mode)
>-{
>-  struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn);
>-
>-  mutex_lock(&mhdp->link_mutex);
>-
>-  if (!cdns_mhdp_bandwidth_ok(mhdp, mode, mhdp->link.num_lanes,
>-  mhdp->link.rate)) {
>-  mutex_unlock(&mhdp->link_mutex);
>-  return MODE_CLOCK_HIGH;
>-  }
>-
>-  mutex_unlock(&mhdp->link_mutex);
>-  return MODE_OK;
>-}
>-
>-static int cdns_mhdp_connector_atomic_check(struct drm_connector *conn,
>-  struct drm_atomic_state *state)
>-{
>-  struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn);
>-  struct drm_connector_state *old_state, *new_state;
>-  struct drm_crtc_state *crtc_state;
>-  u64 old_cp, new_cp;
>-
>-  if (!mhdp->hdcp_supported)
>-  return 0;
>-
>-  old_state = drm_atomic_get_old_connector_state(state, conn);
>-  new_state = drm_atomic_get_new_connector_state(state, conn);
>-  old_cp = old_state->content_protection;
>-  new_cp = new_state->content_protection;
>-
>-  if (old_state->hdcp_content_type != new_state->hdcp_content_type &&
>-  new_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
>-  new_state->content_protection = 
>DRM_MODE_CONTENT_PROTECTION_DESIRED;
>-  goto mode_changed;
>-  }
>-
>-  if (!new_state->crtc) {
>-  if (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)
>-  new_state->content_protection = 
>DRM_MODE_CONTENT_PROTECTION_DESIRED;
>-  return 0;
>-  }
>-
>-  if (old_cp == new_cp ||
>-  (old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
>-   new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED))
>-  return 0;
>-
>-mode_changed:
>-  crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc);
>-  crtc_state->mode_changed = true;
>-
>-  return 0;

Re: [PATCH 1/3] drm/sched: add drm_sched_prealloc_dependency_slots v3

2025-05-21 Thread Christian König
Sorry for the delayed reply.

On 5/19/25 11:04, Philipp Stanner wrote:
>>>
>
> Also, if someone preallocates and does not consume the
> slot
> will that
> confuse the iteration in drm_sched_job_dependency()?

No it doesn't. The xarray is filtering NULL and XA_ZERO_ENTRY values in the 
iterator.

As far as I know that is *not* documented anywhere and it took me quite some 
time to figure that out.

E.g. you can explicitly ask for a NULL/XA_ZERO_ENTRY entry with xa_load(), but 
you won't see it in xa_for_each().


 drm_sched_job_add_dependency() you mean.
>>>
>>> I was actually thinking of drm_sched_job_dependency()
>>> because
>>> that
>>> looked it would skip dependencies upon encountering an
>>> unconsumed
>>> preallocated slot, but yes, drm_sched_job_add_dependency()
>>> could
>>> explode
>>> even earlier if adding a normal dependency after
>>> preallocating
>>> a
>>> slot.
>>>
 Yes, it would. All operations simply give you NULL for
 those
 slots. So
 seems to me you have to check for NULL wherever a
 preallocated
 slot
 might drop out. That would then be a bug.

 It's kind of tricky, all that. It's a pity that Wilcox
 didn't
 answer
 our questions about the idiomatic way to do it.

 Maybe reserving slots with already signaled fences wasn't
 such a
 bad
 idea after all?

 If we go for the NULL approach, it's probably the only
 sane
 way
 to then
 check for NULL wherever dependencies are accessed :(

 Opinions?
>>>
>>> Well if the xarray API returns the NULL consistently the
>>> approach
>>> from
>>> this patch is fine I think.
>>>
>>> We just need to add two more checks to the above mentioned
>>> functions,
>>
>> I need to correct myself, drm_sched_job_dependency() wouldn't
>> be
>> able
>> to
>> just skip NULLs since it relies on NULL for "no more
>> dependencies".
>> We
>> would need to track something like job->max_dependency and
>> terminate
>> on
>> job->last_dependency > job->max_dependency or so.
>
> Agreed, that would have to be fixed.
>
> I believe we should reconsider Christian's first idea [1].
>
> Thinking about it some more:
>    * With the NULL version, suddenly the xarray containing only
> valid
>  dependencies can sometimes contain NULL entries.
>    * If we could create our own tag, entries could be returned
> that
> were
>  neither NULL nor valid fences, also requiring checks
> 'everywhere'.
>    * Only the "signaled fence as prealloc reservation" approach
> is
> fully
>  backwards compatible and will never cause anyone to block
> after
>  later reworks.
>
> So maybe it's actually the best idea?
>
> Sorry for the zigg-zagg. No hard requirements intended from my
> side,
> I'm willing to go with what you guys think.
>
> Just saying, at least now I think that the already-signaled
> fence
> seems
> the most elegant solution. And since there's a function
> (dma_fence_get_stub()) for that, it seems to be in alignment
> with
> official dma_fence rules.

 Potential problem there was dma_fence_is_signaled() and fence
 signaling
 annotations. In case some driver is holding a lock over the
 arm+push
 pair. I wish we had a non-signaling is_signaled helper..

>>>
>>> Yes! +1!
>>>
>>> But Christian doesn't like that direction:
>>>
>>> https://lore.kernel.org/all/20250409120640.106408-2-pha...@kernel.org/
>>
>> Thanks, I read this but ended up uncertain on the conclusion.
>>
>> For instance Christian at the end comments like this:
>>
>> """
>> You can test the flag if you know what the fence means to you, that
>> is 
>> not a problem at all.
>> """
>>
>> That was in the context of testing the signaled bit without 
>> opportunistic signaling.
>>
>> For me, from the scheduler dependencies side, that should exactly
>> apply. 
>> Scheduler knows it does not need to add a signaled fence to the dep 
>> array so AFAICS it is fine to skip it. And it may easily be 
>> opportunistic signaling ends up a problem for the scheduler.

Well that was not what I meant.

The code which issued the fence can test the fence flags directly.

But the scheduler is a consumer of fences somebody else issued.

In other words we could do something like dma_fence_is_stub() or similar, to 
have a clean interface. But please no testing of the fence flags in the 
scheduler directly.

Anyway, we don't need it. The general assumption that the xarray returns NULL 
for the iterator is incorrect. NULL entries are simply skipped over.

Regards,
Christian.

>>
>> So maybe suc

Re:Re:[RFC PATCH v2 1/3] drm/bridge: cadence: cdns-mhdp8546-core: Remove legacy support for connector initialisation in bridge

2025-05-21 Thread Andy Yan

Hello Jayesh,

At 2025-05-21 16:15:33, "Andy Yan"  wrote:
>
>
>Hello Javesh,
>
>At 2025-05-21 15:32:35, "Jayesh Choudhary"  wrote:
>>Now that we have DBANC framework, remove the connector initialisation code
>>as that piece of code is not called if DRM_BRIDGE_ATTACH_NO_CONNECTOR flag
>>is used. Only TI K3 platforms consume this driver and tidss (their display
>>controller) has this flag set. So this legacy support can be dropped.
>>
>>Signed-off-by: Jayesh Choudhary 
>>---
>> .../drm/bridge/cadence/cdns-mhdp8546-core.c   | 186 +++---
>> 1 file changed, 25 insertions(+), 161 deletions(-)
>>
>>diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c 
>>b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
>>index b431e7efd1f0..66bd916c2fe9 100644
>>--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
>>+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
>>@@ -1444,56 +1444,6 @@ static const struct drm_edid 
>>*cdns_mhdp_edid_read(struct cdns_mhdp_device *mhdp,
>>  return drm_edid_read_custom(connector, cdns_mhdp_get_edid_block, mhdp);
>> }
>> 
>>-static int cdns_mhdp_get_modes(struct drm_connector *connector)
>>-{
>>- struct cdns_mhdp_device *mhdp = connector_to_mhdp(connector);
>>- const struct drm_edid *drm_edid;
>>- int num_modes;
>>-
>>- if (!mhdp->plugged)
>>- return 0;
>>-
>>- drm_edid = cdns_mhdp_edid_read(mhdp, connector);
>>-
>>- drm_edid_connector_update(connector, drm_edid);
>>-
>>- if (!drm_edid) {
>>- dev_err(mhdp->dev, "Failed to read EDID\n");
>>- return 0;
>>- }
>>-
>>- num_modes = drm_edid_connector_add_modes(connector);
>>- drm_edid_free(drm_edid);
>>-
>>- /*
>>-  * HACK: Warn about unsupported display formats until we deal
>>-  *   with them correctly.
>>-  */
>>- if (connector->display_info.color_formats &&
>>- !(connector->display_info.color_formats &
>>-   mhdp->display_fmt.color_format))
>>- dev_warn(mhdp->dev,
>>-  "%s: No supported color_format found (0x%08x)\n",
>>- __func__, connector->display_info.color_formats);
>>-
>>- if (connector->display_info.bpc &&
>>- connector->display_info.bpc < mhdp->display_fmt.bpc)
>>- dev_warn(mhdp->dev, "%s: Display bpc only %d < %d\n",
>>-  __func__, connector->display_info.bpc,
>>-  mhdp->display_fmt.bpc);
>>-
>>- return num_modes;
>>-}
>>-
>>-static int cdns_mhdp_connector_detect(struct drm_connector *conn,
>>-   struct drm_modeset_acquire_ctx *ctx,
>>-   bool force)
>>-{
>>- struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn);
>>-
>>- return cdns_mhdp_detect(mhdp);
>>-}
>>-
>> static u32 cdns_mhdp_get_bpp(struct cdns_mhdp_display_fmt *fmt)
>> {
>>  u32 bpp;
>>@@ -1547,114 +1497,6 @@ bool cdns_mhdp_bandwidth_ok(struct cdns_mhdp_device 
>>*mhdp,
>>  return true;
>> }
>> 
>>-static
>>-enum drm_mode_status cdns_mhdp_mode_valid(struct drm_connector *conn,
>>-   const struct drm_display_mode *mode)
>>-{
>>- struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn);
>>-
>>- mutex_lock(&mhdp->link_mutex);
>>-
>>- if (!cdns_mhdp_bandwidth_ok(mhdp, mode, mhdp->link.num_lanes,
>>- mhdp->link.rate)) {
>>- mutex_unlock(&mhdp->link_mutex);
>>- return MODE_CLOCK_HIGH;
>>- }
>>-
>>- mutex_unlock(&mhdp->link_mutex);
>>- return MODE_OK;
>>-}
>>-
>>-static int cdns_mhdp_connector_atomic_check(struct drm_connector *conn,
>>- struct drm_atomic_state *state)
>>-{
>>- struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn);
>>- struct drm_connector_state *old_state, *new_state;
>>- struct drm_crtc_state *crtc_state;
>>- u64 old_cp, new_cp;
>>-
>>- if (!mhdp->hdcp_supported)
>>- return 0;
>>-
>>- old_state = drm_atomic_get_old_connector_state(state, conn);
>>- new_state = drm_atomic_get_new_connector_state(state, conn);
>>- old_cp = old_state->content_protection;
>>- new_cp = new_state->content_protection;
>>-
>>- if (old_state->hdcp_content_type != new_state->hdcp_content_type &&
>>- new_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
>>- new_state->content_protection = 
>>DRM_MODE_CONTENT_PROTECTION_DESIRED;
>>- goto mode_changed;
>>- }
>>-
>>- if (!new_state->crtc) {
>>- if (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)
>>- new_state->content_protection = 
>>DRM_MODE_CONTENT_PROTECTION_DESIRED;
>>- return 0;
>>- }
>>-
>>- if (old_cp == new_cp ||
>>- (old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
>>-  new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED))
>>- return 0;
>>-
>>-mode_changed:
>>- crtc

[PATCH v3 03/12] drm/i915/psr: Read all Panel Replay capability registers from DPCD

2025-05-21 Thread Jouni Högander
There are several Panel Replay capability register in DPCD. Read them
all for later use.

v2:
  - avoid using hardcoded indices
  - read all Panel Replay capability registers

Signed-off-by: Jouni Högander 
Reviewed-by: Ankit Nautiyal 
---
 .../drm/i915/display/intel_display_types.h|  4 +++-
 drivers/gpu/drm/i915/display/intel_psr.c  | 20 ---
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index b8836d29a721..9334fcd77072 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1669,7 +1669,9 @@ struct intel_dp {
bool use_max_params;
u8 dpcd[DP_RECEIVER_CAP_SIZE];
u8 psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
-   u8 pr_dpcd;
+   u8 pr_dpcd[DP_PANEL_REPLAY_CAP_SIZE];
+#define INTEL_PR_DPCD_INDEX(pr_dpcd_register)  ((pr_dpcd_register) - 
DP_PANEL_REPLAY_CAP_SUPPORT)
+
u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE];
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 0cfdeff268f9..1072549649cd 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -608,7 +608,8 @@ static void _panel_replay_init_dpcd(struct intel_dp 
*intel_dp)
return;
}
 
-   if (!(intel_dp->pr_dpcd & 
DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT)) {
+   if 
(!(intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] &
+ DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT)) {
drm_dbg_kms(display->drm,
"Panel doesn't support early transport, eDP 
Panel Replay not possible\n");
return;
@@ -617,7 +618,8 @@ static void _panel_replay_init_dpcd(struct intel_dp 
*intel_dp)
 
intel_dp->psr.sink_panel_replay_support = true;
 
-   if (intel_dp->pr_dpcd & DP_PANEL_REPLAY_SU_SUPPORT)
+   if (intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] 
&
+   DP_PANEL_REPLAY_SU_SUPPORT)
intel_dp->psr.sink_panel_replay_su_support = true;
 
drm_dbg_kms(display->drm,
@@ -676,10 +678,12 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
 {
drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
 sizeof(intel_dp->psr_dpcd));
-   drm_dp_dpcd_readb(&intel_dp->aux, DP_PANEL_REPLAY_CAP_SUPPORT,
- &intel_dp->pr_dpcd);
 
-   if (intel_dp->pr_dpcd & DP_PANEL_REPLAY_SUPPORT)
+   drm_dp_dpcd_read(&intel_dp->aux, DP_PANEL_REPLAY_CAP_SUPPORT,
+&intel_dp->pr_dpcd, sizeof(intel_dp->pr_dpcd));
+
+   if (intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] 
&
+   DP_PANEL_REPLAY_SUPPORT)
_panel_replay_init_dpcd(intel_dp);
 
if (intel_dp->psr_dpcd[0])
@@ -736,7 +740,8 @@ static bool psr2_su_region_et_valid(struct intel_dp 
*intel_dp, bool panel_replay
return false;
 
return panel_replay ?
-   intel_dp->pr_dpcd & DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT :
+   
intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] &
+   DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT :
intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_ET_SUPPORTED &&
psr2_su_region_et_global_enabled(intel_dp);
 }
@@ -3916,7 +3921,8 @@ static void intel_psr_sink_capability(struct intel_dp 
*intel_dp,
seq_printf(m, ", Panel Replay = %s", 
str_yes_no(psr->sink_panel_replay_support));
seq_printf(m, ", Panel Replay Selective Update = %s",
   str_yes_no(psr->sink_panel_replay_su_support));
-   if (intel_dp->pr_dpcd & DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT)
+   if (intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] 
&
+   DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT)
seq_printf(m, " (Early Transport)");
seq_printf(m, "\n");
 }
-- 
2.43.0



[PATCH v3 09/12] drm/i915/display: Add PHY_CMN1_CONTROL register definitions

2025-05-21 Thread Jouni Högander
Add PHY_CMN1_CONTROL register and its definitions to configure port LFPS
sending.

Bspec: 68962
Signed-off-by: Jouni Högander 
Reviewed-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
index 59c22beaf1de..580a43be195e 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -285,6 +285,9 @@
 #define PHY_CX0_TX_CONTROL(tx, control)(0x400 + ((tx) - 1) * 0x200 + 
(control))
 #define   CONTROL2_DISABLE_SINGLE_TX   REG_BIT(6)
 
+#define PHY_CMN1_CONTROL(tx, control)  (0x800 + ((tx) - 1) * 0x200 + (control))
+#define   CONTROL0_MAC_TRANSMIT_LFPS   REG_BIT(1)
+
 /* C20 Registers */
 #define PHY_C20_WR_ADDRESS_L   0xC02
 #define PHY_C20_WR_ADDRESS_H   0xC03
-- 
2.43.0



[PATCH v3 11/12] drm/i915/psr: Fix using wrong mask in REG_FIELD_PREP

2025-05-21 Thread Jouni Högander
Wrong mask is used in PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION and
PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION.

Fixes: 295099580f04 ("drm/i915/psr: Add missing ALPM AUX-Less register 
definitions")
Signed-off-by: Jouni Högander 
Reviewed-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_psr_regs.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h 
b/drivers/gpu/drm/i915/display/intel_psr_regs.h
index aad3ac5f502e..8afbf5a38335 100644
--- a/drivers/gpu/drm/i915/display/intel_psr_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h
@@ -335,8 +335,8 @@
 #define  PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION_MASK  REG_GENMASK(20, 
16)
 #define  PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION(val)  
REG_FIELD_PREP(PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION_MASK, val)
 #define  PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION_MASK
REG_GENMASK(12, 8)
-#define  PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION(val)
REG_FIELD_PREP(PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION_MASK, val)
+#define  PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION(val)
REG_FIELD_PREP(PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION_MASK, val)
 #define  PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION_MASK REG_GENMASK(4, 
0)
-#define  PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION(val) 
REG_FIELD_PREP(PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION_MASK, val)
+#define  PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION(val) 
REG_FIELD_PREP(PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION_MASK, val)
 
 #endif /* __INTEL_PSR_REGS_H__ */
-- 
2.43.0



[PATCH v3 10/12] drm/i915/display: Add function to configure LFPS sending

2025-05-21 Thread Jouni Högander
Add function to configre LFPS sending for Panel Replay according to link
training sequence in HAS document.

This assumes we are using AUX Less always if it's supported by the sink and
the source.

v2:
  - drop HAS reference
  - replay kerneldoc comment with a generic comment
  - check display version in intel_lnl_mac_transmit_lfps

Bspec: 68849
Signed-off-by: Jouni Högander 
Reviewed-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 31 
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |  2 ++
 drivers/gpu/drm/i915/display/intel_ddi.c |  8 -
 3 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 91118d115fd3..75caccb65513 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -3225,6 +3225,37 @@ void intel_mtl_pll_enable(struct intel_encoder *encoder,
intel_cx0pll_enable(encoder, crtc_state);
 }
 
+/*
+ * According to HAS we need to enable MAC Transmitting LFPS in the "PHY Common
+ * Control 0" PIPE register in case of AUX Less ALPM is going to be used. This
+ * function is doing that and is called by link retrain sequence.
+ */
+void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder,
+const struct intel_crtc_state *crtc_state)
+{
+   struct intel_display *display = to_intel_display(encoder);
+   u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder);
+   bool enable = intel_alpm_is_alpm_aux_less(enc_to_intel_dp(encoder),
+ crtc_state);
+   int i;
+
+   if (DISPLAY_VER(display) < 20)
+   return;
+
+   for (i = 0; i < 4; i++) {
+   int tx = i % 2 + 1;
+   u8 lane_mask = i < 2 ? INTEL_CX0_LANE0 : INTEL_CX0_LANE1;
+
+   if (!(owned_lane_mask & lane_mask))
+   continue;
+
+   intel_cx0_rmw(encoder, lane_mask, PHY_CMN1_CONTROL(tx, 0),
+ CONTROL0_MAC_TRANSMIT_LFPS,
+ enable ? CONTROL0_MAC_TRANSMIT_LFPS : 0,
+ MB_WRITE_COMMITTED);
+   }
+}
+
 static u8 cx0_power_control_disable_val(struct intel_encoder *encoder)
 {
struct intel_display *display = to_intel_display(encoder);
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index a8f811ca5e7b..c5a7b529955b 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -43,5 +43,7 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder 
*encoder,
 const struct intel_crtc_state *crtc_state);
 int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder);
 void intel_cx0_pll_power_save_wa(struct intel_display *display);
+void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder,
+const struct intel_crtc_state *crtc_state);
 
 #endif /* __INTEL_CX0_PHY_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 65ab012c3eae..70de99cc4ead 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3745,10 +3745,16 @@ static void mtl_ddi_prepare_link_retrain(struct 
intel_dp *intel_dp,
intel_dp->DP |= DDI_BUF_CTL_ENABLE;
 
/*
-* 6.k If AUX-Less ALPM is going to be enabled
+* 6.k If AUX-Less ALPM is going to be enabled:
 * i. Configure PORT_ALPM_CTL and PORT_ALPM_LFPS_CTL here
 */
intel_alpm_port_configure(intel_dp, crtc_state);
+
+   /*
+* ii. Enable MAC Transmits LFPS in the "PHY Common Control 0" PIPE
+* register
+*/
+   intel_lnl_mac_transmit_lfps(encoder, crtc_state);
 }
 
 static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp,
-- 
2.43.0



[PATCH v3 12/12] drm/i915/psr: Do not disable Panel Replay in case VRR is enabled

2025-05-21 Thread Jouni Högander
Allow Panel Replay with VRR. All VRR modes are supposed to work with
Panel Replay.

Bspec: 68920, 68925
Signed-off-by: Jouni Högander 
Reviewed-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 38535e0d2496..db7111374293 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1579,6 +1579,12 @@ static bool _psr_compute_config(struct intel_dp 
*intel_dp,
if (!CAN_PSR(intel_dp))
return false;
 
+   /*
+* Currently PSR doesn't work reliably with VRR enabled.
+*/
+   if (crtc_state->vrr.enable)
+   return false;
+
entry_setup_frames = intel_psr_entry_setup_frames(intel_dp, 
adjusted_mode);
 
if (entry_setup_frames >= 0) {
@@ -1696,12 +1702,6 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
return;
}
 
-   /*
-* Currently PSR/PR doesn't work reliably with VRR enabled.
-*/
-   if (crtc_state->vrr.enable)
-   return;
-
crtc_state->has_panel_replay = _panel_replay_compute_config(intel_dp,
crtc_state,
conn_state);
-- 
2.43.0



[PATCH v3 06/12] drm/i915/psr: Add interface to check if AUXLess ALPM is needed by PSR

2025-05-21 Thread Jouni Högander
Currently we spread ugly PSR details into ALPM code to check if AUXLess
ALPM is needed. Prepare to hide these details to PSR code by adding new
interface for checking if AUXLess ALPM is needed.

v2: remove kerneldoc comment

Signed-off-by: Jouni Högander 
Reviewed-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 6 ++
 drivers/gpu/drm/i915/display/intel_psr.h | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 1072549649cd..38535e0d2496 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -4246,3 +4246,9 @@ bool intel_psr_needs_alpm(struct intel_dp *intel_dp, 
const struct intel_crtc_sta
return intel_dp_is_edp(intel_dp) && (crtc_state->has_sel_update ||
 crtc_state->has_panel_replay);
 }
+
+bool intel_psr_needs_alpm_aux_less(struct intel_dp *intel_dp,
+  const struct intel_crtc_state *crtc_state)
+{
+   return intel_dp_is_edp(intel_dp) && crtc_state->has_panel_replay;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_psr.h 
b/drivers/gpu/drm/i915/display/intel_psr.h
index 73c3fa40844b..0cf53184f13f 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.h
+++ b/drivers/gpu/drm/i915/display/intel_psr.h
@@ -77,5 +77,7 @@ int intel_psr_min_vblank_delay(const struct intel_crtc_state 
*crtc_state);
 void intel_psr_connector_debugfs_add(struct intel_connector *connector);
 void intel_psr_debugfs_register(struct intel_display *display);
 bool intel_psr_needs_alpm(struct intel_dp *intel_dp, const struct 
intel_crtc_state *crtc_state);
+bool intel_psr_needs_alpm_aux_less(struct intel_dp *intel_dp,
+  const struct intel_crtc_state *crtc_state);
 
 #endif /* __INTEL_PSR_H__ */
-- 
2.43.0



[PATCH v3 04/12] drm/i915/alpm: Add PR_ALPM_CTL register definitions

2025-05-21 Thread Jouni Högander
Add PR_ALPM_CTL register definition and bits for it.

Bspec: 71014
Signed-off-by: Jouni Högander 
Reviewed-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_psr_regs.h | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h 
b/drivers/gpu/drm/i915/display/intel_psr_regs.h
index 795e6b9cc575..aad3ac5f502e 100644
--- a/drivers/gpu/drm/i915/display/intel_psr_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h
@@ -266,6 +266,16 @@
 #define _PIPE_SRCSZ_ERLY_TPT_B 0x71074
 #define PIPE_SRCSZ_ERLY_TPT(pipe)  _MMIO_PIPE((pipe), 
_PIPE_SRCSZ_ERLY_TPT_A, _PIPE_SRCSZ_ERLY_TPT_B)
 
+#define _PR_ALPM_CTL_A 0x60948
+#define PR_ALPM_CTL(dev_priv, tran)_MMIO_TRANS2(dev_priv, tran, 
_PR_ALPM_CTL_A)
+#define  PR_ALPM_CTL_ALLOW_LINK_OFF_BETWEEN_AS_SDP_AND_SU  BIT(6)
+#define  PR_ALPM_CTL_RFB_UPDATE_CONTROLBIT(5)
+#define  PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE BIT(4)
+#define  PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK   REG_GENMASK(1, 
0)
+#define  PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1_OR_T2   
REG_FIELD_PREP(PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK, 0)
+#define  PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1 
REG_FIELD_PREP(PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK, 1)
+#define  PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T2 
REG_FIELD_PREP(PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK, 2)
+
 #define _ALPM_CTL_A0x60950
 #define ALPM_CTL(dev_priv, tran)   _MMIO_TRANS2(dev_priv, tran, 
_ALPM_CTL_A)
 #define  ALPM_CTL_ALPM_ENABLE  REG_BIT(31)
-- 
2.43.0



[PATCH v3 08/12] drm/i915/alpm: Move port alpm configuration

2025-05-21 Thread Jouni Högander
It is specified in Bspec where port alpm configuration is supposed to be
performed. Change accordingly.

v2:
  - drop HAS reference
  - ensure PORT_ALPM registers are not writen on older platform

Bspec: 68849
Signed-off-by: Jouni Högander 
Reviewed-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_alpm.c| 48 
 drivers/gpu/drm/i915/display/intel_alpm.h|  2 +
 drivers/gpu/drm/i915/display/intel_cx0_phy.c |  1 +
 drivers/gpu/drm/i915/display/intel_ddi.c |  6 +++
 4 files changed, 39 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index bbcf510b0c25..dfdde8e4eabe 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -336,7 +336,6 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
 {
struct intel_display *display = to_intel_display(intel_dp);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
-   enum port port = dp_to_dig_port(intel_dp)->base.port;
u32 alpm_ctl;
 
if (DISPLAY_VER(display) < 20 || (!intel_psr_needs_alpm(intel_dp, 
crtc_state) &&
@@ -368,23 +367,6 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
   pr_alpm_ctl);
}
 
-   intel_de_write(display,
-  PORT_ALPM_CTL(port),
-  PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE |
-  PORT_ALPM_CTL_MAX_PHY_SWING_SETUP(15) |
-  PORT_ALPM_CTL_MAX_PHY_SWING_HOLD(0) |
-  PORT_ALPM_CTL_SILENCE_PERIOD(
-  
intel_dp->alpm_parameters.silence_period_sym_clocks));
-
-   intel_de_write(display,
-  PORT_ALPM_LFPS_CTL(port),
-  PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT(10) |
-  PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION(
-  
intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) |
-  
PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION(
-  
intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) |
-  PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION(
-  
intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms));
} else {
alpm_ctl = ALPM_CTL_EXTENDED_FAST_WAKE_ENABLE |

ALPM_CTL_EXTENDED_FAST_WAKE_TIME(intel_dp->alpm_parameters.fast_wake_lines);
@@ -408,6 +390,36 @@ void intel_alpm_configure(struct intel_dp *intel_dp,
intel_dp->alpm_parameters.transcoder = crtc_state->cpu_transcoder;
 }
 
+void intel_alpm_port_configure(struct intel_dp *intel_dp,
+  const struct intel_crtc_state *crtc_state)
+{
+   struct intel_display *display = to_intel_display(intel_dp);
+   enum port port = dp_to_dig_port(intel_dp)->base.port;
+   u32 alpm_ctl_val = 0, lfps_ctl_val = 0;
+
+   if (DISPLAY_VER(display) < 20)
+   return;
+
+   if (intel_alpm_is_alpm_aux_less(intel_dp, crtc_state)) {
+   alpm_ctl_val = PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE |
+   PORT_ALPM_CTL_MAX_PHY_SWING_SETUP(15) |
+   PORT_ALPM_CTL_MAX_PHY_SWING_HOLD(0) |
+   PORT_ALPM_CTL_SILENCE_PERIOD(
+   
intel_dp->alpm_parameters.silence_period_sym_clocks);
+   lfps_ctl_val = PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT(10) |
+   PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION(
+   
intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) |
+   PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION(
+   
intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) |
+   PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION(
+   
intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms);
+   }
+
+   intel_de_write(display, PORT_ALPM_CTL(port), alpm_ctl_val);
+
+   intel_de_write(display, PORT_ALPM_LFPS_CTL(port), lfps_ctl_val);
+}
+
 void intel_alpm_pre_plane_update(struct intel_atomic_state *state,
 struct intel_crtc *crtc)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h 
b/drivers/gpu/drm/i915/display/intel_alpm.h
index 86f4d5ab1981..a861c20b5d79 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -27,6 +27,8 @@ void intel_alpm_enable_sink(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state);
 void intel_alpm_pre_plane_update(struct intel_atomic_state *state,
 struct intel_crtc *crtc);
+void intel_alpm_port_c

[PATCH v3 07/12] drm/i915/alpm: Add new interface to check if AUXLess ALPM is used

2025-05-21 Thread Jouni Högander
we need to know if AUXLess ALPM is used when preparing for link
training. Add new interface for this and use it in existing code where
possible.

v2: remove kerneldoc comment

Signed-off-by: Jouni Högander 
Reviewed-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_alpm.c | 10 --
 drivers/gpu/drm/i915/display/intel_alpm.h |  2 ++
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index 0890247085a7..bbcf510b0c25 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -26,6 +26,13 @@ bool intel_alpm_aux_less_wake_supported(struct intel_dp 
*intel_dp)
return intel_dp->alpm_dpcd & DP_ALPM_AUX_LESS_CAP;
 }
 
+bool intel_alpm_is_alpm_aux_less(struct intel_dp *intel_dp,
+const struct intel_crtc_state *crtc_state)
+{
+   return intel_psr_needs_alpm_aux_less(intel_dp, crtc_state) ||
+   (crtc_state->has_lobf && 
intel_alpm_aux_less_wake_supported(intel_dp));
+}
+
 void intel_alpm_init(struct intel_dp *intel_dp)
 {
u8 dpcd;
@@ -341,8 +348,7 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
 * Panel Replay on eDP is always using ALPM aux less. I.e. no need to
 * check panel support at this point.
 */
-   if ((crtc_state->has_panel_replay && intel_dp_is_edp(intel_dp)) ||
-   (crtc_state->has_lobf && 
intel_alpm_aux_less_wake_supported(intel_dp))) {
+   if (intel_alpm_is_alpm_aux_less(intel_dp, crtc_state)) {
alpm_ctl = ALPM_CTL_ALPM_ENABLE |
ALPM_CTL_ALPM_AUX_LESS_ENABLE |
ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS |
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h 
b/drivers/gpu/drm/i915/display/intel_alpm.h
index c9fe21e3e72c..86f4d5ab1981 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -32,6 +32,8 @@ void intel_alpm_post_plane_update(struct intel_atomic_state 
*state,
 void intel_alpm_lobf_debugfs_add(struct intel_connector *connector);
 bool intel_alpm_aux_wake_supported(struct intel_dp *intel_dp);
 bool intel_alpm_aux_less_wake_supported(struct intel_dp *intel_dp);
+bool intel_alpm_is_alpm_aux_less(struct intel_dp *intel_dp,
+const struct intel_crtc_state *crtc_state);
 void intel_alpm_disable(struct intel_dp *intel_dp);
 bool intel_alpm_get_error(struct intel_dp *intel_dp);
 #endif
-- 
2.43.0



[PATCH v3 00/12] Panel Replay + Adaptive sync

2025-05-21 Thread Jouni Högander
This patch set is adding missing configuration to have Panel Replay
and Adaptive Sync enabled simultaneously. Also some issues identified
while debugging are fixed:

1. Source PORT ALPM configuration has to made during modeset.
2. PHY_CMN1_CONTROL is not written according to HAS document
3. Wrong register field definitions for PORT_ALPM_LFPS_CTL.

Patches are tested on LunarLake and PantheLake using our reference panel 
supporting
Adaptive Sync and Panel Replay.

EMP_AS_SDP_TL is currently missing completely from drm-tip. There is a patch 
for that which is needed if testing these patches:

https://patchwork.freedesktop.org/series/148421/

Otherwise "PSR idle timeout" errors are seen while testing.

v3:
  - comment about DP2.1 corrected as DP2.1a
  - referring patch removed from commit message
v2:
  - rework Panel Replay DPCD register definitions
  - do not use hardcoded indices while accessing intel_dp->pr_dpcd
  - ensure ALPM registers are not written on platform where they do
not exist
  - remove kerneldoc comments

Jouni Högander (12):
  drm/panelreplay: Panel Replay capability DPCD register definitions
  drm/dp: Add Panel Replay capability bits from DP2.1 specification
  drm/i915/psr: Read all Panel Replay capability registers from DPCD
  drm/i915/alpm: Add PR_ALPM_CTL register definitions
  drm/i915/alpm: Write PR_ALPM_CTL register
  drm/i915/psr: Add interface to check if AUXLess ALPM is needed by PSR
  drm/i915/alpm: Add new interface to check if AUXLess ALPM is used
  drm/i915/alpm: Move port alpm configuration
  drm/i915/display: Add PHY_CMN1_CONTROL register definitions
  drm/i915/display: Add function to configure LFPS sending
  drm/i915/psr: Fix using wrong mask in REG_FIELD_PREP
  drm/i915/psr: Do not disable Panel Replay in case VRR is enabled

 drivers/gpu/drm/i915/display/intel_alpm.c | 72 +--
 drivers/gpu/drm/i915/display/intel_alpm.h |  4 ++
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 32 +
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |  2 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  3 +
 drivers/gpu/drm/i915/display/intel_ddi.c  | 12 
 .../drm/i915/display/intel_display_types.h|  4 +-
 drivers/gpu/drm/i915/display/intel_psr.c  | 44 +++-
 drivers/gpu/drm/i915/display/intel_psr.h  |  2 +
 drivers/gpu/drm/i915/display/intel_psr_regs.h | 14 +++-
 include/drm/display/drm_dp.h  | 18 +++--
 11 files changed, 163 insertions(+), 44 deletions(-)

-- 
2.43.0



[PATCH v3 05/12] drm/i915/alpm: Write PR_ALPM_CTL register

2025-05-21 Thread Jouni Högander
PR_ALPM_CTL register contains configurations related to Adaptive sync
sdp. Configure these if Adaptive Sync SDP is supported.

v2: avoid using hardcoded indices

Bspec: 71014
Signed-off-by: Jouni Högander 
Reviewed-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_alpm.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index c176bdbc19a3..0890247085a7 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -348,6 +348,20 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS |

ALPM_CTL_AUX_LESS_WAKE_TIME(intel_dp->alpm_parameters.aux_less_wake_lines);
 
+   if (intel_dp->as_sdp_supported) {
+   u32 pr_alpm_ctl = 
PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1;
+
+   if 
(intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)] &
+   
DP_PANEL_REPLAY_LINK_OFF_SUPPORTED_IN_PR_AFTER_ADAPTIVE_SYNC_SDP)
+   pr_alpm_ctl |= 
PR_ALPM_CTL_ALLOW_LINK_OFF_BETWEEN_AS_SDP_AND_SU;
+   if 
(!(intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)] &
+   
DP_PANEL_REPLAY_ASYNC_VIDEO_TIMING_NOT_SUPPORTED_IN_PR))
+   pr_alpm_ctl |= 
PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE;
+
+   intel_de_write(display, PR_ALPM_CTL(display, 
cpu_transcoder),
+  pr_alpm_ctl);
+   }
+
intel_de_write(display,
   PORT_ALPM_CTL(port),
   PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE |
-- 
2.43.0



[PATCH v3 02/12] drm/dp: Add Panel Replay capability bits from DP2.1 specification

2025-05-21 Thread Jouni Högander
Add PANEL REPLAY CAPABILITY register (0xb1) bits.

v2: comment about DP2.1 changed as DP2.1a

Signed-off-by: Jouni Högander 
---
 include/drm/display/drm_dp.h | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index 3371e2edd9e9..c0579f827999 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -554,8 +554,14 @@
 
 #define DP_PANEL_REPLAY_CAP_SIZE   7
 
-#define DP_PANEL_REPLAY_CAP_CAPABILITY 0xb1
-# define DP_PANEL_REPLAY_SU_GRANULARITY_REQUIRED   (1 << 5)
+#define DP_PANEL_REPLAY_CAP_CAPABILITY 0xb1
+# define DP_PANEL_REPLAY_DSC_DECODE_CAPABILITY_IN_PR_SHIFT 
1 /* DP 2.1a */
+# define DP_PANEL_REPLAY_DSC_DECODE_CAPABILITY_IN_PR_MASK  
(3 << 1)
+# define DP_PANEL_REPLAY_ASYNC_VIDEO_TIMING_NOT_SUPPORTED_IN_PR
(1 << 3)
+# define DP_PANEL_REPLAY_DSC_CRC_OF_MULTIPLE_SUS_SUPPORTED 
(1 << 4)
+# define DP_PANEL_REPLAY_SU_GRANULARITY_REQUIRED   
(1 << 5)
+# define DP_PANEL_REPLAY_SU_Y_GRANULARITY_EXTENDED_CAPABILITY_SUPPORTED
(1 << 6)
+# define DP_PANEL_REPLAY_LINK_OFF_SUPPORTED_IN_PR_AFTER_ADAPTIVE_SYNC_SDP  
(1 << 7)
 
 #define DP_PANEL_REPLAY_CAP_X_GRANULARITY  0xb2
 #define DP_PANEL_REPLAY_CAP_Y_GRANULARITY  0xb4
-- 
2.43.0



[PATCH v3 01/12] drm/panelreplay: Panel Replay capability DPCD register definitions

2025-05-21 Thread Jouni Högander
Add new definition for size of Panel Replay DPCD capability registers
area. Rename existing definitions to group capability registers together.

Signed-off-by: Jouni Högander 
Reviewed-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_psr.c |  8 
 include/drm/display/drm_dp.h | 12 +++-
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index cd833b63ea6b..0cfdeff268f9 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -516,7 +516,7 @@ static u8 intel_dp_get_su_capability(struct intel_dp 
*intel_dp)
 
if (intel_dp->psr.sink_panel_replay_su_support)
drm_dp_dpcd_readb(&intel_dp->aux,
- DP_PANEL_PANEL_REPLAY_CAPABILITY,
+ DP_PANEL_REPLAY_CAP_CAPABILITY,
  &su_capability);
else
su_capability = intel_dp->psr_dpcd[1];
@@ -528,7 +528,7 @@ static unsigned int
 intel_dp_get_su_x_granularity_offset(struct intel_dp *intel_dp)
 {
return intel_dp->psr.sink_panel_replay_su_support ?
-   DP_PANEL_PANEL_REPLAY_X_GRANULARITY :
+   DP_PANEL_REPLAY_CAP_X_GRANULARITY :
DP_PSR2_SU_X_GRANULARITY;
 }
 
@@ -536,7 +536,7 @@ static unsigned int
 intel_dp_get_su_y_granularity_offset(struct intel_dp *intel_dp)
 {
return intel_dp->psr.sink_panel_replay_su_support ?
-   DP_PANEL_PANEL_REPLAY_Y_GRANULARITY :
+   DP_PANEL_REPLAY_CAP_Y_GRANULARITY :
DP_PSR2_SU_Y_GRANULARITY;
 }
 
@@ -676,7 +676,7 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
 {
drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
 sizeof(intel_dp->psr_dpcd));
-   drm_dp_dpcd_readb(&intel_dp->aux, DP_PANEL_REPLAY_CAP,
+   drm_dp_dpcd_readb(&intel_dp->aux, DP_PANEL_REPLAY_CAP_SUPPORT,
  &intel_dp->pr_dpcd);
 
if (intel_dp->pr_dpcd & DP_PANEL_REPLAY_SUPPORT)
diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index 3001c0b6e7bb..3371e2edd9e9 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -547,16 +547,18 @@
 /* DFP Capability Extension */
 #define DP_DFP_CAPABILITY_EXTENSION_SUPPORT0x0a3   /* 2.0 */
 
-#define DP_PANEL_REPLAY_CAP0x0b0  /* DP 2.0 */
+#define DP_PANEL_REPLAY_CAP_SUPPORT0x0b0  /* DP 2.0 */
 # define DP_PANEL_REPLAY_SUPPORT   (1 << 0)
 # define DP_PANEL_REPLAY_SU_SUPPORT(1 << 1)
 # define DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT   (1 << 2) /* eDP 1.5 */
 
-#define DP_PANEL_PANEL_REPLAY_CAPABILITY   0xb1
-# define DP_PANEL_PANEL_REPLAY_SU_GRANULARITY_REQUIRED (1 << 5)
+#define DP_PANEL_REPLAY_CAP_SIZE   7
 
-#define DP_PANEL_PANEL_REPLAY_X_GRANULARITY0xb2
-#define DP_PANEL_PANEL_REPLAY_Y_GRANULARITY0xb4
+#define DP_PANEL_REPLAY_CAP_CAPABILITY 0xb1
+# define DP_PANEL_REPLAY_SU_GRANULARITY_REQUIRED   (1 << 5)
+
+#define DP_PANEL_REPLAY_CAP_X_GRANULARITY  0xb2
+#define DP_PANEL_REPLAY_CAP_Y_GRANULARITY  0xb4
 
 /* Link Configuration */
 #defineDP_LINK_BW_SET  0x100
-- 
2.43.0



Re: [PATCH v5 1/3] drm: Create a task info option for wedge events

2025-05-21 Thread Raag Jadav
On Tue, May 20, 2025 at 01:32:41PM -0300, André Almeida wrote:
> When a device get wedged, it might be caused by a guilty application.
> For userspace, knowing which task was the cause can be useful for some
> situations, like for implementing a policy, logs or for giving a chance
> for the compositor to let the user know what task caused the problem.
> This is an optional argument, when the task info is not available, the
> PID and TASK string won't appear in the event string.
> 
> Sometimes just the PID isn't enough giving that the task might be already
> dead by the time userspace will try to check what was this PID's name,
> so to make the life easier also notify what's the task's name in the user
> event.

...

> -int drm_dev_wedged_event(struct drm_device *dev, unsigned long method)
> +int drm_dev_wedged_event(struct drm_device *dev, unsigned long method,
> +  struct drm_wedge_task_info *info)
>  {
>   const char *recovery = NULL;
>   unsigned int len, opt;
> - /* Event string length up to 28+ characters with available methods */
> - char event_string[32];
> - char *envp[] = { event_string, NULL };
> + char event_string[WEDGE_STR_LEN], pid_string[PID_LEN] = "", 
> comm_string[TASK_COMM_LEN] = "";
> + char *envp[] = { event_string, NULL, NULL, NULL };
>  
>   len = scnprintf(event_string, sizeof(event_string), "%s", "WEDGED=");
>  
> @@ -582,6 +586,13 @@ int drm_dev_wedged_event(struct drm_device *dev, 
> unsigned long method)
>   drm_info(dev, "device wedged, %s\n", method == DRM_WEDGE_RECOVERY_NONE ?
>"but recovered through reset" : "needs recovery");
>  
> + if (info && ((info->comm && info->comm[0] != '\0'))) {

Thanks for adding this. Should we check if pid > 0?

Also, I was wondering what if the driver only has info on one of the
given members? Should we allow it to be flagged independently?

> + snprintf(pid_string, sizeof(pid_string), "PID=%u", info->pid);
> + snprintf(comm_string, sizeof(comm_string), "TASK=%s", 
> info->comm);
> + envp[1] = pid_string;
> + envp[2] = comm_string;
> + }
> +
>   return kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
>  }
>  EXPORT_SYMBOL(drm_dev_wedged_event);

...

> diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
> index e2f894f1b90a..c13fe85210f2 100644
> --- a/include/drm/drm_device.h
> +++ b/include/drm/drm_device.h
> @@ -30,6 +30,14 @@ struct pci_controller;
>  #define DRM_WEDGE_RECOVERY_REBINDBIT(1)  /* unbind + bind driver */
>  #define DRM_WEDGE_RECOVERY_BUS_RESET BIT(2)  /* unbind + reset bus device + 
> bind */
>  
> +/**
> + * struct drm_wedge_task_info - information about the guilty app of a wedge 
> dev

s/app/task, missed an instance ;)

> + */
> +struct drm_wedge_task_info {
> + pid_t pid;
> + char *comm;
> +};

Raag


RE: [PATCH v10 03/10] mtd: intel-dg: implement access functions

2025-05-21 Thread Usyskin, Alexander
> Subject: Re: [PATCH v10 03/10] mtd: intel-dg: implement access functions
> 
> On Thu, May 15, 2025 at 04:33:38PM +0300, Alexander Usyskin wrote:
> > Implement read(), erase() and write() functions.
> 
> ...
> 
> > +__maybe_unused
> > +static unsigned int idg_nvm_get_region(const struct intel_dg_nvm *nvm,
> loff_t from)
> > +{
> > +   unsigned int i;
> > +
> > +   for (i = 0; i < nvm->nregions; i++) {
> > +   if ((nvm->regions[i].offset + nvm->regions[i].size - 1) > from
> &&
> 
> Since it's already off by one, I'm wondering if this should be >= ?
> 
Yep, will fix


> > +   nvm->regions[i].offset <= from &&
> > +   nvm->regions[i].size != 0)
> > +   break;
> > +   }
> > +
> > +   return i;
> > +}
> 
> ...
> 
> > +__maybe_unused
> > +static ssize_t
> > +idg_erase(struct intel_dg_nvm *nvm, u8 region, loff_t from, u64 len, u64
> *fail_addr)
> > +{
> > +   u64 i;
> > +   const u32 block = 0x10;
> > +   void __iomem *base = nvm->base;
> 
> Reverse xmas order (along with all other places).
Will do
> 
> > +   for (i = 0; i < len; i += SZ_4K) {
> > +   iowrite32(from + i, base + NVM_ADDRESS_REG);
> > +   iowrite32(region << 24 | block, base + NVM_ERASE_REG);
> > +   /* Since the writes are via sguint
> 
> sguint?

Sgunit, I suppose - will fix

> 
> > +* we cannot do back to back erases.
> > +*/
> > +   msleep(50);
> > +   }
> > +   return len;
> > +}
> 
> Raag


[PATCH] drm/panel-edp: Add KDC KD116N3730A05

2025-05-21 Thread Langyan Ye
Add support for the KDC KD116N3730A05, pleace the EDID here for
subsequent reference.

00 ff ff ff ff ff ff 00 2c 83 20 12 00 00 00 00
30 22 01 04 95 1a 0e 78 03 3a 75 9b 5d 5b 96 28
19 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 09 1e 56 dc 50 00 28 30 30 20
36 00 00 90 10 00 00 1a 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fe
00 4b 44 31 31 36 4e 33 37 33 30 41 30 35 00 e2

Signed-off-by: Langyan Ye 
---
 drivers/gpu/drm/panel/panel-edp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/panel/panel-edp.c 
b/drivers/gpu/drm/panel/panel-edp.c
index 9adbe0f11421..5426648e7116 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -2007,6 +2007,7 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('K', 'D', 'C', 0x044f, &delay_200_500_e50, 
"KD116N9-30NH-F3"),
EDP_PANEL_ENTRY('K', 'D', 'C', 0x05f1, &delay_200_500_e80_d50, 
"KD116N5-30NV-G7"),
EDP_PANEL_ENTRY('K', 'D', 'C', 0x0809, &delay_200_500_e50, 
"KD116N2930A15"),
+   EDP_PANEL_ENTRY('K', 'D', 'C', 0x1220, &delay_200_500_e50, 
"KD116N3730A05"),
 
EDP_PANEL_ENTRY('L', 'G', 'D', 0x, &delay_200_500_e200_d200, 
"Unknown"),
EDP_PANEL_ENTRY('L', 'G', 'D', 0x048d, &delay_200_500_e200_d200, 
"Unknown"),
-- 
2.34.1



[PATCH] drm/sched/tests: Use one lock for fence context

2025-05-21 Thread Philipp Stanner
When the unit tests were implemented, each scheduler job got its own,
distinct lock. This is not how dma_fence context locking rules are to be
implemented. All jobs belonging to the same fence context (in this case:
scheduler) should share a lock for their dma_fences. This is to comply
to various dma_fence rules, e.g., ensuring that only one fence gets
signaled at a time.

Use the fence context (scheduler) lock for the jobs.

Signed-off-by: Philipp Stanner 
---
 drivers/gpu/drm/scheduler/tests/mock_scheduler.c | 5 ++---
 drivers/gpu/drm/scheduler/tests/sched_tests.h| 1 -
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c 
b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
index f999c8859cf7..17023276f4b0 100644
--- a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
+++ b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
@@ -64,7 +64,7 @@ static void drm_mock_sched_job_complete(struct 
drm_mock_sched_job *job)
 
job->flags |= DRM_MOCK_SCHED_JOB_DONE;
list_move_tail(&job->link, &sched->done_list);
-   dma_fence_signal(&job->hw_fence);
+   dma_fence_signal_locked(&job->hw_fence);
complete(&job->done);
 }
 
@@ -123,7 +123,6 @@ drm_mock_sched_job_new(struct kunit *test,
job->test = test;
 
init_completion(&job->done);
-   spin_lock_init(&job->lock);
INIT_LIST_HEAD(&job->link);
hrtimer_setup(&job->timer, drm_mock_sched_job_signal_timer,
  CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
@@ -169,7 +168,7 @@ static struct dma_fence *mock_sched_run_job(struct 
drm_sched_job *sched_job)
 
dma_fence_init(&job->hw_fence,
   &drm_mock_sched_hw_fence_ops,
-  &job->lock,
+  &sched->lock,
   sched->hw_timeline.context,
   atomic_inc_return(&sched->hw_timeline.next_seqno));
 
diff --git a/drivers/gpu/drm/scheduler/tests/sched_tests.h 
b/drivers/gpu/drm/scheduler/tests/sched_tests.h
index 27caf8285fb7..fbba38137f0c 100644
--- a/drivers/gpu/drm/scheduler/tests/sched_tests.h
+++ b/drivers/gpu/drm/scheduler/tests/sched_tests.h
@@ -106,7 +106,6 @@ struct drm_mock_sched_job {
unsigned intduration_us;
ktime_t finish_at;
 
-   spinlock_t  lock;
struct dma_fencehw_fence;
 
struct kunit*test;
-- 
2.49.0



Re: [PATCH v3 00/30] drm/panel: Use refcounted allocation in place of devm_kzalloc() - Part2

2025-05-21 Thread Maxime Ripard
On Tue, 20 May 2025 22:03:31 -0500, Anusha Srivatsa wrote:
> Convert drivers to use the API - devm_drm_panel_alloc().
> There are a lot of occurences of the panel allocation across the
> subsystem. Much thanks to Maxime for the semanic patch which actually
> gives a list of panels allocated unsafely.
> 
> virtual report
> 
> [...]

Applied to misc/kernel.git (drm-misc-next).

Thanks!
Maxime


[PATCH v4 13/20] gpu: nova-core: register sysmem flush page

2025-05-21 Thread Alexandre Courbot
Reserve a page of system memory so sysmembar can perform a read on it if
a system write occurred since the last flush. Do this early as it can be
required to e.g. reset the GPU falcons.

Signed-off-by: Alexandre Courbot 
---
 drivers/gpu/nova-core/gpu.rs  | 45 +--
 drivers/gpu/nova-core/regs.rs | 10 ++
 2 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index 
50417f608dc7b445958ae43444a13c7593204fcf..a4e2cf1b529cc25fc168f68f9eaa6f4a7a9748eb
 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -2,6 +2,7 @@
 
 use kernel::{device, devres::Devres, error::code::*, pci, prelude::*};
 
+use crate::dma::DmaObject;
 use crate::driver::Bar0;
 use crate::firmware::{Firmware, FIRMWARE_VERSION};
 use crate::gfw;
@@ -158,12 +159,32 @@ fn new(bar: &Bar0) -> Result {
 }
 
 /// Structure holding the resources required to operate the GPU.
-#[pin_data]
+#[pin_data(PinnedDrop)]
 pub(crate) struct Gpu {
 spec: Spec,
 /// MMIO mapping of PCI BAR 0
 bar: Devres,
 fw: Firmware,
+/// System memory page required for flushing all pending GPU-side memory 
writes done through
+/// PCIE into system memory.
+sysmem_flush: DmaObject,
+}
+
+#[pinned_drop]
+impl PinnedDrop for Gpu {
+fn drop(self: Pin<&mut Self>) {
+// Unregister the sysmem flush page before we release it.
+let _ = self.bar.try_access_with(|b| {
+regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::default()
+.set_adr_39_08(0)
+.write(b);
+if self.spec.chipset >= Chipset::GA102 {
+regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI::default()
+.set_adr_63_40(0)
+.write(b);
+}
+});
+}
 }
 
 impl Gpu {
@@ -187,10 +208,30 @@ pub(crate) fn new(
 gfw::wait_gfw_boot_completion(bar)
 .inspect_err(|_| dev_err!(pdev.as_ref(), "GFW boot did not 
complete"))?;
 
+// System memory page required for sysmembar to properly flush into 
system memory.
+let sysmem_flush = {
+let page = DmaObject::new(pdev.as_ref(), 
kernel::bindings::PAGE_SIZE)?;
+
+// Register the sysmem flush page.
+let handle = page.dma_handle();
+
+regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::default()
+.set_adr_39_08((handle >> 8) as u32)
+.write(bar);
+if spec.chipset >= Chipset::GA102 {
+regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI::default()
+.set_adr_63_40((handle >> 40) as u32)
+.write(bar);
+}
+
+page
+};
+
 Ok(pin_init!(Self {
 spec,
 bar: devres_bar,
-fw
+fw,
+sysmem_flush,
 }))
 }
 }
diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs
index 
cba442da51181971f209b338249307c11ac481e3..b599e7ddad57ed8defe0324056571ba46b926cf6
 100644
--- a/drivers/gpu/nova-core/regs.rs
+++ b/drivers/gpu/nova-core/regs.rs
@@ -38,6 +38,16 @@ pub(crate) fn chipset(self) -> Result {
 }
 }
 
+/* PFB */
+
+register!(NV_PFB_NISO_FLUSH_SYSMEM_ADDR @ 0x00100c10 {
+31:0adr_39_08 as u32;
+});
+
+register!(NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI @ 0x00100c40 {
+23:0adr_63_40 as u32;
+});
+
 /* PGC6 */
 
 register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK @ 0x00118128 {

-- 
2.49.0



Re: [PATCH v4 02/20] rust: make ETIMEDOUT error available

2025-05-21 Thread Benno Lossin
On Wed May 21, 2025 at 8:44 AM CEST, Alexandre Courbot wrote:
> We will use this error in the nova-core driver.
>
> Signed-off-by: Alexandre Courbot 
> ---
>  rust/kernel/error.rs | 1 +
>  1 file changed, 1 insertion(+)

Reviewed-by: Benno Lossin 

---
Cheers,
Benno


[RFC PATCH v2 1/3] drm/bridge: cadence: cdns-mhdp8546-core: Remove legacy support for connector initialisation in bridge

2025-05-21 Thread Jayesh Choudhary
Now that we have DBANC framework, remove the connector initialisation code
as that piece of code is not called if DRM_BRIDGE_ATTACH_NO_CONNECTOR flag
is used. Only TI K3 platforms consume this driver and tidss (their display
controller) has this flag set. So this legacy support can be dropped.

Signed-off-by: Jayesh Choudhary 
---
 .../drm/bridge/cadence/cdns-mhdp8546-core.c   | 186 +++---
 1 file changed, 25 insertions(+), 161 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
index b431e7efd1f0..66bd916c2fe9 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
@@ -1444,56 +1444,6 @@ static const struct drm_edid *cdns_mhdp_edid_read(struct 
cdns_mhdp_device *mhdp,
return drm_edid_read_custom(connector, cdns_mhdp_get_edid_block, mhdp);
 }
 
-static int cdns_mhdp_get_modes(struct drm_connector *connector)
-{
-   struct cdns_mhdp_device *mhdp = connector_to_mhdp(connector);
-   const struct drm_edid *drm_edid;
-   int num_modes;
-
-   if (!mhdp->plugged)
-   return 0;
-
-   drm_edid = cdns_mhdp_edid_read(mhdp, connector);
-
-   drm_edid_connector_update(connector, drm_edid);
-
-   if (!drm_edid) {
-   dev_err(mhdp->dev, "Failed to read EDID\n");
-   return 0;
-   }
-
-   num_modes = drm_edid_connector_add_modes(connector);
-   drm_edid_free(drm_edid);
-
-   /*
-* HACK: Warn about unsupported display formats until we deal
-*   with them correctly.
-*/
-   if (connector->display_info.color_formats &&
-   !(connector->display_info.color_formats &
- mhdp->display_fmt.color_format))
-   dev_warn(mhdp->dev,
-"%s: No supported color_format found (0x%08x)\n",
-   __func__, connector->display_info.color_formats);
-
-   if (connector->display_info.bpc &&
-   connector->display_info.bpc < mhdp->display_fmt.bpc)
-   dev_warn(mhdp->dev, "%s: Display bpc only %d < %d\n",
-__func__, connector->display_info.bpc,
-mhdp->display_fmt.bpc);
-
-   return num_modes;
-}
-
-static int cdns_mhdp_connector_detect(struct drm_connector *conn,
- struct drm_modeset_acquire_ctx *ctx,
- bool force)
-{
-   struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn);
-
-   return cdns_mhdp_detect(mhdp);
-}
-
 static u32 cdns_mhdp_get_bpp(struct cdns_mhdp_display_fmt *fmt)
 {
u32 bpp;
@@ -1547,114 +1497,6 @@ bool cdns_mhdp_bandwidth_ok(struct cdns_mhdp_device 
*mhdp,
return true;
 }
 
-static
-enum drm_mode_status cdns_mhdp_mode_valid(struct drm_connector *conn,
- const struct drm_display_mode *mode)
-{
-   struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn);
-
-   mutex_lock(&mhdp->link_mutex);
-
-   if (!cdns_mhdp_bandwidth_ok(mhdp, mode, mhdp->link.num_lanes,
-   mhdp->link.rate)) {
-   mutex_unlock(&mhdp->link_mutex);
-   return MODE_CLOCK_HIGH;
-   }
-
-   mutex_unlock(&mhdp->link_mutex);
-   return MODE_OK;
-}
-
-static int cdns_mhdp_connector_atomic_check(struct drm_connector *conn,
-   struct drm_atomic_state *state)
-{
-   struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn);
-   struct drm_connector_state *old_state, *new_state;
-   struct drm_crtc_state *crtc_state;
-   u64 old_cp, new_cp;
-
-   if (!mhdp->hdcp_supported)
-   return 0;
-
-   old_state = drm_atomic_get_old_connector_state(state, conn);
-   new_state = drm_atomic_get_new_connector_state(state, conn);
-   old_cp = old_state->content_protection;
-   new_cp = new_state->content_protection;
-
-   if (old_state->hdcp_content_type != new_state->hdcp_content_type &&
-   new_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
-   new_state->content_protection = 
DRM_MODE_CONTENT_PROTECTION_DESIRED;
-   goto mode_changed;
-   }
-
-   if (!new_state->crtc) {
-   if (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)
-   new_state->content_protection = 
DRM_MODE_CONTENT_PROTECTION_DESIRED;
-   return 0;
-   }
-
-   if (old_cp == new_cp ||
-   (old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
-new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED))
-   return 0;
-
-mode_changed:
-   crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc);
-   crtc_state->mode_changed = true;
-
-   return 0;
-}
-
-static const struct drm_connector_helper_funcs cdns_mhdp_conn_helper_funcs = {
-   .detect_ctx = cdns_mhdp_connector_de

[RFC PATCH v2 3/3] drm/bridge: cadence: cdns-mhdp8546-core: Reduce log level for DPCD read/write

2025-05-21 Thread Jayesh Choudhary
Reduce the log level for cdns_mhdp_dpcd_read and cdns_mhdp_dpcd_write
errors in cdns_mhdp_transfer function as in case of failure, there is
flooding of these prints along with other indicators like EDID failure
logs which are fairly intuitive in themselves rendering these error logs
useless.
Also, the caller functions for the cdns_mhdp_transfer in drm_dp_helper.c
(which calls it 32 times), has debug log level in case transfer fails.
So having a superseding log level in cdns_mhdp_transfer seems bad.

Signed-off-by: Jayesh Choudhary 
---
 drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
index 5388e62f230b..71d35d0d3e74 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
@@ -782,7 +782,7 @@ static ssize_t cdns_mhdp_transfer(struct drm_dp_aux *aux,
if (!ret)
continue;
 
-   dev_err(mhdp->dev,
+   dev_dbg(mhdp->dev,
"Failed to write DPCD addr %u\n",
msg->address + i);
 
@@ -792,7 +792,7 @@ static ssize_t cdns_mhdp_transfer(struct drm_dp_aux *aux,
ret = cdns_mhdp_dpcd_read(mhdp, msg->address,
  msg->buffer, msg->size);
if (ret) {
-   dev_err(mhdp->dev,
+   dev_dbg(mhdp->dev,
"Failed to read DPCD addr %u\n",
msg->address);
 
-- 
2.34.1



[RFC PATCH v2 2/3] drm/bridge: cadence: cdns-mhdp8546*: Change drm_connector from pointer to structure

2025-05-21 Thread Jayesh Choudhary
After adding DBANC framework, mhdp->connector is not initialised during
bridge calls. But the asyncronous work scheduled depends on the connector.
We cannot get to drm_atomic_state in these asyncronous calls running on
worker threads. So we need to store the data that we need in mhdp bridge
structure.
Like other bridge drivers, use drm_connector pointer instead of structure
and make appropriate changes to the conditionals and assignments related
to mhdp->connector.
Also, in the atomic enable call, move the connector  and connector state
calls above, so that we do have a connector before we can retry the
asyncronous work in case of any failure.

Fixes: fb43aa0acdfd ("drm: bridge: Add support for Cadence MHDP8546 DPI/DP 
bridge")
Signed-off-by: Jayesh Choudhary 
---
 .../drm/bridge/cadence/cdns-mhdp8546-core.c   | 28 +--
 .../drm/bridge/cadence/cdns-mhdp8546-core.h   |  2 +-
 .../drm/bridge/cadence/cdns-mhdp8546-hdcp.c   |  8 +++---
 3 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
index 66bd916c2fe9..5388e62f230b 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
@@ -740,7 +740,7 @@ static void cdns_mhdp_fw_cb(const struct firmware *fw, void 
*context)
bridge_attached = mhdp->bridge_attached;
spin_unlock(&mhdp->start_lock);
if (bridge_attached) {
-   if (mhdp->connector.dev)
+   if (mhdp->connector)
drm_kms_helper_hotplug_event(mhdp->bridge.dev);
else
drm_bridge_hpd_notify(&mhdp->bridge, 
cdns_mhdp_detect(mhdp));
@@ -1759,17 +1759,25 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge 
*bridge,
struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
struct cdns_mhdp_bridge_state *mhdp_state;
struct drm_crtc_state *crtc_state;
-   struct drm_connector *connector;
struct drm_connector_state *conn_state;
struct drm_bridge_state *new_state;
const struct drm_display_mode *mode;
u32 resp;
-   int ret;
+   int ret = 0;
 
dev_dbg(mhdp->dev, "bridge enable\n");
 
mutex_lock(&mhdp->link_mutex);
 
+   mhdp->connector = drm_atomic_get_new_connector_for_encoder(state,
+  
bridge->encoder);
+   if (WARN_ON(!mhdp->connector))
+   goto out;
+
+   conn_state = drm_atomic_get_new_connector_state(state, mhdp->connector);
+   if (WARN_ON(!conn_state))
+   goto out;
+
if (mhdp->plugged && !mhdp->link_up) {
ret = cdns_mhdp_link_up(mhdp);
if (ret < 0)
@@ -1789,15 +1797,6 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge 
*bridge,
cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
resp | CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN);
 
-   connector = drm_atomic_get_new_connector_for_encoder(state,
-bridge->encoder);
-   if (WARN_ON(!connector))
-   goto out;
-
-   conn_state = drm_atomic_get_new_connector_state(state, connector);
-   if (WARN_ON(!conn_state))
-   goto out;
-
if (mhdp->hdcp_supported &&
mhdp->hw_state == MHDP_HW_READY &&
conn_state->content_protection ==
@@ -1857,6 +1856,7 @@ static void cdns_mhdp_atomic_disable(struct drm_bridge 
*bridge,
cdns_mhdp_hdcp_disable(mhdp);
 
mhdp->bridge_enabled = false;
+   mhdp->connector = NULL;
cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &resp);
resp &= ~CDNS_DP_FRAMER_EN;
resp |= CDNS_DP_NO_VIDEO_MODE;
@@ -2157,7 +2157,7 @@ static void cdns_mhdp_modeset_retry_fn(struct work_struct 
*work)
 
mhdp = container_of(work, typeof(*mhdp), modeset_retry_work);
 
-   conn = &mhdp->connector;
+   conn = mhdp->connector;
 
/* Grab the locks before changing connector property */
mutex_lock(&conn->dev->mode_config.mutex);
@@ -2234,7 +2234,7 @@ static void cdns_mhdp_hpd_work(struct work_struct *work)
int ret;
 
ret = cdns_mhdp_update_link_status(mhdp);
-   if (mhdp->connector.dev) {
+   if (mhdp->connector) {
if (ret < 0)
schedule_work(&mhdp->modeset_retry_work);
else
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h 
b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
index bad2fc0c7306..b297db53ba28 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
@@ -375,7 +375,7 @@ struct cdns_mhdp_device {
 */
struct mutex link_mutex;
 
-   struct drm_connector connector;
+   struct drm_connector *connector;
struct 

[RFC PATCH v2 0/3] CDNS-MHDP8546 minor cleanups

2025-05-21 Thread Jayesh Choudhary
Hello All,

These 3 patches does some fixup for the cdns-mhdp8546 bridge.
- First of all, it removes the legacy !DRM_BRIDGE_ATTACH_NO_CONNECTOR
  usecase.
- Then it fixes possible NULL POINTER in cdns_mhdp_modeset_retry_fn
  function call where the connector mutex is called. Since we cannot
  use the atomic_state in these worker threads, we cannot get to
  connector state in the worker thread. So we ensure that connector
  field is propagated before the first possible call for this worker
  thread by using pointer to the drm_connector.
- Then it reduces log level inside cdns_mhdp_transfer to avoid flooding
  of these logs.

v1 patch:


Changelog v1->v2:
- Remove !DRM_BRIDGE_ATTACH_NO_CONNECTOR entirely
- Add mode_valid in drm_bridge_funcs[0]
- Fix NULL POINTER differently since we cannot access atomic_state
- Reduce log level in cdns_mhdp_transfer call

[0]: https://lore.kernel.org/all/20240530091757.433106-1-j-choudh...@ti.com/

Jayesh Choudhary (3):
  drm/bridge: cadence: cdns-mhdp8546-core: Remove legacy support for
connector initialisation in bridge
  drm/bridge: cadence: cdns-mhdp8546*: Change drm_connector from pointer
to structure
  drm/bridge: cadence: cdns-mhdp8546-core: Reduce log level for DPCD
read/write

 .../drm/bridge/cadence/cdns-mhdp8546-core.c   | 218 --
 .../drm/bridge/cadence/cdns-mhdp8546-core.h   |   2 +-
 .../drm/bridge/cadence/cdns-mhdp8546-hdcp.c   |   8 +-
 3 files changed, 46 insertions(+), 182 deletions(-)

-- 
2.34.1



Re: [PATCH 2/2] dmabuf/heaps: implement DMA_BUF_IOCTL_RW_FILE for system_heap

2025-05-21 Thread Christian König
On 5/21/25 06:17, wangtao wrote:
>>> Reducing CPU overhead/power consumption is critical for mobile devices.
>>> We need simpler and more efficient dmabuf direct I/O support.
>>>
>>> As Christian evaluated sendfile performance based on your data, could
>>> you confirm whether the cache was cleared? If not, please share the
>>> post-cache-clearing test data. Thank you for your support.
>>
>> Yes sorry, I was out yesterday riding motorcycles. I did not clear the cache 
>> for
>> the buffered reads, I didn't realize you had. The IO plus the copy certainly
>> explains the difference.
>>
>> Your point about the unlikelihood of any of that data being in the cache also
>> makes sense.
> [wangtao] Thank you for testing and clarifying.
> 
>>
>> I'm not sure it changes anything about the ioctl approach though.
>> Another way to do this would be to move the (optional) support for direct IO
>> into the exporter via dma_buf_fops and dma_buf_ops. Then normal read()
>> syscalls would just work for buffers that support them.
>> I know that's more complicated, but at least it doesn't require inventing new
>> uapi to do it.
>>
> [wangtao] Thank you for the discussion. I fully support any method that 
> enables
> dmabuf direct I/O.
> 
> I understand using sendfile/splice with regular files for dmabuf
> adds an extra CPU copy, preventing zero-copy. For example:
> sendfile path: [DISK] → DMA → [page cache] → CPU copy → [memory file].

Yeah, but why can't you work on improving that?

> The read() syscall can't pass regular file fd parameters, so I added
> an ioctl command.
> While copy_file_range() supports two fds (fd_in/fd_out), it blocks cross-fs 
> use.
> Even without this restriction, file_out->f_op->copy_file_range
> only enables dmabuf direct reads from regular files, not writes.
> 
> Since dmabuf's direct I/O limitation comes from its unique
> attachment/map/fence model and lacks suitable syscalls, adding
> an ioctl seems necessary.

I absolutely don't see that. Both splice and sendfile can take two regular file 
descriptors.

That the underlying fops currently can't do that is not a valid argument for 
adding new uAPI. It just means that you need to work on improving those fops.

As long as nobody proves to me that the existing uAPI isn't sufficient for this 
use case I will systematically reject any approach to adding new one.

Regards,
Christian.

> When system exporters return a duplicated sg_table via map_dma_buf
> (used exclusively like a pages array), they should retain control
> over it.
> 
> I welcome all solutions to achieve dmabuf direct I/O! Your feedback
> is greatly appreciated.
>  
>> 1G from ext4 on 6.12.20 | read/sendfile (ms) w/ 3 > drop_caches
>> |---
>> udmabuf buffer read | 1210
>> udmabuf direct read | 671
>> udmabuf buffer sendfile | 1096
>> udmabuf direct sendfile | 2340
>>
>>
>>
>>>
>
>>> dmabuf buffer read | 51 | 1068  | 1118
>>> dmabuf direct read | 52 | 297   | 349
>>>
>>> udmabuf sendfile test steps:
>>> 1. Open data file(1024MB), get back_fd 2. Create memfd(32MB) #
>>> Loop steps 2-6 3. Allocate udmabuf with memfd 4. Call
>>> sendfile(memfd,
>>> back_fd) 5. Close memfd after sendfile 6. Close udmabuf 7.
>>> Close back_fd
>>>

 Regards,
 Christian.
>>>
>>
>>>



Re: [PATCH 1/3] drm/sched: add drm_sched_prealloc_dependency_slots v3

2025-05-21 Thread Philipp Stanner
On Tue, 2025-05-20 at 17:15 +0100, Tvrtko Ursulin wrote:
> 
> On 19/05/2025 10:04, Philipp Stanner wrote:
> > On Mon, 2025-05-19 at 09:51 +0100, Tvrtko Ursulin wrote:
> > > 
> > > On 16/05/2025 18:16, Philipp Stanner wrote:
> > > > On Fri, 2025-05-16 at 15:30 +0100, Tvrtko Ursulin wrote:
> > > > > 
> > > > > On 16/05/2025 14:38, Philipp Stanner wrote:
> > > > > > On Fri, 2025-05-16 at 13:10 +0100, Tvrtko Ursulin wrote:
> > > > > > > 
> > > > > > > On 16/05/2025 12:53, Tvrtko Ursulin wrote:
> > > > > > > > 
> > > > > > > > 
> > 
> > [snip]
> > 
> > > > > > > > > > > +
> > > > > > > > > > > +/**
> > > > > > > > > > > + * drm_sched_job_add_prealloc_dep - add
> > > > > > > > > > > dependency
> > > > > > > > > > > to
> > > > > > > > > > > preallocated
> > > > > > > > > > > slot
> > > > > > > > > > > + * @job: scheduler job where dependencies will
> > > > > > > > > > > be
> > > > > > > > > > > added
> > > > > > > > > > > + * @id: the preallocated slot index
> > > > > > > > > > > + * @fence: the dependency to add
> > > > > > > > > > > + *
> > > > > > > > > > > + * Consumes @fence and adds it to the
> > > > > > > > > > > preallocated
> > > > > > > > > > > slot
> > > > > > > > > > > dependency.
> > > > > > > > > > > + */
> > > > > > > > > > > +void drm_sched_job_add_prealloc_dep(struct
> > > > > > > > > > > drm_sched_job
> > > > > > > > > > > *job, u32
> > > > > > > > > > > id,
> > > > > > > > > > > +        struct dma_fence *fence)
> > > > > > > > > > > +{
> > > > > > > > > > > +    fence = xa_store(&job->dependencies, id,
> > > > > > > > > > > fence,
> > > > > > > > > > > GFP_ATOMIC);
> > > > > > > > > > 
> > > > > > > > > > Add assert that the passed id exists (was
> > > > > > > > > > preallocated)
> > > > > > > > > > and
> > > > > > > > > > is
> > > > > > > > > > NULL?
> > > > > > > > > 
> > > > > > > > > You
> > > > > > > > 
> > > > > > > > Hm?
> > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > Also, if someone preallocates and does not consume
> > > > > > > > > > the
> > > > > > > > > > slot
> > > > > > > > > > will that
> > > > > > > > > > confuse the iteration in
> > > > > > > > > > drm_sched_job_dependency()?
> > > > > > > > > 
> > > > > > > > > drm_sched_job_add_dependency() you mean.
> > > > > > > > 
> > > > > > > > I was actually thinking of drm_sched_job_dependency()
> > > > > > > > because
> > > > > > > > that
> > > > > > > > looked it would skip dependencies upon encountering an
> > > > > > > > unconsumed
> > > > > > > > preallocated slot, but yes,
> > > > > > > > drm_sched_job_add_dependency()
> > > > > > > > could
> > > > > > > > explode
> > > > > > > > even earlier if adding a normal dependency after
> > > > > > > > preallocating
> > > > > > > > a
> > > > > > > > slot.
> > > > > > > > 
> > > > > > > > > Yes, it would. All operations simply give you NULL
> > > > > > > > > for
> > > > > > > > > those
> > > > > > > > > slots. So
> > > > > > > > > seems to me you have to check for NULL wherever a
> > > > > > > > > preallocated
> > > > > > > > > slot
> > > > > > > > > might drop out. That would then be a bug.
> > > > > > > > > 
> > > > > > > > > It's kind of tricky, all that. It's a pity that
> > > > > > > > > Wilcox
> > > > > > > > > didn't
> > > > > > > > > answer
> > > > > > > > > our questions about the idiomatic way to do it.
> > > > > > > > > 
> > > > > > > > > Maybe reserving slots with already signaled fences
> > > > > > > > > wasn't
> > > > > > > > > such a
> > > > > > > > > bad
> > > > > > > > > idea after all?
> > > > > > > > > 
> > > > > > > > > If we go for the NULL approach, it's probably the
> > > > > > > > > only
> > > > > > > > > sane
> > > > > > > > > way
> > > > > > > > > to then
> > > > > > > > > check for NULL wherever dependencies are accessed :(
> > > > > > > > > 
> > > > > > > > > Opinions?
> > > > > > > > 
> > > > > > > > Well if the xarray API returns the NULL consistently
> > > > > > > > the
> > > > > > > > approach
> > > > > > > > from
> > > > > > > > this patch is fine I think.
> > > > > > > > 
> > > > > > > > We just need to add two more checks to the above
> > > > > > > > mentioned
> > > > > > > > functions,
> > > > > > > 
> > > > > > > I need to correct myself, drm_sched_job_dependency()
> > > > > > > wouldn't
> > > > > > > be
> > > > > > > able
> > > > > > > to
> > > > > > > just skip NULLs since it relies on NULL for "no more
> > > > > > > dependencies".
> > > > > > > We
> > > > > > > would need to track something like job->max_dependency
> > > > > > > and
> > > > > > > terminate
> > > > > > > on
> > > > > > > job->last_dependency > job->max_dependency or so.
> > > > > > 
> > > > > > Agreed, that would have to be fixed.
> > > > > > 
> > > > > > I believe we should reconsider Christian's first idea [1].
> > > > > > 
> > > > > > Thinking about it some more:
> > > > > >     * With the NULL version, suddenly the xarray containing
> > > > > > only
> > > > > > valid
> > > > > >   dependencies can sometimes contain NULL entries.
> > > > > >     * If we 

Re: [RFC PATCH] drm: bridge: cdns-mhdp8546: Fix possible null pointer dereference

2025-05-21 Thread Jayesh Choudhary

Hello Tomi,

On 28/01/25 11:27, Jayesh Choudhary wrote:

Hello Tomi, Alexander,

On 24/01/25 13:38, Alexander Stein wrote:

Hi,

Am Donnerstag, 23. Januar 2025, 17:20:34 CET schrieb Tomi Valkeinen:

Hi,

On 16/01/2025 13:16, Jayesh Choudhary wrote:

For the cases we have DRM_BRIDGE_ATTACH_NO_CONNECTOR flag set,


Any idea if any other platform than K3 is using this driver? tidss
supports DRM_BRIDGE_ATTACH_NO_CONNECTOR, so if K3 is the only user, we
could drop the legacy !DRM_BRIDGE_ATTACH_NO_CONNECTOR case. Which would
remove quite a bit of code, I think, and make the driver a bit more easy
to understand (although I think it could use a major cleanup...).




I cannot access the atomic state in this worker thread so I cannot reach
the connector using drm_atomic_get_new_connector_for_encoder.
I can't find any other way to do this. So I am rolling v2 for RFC while
addressing your other comments and fixing it in a different manner.
Please let me know if that is acceptable.

v2: https://lore.kernel.org/all/20250521073237.366463-1-j-choudh...@ti.com/

Warm Regards,
Jayesh




FYI: Not directly using it, but patch series [1] is at least touching
this file.


I can't see any other platform using this.
No one uses compatible "cdns,mhdp8546" and only K3 devices uses the
wrapper compatible "ti,j721e-mhdp8546"
Let me post next RFC version with legacy !DRM_BRIDGE_ATTACH_NO_CONNECTOR
dropped.

And the mentioned series only touches mailbox access function to move
then to a common helper file. (So independent change)




Best regards,
Alexander

[1] https://lore.kernel.org/all/cover.1734340233.git.sandor...@nxp.com/



Warm Regards,
Jayesh


RE: [PATCH 1/2] drm: rcar-du: rzg2l_mipi_dsi: Implement host transfers

2025-05-21 Thread Biju Das
Hi Hugo,

Thanks for the patch.

For some reason, your cover letter is not showing link to this patch
[1] https://lore.kernel.org/all/20250520164034.3453315-1-h...@hugovil.com/

> -Original Message-
> From: Hugo Villeneuve 
> Sent: 20 May 2025 18:11
> Subject: [PATCH 1/2] drm: rcar-du: rzg2l_mipi_dsi: Implement host transfers

rcar-du->rz-du

> 
> From: Hugo Villeneuve 
> 
> Add support for sending MIPI DSI command packets from the host to a 
> peripheral. This is required for
> panels that need configuration before they accept video data.
> 
> Based on Renesas Linux kernel v5.10 repos [1].

> 
> Link: https://github.com/renesas-rz/rz_linux-cip.git
> Cc: Biju Das 
> Cc: Chris Brandt 
> Signed-off-by: Hugo Villeneuve 
> ---
>  .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c| 174 ++
>  .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  56 ++
>  2 files changed, 230 insertions(+)
> 
> diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c 
> b/drivers/gpu/drm/renesas/rz-
> du/rzg2l_mipi_dsi.c
> index dc6ab012cdb69..77d3a31ff8e35 100644
> --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> @@ -6,6 +6,7 @@
>   */
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -23,9 +24,12 @@
>  #include 
>  #include 
>  #include 
> +#include 
> 
>  #include "rzg2l_mipi_dsi_regs.h"
> 
> +#define RZG2L_DCS_BUF_SIZE   128 /* Maximum DCS buffer size in external 
> memory. */
> +
>  struct rzg2l_mipi_dsi {
>   struct device *dev;
>   void __iomem *mmio;
> @@ -44,6 +48,10 @@ struct rzg2l_mipi_dsi {
>   unsigned int num_data_lanes;
>   unsigned int lanes;
>   unsigned long mode_flags;
> +
> + /* DCS buffer pointers when using external memory. */
> + dma_addr_t dcs_buf_phys;
> + u8 *dcs_buf_virt;
>  };
> 
>  static inline struct rzg2l_mipi_dsi *
> @@ -651,9 +659,168 @@ static int rzg2l_mipi_dsi_host_detach(struct 
> mipi_dsi_host *host,
>   return 0;
>  }
> 
> +static ssize_t rzg2l_mipi_dsi_read_response(struct rzg2l_mipi_dsi *dsi,
> + const struct mipi_dsi_msg *msg) {
> + u8 *msg_rx = msg->rx_buf;
> + u16 size;
> + u8 datatype;
> + u32 result;

Please arrange the variables in reverse xmas tree fashion.
 
> +
> + result = rzg2l_mipi_dsi_link_read(dsi, RXRSS0R);
> + if (result & RXRSS0R_RXPKTDFAIL) {
> + dev_err(dsi->dev, "packet rx data did not save correctly\n");
> + return -EPROTO;
> + }
> +
> + if (result & RXRSS0R_RXFAIL) {
> + dev_err(dsi->dev, "packet rx failure\n");
> + return -EPROTO;
> + }
> +
> + if (!(result & RXRSS0R_RXSUC))
> + return -EPROTO;
> +
> + datatype = FIELD_GET(RXRSS0R_DT, result);
> +
> + switch (datatype) {
> + case 0:
> + dev_dbg(dsi->dev, "ACK\n");
> + return 0;
> + case MIPI_DSI_RX_END_OF_TRANSMISSION:
> + dev_dbg(dsi->dev, "EoTp\n");
> + return 0;
> + case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
> + dev_dbg(dsi->dev, "Acknowledge and error report: $%02x%02x\n",
> + (u8)FIELD_GET(RXRSS0R_DATA1, result),
> + (u8)FIELD_GET(RXRSS0R_DATA0, result));
> + return 0;
> + case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
> + case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
> + msg_rx[0] = FIELD_GET(RXRSS0R_DATA0, result);
> + return 1;
> + case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
> + case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
> + msg_rx[0] = FIELD_GET(RXRSS0R_DATA0, result);
> + msg_rx[1] = FIELD_GET(RXRSS0R_DATA1, result);
> + return 2;
> + case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
> + case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
> + size = FIELD_GET(RXRSS0R_WC, result);
> +
> + if (size > msg->rx_len) {
> + dev_err(dsi->dev, "rx buffer too small");
> + return -ENOSPC;
> + }
> +
> + memcpy(msg_rx, dsi->dcs_buf_virt, size);
> + return size;
> + default:
> + dev_err(dsi->dev, "unhandled response type: %02x\n", datatype);
> + return -EPROTO;
> + }
> +}
> +
> +static ssize_t rzg2l_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
> + const struct mipi_dsi_msg *msg) {
> + struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
> + struct mipi_dsi_packet packet;
> + bool need_bta;
> + u32 value;
> + int ret;
> +
> + ret = mipi_dsi_create_packet(&packet, msg);
> + if (ret < 0)
> + return ret;
> +
> + /* Terminate operation after this descriptor is finished */
> + value = SQCH0DSC0AR_NXACT_TERM;
> +
> + if (msg->flags & MIPI_DSI_MSG_REQ_ACK) {
> + need_bta = true;

Re: [rfc] drm/ttm/memcg: simplest initial memcg/ttm integration (v2)

2025-05-21 Thread Christian König
On 5/21/25 04:23, Dave Airlie wrote:
>>
>> So in the GPU case, you'd charge on allocation, free objects into a
>> cgroup-specific pool, and shrink using a cgroup-specific LRU
>> list. Freed objects can be reused by this cgroup, but nobody else.
>> They're reclaimed through memory pressure inside the cgroup, not due
>> to the action of others. And all allocated memory is accounted for.
>>
>> I have to admit I'm pretty clueless about the gpu driver internals and
>> can't really judge how feasible this is. But from a cgroup POV, if you
>> want proper memory isolation between groups, it seems to me that's the
>> direction you'd have to take this in.
> 
> I've been digging into this a bit today, to try and work out what
> various paths forward might look like and run into a few impedance
> mismatches.
> 
> 1. TTM doesn't pool objects, it pools pages. TTM objects are varied in
> size, we don't need to keep any sort of special allocator that we
> would need if we cached sized objects (size buckets etc). list_lru
> doesn't work on pages, if we were pooling the ttm objects I can see
> being able to enable list_lru. But I'm seeing increased complexity for
> no major return, but I might dig a bit more into whether caching
> objects might help.
> 
> 2. list_lru isn't suitable for pages, AFAICS we have to stick the page
> into another object to store it in the list_lru, which would mean we'd
> be allocating yet another wrapper object. Currently TTM uses the page
> LRU pointer to add it to the shrinker_list, which is simple and low
> overhead.
> 
> If we wanted to stick with keeping pages in the pool, I do feel moving
> the pool code closer to the mm core and having some sort of more
> tightly integrated reclaim to avoid the overheads. Now in an ideal
> world we'd get a page flag like PG_uncached, and we can keep an
> uncached inactive list per memcg/node and migrate pages off it, but I
> don't think anyone is willing to give us a page flag for this, so I
> think we do need to find a compromise that isn't ideal but works for
> us now. I've also played a bit with the idea of MEMCG_LOWOVERHEAD
> which adds a shrinker to start of shrinker list instead of end and
> registering TTM pool shrinker as one of those.
> 
> Have I missed anything here that might make this easier?

Just for completeness of the picture, there is also the generic memory pool 
allocator (see include/linux/genalloc.h) which is an alternative to kmalloc() 
for uncached memory.

But we never used it because it isn't optimized for pages, but rather objects 
of certain size (e.g. like kmalloc/vmalloc).

Apart from that the general idea of having cgroup specific pools sounds bad to 
me. Instead of a technical need for this it only exists because we failed to 
integrate those device pools into the core memory management.

Regards,
Christian.


> 
> Dave.



[PATCH v4 18/20] gpu: nova-core: add types for patching firmware binaries

2025-05-21 Thread Alexandre Courbot
Some of the firmwares need to be patched at load-time with a signature.
Add a couple of types and traits that sub-modules can use to implement
this behavior, while ensuring that the correct kind of signature is
applied to the firmware.

Signed-off-by: Alexandre Courbot 
---
 drivers/gpu/nova-core/dma.rs  |  3 ---
 drivers/gpu/nova-core/firmware.rs | 44 +++
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/nova-core/dma.rs b/drivers/gpu/nova-core/dma.rs
index 
4b063aaef65ec4e2f476fc5ce9dc25341b6660ca..1f1f8c378d8e2cf51edc772e7afe392e9c9c8831
 100644
--- a/drivers/gpu/nova-core/dma.rs
+++ b/drivers/gpu/nova-core/dma.rs
@@ -2,9 +2,6 @@
 
 //! Simple DMA object wrapper.
 
-// To be removed when all code is used.
-#![expect(dead_code)]
-
 use core::ops::{Deref, DerefMut};
 
 use kernel::device;
diff --git a/drivers/gpu/nova-core/firmware.rs 
b/drivers/gpu/nova-core/firmware.rs
index 
c5d0f16d0de0e29f9f68f2e0b37e1e997a72782d..3909ceec6ffd28466d8b2930a0116ac73629d967
 100644
--- a/drivers/gpu/nova-core/firmware.rs
+++ b/drivers/gpu/nova-core/firmware.rs
@@ -3,11 +3,15 @@
 //! Contains structures and functions dedicated to the parsing, building and 
patching of firmwares
 //! to be loaded into a given execution unit.
 
+use core::marker::PhantomData;
+
 use kernel::device;
 use kernel::firmware;
 use kernel::prelude::*;
 use kernel::str::CString;
 
+use crate::dma::DmaObject;
+use crate::falcon::FalconFirmware;
 use crate::gpu;
 use crate::gpu::Chipset;
 
@@ -82,6 +86,46 @@ pub(crate) fn size(&self) -> usize {
 }
 }
 
+/// A [`DmaObject`] containing a specific microcode ready to be loaded into a 
falcon.
+///
+/// This is module-local and meant for sub-modules to use internally.
+struct FirmwareDmaObject(DmaObject, PhantomData);
+
+/// Trait for signatures to be patched directly into a given firmware.
+///
+/// This is module-local and meant for sub-modules to use internally.
+trait FirmwareSignature: AsRef<[u8]> {}
+
+#[expect(unused)]
+impl FirmwareDmaObject {
+/// Creates a new `UcodeDmaObject` containing `data`.
+fn new(dev: &device::Device, data: &[u8]) -> Result {
+DmaObject::from_data(dev, data).map(|dmaobj| Self(dmaobj, PhantomData))
+}
+
+/// Patches the firmware at offset `sig_base_img` with `signature`.
+fn patch_signature>(
+&mut self,
+signature: &S,
+sig_base_img: usize,
+) -> Result<()> {
+let signature_bytes = signature.as_ref();
+if sig_base_img + signature_bytes.len() > self.0.size() {
+return Err(EINVAL);
+}
+
+// SAFETY: we are the only user of this object, so there cannot be any 
race.
+let dst = unsafe { self.0.start_ptr_mut().add(sig_base_img) };
+
+// SAFETY: `signature` and `dst` are valid, properly aligned, and do 
not overlap.
+unsafe {
+core::ptr::copy_nonoverlapping(signature_bytes.as_ptr(), dst, 
signature_bytes.len())
+};
+
+Ok(())
+}
+}
+
 pub(crate) struct ModInfoBuilder(firmware::ModInfoBuilder);
 
 impl ModInfoBuilder {

-- 
2.49.0



Re: [PATCH v5 01/10] dt-bindings: npu: rockchip,rknn: Add bindings

2025-05-21 Thread Krzysztof Kozlowski
On Tue, May 20, 2025 at 12:26:54PM GMT, Tomeu Vizoso wrote:
> Add the bindings for the Neural Processing Unit IP from Rockchip.
> 
> v2:
> - Adapt to new node structure (one node per core, each with its own
>   IOMMU)
> - Several misc. fixes from Sebastian Reichel
> 
> v3:
> - Split register block in its constituent subblocks, and only require
>   the ones that the kernel would ever use (Nicolas Frattaroli)
> - Group supplies (Rob Herring)
> - Explain the way in which the top core is special (Rob Herring)
> 
> v4:
> - Change required node name to npu@ (Rob Herring and Krzysztof Kozlowski)
> - Remove unneeded items: (Krzysztof Kozlowski)
> - Fix use of minItems/maxItems (Krzysztof Kozlowski)
> - Add reg-names to list of required properties (Krzysztof Kozlowski)
> - Fix example (Krzysztof Kozlowski)
> 
> v5:
> - Rename file to rockchip,rk3588-rknn-core.yaml (Krzysztof Kozlowski)
> - Streamline compatible property (Krzysztof Kozlowski)
> 

This is a big patchset, so please slow down and do not send it every day
but allow people to actually review the version you post.

Reviewed-by: Krzysztof Kozlowski 

Best regards,
Krzysztof



Re: [PATCH v3 4/5] drm/panfrost: show device-wide list of DRM GEM objects over DebugFS

2025-05-21 Thread Boris Brezillon
On Tue, 20 May 2025 18:44:01 +0100
Adrián Larumbe  wrote:

> This change is essentially a Panfrost port of commit a3707f53eb3f
> ("drm/panthor: show device-wide list of DRM GEM objects over DebugFS").
> 
> The DebugFS file is almost the same as in Panthor, minus the GEM object
> usage flags, since Panfrost has no kernel-only BO's.
> 
> Two additional GEM state flags which are displayed but aren't relevant
> to Panthor are 'Purged' and 'Purgeable', since Panfrost implements an
> explicit shrinker and a madvise ioctl to flag objects as reclaimable.
> 
> Signed-off-by: Adrián Larumbe 

Reviewed-by: Boris Brezillon 

> ---
>  drivers/gpu/drm/panfrost/panfrost_device.c |   5 +
>  drivers/gpu/drm/panfrost/panfrost_device.h |  15 +++
>  drivers/gpu/drm/panfrost/panfrost_drv.c|  35 ++
>  drivers/gpu/drm/panfrost/panfrost_gem.c| 134 +
>  drivers/gpu/drm/panfrost/panfrost_gem.h|  47 
>  5 files changed, 236 insertions(+)
> 
> diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c 
> b/drivers/gpu/drm/panfrost/panfrost_device.c
> index 5d35076b2e6d..04bec27449cb 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_device.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_device.c
> @@ -209,6 +209,11 @@ int panfrost_device_init(struct panfrost_device *pfdev)
>  
>   spin_lock_init(&pfdev->cycle_counter.lock);
>  
> +#ifdef CONFIG_DEBUG_FS
> + mutex_init(&pfdev->debugfs.gems_lock);
> + INIT_LIST_HEAD(&pfdev->debugfs.gems_list);
> +#endif
> +
>   err = panfrost_pm_domain_init(pfdev);
>   if (err)
>   return err;
> diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h 
> b/drivers/gpu/drm/panfrost/panfrost_device.h
> index dcff70f905cd..077525a3ad68 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_device.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_device.h
> @@ -111,6 +111,17 @@ struct panfrost_compatible {
>   u8 gpu_quirks;
>  };
>  
> +/**
> + * struct panfrost_device_debugfs - Device-wide DebugFS tracking structures
> + */
> +struct panfrost_device_debugfs {
> + /** @gems_list: Device-wide list of GEM objects owned by at least one 
> file. */
> + struct list_head gems_list;
> +
> + /** @gems_lock: Serializes access to the device-wide list of GEM 
> objects. */
> + struct mutex gems_lock;
> +};
> +
>  struct panfrost_device {
>   struct device *dev;
>   struct drm_device *ddev;
> @@ -164,6 +175,10 @@ struct panfrost_device {
>   atomic_t use_count;
>   spinlock_t lock;
>   } cycle_counter;
> +
> +#ifdef CONFIG_DEBUG_FS
> + struct panfrost_device_debugfs debugfs;
> +#endif
>  };
>  
>  struct panfrost_mmu {
> diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c 
> b/drivers/gpu/drm/panfrost/panfrost_drv.c
> index 179fbaa1cd0c..f576cb215898 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_drv.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
> @@ -13,6 +13,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -659,6 +660,37 @@ static const struct file_operations 
> panfrost_drm_driver_fops = {
>   .show_fdinfo = drm_show_fdinfo,
>  };
>  
> +#ifdef CONFIG_DEBUG_FS
> +static int panthor_gems_show(struct seq_file *m, void *data)
> +{
> + struct drm_info_node *node = m->private;
> + struct drm_device *dev = node->minor->dev;
> + struct panfrost_device *pfdev = dev->dev_private;
> +
> + panfrost_gem_debugfs_print_bos(pfdev, m);
> +
> + return 0;
> +}
> +
> +static struct drm_info_list panthor_debugfs_list[] = {
> + {"gems", panthor_gems_show, 0, NULL},
> +};
> +
> +static int panthor_gems_debugfs_init(struct drm_minor *minor)
> +{
> + drm_debugfs_create_files(panthor_debugfs_list,
> +  ARRAY_SIZE(panthor_debugfs_list),
> +  minor->debugfs_root, minor);
> +
> + return 0;
> +}
> +
> +static void panfrost_debugfs_init(struct drm_minor *minor)
> +{
> + panthor_gems_debugfs_init(minor);
> +}
> +#endif
> +
>  /*
>   * Panfrost driver version:
>   * - 1.0 - initial interface
> @@ -683,6 +715,9 @@ static const struct drm_driver panfrost_drm_driver = {
>  
>   .gem_create_object  = panfrost_gem_create_object,
>   .gem_prime_import_sg_table = panfrost_gem_prime_import_sg_table,
> +#ifdef CONFIG_DEBUG_FS
> + .debugfs_init = panfrost_debugfs_init,
> +#endif
>  };
>  
>  static int panfrost_probe(struct platform_device *pdev)
> diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c 
> b/drivers/gpu/drm/panfrost/panfrost_gem.c
> index 04483d5fb45d..bb73f2a68a12 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_gem.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c
> @@ -12,6 +12,36 @@
>  #include "panfrost_gem.h"
>  #include "panfrost_mmu.h"
>  
> +#ifdef CONFIG_DEBUG_FS
> +static void panfrost_gem_debugfs_bo_add(struct panfrost_device *pfdev,
> + struct panfrost_gem_object *bo)
> +{
> + bo->debugfs.creator.tgid = curren

Re: [PATCH v3 16/19] nova-core: Add support for VBIOS ucode extraction for boot

2025-05-21 Thread Joel Fernandes



On 5/20/2025 5:32 PM, Dave Airlie wrote:
> On Wed, 21 May 2025 at 04:13, Joel Fernandes  wrote:
>>
>>
>>
>> On 5/20/2025 11:36 AM, Danilo Krummrich wrote:
> If you want a helper type with Options while parsing that's totally fine, 
> but
> the final result can clearly be without Options. For instance:
>
> struct Data {
>image: KVec,
> }
>
> impl Data {
>fn new() -> Result {
>   let parser = DataParser::new();
>
>   Self { image: parser.parse()? }
>}
>
>fn load_image(&self) {
>   ...
>}
> }
>
> struct DataParser {
>// Only some images have a checksum.
>checksum: Option,
>// Some images have an extra offset.
>offset: Option,
>// Some images need to be patched.
>patch: Option>,
>image: KVec,
> }
>
> impl DataParser {
>fn new() -> Self {
>   Self {
>  checksum: None,
>  offset: None,
>  patch: None,
>  bytes: KVec::new(),
>   }
>}
>
>fn parse(self) -> Result> {
>   // Fetch all the required data.
>   self.fetch_checksum()?;
>   self.fetch_offset()?;
>   self.fetch_patch()?;
>   self.fetch_byes()?;
>
>   // Doesn't do anything if `checksum == None`.
>   self.validate_checksum()?;
>
>   // Doesn't do anything if `offset == None`.
>   self.apply_offset()?;
>
>   // Doesn't do anything if `patch == None`.
>   self.apply_patch()?;
>
>   // Return the final image.
>   self.image
>}
> }
>
> I think the pattern here is the same, but in this example you keep 
> working with
> the DataParser, instead of a new instance of Data.
 I think this would be a fundamental rewrite of the patch. I am Ok with 
 looking
 into it as a future item, but right now I am not sure if it justifies not 
 using
 Option for these few. There's a lot of immediate work we have to do for 
 boot,
 lets please not block the patch on just this if that's Ok with you. If you 
 want,
 I could add a TODO here.
>>>
>>> Honestly, I don't think it'd be too bad to fix this up. It's "just" a bit of
>>> juggling fields and moving code around. The actual code should not change 
>>> much.
>>>
>>> Having Option where the corresponding value T isn't actually optional is
>>> extremely confusing and makes it hard for everyone, but especially new
>>> contributors, to understand the code and can easily trick people into taking
>>> wrong assumptions.
>>>
>>> Making the code reasonably accessible for (new) contributors is one of the
>>> objectives of nova and one of the learnings from nouveau.
> 
> I just want to back Danilo up on this concept as well.
> 
> When I did the experiments code, I faced the not fully constructed
> object problem a lot, and I tried to resist the C pattern of Option<>
> all the things, it's a very C based thing where we create an object
> then initialise it as we go, and it's not a great pattern to have for
> rust code.
> 
> I'm not a huge fan of constructor/builder objects either if they can
> be avoided, please do, and I tried to also avoid proliferating them,
> but I think for most things we can build the pieces and then the final
> object as we go, it just requires doing so from the start, and not
> giving into the Option<> pattern.

Sure, I am on the same page there as well. For next revision of this patch,
struct Vbios will contain a struct FwsecBiosImage without any Option in either
struct Vbios or struct FwsecBiosImage. This is only logical, because there is
nothing optional about it (in what Vbios::new() returns).

thanks,

 - Joel



Re: [PATCH/RFC 0/3] Atari DRM driver

2025-05-21 Thread Geert Uytterhoeven
Hi Eero,

On Wed, 21 May 2025 at 01:59, Eero Tamminen  wrote:
> On 23.1.2023 17.10, Geert Uytterhoeven wrote:
> > On Mon, Jan 23, 2023 at 4:09 PM John Paul Adrian Glaubitz
> >  wrote:
> >> On 11/25/22 21:31, Geert Uytterhoeven wrote:
> >>> This RFC patch series adds a DRM driver for the good old Atari
> >>> ST/TT/Falcon hardware.  It was developed and tested (only) on the ARAnyM
> >>> emulator.
> >>
> >> I just remembered this WIP driver. Has there been any progress?
> >
> > So far no further progress.
>
> I tried your "atari-drm-wip-v1" branch commits on top of 6.14.

Thanks for testing!

> After some minor changes those applied. Getting it to build required
> adding "&shadow_plane_state->fmtcnv_state" (struct drm_format_conv_state
> *) argument to *_blit() functions in atari_drm.c, and changing:
> drm_fbdev_generic_setup(dev, dev->mode_config.preferred_depth);
> in its probe function to:
> struct drm_format_info *format = NULL;
>  drm_client_setup(dev, format);

I do keep it up-to-date locally, so I could provide these changes,
if you are interested.

> However, the result is not working very well yet.
>
> Driver gets initialized fine under Hatari TT emulation:
> -
> atafb atafb: phys_screen_base 511000 screen_len 311296
> atafb atafb: Determined 1280x960, depth 1
> atafb atafb:virtual 1280x1945
> Console: switching to mono frame buffer device 160x60
> fb0: frame buffer device, using 304K of video memory
> ...
> atari_drm atari_drm: phys_screen_base 55d000 screen_len 311296
> atari_drm atari_drm: Determined 1280x960, depth 1
> atari_drm atari_drm:virtual 1280x1945
> [drm] Initialized atari_drm 1.0.0 for atari_drm on minor 0
> atari_drm atari_drm: Atari DRM, using 304K of video memory
> -
>
> However, once screen switches from "atafb" to "atari_drm" driver, Linux
> boot logo & texts disappear, and (emulated) screen is either all white
> (on mono monitor) or all black (on VGA & RGGB monitors).

So you have both atafb and atari_drm enabled? Please don't do that.

> And while "atafb" works fine also under Falcon emulation with RGB (50Hz)
> or VGA (60Hz) monitor, "atari_drm" probing fails:
> -
> genirq: Flags mismatch irq 4. 0020 (framebuffer:modeswitch) vs.
> 0020 (framebuffer:modeswitch)

That's also a sign of two drivers requesting the same IRQ unexpectedly.

> atari_drm atari_drm: probe with driver atari_drm failed with error -16

i.e. -EBUSY.

Gr{oetje,eeting}s,

Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


[PATCH v1] drm/panel-edp: Add support for AUO G156HAN03.0 panel

2025-05-21 Thread ernestvanhoecke
From: Ernest Van Hoecke 

AUO G156HAN03.0 EDID:

00 ff ff ff ff ff ff 00 06 af ed 30 00 00 00 00
1a 1c 01 04 a5 22 13 78 02 05 b5 94 59 59 92 28
1d 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 78 37 80 b4 70 38 2e 40 6c 30
aa 00 58 c1 10 00 00 18 00 00 00 0f 00 00 00 00
00 00 00 00 00 00 00 00 00 20 00 00 00 fe 00 41
55 4f 0a 20 20 20 20 20 20 20 20 20 00 00 00 fe
00 47 31 35 36 48 41 4e 30 33 2e 30 20 0a 00 bb

Signed-off-by: Ernest Van Hoecke 
---
 drivers/gpu/drm/panel/panel-edp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/panel/panel-edp.c 
b/drivers/gpu/drm/panel/panel-edp.c
index 00dae545832e..9adbe0f11421 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -1869,6 +1869,7 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('A', 'U', 'O', 0x235c, &delay_200_500_e50, 
"B116XTN02.3"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x239b, &delay_200_500_e50, 
"B116XAN06.1"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x255c, &delay_200_500_e50, 
"B116XTN02.5"),
+   EDP_PANEL_ENTRY('A', 'U', 'O', 0x30ed, &delay_200_500_e50, 
"G156HAN03.0"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x403d, &delay_200_500_e50, 
"B140HAN04.0"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, 
"B116XAN04.0"),
EDP_PANEL_ENTRY2('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, 
"B116XAK01.0",
-- 
2.43.0



Re: [PATCH v4 01/20] rust: dma: expose the count and size of CoherentAllocation

2025-05-21 Thread Danilo Krummrich
On Wed, May 21, 2025 at 03:44:56PM +0900, Alexandre Courbot wrote:
> These properties are very useful to have and should be accessible.
> 
> Signed-off-by: Alexandre Courbot 
> ---
>  rust/kernel/dma.rs | 18 ++
>  1 file changed, 18 insertions(+)
> 
> diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
> index 
> 605e01e35715667f93297fd9ec49d8e7032e0910..2a60eefa47dfc1f836c30ee342e26c6ff3e9b13a
>  100644
> --- a/rust/kernel/dma.rs
> +++ b/rust/kernel/dma.rs
> @@ -129,6 +129,10 @@ pub mod attrs {
>  //
>  // Hence, find a way to revoke the device resources of a 
> `CoherentAllocation`, but not the
>  // entire `CoherentAllocation` including the allocated memory itself.
> +//
> +// # Invariants
> +//
> +// The size in bytes of the allocation is equal to `size_of:: * count()`.

I think this also needs an invariant comment whenever self.count is set.

>  pub struct CoherentAllocation {
>  dev: ARef,
>  dma_handle: bindings::dma_addr_t,
> @@ -201,6 +205,20 @@ pub fn alloc_coherent(
>  CoherentAllocation::alloc_attrs(dev, count, gfp_flags, Attrs(0))
>  }
>  
> +/// Returns the number of elements `T` in this allocation.
> +///
> +/// Note that this is not the size of the allocation in bytes, which is 
> provided by
> +/// [`Self::size`].
> +pub fn count(&self) -> usize {
> +self.count
> +}
> +
> +/// Returns the size in bytes of this allocation.
> +pub fn size(&self) -> usize {
> +// As per the invariants of `CoherentAllocation`.
> +self.count * core::mem::size_of::()
> +}
> +
>  /// Returns the base address to the allocated region in the CPU's 
> virtual address space.
>  pub fn start_ptr(&self) -> *const T {
>  self.cpu_addr
> 
> -- 
> 2.49.0
> 


Re: [PATCH/RFC 0/3] Atari DRM driver

2025-05-21 Thread Eero Tamminen

Hi Geert,

On 23.1.2023 17.10, Geert Uytterhoeven wrote:

On Mon, Jan 23, 2023 at 4:09 PM John Paul Adrian Glaubitz
 wrote:

On 11/25/22 21:31, Geert Uytterhoeven wrote:

This RFC patch series adds a DRM driver for the good old Atari
ST/TT/Falcon hardware.  It was developed and tested (only) on the ARAnyM
emulator.


I just remembered this WIP driver. Has there been any progress?


So far no further progress.


I tried your "atari-drm-wip-v1" branch commits on top of 6.14.

After some minor changes those applied. Getting it to build required 
adding "&shadow_plane_state->fmtcnv_state" (struct drm_format_conv_state 
*) argument to *_blit() functions in atari_drm.c, and changing:

drm_fbdev_generic_setup(dev, dev->mode_config.preferred_depth);
in its probe function to:
struct drm_format_info *format = NULL;
drm_client_setup(dev, format);

However, the result is not working very well yet.

Driver gets initialized fine under Hatari TT emulation:
-
atafb atafb: phys_screen_base 511000 screen_len 311296
atafb atafb: Determined 1280x960, depth 1
atafb atafb:virtual 1280x1945
Console: switching to mono frame buffer device 160x60
fb0: frame buffer device, using 304K of video memory
...
atari_drm atari_drm: phys_screen_base 55d000 screen_len 311296
atari_drm atari_drm: Determined 1280x960, depth 1
atari_drm atari_drm:virtual 1280x1945
[drm] Initialized atari_drm 1.0.0 for atari_drm on minor 0
atari_drm atari_drm: Atari DRM, using 304K of video memory
-

However, once screen switches from "atafb" to "atari_drm" driver, Linux 
boot logo & texts disappear, and (emulated) screen is either all white 
(on mono monitor) or all black (on VGA & RGGB monitors).



And while "atafb" works fine also under Falcon emulation with RGB (50Hz) 
or VGA (60Hz) monitor, "atari_drm" probing fails:

-
genirq: Flags mismatch irq 4. 0020 (framebuffer:modeswitch) vs. 
0020 (framebuffer:modeswitch)
CPU: 0 UID: 0 PID: 1 Comm: swapper Not tainted 
6.14.0hatari-1-g1d98935cdfd7-dirty #4

Stack from 01029c78:
...
Call Trace: [<88b0>] dump_stack+0x10/0x16
 [<0005852a>] __setup_irq+0x264/0x4a4
 [<0020>] dma_buf_map_attachment_unlocked+0x34/0x6a
 [<0020>] dma_buf_map_attachment_unlocked+0x34/0x6a
 [<001e874c>] falcon_vbl_switcher+0x0/0x14a
 [<00058876>] request_threaded_irq+0x10c/0x142
 [<0030fa1e>] strsep+0x0/0x36
 [<00449cfe>] atari_drm_probe+0x8ba/0xe28
 [<001e874c>] falcon_vbl_switcher+0x0/0x14a
 [<0020>] dma_buf_map_attachment_unlocked+0x34/0x6a
 [<00042d6c>] parse_args+0x0/0x260
 [<00300c2a>] klist_next+0x0/0x8a
 [<00300c2a>] klist_next+0x0/0x8a
 [<00116d3c>] sysfs_do_create_link_sd+0x68/0x92
 [<00116d8e>] sysfs_create_link+0x28/0x3a
 [<001f2a52>] driver_sysfs_add+0x46/0x6c
 [<001f4dd0>] platform_probe+0x26/0x58
 [<001f3390>] really_probe+0xfa/0x1f8
 [<001f3296>] really_probe+0x0/0x1f8
 [<001f3558>] __driver_probe_device+0xca/0xd8
 [<00042d6c>] parse_args+0x0/0x260
 [<00300c2a>] klist_next+0x0/0x8a
 [<001f35da>] driver_probe_device+0x24/0x7c
 [<001f378a>] __driver_attach+0xca/0xda
 [<00300c2a>] klist_next+0x0/0x8a
 [<001f2156>] bus_for_each_dev+0x64/0x8a
 [<001f2d24>] driver_attach+0x1a/0x1e
 [<001f36c0>] __driver_attach+0x0/0xda
 [<001f270c>] bus_add_driver+0x9a/0x188
 [<001f3e66>] driver_register+0xa6/0xe4
 [<0044a790>] __platform_driver_probe+0x6c/0xa4
 [<004493ee>] atari_drm_init+0x0/0x56
 [<0044943c>] atari_drm_init+0x4e/0x56
 [<00449444>] atari_drm_probe+0x0/0xe28
 [<00437578>] do_one_initcall+0x5a/0x164
 [<0030f7e4>] strcpy+0x0/0x22
 [<00042d6c>] parse_args+0x0/0x260
 [<00060006>] __timer_delete_sync+0x38/0x6a
 [<00437820>] kernel_init_freeable+0x13e/0x198
 [<00437876>] kernel_init_freeable+0x194/0x198
 [<004493ee>] atari_drm_init+0x0/0x56
 [<00315cac>] kernel_init+0x0/0xf4
 [<00315cc4>] kernel_init+0x18/0xf4
 [<00315cac>] kernel_init+0x0/0xf4
 [<934c>] ret_from_kernel_thread+0xc/0x14

atari_drm atari_drm: probe with driver atari_drm failed with error -16
-

Any ideas?




Btw. While testing this, I noticed quite a few "atafb" issues:

It panics under Falcon with mono monitor, so I couldn't test that with 
"atari_drm":

-
Kernel panic - not syncing: can't set default video mode
-

"video=atafb:stlow" CLI arg causes probe fail on Falcon + VGA monitor 
(but works with RGB monitor, and on TT):

-
atafb atafb: probe with driver atafb failed with error -22
-

Kernel CLI argument "video=atafb:falh2" gives 16-color mode, same as 
"falh16", not 2-color one as documented (in arch/m68k/kernel-options.rst).


Monochrome Tux logo is not shown in 2-color ("vga2", "sthigh") modes, 
only in 4-color ("vga4", "stmed") ones.


On TT, requesting unsupported mode, e.g. "fal2" or "tthigh" on color 
monitor, gives lowest (320x200x4) resolut

Re: [RFC 0/2] Introduce a sysfs interface for lmem information

2025-05-21 Thread Tvrtko Ursulin



On 20/05/2025 16:01, Joonas Lahtinen wrote:

(+ Tvrtko, Rodrigo and Jani)

Quoting Krzysztof Niemiec (2025-05-19 18:34:14)

Hi,

This series introduces a way for applications to read local memory
information via files in the sysfs. So far the only way to do this was
via i915_query ioctl. This is slightly less handy than sysfs for
external users. Additionally, the ioctl has a capability check which
limits which users of a system might use it to get information.

The goals of this series are:

 1) Introduce a simpler interface to access lmem information,
 2) Lift the CAP_PERFMON check on that information, OR provide
the administrator with a way to optionally lift it.

The first patch introduces the general mechanism without protections.
This will effectively lift a capability check on obtaining the memory
information. The second patch introduces that check back inside the
_show() functions, but also adds a sysctl parameter allowing to override
the checks, if an administrator so decides.

I'm sending this as RFC because I have a feeling that there's no
consensus whether memory information exposed in the patch should be
protected or not. Showing it to any user is strictly speaking an info
leak, but the severity thereof might be considered not that high, so I'd
rather leave it up to discussion first.

If we decide for lifting the check, the first patch is sufficient.


Nack on that.

CPU memory footprint and GPU memory footprint have a very different
nature. This was discussed to quite a length, please refer to mailing
list archives.


If we
decide against it, the second patch protects the information by default,
but with a way to expose it as a conscious decision of the admin. I find
it a decent compromise.


No need for the added complexity if we were to add a sysfs.

If a sysfs is added, it can be made root readable by default but system
admin is free to chown or chmod the file for more relaxed access. Back
in the original discussion time, this was omitted for lack of users.


Agreed, no need to complicate with redundant access controls in the kernel.


Even now, userspace/sysadmin could already essentially use setuid helper
process that will only report the memory statistics.

So I'm not really fully convinced this is needed at all.

And if it is to be added for the convenience of usersppace, it should
probably then be considered to be a standard interface across DRM drivers
ala fdinfo or cgroups.


Cgroup visibility for device memory exists in principle although i915 
hasn't been wired up to it.


For system memory (integrated GPUs) there is some work in progress 
around memcg accounting, although I am unsure if i915 would be 
automatically covered or not.


Also going a step back, from MangoHUDs point of view, I don't really see 
why total GPU memory is very interesting? I would have thought it is 
more interesting to know how much the monitored client is using, which 
is already available via fdinfo. Total memory sounds like something 
which it could leave to interpretation by the entity looking at the 
traces. (If the monitored client is running alone then total_free =~ 
total - client, and if it isn't running alone then it doesn't matter, no?)


Regards,

Tvrtko


This change has been requested in these parallel issues for i915 and Xe:

https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14153
https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/4861

Thanks
Krzysztof

Krzysztof Niemiec (2):
   drm/i915: Expose local memory information via sysfs
   drm/i915: Add protections to sysfs local memory information

  drivers/gpu/drm/i915/i915_sysfs.c  |   6 +
  drivers/gpu/drm/i915/intel_memory_region.c | 136 +
  drivers/gpu/drm/i915/intel_memory_region.h |   3 +
  3 files changed, 145 insertions(+)

--
2.45.2
_




Re: [PATCH v2 10/12] drm/i915/display: Add function to configure LFPS sending

2025-05-21 Thread Nautiyal, Ankit K



On 5/20/2025 10:23 PM, Jouni Högander wrote:

Add function to configre LFPS sending for Panel Replay according to link
training sequence in HAS document.

This assumes we are using AUX Less always if it's supported by the sink and
the source.

v2:
   - drop HAS reference
   - replay kerneldoc comment with a generic comment
   - check display version in intel_lnl_mac_transmit_lfps

Bspec: 68849
Signed-off-by: Jouni Högander 
---
  drivers/gpu/drm/i915/display/intel_cx0_phy.c | 31 
  drivers/gpu/drm/i915/display/intel_cx0_phy.h |  2 ++
  drivers/gpu/drm/i915/display/intel_ddi.c |  8 -
  3 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 91118d115fd3..75caccb65513 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -3225,6 +3225,37 @@ void intel_mtl_pll_enable(struct intel_encoder *encoder,
intel_cx0pll_enable(encoder, crtc_state);
  }
  
+/*

+ * According to HAS we need to enable MAC Transmitting LFPS in the "PHY Common
+ * Control 0" PIPE register in case of AUX Less ALPM is going to be used. This
+ * function is doing that and is called by link retrain sequence.
+ */
+void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder,
+const struct intel_crtc_state *crtc_state)
+{
+   struct intel_display *display = to_intel_display(encoder);
+   u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder);
+   bool enable = intel_alpm_is_alpm_aux_less(enc_to_intel_dp(encoder),
+ crtc_state);
+   int i;
+
+   if (DISPLAY_VER(display) < 20)
+   return;
+
+   for (i = 0; i < 4; i++) {
+   int tx = i % 2 + 1;
+   u8 lane_mask = i < 2 ? INTEL_CX0_LANE0 : INTEL_CX0_LANE1;
+
+   if (!(owned_lane_mask & lane_mask))
+   continue;


Perhaps a macro for the loop pattern would make sense, as this is used 
for other CX0 register.


Regardless of the above, patch looks good to me.

Reviewed-by: Ankit Nautiyal 



+
+   intel_cx0_rmw(encoder, lane_mask, PHY_CMN1_CONTROL(tx, 0),
+ CONTROL0_MAC_TRANSMIT_LFPS,
+ enable ? CONTROL0_MAC_TRANSMIT_LFPS : 0,
+ MB_WRITE_COMMITTED);
+   }
+}
+
  static u8 cx0_power_control_disable_val(struct intel_encoder *encoder)
  {
struct intel_display *display = to_intel_display(encoder);
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index a8f811ca5e7b..c5a7b529955b 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -43,5 +43,7 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder 
*encoder,
 const struct intel_crtc_state *crtc_state);
  int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder);
  void intel_cx0_pll_power_save_wa(struct intel_display *display);
+void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder,
+const struct intel_crtc_state *crtc_state);
  
  #endif /* __INTEL_CX0_PHY_H__ */

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 65ab012c3eae..70de99cc4ead 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3745,10 +3745,16 @@ static void mtl_ddi_prepare_link_retrain(struct 
intel_dp *intel_dp,
intel_dp->DP |= DDI_BUF_CTL_ENABLE;
  
  	/*

-* 6.k If AUX-Less ALPM is going to be enabled
+* 6.k If AUX-Less ALPM is going to be enabled:
 * i. Configure PORT_ALPM_CTL and PORT_ALPM_LFPS_CTL here
 */
intel_alpm_port_configure(intel_dp, crtc_state);
+
+   /*
+* ii. Enable MAC Transmits LFPS in the "PHY Common Control 0" PIPE
+* register
+*/
+   intel_lnl_mac_transmit_lfps(encoder, crtc_state);
  }
  
  static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp,


Re: [PATCH v4 08/20] gpu: nova-core: allow register aliases

2025-05-21 Thread Danilo Krummrich
On Wed, May 21, 2025 at 03:45:03PM +0900, Alexandre Courbot wrote:
> Some registers (notably scratch registers) don't have a definitive
> purpose, but need to be interpreted differently depending on context.
> 
> Expand the register!() macro to support a syntax indicating that a
> register type should be at the same offset as another one, but under a
> different name, and with different fields and documentation.
> 
> Signed-off-by: Alexandre Courbot 
> ---
>  drivers/gpu/nova-core/regs/macros.rs | 40 
> ++--
>  1 file changed, 38 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/nova-core/regs/macros.rs 
> b/drivers/gpu/nova-core/regs/macros.rs
> index 
> 7cd013f3c90bbd8ca437d4072cae8f11d7946fcd..64dda1d4d93d3c7022ef02b6f6fb81b58e90dd44
>  100644
> --- a/drivers/gpu/nova-core/regs/macros.rs
> +++ b/drivers/gpu/nova-core/regs/macros.rs
> @@ -71,6 +71,20 @@
>  /// pr_info!("CPU CTL: {:#x}", cpuctl);
>  /// cpuctl.set_start(true).write(&bar, CPU_BASE);
>  /// ```
> +///
> +/// It is also possible to create a alias register by using the `=> PARENT` 
> syntax. This is useful
> +/// for cases where a register's interpretation depends on the context:
> +///
> +/// ```no_run
> +/// register!(SCRATCH_0 @ 0x100, "Scratch register 0" {
> +///31:0 value as u32, "Raw value";
> +///
> +/// register!(SCRATCH_0_BOOT_STATUS => SCRATCH_0, "Boot status of the 
> firmware" {

NIT: I'd put the arrow the other way around, i.e. SCRATCH_0_BOOT_STATUS is
derived from SCRATCH_0, not the other way around.


Re: [PATCH 1/3] drm/sched: add drm_sched_prealloc_dependency_slots v3

2025-05-21 Thread Christian König
On 5/15/25 18:17, Tvrtko Ursulin wrote:
> 
> On 15/05/2025 16:00, Christian König wrote:
>> Sometimes drivers need to be able to submit multiple jobs which depend on
>> each other to different schedulers at the same time, but using
>> drm_sched_job_add_dependency() can't fail any more after the first job is
>> initialized.
>>
>> This function preallocate memory for dependency slots so that no ENOMEM
>> can come later while adding dependencies.
>>
>> v2: rework implementation an documentation
>> v3: rework from scratch, use separate function to add preallocated deps
>>
>> Signed-off-by: Christian König 
>> ---
>>   drivers/gpu/drm/scheduler/sched_main.c | 45 ++
>>   include/drm/gpu_scheduler.h    |  4 +++
>>   2 files changed, 49 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/scheduler/sched_main.c 
>> b/drivers/gpu/drm/scheduler/sched_main.c
>> index f7118497e47a..b95e7089aa70 100644
>> --- a/drivers/gpu/drm/scheduler/sched_main.c
>> +++ b/drivers/gpu/drm/scheduler/sched_main.c
>> @@ -858,6 +858,51 @@ void drm_sched_job_arm(struct drm_sched_job *job)
>>   }
>>   EXPORT_SYMBOL(drm_sched_job_arm);
>>   +/**
>> + * drm_sched_job_prealloc_dependency_slot - avoid ENOMEM on adding 
>> dependencies
>> + * @job: scheduler job where dependencies will be added
>> + * @id: id for the allocated slot
>> +  *
>> + * Sometimes drivers need to be able to submit multiple jobs which depend on
>> + * each other to different schedulers at the same time, but using
>> + * drm_sched_job_add_dependency() can't fail any more after the first job is
>> + * initialized.
>> + *
>> + * This function preallocate memory for a dependency slot so that no ENOMEM 
>> can
>> + * come later while adding dependencies. The index of the preallocated slot 
>> is
>> + * returned in @id.
>> + *
>> + * Return:
>> + * 0 on success, or an error on failing to expand the array.
>> + */
>> +int drm_sched_job_prealloc_dependency_slot(struct drm_sched_job *job,
>> +   u32 *id)
>> +{
>> +    return xa_alloc(&job->dependencies, id, NULL, xa_limit_32b, GFP_KERNEL);
>> +}
>> +EXPORT_SYMBOL(drm_sched_job_prealloc_dependency_slot);
>> +
>> +/**
>> + * drm_sched_job_add_prealloc_dep - add dependency to preallocated slot
>> + * @job: scheduler job where dependencies will be added
>> + * @id: the preallocated slot index
>> + * @fence: the dependency to add
>> + *
>> + * Consumes @fence and adds it to the preallocated slot dependency.
>> + */
>> +void drm_sched_job_add_prealloc_dep(struct drm_sched_job *job, u32 id,
>> +    struct dma_fence *fence)
>> +{
>> +    fence = xa_store(&job->dependencies, id, fence, GFP_ATOMIC);
> 
> Add assert that the passed id exists (was preallocated) and is NULL?

That is partially done by the WARN_ON below, but I couldn't find a way to check 
if the slot was pre-allocated.

> Also, if someone preallocates and does not consume the slot will that confuse 
> the iteration in drm_sched_job_dependency()?

No, slots with NULL in them are skipped by xa_for_each(). I will add a comment 
explaining that.

Thanks,
Christian.

> 
> Regards,
> 
> Tvrtko
> 
>> +    /*
>> + * Be defensive just in case driver messed it up and used preallocated
>> + * slot twice.
>> + */
>> +    if (WARN_ON(fence))
>> +    dma_fence_put(fence);
>> +}
>> +EXPORT_SYMBOL(drm_sched_job_add_prealloc_dep);
>> +
>>   /**
>>    * drm_sched_job_add_dependency - adds the fence as a job dependency
>>    * @job: scheduler job to add the dependencies to
>> diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
>> index d860db087ea5..0286e0934317 100644
>> --- a/include/drm/gpu_scheduler.h
>> +++ b/include/drm/gpu_scheduler.h
>> @@ -632,6 +632,10 @@ int drm_sched_job_init(struct drm_sched_job *job,
>>  u32 credits, void *owner);
>>   void drm_sched_job_arm(struct drm_sched_job *job);
>>   void drm_sched_entity_push_job(struct drm_sched_job *sched_job);
>> +int drm_sched_job_prealloc_dependency_slot(struct drm_sched_job *job,
>> +   u32 *id);
>> +void drm_sched_job_add_prealloc_dep(struct drm_sched_job *job, u32 id,
>> +    struct dma_fence *fence);
>>   int drm_sched_job_add_dependency(struct drm_sched_job *job,
>>    struct dma_fence *fence);
>>   int drm_sched_job_add_syncobj_dependency(struct drm_sched_job *job,
> 



Re: [PATCH] drm/sched/tests: Use one lock for fence context

2025-05-21 Thread Tvrtko Ursulin



On 21/05/2025 11:04, Philipp Stanner wrote:

When the unit tests were implemented, each scheduler job got its own,
distinct lock. This is not how dma_fence context locking rules are to be
implemented. All jobs belonging to the same fence context (in this case:
scheduler) should share a lock for their dma_fences. This is to comply
to various dma_fence rules, e.g., ensuring that only one fence gets
signaled at a time.

Use the fence context (scheduler) lock for the jobs.


I think for the mock scheduler it works to share the lock, but I don't 
think see that the commit message is correct. Where do you see the 
requirement to share the lock? AFAIK fence->lock is a fence lock, 
nothing more semantically.


And what does "ensuring that only one fence gets signalled at a time" 
mean? You mean signal in seqno order? Even that is not guaranteed in the 
contract due opportunistic signalling.


Regards,

Tvrtko


Signed-off-by: Philipp Stanner 
---
  drivers/gpu/drm/scheduler/tests/mock_scheduler.c | 5 ++---
  drivers/gpu/drm/scheduler/tests/sched_tests.h| 1 -
  2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c 
b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
index f999c8859cf7..17023276f4b0 100644
--- a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
+++ b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
@@ -64,7 +64,7 @@ static void drm_mock_sched_job_complete(struct 
drm_mock_sched_job *job)
  
  	job->flags |= DRM_MOCK_SCHED_JOB_DONE;

list_move_tail(&job->link, &sched->done_list);
-   dma_fence_signal(&job->hw_fence);
+   dma_fence_signal_locked(&job->hw_fence);
complete(&job->done);
  }
  
@@ -123,7 +123,6 @@ drm_mock_sched_job_new(struct kunit *test,

job->test = test;
  
  	init_completion(&job->done);

-   spin_lock_init(&job->lock);
INIT_LIST_HEAD(&job->link);
hrtimer_setup(&job->timer, drm_mock_sched_job_signal_timer,
  CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
@@ -169,7 +168,7 @@ static struct dma_fence *mock_sched_run_job(struct 
drm_sched_job *sched_job)
  
  	dma_fence_init(&job->hw_fence,

   &drm_mock_sched_hw_fence_ops,
-  &job->lock,
+  &sched->lock,
   sched->hw_timeline.context,
   atomic_inc_return(&sched->hw_timeline.next_seqno));
  
diff --git a/drivers/gpu/drm/scheduler/tests/sched_tests.h b/drivers/gpu/drm/scheduler/tests/sched_tests.h

index 27caf8285fb7..fbba38137f0c 100644
--- a/drivers/gpu/drm/scheduler/tests/sched_tests.h
+++ b/drivers/gpu/drm/scheduler/tests/sched_tests.h
@@ -106,7 +106,6 @@ struct drm_mock_sched_job {
unsigned intduration_us;
ktime_t finish_at;
  
-	spinlock_t		lock;

struct dma_fencehw_fence;
  
  	struct kunit		*test;




Re: [RFC PATCH 00/12] Private MMIO support for private assigned dev

2025-05-21 Thread Alexey Kardashevskiy




On 16/5/25 02:53, Zhi Wang wrote:

On Thu, 15 May 2025 16:44:47 +
Zhi Wang  wrote:


On 15.5.2025 13.29, Alexey Kardashevskiy wrote:



On 13/5/25 20:03, Zhi Wang wrote:

On Mon, 12 May 2025 11:06:17 -0300
Jason Gunthorpe  wrote:


On Mon, May 12, 2025 at 07:30:21PM +1000, Alexey Kardashevskiy
wrote:


I'm surprised by this.. iommufd shouldn't be doing PCI stuff,
it is just about managing the translation control of the
device.


I have a little difficulty to understand. Is TSM bind PCI stuff?
To me it is. Host sends PCI TDISP messages via PCI DOE to put
the device in TDISP LOCKED state, so that device behaves
differently from before. Then why put it in IOMMUFD?



"TSM bind" sets up the CPU side of it, it binds a VM to a piece
of IOMMU on the host CPU. The device does not know about the VM,
it just enables/disables encryption by a request from the CPU
(those start/stop interface commands). And IOMMUFD won't be
doing DOE, the platform driver (such as AMD CCP) will. Nothing
to do for VFIO here.

We probably should notify VFIO about the state transition but I
do not know VFIO would want to do in response.


We have an awkward fit for what CCA people are doing to the
various Linux APIs. Looking somewhat maximally across all the
arches a "bind" for a CC vPCI device creation operation does:

   - Setup the CPU page tables for the VM to have access to the
MMIO
   - Revoke hypervisor access to the MMIO
   - Setup the vIOMMU to understand the vPCI device
   - Take over control of some of the IOVA translation, at least
for T=1, and route to the the vIOMMU
   - Register the vPCI with any attestation functions the VM might
use
   - Do some DOE stuff to manage/validate TDSIP/etc

So we have interactions of things controlled by PCI, KVM, VFIO,
and iommufd all mushed together.

iommufd is the only area that already has a handle to all the
required objects:
   - The physical PCI function
   - The CC vIOMMU object
   - The KVM FD
   - The CC vPCI object

Which is why I have been thinking it is the right place to manage
this.

It doesn't mean that iommufd is suddenly doing PCI stuff, no, that
stays in VFIO.


So your issue is you need to shoot down the dmabuf during vPCI
device destruction?


I assume "vPCI device" refers to assigned device in both shared
mode & prvate mode. So no, I need to shoot down the dmabuf
during TSM unbind, a.k.a. when assigned device is converting
from private to shared. Then recover the dmabuf after TSM
unbind. The device could still work in VM in shared mode.


What are you trying to protect with this? Is there some intelism
where you can't have references to encrypted MMIO pages?



I think it is a matter of design choice. The encrypted MMIO page is
related to the TDI context and secure second level translation
table (S-EPT). and S-EPT is related to the confidential VM's
context.

AMD and ARM have another level of HW control, together
with a TSM-owned meta table, can simply mask out the access to
those encrypted MMIO pages. Thus, the life cycle of the encrypted
mappings in the second level translation table can be de-coupled
from the TDI unbound. They can be reaped un-harmfully later by
hypervisor in another path.

While on Intel platform, it doesn't have that additional level of
HW control by design. Thus, the cleanup of encrypted MMIO page
mapping in the S-EPT has to be coupled tightly with TDI context
destruction in the TDI unbind process.

If the TDI unbind is triggered in VFIO/IOMMUFD, there has be a
cross-module notification to KVM to do cleanup in the S-EPT.


QEMU should know about this unbind and can tell KVM about it too.
No cross module notification needed, it is not a hot path.



Yes. QEMU knows almost everything important, it can do the required
flow and kernel can enforce the requirements. There shouldn't be
problem at runtime.

But if QEMU crashes, what are left there are only fd closing paths
and objects that fds represent in the kernel. The modules those fds
belongs need to solve the dependencies of tearing down objects
without the help of QEMU.

There will be private MMIO dmabuf fds, VFIO fds, IOMMU device fd, KVM
fds at that time. Who should trigger the TDI unbind at this time?

I think it should be triggered in the vdevice teardown path in IOMMUfd
fd closing path, as it is where the bind is initiated.


This is how I do it now, yes.




iommufd vdevice tear down (iommu fd closing path)
  > tsm_tdi_unbind
  > intel_tsm_tdi_unbind
  ...
  > private MMIO un-maping in KVM
  > cleanup private MMIO mapping in S-EPT and
others > signal MMIO dmabuf can be safely removed.
 ^TVM teardown path (dmabuf uninstall path)
checks this state and wait before it can decrease the
 dmabuf fd refcount


This extra signaling is not needed on AMD SEV though - 1) VFIO will destroy 
this dmabuf on teardown (and it won't care about its RMP state) and 2) the CCP 
driver will cl

RE: [PATCH 2/2] dmabuf/heaps: implement DMA_BUF_IOCTL_RW_FILE for system_heap

2025-05-21 Thread wangtao


> -Original Message-
> From: Christian König 
> Sent: Wednesday, May 21, 2025 3:36 PM
> To: wangtao ; T.J. Mercier
> 
> Cc: sumit.sem...@linaro.org; benjamin.gaign...@collabora.com;
> brian.star...@arm.com; jstu...@google.com; linux-me...@vger.kernel.org;
> dri-devel@lists.freedesktop.org; linaro-mm-...@lists.linaro.org; linux-
> ker...@vger.kernel.org; wangbintian(BintianWang)
> ; yipengxiang ; liulu
> 00013167 ; hanfeng 00012985 
> Subject: Re: [PATCH 2/2] dmabuf/heaps: implement
> DMA_BUF_IOCTL_RW_FILE for system_heap
> 
> On 5/21/25 06:17, wangtao wrote:
> >>> Reducing CPU overhead/power consumption is critical for mobile
> devices.
> >>> We need simpler and more efficient dmabuf direct I/O support.
> >>>
> >>> As Christian evaluated sendfile performance based on your data,
> >>> could you confirm whether the cache was cleared? If not, please
> >>> share the post-cache-clearing test data. Thank you for your support.
> >>
> >> Yes sorry, I was out yesterday riding motorcycles. I did not clear
> >> the cache for the buffered reads, I didn't realize you had. The IO
> >> plus the copy certainly explains the difference.
> >>
> >> Your point about the unlikelihood of any of that data being in the
> >> cache also makes sense.
> > [wangtao] Thank you for testing and clarifying.
> >
> >>
> >> I'm not sure it changes anything about the ioctl approach though.
> >> Another way to do this would be to move the (optional) support for
> >> direct IO into the exporter via dma_buf_fops and dma_buf_ops. Then
> >> normal read() syscalls would just work for buffers that support them.
> >> I know that's more complicated, but at least it doesn't require
> >> inventing new uapi to do it.
> >>
> > [wangtao] Thank you for the discussion. I fully support any method
> > that enables dmabuf direct I/O.
> >
> > I understand using sendfile/splice with regular files for dmabuf adds
> > an extra CPU copy, preventing zero-copy. For example:
> > sendfile path: [DISK] → DMA → [page cache] → CPU copy → [memory
> file].
> 
> Yeah, but why can't you work on improving that?
> 
> > The read() syscall can't pass regular file fd parameters, so I added
> > an ioctl command.
> > While copy_file_range() supports two fds (fd_in/fd_out), it blocks cross-fs
> use.
> > Even without this restriction, file_out->f_op->copy_file_range only
> > enables dmabuf direct reads from regular files, not writes.
> >
> > Since dmabuf's direct I/O limitation comes from its unique
> > attachment/map/fence model and lacks suitable syscalls, adding an
> > ioctl seems necessary.
> 
> I absolutely don't see that. Both splice and sendfile can take two regular 
> file
> descriptors.
> 
> That the underlying fops currently can't do that is not a valid argument for
> adding new uAPI. It just means that you need to work on improving those
> fops.
> 
> As long as nobody proves to me that the existing uAPI isn't sufficient for 
> this
> use case I will systematically reject any approach to adding new one.
> 
[wangtao] I previously explained that read/sendfile/splice/copy_file_range
syscalls can't achieve dmabuf direct IO zero-copy.
1. read() can't pass regular file fd to dmabuf.
2. sendfile() supports regular file <-> regular file/socket zero-copy,
but not regular file <-> memory file.
Example:
sendfile(dst_net, src_disk):
[DISK] --DMA--> [page buffer] --DMA--> [NIC]

sendfile(dst_disk, src_disk):
[DISK] --DMA--> [page buffer] --DMA--> [DISK]

sendfile(dst_memfile, src_disk):
[DISK] --DMA--> [page buffer] --CPU copy--> [MEMORY file]

3. splice() requires one end to be a pipe, making it unsuitable.
4. copy_file_range() is blocked by cross-FS restrictions (Amir's commit
868f9f2f8e004bfe0d3935b1976f625b2924893b). Even without this,
file_out->f_op->copy_file_range only enables dmabuf read from regular files,
not write.

My focus is enabling dmabuf direct I/O for [regular file] <--DMA--> [dmabuf]
zero-copy. Any API achieving this would work. Are there other uAPIs you think
could help? Could you recommend experts who might offer suggestions?
Thank you.

> Regards,
> Christian.
> 
> > When system exporters return a duplicated sg_table via map_dma_buf
> > (used exclusively like a pages array), they should retain control over
> > it.
> >
> > I welcome all solutions to achieve dmabuf direct I/O! Your feedback is
> > greatly appreciated.
> >
> >> 1G from ext4 on 6.12.20 | read/sendfile (ms) w/ 3 > drop_caches
> >> |---
> >> udmabuf buffer read | 1210
> >> udmabuf direct read | 671
> >> udmabuf buffer sendfile | 1096
> >> udmabuf direct sendfile | 2340
> >>
> >>
> >>
> >>>
> >
> >>> dmabuf buffer read | 51 | 1068  | 1118
> >>> dmabuf direct read | 52 | 297   | 349
> >>>
> >>> udmabuf sendfile test steps:
> >>> 1. Open data file(1024MB), get back_fd 2. Create memfd(32MB) #
> >>> Loop steps 2-6 3. Allocate udmabuf with memfd 4. Call
> >>> sendfile(memfd,
> >>> back_fd)

Re: [PATCH v6 2/2] i2c: i2c-qcom-geni: Add Block event interrupt support

2025-05-21 Thread Jyothi Kumar Seerapu




On 5/9/2025 9:31 PM, Dmitry Baryshkov wrote:

On 09/05/2025 09:18, Jyothi Kumar Seerapu wrote:

Hi Dimitry, Thanks for providing the review comments.

On 5/6/2025 5:16 PM, Dmitry Baryshkov wrote:

On Tue, May 06, 2025 at 04:48:44PM +0530, Jyothi Kumar Seerapu wrote:

The I2C driver gets an interrupt upon transfer completion.
When handling multiple messages in a single transfer, this
results in N interrupts for N messages, leading to significant
software interrupt latency.

To mitigate this latency, utilize Block Event Interrupt (BEI)
mechanism. Enabling BEI instructs the hardware to prevent interrupt
generation and BEI is disabled when an interrupt is necessary.

Large I2C transfer can be divided into chunks of 8 messages internally.
Interrupts are not expected for the first 7 message completions, only
the last message triggers an interrupt, indicating the completion of
8 messages. This BEI mechanism enhances overall transfer efficiency.


Why do you need this complexity? Is it possible to set the
DMA_PREP_INTERRUPT flag on the last message in the transfer?


If i undertsand correctly, the suggestion is to get the single 
intetrrupt for last i2c message only.


But With this approach, we can't handle large number of i2c messages 
in the transfer.


In GPI driver, number of max TREs support is harcoded to 64 (#define 
CHAN_TRES   64) and for I2C message, we need Config TRE, GO TRE and 
DMA TREs. So, the avilable TREs are not sufficient to handle all the N 
messages.


It sounds like a DMA driver issue. In other words, the DMA driver can 
know that it must issue an interrupt before exausting 64 TREs in order to




Here, the plan is to queue i2c messages (QCOM_I2C_GPI_MAX_NUM_MSGS or 
'num' incase for less messsages), process and unmap/free upon the 
interrupt based on QCOM_I2C_GPI_NUM_MSGS_PER_IRQ.


Why? This is some random value which has no connection with CHAN_TREs. 
Also, what if one of the platforms get a 'liter' GPI which supports less 
TREs in a single run? Or a super-premium platform which can use 256 
TREs? Please don't workaround issues from one driver in another one.


We are trying to utilize the existing CHAN_TRES mentioned in the GPI 
driver.
With the following approach, the GPI hardware can process N number of 
I2C messages, thereby improving throughput and transfer efficiency.


The main design consideration for using the block event interrupt is as 
follows:


Allow the hardware to process the TREs (I2C messages), while the 
software concurrently prepares the next set of TREs to be submitted to 
the hardware. Once the TREs are processed, they can be freed, enabling 
the software to queue new TREs. This approach enhances overall optimization.


Please let me know if you have any questions, concerns, or suggestions.









This optimization reduces transfer time from 168 ms to 48 ms for a
series of 200 I2C write messages in a single transfer, with a
clock frequency support of 100 kHz.

BEI optimizations are currently implemented for I2C write transfers 
only,
as there is no use case for multiple I2C read messages in a single 
transfer

at this time.

Signed-off-by: Jyothi Kumar Seerapu 
---
v5 -> v6:
   - Instead of using bei_flag, moved the logic to use with DMA
 supported flags like DMA_PREP_INTERRUPT.
   - Additional parameter comments removed from 
geni_i2c_gpi_multi_desc_unmap

 function documentation.
v4 -> v5:
   - Block event interrupt flag naming changed from flags to bei_flag.
   - Documentation added for "struct geni_i2c_dev".

v3 -> v4:
   - API's added for Block event interrupt with multi descriptor 
support for
 I2C is moved from qcom-gpi-dma.h file to I2C geni qcom driver 
file.
   - gpi_multi_xfer_timeout_handler function is moved from GPI 
driver to

 I2C driver.
   - geni_i2c_gpi_multi_desc_xfer structure is added as a member of
 struct geni_i2c_dev.

v2 -> v3:
    - In i2c_gpi_cb_result function, moved the logic of
 "!is_tx_multi_xfer" to else.
    - MIN_NUM_OF_MSGS_MULTI_DESC changed from 4 to 2
    - Updated commit description

v1 -> v2:
    - Moved gi2c_gpi_xfer->msg_idx_cnt to separate local variable.
    - Updated goto labels for error scenarios in geni_i2c_gpi function
    - memset tx_multi_xfer to 0.
    - Removed passing current msg index to geni_i2c_gpi
    - Fixed kernel test robot reported compilation issues.


  drivers/i2c/busses/i2c-qcom-geni.c | 307 + 
+---

  1 file changed, 280 insertions(+), 27 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/ 
busses/ i2c-qcom-geni.c

index 515a784c951c..e390cf5b4ddc 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -78,6 +78,62 @@ enum geni_i2c_err_code {
  #define XFER_TIMEOUT    HZ
  #define RST_TIMEOUT    HZ
+#define QCOM_I2C_GPI_MAX_NUM_MSGS    16
+#define QCOM_I2C_GPI_NUM_MSGS_PER_IRQ    8
+#define QCOM_I2C_MIN_NUM_OF_MSGS_MULTI_DESC    2
+
+/**
+ * struct geni_i2c_gpi_multi_des

Re: [PATCH v3 02/12] drm/dp: Add Panel Replay capability bits from DP2.1 specification

2025-05-21 Thread Nautiyal, Ankit K



On 5/21/2025 3:02 PM, Jouni Högander wrote:

Add PANEL REPLAY CAPABILITY register (0xb1) bits.

v2: comment about DP2.1 changed as DP2.1a

Signed-off-by: Jouni Högander 
---
  include/drm/display/drm_dp.h | 10 --
  1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index 3371e2edd9e9..c0579f827999 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -554,8 +554,14 @@
  
  #define DP_PANEL_REPLAY_CAP_SIZE	7
  
-#define DP_PANEL_REPLAY_CAP_CAPABILITY			0xb1

-# define DP_PANEL_REPLAY_SU_GRANULARITY_REQUIRED   (1 << 5)
+#define DP_PANEL_REPLAY_CAP_CAPABILITY 0xb1
+# define DP_PANEL_REPLAY_DSC_DECODE_CAPABILITY_IN_PR_SHIFT 
1 /* DP 2.1a */
+# define DP_PANEL_REPLAY_DSC_DECODE_CAPABILITY_IN_PR_MASK  (3 
<< 1)


Thanks for clarification about DP2.1 a.

IMHO if we are using the shift 
DP_PANEL_REPLAY_DSC_DECODE_CAPABILITY_IN_PR_SHIFT1

then perhaps DP_PANEL_REPLAY_DSC_DECODE_CAPABILITY_IN_PR_MASK should be:
(3<
+# define DP_PANEL_REPLAY_ASYNC_VIDEO_TIMING_NOT_SUPPORTED_IN_PR  
  (1 << 3)
+# define DP_PANEL_REPLAY_DSC_CRC_OF_MULTIPLE_SUS_SUPPORTED (1 
<< 4)
+# define DP_PANEL_REPLAY_SU_GRANULARITY_REQUIRED   (1 
<< 5)
+# define DP_PANEL_REPLAY_SU_Y_GRANULARITY_EXTENDED_CAPABILITY_SUPPORTED  
  (1 << 6)
+# define DP_PANEL_REPLAY_LINK_OFF_SUPPORTED_IN_PR_AFTER_ADAPTIVE_SYNC_SDP  (1 
<< 7)
  
  #define DP_PANEL_REPLAY_CAP_X_GRANULARITY		0xb2

  #define DP_PANEL_REPLAY_CAP_Y_GRANULARITY 0xb4


linux-next: build warning after merge of the drm tree

2025-05-21 Thread Stephen Rothwell
Hi all,

After merging the drm tree, today's linux-next build (htmldocs) produced
this warning:

Error: Cannot open file drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c

Introduced by commit

  c472d828348c ("drm/nouveau/gsp: move subdev/engine impls to 
subdev/gsp/rm/r535/")

-- 
Cheers,
Stephen Rothwell


pgp5puk6_FqEF.pgp
Description: OpenPGP digital signature


RE: [PATCH v5 08/12] drm: renesas: rz-du: mipi_dsi: Use mHz for D-PHY frequency calculations

2025-05-21 Thread Fabrizio Castro
Hi Laurent,

Thanks for your feedback.

> From: Laurent Pinchart 
> Sent: 20 May 2025 15:24
> Subject: Re: [PATCH v5 08/12] drm: renesas: rz-du: mipi_dsi: Use mHz for 
> D-PHY frequency calculations
> 
> Hi Prabhakar,
> 
> Thank you for the patch.
> 
> On Mon, May 12, 2025 at 07:23:26PM +0100, Prabhakar wrote:
> > From: Lad Prabhakar 
> >
> > Pass the HSFREQ in milli-Hz to the `dphy_init()` callback to improve
> > precision, especially for the RZ/V2H(P) SoC, where PLL dividers require
> > high accuracy.
> 
> I have a hard time imagining the need for milliHz accuracy. Could you
> please explain why that is needed on V2H ?

This is needed because of the clock architecture found on the Renesas RZ/V2H,
in combination with a tight tolerance on the HFSFREQ calculation.

The clock architecture found on the RZ/V2H DSI is modelled as below:

 __ 
|  |   ||
| CPG  |   | DSI|
|      |   |__  |
| |||| |   |   | | vclk | | |
| | PLLDSI |--->| CSDIV_2to32_PLLDSI |-|-->|-->| PLL |->| PHY | |
| |||| |   |   |_|  |_| |
|__|   ||


The PLL found inside the DSI IP is very similar to the PLLDSI found in the
CPG IP block, although the limits for some of the parameters are different.
Also, the PLLDSI is followed by a programmable divider, whereas there is no
such thing in the DSI PLL IP.

The limits for the PLL found within the DSI IP are:
1 <= PLL_P <= 4
64 <= PLL_M <= 1023
0 <= PLL_S <= 5
−32768 <= PLL_K <= 32767

The limits for PLLDSI (found in CPG) are:
1 <= PLL_P <= 4
64 <= PLL_M <= 533
0 <= PLL_S <= 6
−32768 <= PLL_K <= 32767
The limits for the CSDIV_2to32_PLLDSI divider are:
CSDIV = 1/(2 + 2 * n), with n=0,...,15

Using mHz internally for representing VCLK and HSFREQ is vital to allow the DSI
Driver to keep the error between the calculated value of HSFREQ and the actual
value of HSFREQ below a certain threshold (0.5 Hz).
The difficulty in achieving a small error is down to the accuracy of the VCLK
representation.
Since the clock subsystem only allows for Hz, a 0.5 Hz error on the 
representation of
VCLK (down to the selection of frequencies that cannot be precisely achieved and
related rounding errors) may lead to a very big error in the calculation
of HSFREQ, which uses the below formula:
HSFREQ = (VCLK * bpp) / num_lanes
In the worst-case scenario (1 lane and 24 bpp), a 0.5 Hz error on the 
representation
of VCLK will lead to an error of 12 Hz(!) on the calculation of HSFREQ, leading
to a non-working video output.

By internally representing VCLK (and HSFREQ) in mHZ, the maximum error we make 
on
its representation is 0.5 mHz, with a total maximum error of 12 mHz on the
calculation of HSFREQ.

HSFREQ then gets converted back to Hz (bringing the error back to a maximum 
value
of 0.5 Hz) for calculating the PHY parameters, which at that point is good 
enough.

We have empirically proven this, so there is no way around it.

The thing that we got lucky about is that we can use the same algorithm to 
calculate
the parameters for PLLDSI and for the DSI PLL, therefore by sharing a function 
between
the CPG driver and the DSI driver we can, to some extent, bypass the limitations
of the clock subsystem and achieve the accuracy required by DSI.

Also, RZ/G3E has a similar architecture therefore it is subjected to similar
constraints.

I hope this clarifies things?

Cheers,
Fab

> 
> > These changes prepare the driver for upcoming RZ/V2H(P) SoC support.
> >
> > Co-developed-by: Fabrizio Castro 
> > Signed-off-by: Fabrizio Castro 
> > Signed-off-by: Lad Prabhakar 
> > Reviewed-by: Biju Das 
> > ---
> > v4->v5:
> > - Added Reviewed tag from Biju
> >
> > v3->v4:
> > - Used MILLI instead of KILO
> > - Made use of mul_u32_u32() for multiplication
> >
> > v2->v3:
> > - Replaced `unsigned long long` with `u64`
> > - Replaced *_mhz with *_millihz` in functions
> >
> > v1->v2:
> > - No changes
> > ---
> >  drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 13 -
> >  1 file changed, 8 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c 
> > b/drivers/gpu/drm/renesas/rz-
> du/rzg2l_mipi_dsi.c
> > index 5fc607be0c46..f93519613662 100644
> > --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > @@ -31,7 +31,7 @@
> >  struct rzg2l_mipi_dsi;
> >
> >  struct rzg2l_mipi_dsi_hw_info {
> > -   int (*dphy_init)(struct rzg2l_mipi_dsi *dsi, unsigned long hsfreq);
> > +   int (*dphy_init)(struct rzg2l_mipi_dsi *dsi, u64 hsfreq_millihz);
> > void (*dphy_exit)(struct rzg2l_mipi_dsi *dsi);
> > u32 phy_reg_offset;
> > u32 link_reg_offset;
> > @@ -200,8 +200,9 @@

Re: [PATCH] drm/rockchip: cdn-dp: Convert to drm bridge

2025-05-21 Thread Chaoyi Chen

Hi Andy,

On 2025/5/21 20:09, Andy Yan wrote:

Hi Chaoyi,

At 2025-05-07 11:51:48, "Chaoyi Chen"  wrote:

From: Chaoyi Chen 

Convert it to drm bridge driver, it will be convenient for us to
migrate the connector part to the display driver later.

Tested with RK3399 EVB IND board.

Signed-off-by: Chaoyi Chen 
---
drivers/gpu/drm/rockchip/cdn-dp-core.c | 163 +
drivers/gpu/drm/rockchip/cdn-dp-core.h |   5 +-
2 files changed, 86 insertions(+), 82 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 292c31de18f1..bc70dae8ff72 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -25,9 +25,9 @@
#include "cdn-dp-core.h"
#include "cdn-dp-reg.h"

-static inline struct cdn_dp_device *connector_to_dp(struct drm_connector 
*connector)
+static inline struct cdn_dp_device *bridge_to_dp(struct drm_bridge *bridge)
{
-   return container_of(connector, struct cdn_dp_device, connector);
+   return container_of(bridge, struct cdn_dp_device, bridge);
}

static inline struct cdn_dp_device *encoder_to_dp(struct drm_encoder *encoder)
@@ -231,9 +231,9 @@ static bool cdn_dp_check_sink_connection(struct 
cdn_dp_device *dp)
}

static enum drm_connector_status
-cdn_dp_connector_detect(struct drm_connector *connector, bool force)
+cdn_dp_bridge_detect(struct drm_bridge *bridge)
{
-   struct cdn_dp_device *dp = connector_to_dp(connector);
+   struct cdn_dp_device *dp = bridge_to_dp(bridge);
enum drm_connector_status status = connector_status_disconnected;

mutex_lock(&dp->lock);
@@ -244,41 +244,26 @@ cdn_dp_connector_detect(struct drm_connector *connector, 
bool force)
return status;
}

-static void cdn_dp_connector_destroy(struct drm_connector *connector)
+static const struct drm_edid *
+cdn_dp_connector_edid_read(struct drm_bridge *bridge, struct drm_connector 
*connector)

This should be cdn_dp_bridge_edid_read


Will fix in v2.





{
-   drm_connector_unregister(connector);
-   drm_connector_cleanup(connector);
-}
-
-static const struct drm_connector_funcs cdn_dp_atomic_connector_funcs = {
-   .detect = cdn_dp_connector_detect,
-   .destroy = cdn_dp_connector_destroy,
-   .fill_modes = drm_helper_probe_single_connector_modes,
-   .reset = drm_atomic_helper_connector_reset,
-   .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-   .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-static int cdn_dp_connector_get_modes(struct drm_connector *connector)
-{
-   struct cdn_dp_device *dp = connector_to_dp(connector);
-   int ret = 0;
+   struct cdn_dp_device *dp = bridge_to_dp(bridge);
+   const struct drm_edid *drm_edid;

mutex_lock(&dp->lock);
-
-   ret = drm_edid_connector_add_modes(connector);
-
+   drm_edid = drm_edid_read_custom(dp->connector,
+   cdn_dp_get_edid_block, dp);

Use drm_edid_read_ddc


drm_edid_read_ddc() need a i2c_adapter, but cdn-dp doesn't have it.





mutex_unlock(&dp->lock);

-   return ret;
+   return drm_edid;
}

static enum drm_mode_status
-cdn_dp_connector_mode_valid(struct drm_connector *connector,
-   const struct drm_display_mode *mode)
+cdn_dp_bridge_mode_valid(struct drm_bridge *bridge,
+const struct drm_display_info *display_info,
+const struct drm_display_mode *mode)
{
-   struct cdn_dp_device *dp = connector_to_dp(connector);
-   struct drm_display_info *display_info = &dp->connector.display_info;
+   struct cdn_dp_device *dp = bridge_to_dp(bridge);
u32 requested, actual, rate, sink_max, source_max = 0;
u8 lanes, bpc;

@@ -323,11 +308,6 @@ cdn_dp_connector_mode_valid(struct drm_connector 
*connector,
return MODE_OK;
}

-static struct drm_connector_helper_funcs cdn_dp_connector_helper_funcs = {
-   .get_modes = cdn_dp_connector_get_modes,
-   .mode_valid = cdn_dp_connector_mode_valid,
-};
-
static int cdn_dp_firmware_init(struct cdn_dp_device *dp)
{
int ret;
@@ -360,7 +340,7 @@ static int cdn_dp_firmware_init(struct cdn_dp_device *dp)

static int cdn_dp_get_sink_capability(struct cdn_dp_device *dp)
{
-   const struct drm_display_info *info = &dp->connector.display_info;
+   const struct drm_display_info *info = &dp->connector->display_info;
int ret;

if (!cdn_dp_check_sink_connection(dp))
@@ -374,9 +354,9 @@ static int cdn_dp_get_sink_capability(struct cdn_dp_device 
*dp)
}

drm_edid_free(dp->drm_edid);
-   dp->drm_edid = drm_edid_read_custom(&dp->connector,
+   dp->drm_edid = drm_edid_read_custom(dp->connector,
cdn_dp_get_edid_block, dp);
-   drm_edid_connector_update(&dp->connector, dp->drm_edid);
+   drm_edid_connector_update(dp->connector, dp->drm_edi

Re: [PATCH v2] drm/bridge: ti-sn65dsi86: Add HPD for DisplayPort connector type

2025-05-21 Thread Doug Anderson
Hi,

On Thu, May 8, 2025 at 4:54 AM Jayesh Choudhary  wrote:
>
> By default, HPD was disabled on SN65DSI86 bridge. When the driver was
> added (commit "a095f15c00e27"), the HPD_DISABLE bit was set in pre-enable
> call which was moved to other function calls subsequently.
> Later on, commit "c312b0df3b13" added detect utility for DP mode. But with
> HPD_DISABLE bit set, all the HPD events are disabled[0] and the debounced
> state always return 1 (always connected state)
>
> Also, with the suspend and resume calls before every register access, the
> bridge starts with disconnected state and the HPD state is reflected
> correctly only after debounce time (400ms). However, adding this delay
> in the detect function causes frame drop and visible glitch in display.
>
> So to get the detect utility working properly for DP mode without any
> performance issues in display, instead of reading HPD state from the
> register, rely on aux communication. Use 'drm_dp_dpcd_read_link_status'
> to find if we have something connected at the sink.
>
> [0]:  (Pg. 32)
>
> Fixes: c312b0df3b13 ("drm/bridge: ti-sn65dsi86: Implement bridge connector 
> operations for DP")
> Cc: Max Krummenacher 
> Signed-off-by: Jayesh Choudhary 
> ---
>
> v1 patch link which was sent as RFC:
> 
>
> Changelog v1->v2:
> - Drop additional property in bindings and use conditional.
> - Instead of register read for HPD state, use dpcd read which returns 0
>   for success and error codes for no connection
> - Add relevant history for the required change in commit message
> - Drop RFC subject-prefix in v2 as v2 is in better state after discussion
>   in v1 and Max's mail thread
> - Add "Cc:" tag
>
> This approach does not make suspend/resume no-op and no additional
> delay needs to be added in the detect hook which causes frame drops.
>
> Here, I am adding conditional to HPD_DISABLE bit even when we are
> not using the register read to get HPD state. This is to prevent
> unnecessary register updates in every resume call.
> (It was adding to latency and leading to ~2-3 frame drop every 10 sec)
>
> Tested and verified on TI's J784S4-EVM platform:
> - Display comes up
> - Detect utility works with a couple of seconds latency.
>   But I guess without interrupt support, this is acceptable.
> - No frame-drop observed
>
> Discussion thread for Max's patch:
> 
>
>  drivers/gpu/drm/bridge/ti-sn65dsi86.c | 17 ++---
>  1 file changed, 10 insertions(+), 7 deletions(-)

Sorry for the delay in responding. Things got a little crazy over the
last few weeks.


> diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c 
> b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> index 60224f476e1d..9489e78b6da3 100644
> --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> @@ -352,8 +352,10 @@ static void ti_sn65dsi86_enable_comms(struct 
> ti_sn65dsi86 *pdata,
>  * change this to be conditional on someone specifying that HPD should
>  * be used.
>  */
> -   regmap_update_bits(pdata->regmap, SN_HPD_DISABLE_REG, HPD_DISABLE,
> -  HPD_DISABLE);
> +
> +   if (pdata->bridge.type == DRM_MODE_CONNECTOR_eDP)
> +   regmap_update_bits(pdata->regmap, SN_HPD_DISABLE_REG, 
> HPD_DISABLE,
> +  HPD_DISABLE);

Given your an Max's testing, I'm totally on-board with the above.

>
> pdata->comms_enabled = true;
>
> @@ -1194,13 +1196,14 @@ static enum drm_connector_status 
> ti_sn_bridge_detect(struct drm_bridge *bridge)
>  {
> struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
> int val = 0;
> +   u8 link_status[DP_LINK_STATUS_SIZE];
>
> -   pm_runtime_get_sync(pdata->dev);
> -   regmap_read(pdata->regmap, SN_HPD_DISABLE_REG, &val);
> -   pm_runtime_put_autosuspend(pdata->dev);
> +   val = drm_dp_dpcd_read_link_status(&pdata->aux, link_status);
>
> -   return val & HPD_DEBOUNCED_STATE ? connector_status_connected
> -: connector_status_disconnected;
> +   if (val < 0)
> +   return connector_status_disconnected;
> +   else
> +   return connector_status_connected;

I'd really rather not do this. It took me a little while to realize
why this was working and also not being slow like your 400ms delay
was. I believe that each time you do the AUX transfer it grabs a
pm_runtime reference and then puts it with "autosuspend". Then you're
relying on the fact that detect is called often enough so that the
autosuspend doesn't actually hit so the next time your function runs
then it's fast. Is that accurate?

I'd rather see something like this in the bridge's probe (untested)

  if (pdata->bridge.type == DRM_MODE_CONNECT

Re: [PATCH 1/2] drm: rcar-du: rzg2l_mipi_dsi: Implement host transfers

2025-05-21 Thread Hugo Villeneuve
Hi Biju,

On Wed, 21 May 2025 07:43:08 +
Biju Das  wrote:

> Hi Hugo,
> 
> Thanks for the patch.
> 
> For some reason, your cover letter is not showing link to this patch
> [1] https://lore.kernel.org/all/20250520164034.3453315-1-h...@hugovil.com/

My server had problems, and only sent the cover letter, forcing me to
manually send the two remaining patches thinking it would be ok :)

> 
> > -Original Message-
> > From: Hugo Villeneuve 
> > Sent: 20 May 2025 18:11
> > Subject: [PATCH 1/2] drm: rcar-du: rzg2l_mipi_dsi: Implement host transfers
> 
> rcar-du->rz-du

Yes, and other commits use "drm: renesas: rz-du:", so I will change it
to this prefix.


> > From: Hugo Villeneuve 
> > 
> > Add support for sending MIPI DSI command packets from the host to a 
> > peripheral. This is required for
> > panels that need configuration before they accept video data.
> > 
> > Based on Renesas Linux kernel v5.10 repos [1].
> 
> > 
> > Link: https://github.com/renesas-rz/rz_linux-cip.git
> > Cc: Biju Das 
> > Cc: Chris Brandt 
> > Signed-off-by: Hugo Villeneuve 
> > ---
> >  .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c| 174 ++
> >  .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  56 ++
> >  2 files changed, 230 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c 
> > b/drivers/gpu/drm/renesas/rz-
> > du/rzg2l_mipi_dsi.c
> > index dc6ab012cdb69..77d3a31ff8e35 100644
> > --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > @@ -6,6 +6,7 @@
> >   */
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -23,9 +24,12 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> > 
> >  #include "rzg2l_mipi_dsi_regs.h"
> > 
> > +#define RZG2L_DCS_BUF_SIZE 128 /* Maximum DCS buffer size in external 
> > memory. */
> > +
> >  struct rzg2l_mipi_dsi {
> > struct device *dev;
> > void __iomem *mmio;
> > @@ -44,6 +48,10 @@ struct rzg2l_mipi_dsi {
> > unsigned int num_data_lanes;
> > unsigned int lanes;
> > unsigned long mode_flags;
> > +
> > +   /* DCS buffer pointers when using external memory. */
> > +   dma_addr_t dcs_buf_phys;
> > +   u8 *dcs_buf_virt;
> >  };
> > 
> >  static inline struct rzg2l_mipi_dsi *
> > @@ -651,9 +659,168 @@ static int rzg2l_mipi_dsi_host_detach(struct 
> > mipi_dsi_host *host,
> > return 0;
> >  }
> > 
> > +static ssize_t rzg2l_mipi_dsi_read_response(struct rzg2l_mipi_dsi *dsi,
> > +   const struct mipi_dsi_msg *msg) {
> > +   u8 *msg_rx = msg->rx_buf;
> > +   u16 size;
> > +   u8 datatype;
> > +   u32 result;
> 
> Please arrange the variables in reverse xmas tree fashion.

Ok.

  
> > +
> > +   result = rzg2l_mipi_dsi_link_read(dsi, RXRSS0R);
> > +   if (result & RXRSS0R_RXPKTDFAIL) {
> > +   dev_err(dsi->dev, "packet rx data did not save correctly\n");
> > +   return -EPROTO;
> > +   }
> > +
> > +   if (result & RXRSS0R_RXFAIL) {
> > +   dev_err(dsi->dev, "packet rx failure\n");
> > +   return -EPROTO;
> > +   }
> > +
> > +   if (!(result & RXRSS0R_RXSUC))
> > +   return -EPROTO;
> > +
> > +   datatype = FIELD_GET(RXRSS0R_DT, result);
> > +
> > +   switch (datatype) {
> > +   case 0:
> > +   dev_dbg(dsi->dev, "ACK\n");
> > +   return 0;
> > +   case MIPI_DSI_RX_END_OF_TRANSMISSION:
> > +   dev_dbg(dsi->dev, "EoTp\n");
> > +   return 0;
> > +   case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
> > +   dev_dbg(dsi->dev, "Acknowledge and error report: $%02x%02x\n",
> > +   (u8)FIELD_GET(RXRSS0R_DATA1, result),
> > +   (u8)FIELD_GET(RXRSS0R_DATA0, result));
> > +   return 0;
> > +   case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
> > +   case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
> > +   msg_rx[0] = FIELD_GET(RXRSS0R_DATA0, result);
> > +   return 1;
> > +   case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
> > +   case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
> > +   msg_rx[0] = FIELD_GET(RXRSS0R_DATA0, result);
> > +   msg_rx[1] = FIELD_GET(RXRSS0R_DATA1, result);
> > +   return 2;
> > +   case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
> > +   case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
> > +   size = FIELD_GET(RXRSS0R_WC, result);
> > +
> > +   if (size > msg->rx_len) {
> > +   dev_err(dsi->dev, "rx buffer too small");
> > +   return -ENOSPC;
> > +   }
> > +
> > +   memcpy(msg_rx, dsi->dcs_buf_virt, size);
> > +   return size;
> > +   default:
> > +   dev_err(dsi->dev, "unhandled response type: %02x\n", datatype);
> > +   return -EPROTO;
> > +   }
> > +}
> > +
> > +static ssize_t rzg2l_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
> > +   const struct mipi_dsi_msg *msg) {
> > +   struct r

[PATCH v2 09/12] rust: drm: gem: Introduce OwnedSGTable

2025-05-21 Thread Lyude Paul
Currently we expose the ability to retrieve an SGTable for an shmem gem
object using gem::shmem::Objectsg_table(). However, this only gives us a
borrowed reference. This being said - retrieving an SGTable is a fallible
operation, and as such it's reasonable that a driver may want to hold
onto an SGTable for longer then a reference would allow in order to avoid
having to deal with fallibility every time they want to access the SGTable.
One such driver with this usecase is the Asahi driver.

So to support this, let's introduce OwnedSGTable - which both holds a
pointer to the SGTable and a reference to its respective GEM object in
order to keep the GEM object alive for as long as the OwnedSGTable. The
type can be used identically to a normal SGTable.

Signed-off-by: Lyude Paul 
---
 rust/kernel/drm/gem/shmem.rs | 29 +
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs
index c38fca715429e..bff038df93334 100644
--- a/rust/kernel/drm/gem/shmem.rs
+++ b/rust/kernel/drm/gem/shmem.rs
@@ -20,7 +20,7 @@
 prelude::*,
 types::{ARef, Opaque},
 container_of,
-scatterlist,
+scatterlist::SGTable,
 };
 use core::{
 mem::MaybeUninit,
@@ -172,23 +172,36 @@ extern "C" fn free_callback(obj: *mut 
bindings::drm_gem_object) {
 let _ = unsafe { KBox::from_raw(this) };
 }
 
-/// Creates (if necessary) and returns a scatter-gather table of DMA pages 
for this object.
+/// Creates (if necessary) and returns an immutable reference to a 
scatter-gather table of DMA
+/// pages for this object.
 ///
 /// This will pin the object in memory.
-pub fn sg_table(&self) -> Result> {
+#[inline]
+pub fn sg_table(&self) -> Result<&SGTable> {
 // SAFETY:
 // - drm_gem_shmem_get_pages_sgt is thread-safe.
 // - drm_gem_shmem_get_pages_sgt returns either a valid pointer to a 
scatterlist, or an
 //   error pointer.
 let sgt = from_err_ptr(unsafe { 
bindings::drm_gem_shmem_get_pages_sgt(self.as_shmem()) })?;
 
-Ok(SGTable {
-// SAFETY: We checked that `sgt` is not an error pointer, so it 
must be a valid pointer
-// to a scatterlist.
-sgt: NonNull::from(unsafe { scatterlist::SGTable::as_ref(sgt) }),
+// SAFETY: We checked above that `sgt` is not an error pointer, so it 
must be a valid
+// pointer to a scatterlist
+Ok(unsafe { SGTable::as_ref(sgt) })
+}
+
+/// Creates (if necessary) and returns an owned scatter-gather table of 
DMA pages for this
+/// object.
+///
+/// This is the same as [`sg_table`](Self::sg_table), except that it 
instead returns a
+/// [`OwnedSGTable`] which holds a reference to the associated gem object.
+///
+/// This will pin the object in memory.
+pub fn owned_sg_table(&self) -> Result> {
+Ok(OwnedSGTable {
+sgt: self.sg_table()?.into(),
 // INVARIANT: We take an owned refcount to `self` here, ensuring 
that `sgt` remains
 // valid for as long as this `OwnedSGTable`.
-_owner: self.into()
+_owner: self.into(),
 })
 }
 
-- 
2.49.0



Re: [PATCH] drm/panel-edp: Add KDC KD116N3730A05

2025-05-21 Thread Doug Anderson
Hi,

On Wed, May 21, 2025 at 2:37 AM Langyan Ye
 wrote:
>
> Add support for the KDC KD116N3730A05, pleace the EDID here for
> subsequent reference.
>
> 00 ff ff ff ff ff ff 00 2c 83 20 12 00 00 00 00
> 30 22 01 04 95 1a 0e 78 03 3a 75 9b 5d 5b 96 28
> 19 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01
> 01 01 01 01 01 01 09 1e 56 dc 50 00 28 30 30 20
> 36 00 00 90 10 00 00 1a 00 00 00 00 00 00 00 00
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fe
> 00 4b 44 31 31 36 4e 33 37 33 30 41 30 35 00 e2
>
> Signed-off-by: Langyan Ye 
> ---
>  drivers/gpu/drm/panel/panel-edp.c | 1 +
>  1 file changed, 1 insertion(+)

Reviewed-by: Douglas Anderson 

Pushed to drm-misc-next:

[1/1] drm/panel-edp: Add KDC KD116N3730A05
  commit: a3436f63aa4f93b043a970cc72a196a501191ecc


[PATCH] drm/panel-edp: Clarify the `prepare_to_enable` description in comments

2025-05-21 Thread Douglas Anderson
It's unclear why I originally wrote in the description of
`prepare_to_enable` that "This is not specified in a standard way on
eDP timing diagrams" and then also wrote "It is effectively the time
from HPD going high till you can turn on the backlight." It seems
pretty clear that it's (T4+T5+T6+T8)-min. Either I was confused when I
wrote this or I was looking at some strange panel datasheet that I can
no longer find.

Update the description of the field so it's easier for people to fill
this in. Couch the description with "usually" in case there really was
some weird datasheet where things were specified in a different way.

Signed-off-by: Douglas Anderson 
---

 drivers/gpu/drm/panel/panel-edp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/panel/panel-edp.c 
b/drivers/gpu/drm/panel/panel-edp.c
index 9adbe0f11421..74f5f9006a5b 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -113,7 +113,7 @@ struct panel_delay {
 * // do fixed enable delay
 * // enforce prepare_to_enable min time
 *
-* This is not specified in a standard way on eDP timing diagrams.
+* This is usually (T4+T5+T6+T8)-min on eDP timing diagrams.
 * It is effectively the time from HPD going high till you can
 * turn on the backlight.
 */
-- 
2.49.0.1151.ga128411c76-goog



[PATCH] drm/xe: don't store the xe device pointer inside xe_ttm_tt

2025-05-21 Thread Dave Airlie
From: Dave Airlie 

This device pointer is nearly always available without storing
an extra copy for each tt in the system.

Just noticed this while reading over the xe shrinker code.

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/xe/tests/xe_bo.c |  4 +--
 drivers/gpu/drm/xe/xe_bo.c   | 59 
 2 files changed, 32 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/xe/tests/xe_bo.c b/drivers/gpu/drm/xe/tests/xe_bo.c
index 378dcd0fb414..77ca1ab527ec 100644
--- a/drivers/gpu/drm/xe/tests/xe_bo.c
+++ b/drivers/gpu/drm/xe/tests/xe_bo.c
@@ -514,9 +514,9 @@ static int shrink_test_run_device(struct xe_device *xe)
 * other way around, they may not be subject to swapping...
 */
if (alloced < purgeable) {
-   xe_ttm_tt_account_subtract(&xe_tt->ttm);
+   xe_ttm_tt_account_subtract(xe, &xe_tt->ttm);
xe_tt->purgeable = true;
-   xe_ttm_tt_account_add(&xe_tt->ttm);
+   xe_ttm_tt_account_add(xe, &xe_tt->ttm);
bo->ttm.priority = 0;
spin_lock(&bo->ttm.bdev->lru_lock);
ttm_bo_move_to_lru_tail(&bo->ttm);
diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index d99d91fe8aa9..4074e6f64fd0 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -336,15 +336,13 @@ static void xe_evict_flags(struct ttm_buffer_object *tbo,
 /* struct xe_ttm_tt - Subclassed ttm_tt for xe */
 struct xe_ttm_tt {
struct ttm_tt ttm;
-   /** @xe - The xe device */
-   struct xe_device *xe;
struct sg_table sgt;
struct sg_table *sg;
/** @purgeable: Whether the content of the pages of @ttm is purgeable. 
*/
bool purgeable;
 };
 
-static int xe_tt_map_sg(struct ttm_tt *tt)
+static int xe_tt_map_sg(struct xe_device *xe, struct ttm_tt *tt)
 {
struct xe_ttm_tt *xe_tt = container_of(tt, struct xe_ttm_tt, ttm);
unsigned long num_pages = tt->num_pages;
@@ -359,13 +357,13 @@ static int xe_tt_map_sg(struct ttm_tt *tt)
ret = sg_alloc_table_from_pages_segment(&xe_tt->sgt, tt->pages,
num_pages, 0,
(u64)num_pages << PAGE_SHIFT,
-   
xe_sg_segment_size(xe_tt->xe->drm.dev),
+   xe_sg_segment_size(xe->drm.dev),
GFP_KERNEL);
if (ret)
return ret;
 
xe_tt->sg = &xe_tt->sgt;
-   ret = dma_map_sgtable(xe_tt->xe->drm.dev, xe_tt->sg, DMA_BIDIRECTIONAL,
+   ret = dma_map_sgtable(xe->drm.dev, xe_tt->sg, DMA_BIDIRECTIONAL,
  DMA_ATTR_SKIP_CPU_SYNC);
if (ret) {
sg_free_table(xe_tt->sg);
@@ -376,12 +374,12 @@ static int xe_tt_map_sg(struct ttm_tt *tt)
return 0;
 }
 
-static void xe_tt_unmap_sg(struct ttm_tt *tt)
+static void xe_tt_unmap_sg(struct xe_device *xe, struct ttm_tt *tt)
 {
struct xe_ttm_tt *xe_tt = container_of(tt, struct xe_ttm_tt, ttm);
 
if (xe_tt->sg) {
-   dma_unmap_sgtable(xe_tt->xe->drm.dev, xe_tt->sg,
+   dma_unmap_sgtable(xe->drm.dev, xe_tt->sg,
  DMA_BIDIRECTIONAL, 0);
sg_free_table(xe_tt->sg);
xe_tt->sg = NULL;
@@ -400,24 +398,24 @@ struct sg_table *xe_bo_sg(struct xe_bo *bo)
  * Account ttm pages against the device shrinker's shrinkable and
  * purgeable counts.
  */
-static void xe_ttm_tt_account_add(struct ttm_tt *tt)
+static void xe_ttm_tt_account_add(struct xe_device *xe, struct ttm_tt *tt)
 {
struct xe_ttm_tt *xe_tt = container_of(tt, struct xe_ttm_tt, ttm);
 
if (xe_tt->purgeable)
-   xe_shrinker_mod_pages(xe_tt->xe->mem.shrinker, 0, 
tt->num_pages);
+   xe_shrinker_mod_pages(xe->mem.shrinker, 0, tt->num_pages);
else
-   xe_shrinker_mod_pages(xe_tt->xe->mem.shrinker, tt->num_pages, 
0);
+   xe_shrinker_mod_pages(xe->mem.shrinker, tt->num_pages, 0);
 }
 
-static void xe_ttm_tt_account_subtract(struct ttm_tt *tt)
+static void xe_ttm_tt_account_subtract(struct xe_device *xe, struct ttm_tt *tt)
 {
struct xe_ttm_tt *xe_tt = container_of(tt, struct xe_ttm_tt, ttm);
 
if (xe_tt->purgeable)
-   xe_shrinker_mod_pages(xe_tt->xe->mem.shrinker, 0, 
-(long)tt->num_pages);
+   xe_shrinker_mod_pages(xe->mem.shrinker, 0, 
-(long)tt->num_pages);
else
-   xe_shrinker_mod_pages(xe_tt->xe->mem.shrinker, 
-(long)tt->num_pages, 0);
+   xe_shrinker_mod_pages(xe->mem.shrinker, -(long)tt->num_pages, 
0);
 }
 
 static struct ttm_tt *xe_ttm_tt_create(struct ttm_buffer_object *ttm_bo,
@@ -436,7 +434,6 @@ static struct ttm_tt *xe_ttm_tt_create

Re: [PATCH V9 00/43] Color Pipeline API w/ VKMS

2025-05-21 Thread Harry Wentland



On 2025-05-17 07:51, Xaver Hugl wrote:
> Am Do., 15. Mai 2025 um 22:00 Uhr schrieb Leandro Ribeiro
> :
>>
>>
>>
>> On 5/15/25 15:39, Daniel Stone wrote:
>>> Hi,
>>>
>>> On Thu, 15 May 2025 at 19:02, Harry Wentland  wrote:
 On 2025-05-15 13:19, Daniel Stone wrote:
> Yeah, the Weston patches are marching on. We've still been doing a
> little bit of cleanup and prep work in the background to land them,
> but we also can't land them until the kernel lands. None of that work
> is material to the uAPI though: as said previously, the uAPI looks
> completely solid and it's something we can definitely beneficially use
> in Weston. (Even if we do need the obvious follow-ons for
> post-blending as well ...)

 We can't merge kernel uAPI without canonical userspace that uses it.
 To move forward we'll need a userspace to at least publish a branch
 that shows the use of this new uAPI.

 Do you have a public branch for the Weston work for this?
>>>
>>> Yeah, https://gitlab.freedesktop.org/wayland/weston/-/merge_requests/1702
>>> has been around for a little while now. There are some driver bugs
>>> that Leandro commented on, but they don't seem material to the uAPI as
>>> such?
>>
>> Hello,
>>
>> Yes, there's nothing related to the API that is blocking us. It seemed
>> very flexible and easy to use. The bugs that I've spotted are probably
>> internal to AMD driver.
>>
>> I'd say that the Weston patches are converging nicely, we just need time
>> to get them fully reviewed. We had a few preparation MR's to land
>> before !1702, and now there's only one left (!1617).
> 
> I also updated the KWin MR
> (https://invent.kde.org/plasma/kwin/-/merge_requests/6600), it can now
> use all the available properties and I think it's ready. I found two
> issues with the kernel patches though:
> - while attempting to set COLOR_ENCODING and COLOR_RANGE results in
> the atomic commit being rejected, the existing values still get
> applied if you use YCbCr-type buffers. I would've expected the color
> pipeline to operate on the YUV values in that case - and leave
> conversion to RGB up to the compositor adding the relevant matrix to
> the pipeline

AMD HW always operates on RGB values, so there'll always be an
implicit conversion of YCbCr-type buffers to RGB. What we should
do is reject YCbCr-type buffers with the color pipeline until we
implement support for COLOR_ENCODING and COLOR_RANGE as a new
CSC colorop.

> - the interpolation mode drm properties for 1D and 3D LUTs are
> immutable, I think they shouldn't be - to make it less annoying if in
> the future we decide to add modes that userspace can set
> 

Makes sense to me.

Harry

> Other than that, I agree that it's ready to go.
> 
>> Thanks,
>> Leandro
>>>
>>> Cheers,
>>> Daniel
>>



Re: [PATCH v2 2/2] drm/bridge: fsl-ldb: simplify device_node error handling

2025-05-21 Thread Laurent Pinchart
Hi Marco,

Thank you for the patch.

On Thu, May 15, 2025 at 07:36:43PM +0200, Marco Felsch wrote:
> Make use of __free(device_node) to simplify the of_node_put() error
> handling paths. No functional changes.
> 
> Signed-off-by: Marco Felsch 

Reviewed-by: Laurent Pinchart 

> ---
> Changelog:
> v2:
>  - drop __free() from panel_node
> 
>  drivers/gpu/drm/bridge/fsl-ldb.c | 22 --
>  1 file changed, 8 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/fsl-ldb.c 
> b/drivers/gpu/drm/bridge/fsl-ldb.c
> index 6916cdb15372..f80c68617ce5 100644
> --- a/drivers/gpu/drm/bridge/fsl-ldb.c
> +++ b/drivers/gpu/drm/bridge/fsl-ldb.c
> @@ -293,7 +293,8 @@ static int fsl_ldb_probe(struct platform_device *pdev)
>  {
>   struct device *dev = &pdev->dev;
>   struct device_node *panel_node;
> - struct device_node *remote1, *remote2;
> + struct device_node *remote1 __free(device_node) = NULL;
> + struct device_node *remote2 __free(device_node) = NULL;
>   struct drm_panel *panel;
>   struct fsl_ldb *fsl_ldb;
>   int dual_link;
> @@ -325,21 +326,16 @@ static int fsl_ldb_probe(struct platform_device *pdev)
>   remote2 = of_graph_get_remote_node(dev->of_node, 2, 0);
>   fsl_ldb->ch0_enabled = (remote1 != NULL);
>   fsl_ldb->ch1_enabled = (remote2 != NULL);
> - panel_node = of_node_get(remote1 ? remote1 : remote2);
> - of_node_put(remote1);
> - of_node_put(remote2);
> + panel_node = remote1 ? remote1 : remote2;
>  
> - if (!fsl_ldb->ch0_enabled && !fsl_ldb->ch1_enabled) {
> - of_node_put(panel_node);
> + if (!fsl_ldb->ch0_enabled && !fsl_ldb->ch1_enabled)
>   return dev_err_probe(dev, -ENXIO, "No panel node found");
> - }
>  
>   dev_dbg(dev, "Using %s\n",
>   fsl_ldb_is_dual(fsl_ldb) ? "dual-link mode" :
>   fsl_ldb->ch0_enabled ? "channel 0" : "channel 1");
>  
>   panel = of_drm_find_panel(panel_node);
> - of_node_put(panel_node);
>   if (IS_ERR(panel))
>   return dev_err_probe(dev, PTR_ERR(panel), "drm panel not 
> found\n");
>  
> @@ -349,14 +345,12 @@ static int fsl_ldb_probe(struct platform_device *pdev)
>"drm panel-bridge add failed\n");
>  
>   if (fsl_ldb_is_dual(fsl_ldb)) {
> - struct device_node *port1, *port2;
> + struct device_node *port1 __free(device_node) =
> + of_graph_get_port_by_id(dev->of_node, 1);
> + struct device_node *port2 __free(device_node) =
> + of_graph_get_port_by_id(dev->of_node, 2);
>  
> - port1 = of_graph_get_port_by_id(dev->of_node, 1);
> - port2 = of_graph_get_port_by_id(dev->of_node, 2);
>   dual_link = drm_of_lvds_get_dual_link_pixel_order(port1, port2);
> - of_node_put(port1);
> - of_node_put(port2);
> -
>   if (dual_link < 0)
>   return dev_err_probe(dev, dual_link,
>"Error getting dual link 
> configuration\n");

-- 
Regards,

Laurent Pinchart


Re: [PATCH v10 03/10] mtd: intel-dg: implement access functions

2025-05-21 Thread Raag Jadav
On Thu, May 15, 2025 at 04:33:38PM +0300, Alexander Usyskin wrote:
> Implement read(), erase() and write() functions.

...

> +__maybe_unused
> +static ssize_t idg_write(struct intel_dg_nvm *nvm, u8 region,
> +  loff_t to, size_t len, const unsigned char *buf)
> +{
> + size_t i;
> + size_t len8;
> + size_t len4;
> + size_t to4;
> + size_t to_shift;
> + size_t len_s = len;
> + ssize_t ret;
> +
> + idg_nvm_set_region_id(nvm, region);
> +
> + to4 = ALIGN_DOWN(to, sizeof(u32));
> + to_shift = min(sizeof(u32) - ((size_t)to - to4), len);
> + if (to - to4) {
> + ret = idg_nvm_rewrite_partial(nvm, to4, to - to4, to_shift, 
> (uint32_t *)&buf[0]);

Forgot to add, you're using both uint32_t and u32.
Perhaps make it consistent?

> + if (ret < 0)
> + return ret;
> +
> + buf += to_shift;
> + to += to_shift;
> + len_s -= to_shift;
> + }
> +
> + len8 = ALIGN_DOWN(len_s, sizeof(u64));
> + for (i = 0; i < len8; i += sizeof(u64)) {
> + u64 data;
> +
> + memcpy(&data, &buf[i], sizeof(u64));
> + idg_nvm_write64(nvm, to + i, data);
> + if (idg_nvm_error(nvm))
> + return -EIO;
> + }
> +
> + len4 = len_s - len8;
> + if (len4 >= sizeof(u32)) {
> + u32 data;
> +
> + memcpy(&data, &buf[i], sizeof(u32));
> + idg_nvm_write32(nvm, to + i, data);
> + if (idg_nvm_error(nvm))
> + return -EIO;
> + i += sizeof(u32);
> + len4 -= sizeof(u32);
> + }
> +
> + if (len4 > 0) {
> + ret = idg_nvm_rewrite_partial(nvm, to + i, 0, len4, (uint32_t 
> *)&buf[i]);

Ditto (and also in all other places if any).

> + if (ret < 0)
> + return ret;
> + }
> +
> + return len;
> +}

Raag


[PATCH RESEND] drm: Use strscpy() instead of strscpy_pad()

2025-05-21 Thread Thorsten Blum
kzalloc() already zero-initializes the destination buffers, making
strscpy() sufficient for safely copying the names. The additional
NUL-padding performed by strscpy_pad() is unnecessary.

If the destination buffer has a fixed length, strscpy() automatically
determines its size using sizeof() when the argument is omitted. This
makes the explicit size arguments unnecessary.

No functional changes intended.

Signed-off-by: Thorsten Blum 
---
 drivers/gpu/drm/drm_property.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
index 596272149a35..47f2891f3f06 100644
--- a/drivers/gpu/drm/drm_property.c
+++ b/drivers/gpu/drm/drm_property.c
@@ -128,7 +128,7 @@ struct drm_property *drm_property_create(struct drm_device 
*dev,
property->num_values = num_values;
INIT_LIST_HEAD(&property->enum_list);
 
-   strscpy_pad(property->name, name, DRM_PROP_NAME_LEN);
+   strscpy(property->name, name);
 
list_add_tail(&property->head, &dev->mode_config.property_list);
 
@@ -421,7 +421,7 @@ int drm_property_add_enum(struct drm_property *property,
if (!prop_enum)
return -ENOMEM;
 
-   strscpy_pad(prop_enum->name, name, DRM_PROP_NAME_LEN);
+   strscpy(prop_enum->name, name);
prop_enum->value = value;
 
property->values[index] = value;
-- 
2.49.0



Re: [PATCH v5 05/12] drm: renesas: rz-du: mipi_dsi: Use VCLK for HSFREQ calculation

2025-05-21 Thread Lad, Prabhakar
Hi Geert,

Thank you for the review.

On Tue, May 20, 2025 at 3:55 PM Geert Uytterhoeven  wrote:
>
> Hi Prabhakar,
>
> On Mon, 12 May 2025 at 20:23, Prabhakar  wrote:
> > From: Lad Prabhakar 
> >
> > Update the RZ/G2L MIPI DSI driver to calculate HSFREQ using the actual
> > VCLK rate instead of the mode clock. The relationship between HSCLK and
> > VCLK is:
> >
> > vclk * bpp <= hsclk * 8 * lanes
> >
> > Retrieve the VCLK rate using `clk_get_rate(dsi->vclk)`, ensuring that
> > HSFREQ accurately reflects the clock rate set in hardware, leading to
> > better precision in data transmission.
> >
> > Additionally, use `DIV_ROUND_CLOSEST_ULL` for a more precise division
> > when computing `hsfreq`. Also, update unit conversions to use correct
> > scaling factors for better clarity and correctness.
> >
> > Since `clk_get_rate()` returns the clock rate in Hz, update the HSFREQ
> > threshold comparisons to use Hz instead of kHz to ensure correct behavior.
> >
> > Co-developed-by: Fabrizio Castro 
> > Signed-off-by: Fabrizio Castro 
> > Signed-off-by: Lad Prabhakar 
> > Reviewed-by: Biju Das 
> > ---
> > v4->v5:
> > - Added dev_info() to print the VCLK rate if it doesn't match the
> >   requested rate.
> > - Added Reviewed-by tag from Biju
> >
> > v3->v4:
> > - Used MILLI instead of KILO
>
> Thanks for the update!
>
> > --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
>
> > @@ -269,6 +271,12 @@ static int rzg2l_mipi_dsi_startup(struct 
> > rzg2l_mipi_dsi *dsi,
> > u32 golpbkt;
> > int ret;
> >
> > +   ret = pm_runtime_resume_and_get(dsi->dev);
> > +   if (ret < 0)
> > +   return ret;
> > +
> > +   clk_set_rate(dsi->vclk, mode->clock * MILLI);
>
> drm_display_mode.clock is in kHz, so s/MILLI/KILO/
>
Agreed, I will update it to use KILO (and below).

Cheers,
Prabhakar

> > +
> > /*
> >  * Relationship between hsclk and vclk must follow
> >  * vclk * bpp = hsclk * 8 * lanes
> > @@ -280,13 +288,11 @@ static int rzg2l_mipi_dsi_startup(struct 
> > rzg2l_mipi_dsi *dsi,
> >  * hsclk(bit) = hsclk(byte) * 8 = hsfreq
> >  */
> > bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
> > -   hsfreq = (mode->clock * bpp) / dsi->lanes;
> > -
> > -   ret = pm_runtime_resume_and_get(dsi->dev);
> > -   if (ret < 0)
> > -   return ret;
> > -
> > -   clk_set_rate(dsi->vclk, mode->clock * 1000);
> > +   vclk_rate = clk_get_rate(dsi->vclk);
> > +   if (vclk_rate != mode->clock * MILLI)
> > +   dev_info(dsi->dev, "Requested vclk rate %lu, actual %lu 
> > mismatch\n",
> > +mode->clock * MILLI, vclk_rate);
>
> Likewise.
>
> > +   hsfreq = DIV_ROUND_CLOSEST_ULL(vclk_rate * bpp, dsi->lanes);
> >
> > ret = rzg2l_mipi_dsi_dphy_init(dsi, hsfreq);
> > if (ret < 0)
>
> Gr{oetje,eeting}s,
>
> Geert
>
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- 
> ge...@linux-m68k.org
>
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like 
> that.
> -- Linus Torvalds


RE: [PATCH v5 05/12] drm: renesas: rz-du: mipi_dsi: Use VCLK for HSFREQ calculation

2025-05-21 Thread Biju Das


> -Original Message-
> From: Lad, Prabhakar 
> Sent: Wednesday, May 21, 2025 2:05 PM
> Subject: Re: [PATCH v5 05/12] drm: renesas: rz-du: mipi_dsi: Use VCLK for
> HSFREQ calculation
> 
> Hi Laurent,
> 
> Thank you for the review.
> 
> On Tue, May 20, 2025 at 3:16 PM Laurent Pinchart
>  wrote:
> >
> > Hi Prabhakar,
> >
> > On Mon, May 12, 2025 at 07:23:23PM +0100, Prabhakar wrote:
> > > From: Lad Prabhakar 
> > >
> > > Update the RZ/G2L MIPI DSI driver to calculate HSFREQ using the
> > > actual VCLK rate instead of the mode clock. The relationship between
> > > HSCLK and VCLK is:
> > >
> > > vclk * bpp <= hsclk * 8 * lanes
> > >
> > > Retrieve the VCLK rate using `clk_get_rate(dsi->vclk)`, ensuring
> > > that HSFREQ accurately reflects the clock rate set in hardware,
> > > leading to better precision in data transmission.
> > >
> > > Additionally, use `DIV_ROUND_CLOSEST_ULL` for a more precise
> > > division when computing `hsfreq`. Also, update unit conversions to
> > > use correct scaling factors for better clarity and correctness.
> > >
> > > Since `clk_get_rate()` returns the clock rate in Hz, update the
> > > HSFREQ threshold comparisons to use Hz instead of kHz to ensure
> correct behavior.
> > >
> > > Co-developed-by: Fabrizio Castro 
> > > Signed-off-by: Fabrizio Castro 
> > > Signed-off-by: Lad Prabhakar
> > > 
> > > Reviewed-by: Biju Das 
> > > ---
> > > v4->v5:
> > > - Added dev_info() to print the VCLK rate if it doesn't match the
> > >   requested rate.
> > > - Added Reviewed-by tag from Biju
> > >
> > > v3->v4:
> > > - Used MILLI instead of KILO
> > >
> > > v2->v3:
> > > - No changes
> > >
> > > v1->v2:
> > > - No changes
> > > ---
> > >  .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c| 30 +++---
> -
> > >  1 file changed, 18 insertions(+), 12 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > > b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > > index c5f698cd74f1..3f6988303e63 100644
> > > --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > > +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > > @@ -8,6 +8,7 @@
> > >  #include 
> > >  #include 
> > >  #include 
> > > +#include 
> > >  #include 
> > >  #include 
> > >  #include 
> > > @@ -15,6 +16,7 @@
> > >  #include 
> > >  #include 
> > >  #include 
> > > +#include 
> > >
> > >  #include 
> > >  #include 
> > > @@ -199,7 +201,7 @@ static int rzg2l_mipi_dsi_dphy_init(struct
> rzg2l_mipi_dsi *dsi,
> > >   /* All DSI global operation timings are set with recommended
> setting */
> > >   for (i = 0; i < ARRAY_SIZE(rzg2l_mipi_dsi_global_timings); ++i)
> {
> > >   dphy_timings = &rzg2l_mipi_dsi_global_timings[i];
> > > - if (hsfreq <= dphy_timings->hsfreq_max)
> > > + if (hsfreq <= (dphy_timings->hsfreq_max * MILLI))
> >
> > No need for the inner parentheses.
> >
> Agreed, I will drop it.
> 
> > >   break;
> > >   }
> > >
> > > @@ -258,7 +260,7 @@ static void rzg2l_mipi_dsi_dphy_exit(struct
> > > rzg2l_mipi_dsi *dsi)  static int rzg2l_mipi_dsi_startup(struct
> rzg2l_mipi_dsi *dsi,
> > > const struct drm_display_mode *mode)
> > > {
> > > - unsigned long hsfreq;
> > > + unsigned long hsfreq, vclk_rate;
> > >   unsigned int bpp;
> > >   u32 txsetr;
> > >   u32 clstptsetr;
> > > @@ -269,6 +271,12 @@ static int rzg2l_mipi_dsi_startup(struct
> rzg2l_mipi_dsi *dsi,
> > >   u32 golpbkt;
> > >   int ret;
> > >
> > > + ret = pm_runtime_resume_and_get(dsi->dev);
> > > + if (ret < 0)
> > > + return ret;
> > > +
> > > + clk_set_rate(dsi->vclk, mode->clock * MILLI);
> > > +
> > >   /*
> > >* Relationship between hsclk and vclk must follow
> > >* vclk * bpp = hsclk * 8 * lanes @@ -280,13 +288,11 @@ static
> > > int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
> > >* hsclk(bit) = hsclk(byte) * 8 = hsfreq
> > >*/
> > >   bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
> > > - hsfreq = (mode->clock * bpp) / dsi->lanes;
> > > -
> > > - ret = pm_runtime_resume_and_get(dsi->dev);
> > > - if (ret < 0)
> > > - return ret;
> > > -
> > > - clk_set_rate(dsi->vclk, mode->clock * 1000);
> > > + vclk_rate = clk_get_rate(dsi->vclk);
> > > + if (vclk_rate != mode->clock * MILLI)
> > > + dev_info(dsi->dev, "Requested vclk rate %lu, actual %lu
> mismatch\n",
> > > +  mode->clock * MILLI, vclk_rate);
> >
> > There's a high risk that the requested rate won't be achieved exactly.
> > Do we really want to print a non-debug message to the kernel log every
> > time ?
> >
> Actually Biju requested the above.

Yes, I was looking for dev_dbg.

Cheers,
Biju

> 
> > > + hsfreq = DIV_ROUND_CLOSEST_ULL(vclk_rate * bpp, dsi->lanes);
> >
> > I doubt DIV_ROUND_CLOSEST_ULL() will make any difference in practice
> > given that you can't have more than 4 l

Re: [PATCH v6 2/2] i2c: i2c-qcom-geni: Add Block event interrupt support

2025-05-21 Thread Dmitry Baryshkov
On Wed, May 21, 2025 at 03:58:48PM +0530, Jyothi Kumar Seerapu wrote:
> 
> 
> On 5/9/2025 9:31 PM, Dmitry Baryshkov wrote:
> > On 09/05/2025 09:18, Jyothi Kumar Seerapu wrote:
> > > Hi Dimitry, Thanks for providing the review comments.
> > > 
> > > On 5/6/2025 5:16 PM, Dmitry Baryshkov wrote:
> > > > On Tue, May 06, 2025 at 04:48:44PM +0530, Jyothi Kumar Seerapu wrote:
> > > > > The I2C driver gets an interrupt upon transfer completion.
> > > > > When handling multiple messages in a single transfer, this
> > > > > results in N interrupts for N messages, leading to significant
> > > > > software interrupt latency.
> > > > > 
> > > > > To mitigate this latency, utilize Block Event Interrupt (BEI)
> > > > > mechanism. Enabling BEI instructs the hardware to prevent interrupt
> > > > > generation and BEI is disabled when an interrupt is necessary.
> > > > > 
> > > > > Large I2C transfer can be divided into chunks of 8 messages 
> > > > > internally.
> > > > > Interrupts are not expected for the first 7 message completions, only
> > > > > the last message triggers an interrupt, indicating the completion of
> > > > > 8 messages. This BEI mechanism enhances overall transfer efficiency.
> > > > 
> > > > Why do you need this complexity? Is it possible to set the
> > > > DMA_PREP_INTERRUPT flag on the last message in the transfer?
> > > 
> > > If i undertsand correctly, the suggestion is to get the single
> > > intetrrupt for last i2c message only.
> > > 
> > > But With this approach, we can't handle large number of i2c messages
> > > in the transfer.
> > > 
> > > In GPI driver, number of max TREs support is harcoded to 64 (#define
> > > CHAN_TRES   64) and for I2C message, we need Config TRE, GO TRE and
> > > DMA TREs. So, the avilable TREs are not sufficient to handle all the
> > > N messages.
> > 
> > It sounds like a DMA driver issue. In other words, the DMA driver can
> > know that it must issue an interrupt before exausting 64 TREs in order
> > to
> > 
> > > 
> > > Here, the plan is to queue i2c messages (QCOM_I2C_GPI_MAX_NUM_MSGS
> > > or 'num' incase for less messsages), process and unmap/free upon the
> > > interrupt based on QCOM_I2C_GPI_NUM_MSGS_PER_IRQ.
> > 
> > Why? This is some random value which has no connection with CHAN_TREs.
> > Also, what if one of the platforms get a 'liter' GPI which supports less
> > TREs in a single run? Or a super-premium platform which can use 256
> > TREs? Please don't workaround issues from one driver in another one.
> 
> We are trying to utilize the existing CHAN_TRES mentioned in the GPI driver.
> With the following approach, the GPI hardware can process N number of I2C
> messages, thereby improving throughput and transfer efficiency.
> 
> The main design consideration for using the block event interrupt is as
> follows:
> 
> Allow the hardware to process the TREs (I2C messages), while the software
> concurrently prepares the next set of TREs to be submitted to the hardware.
> Once the TREs are processed, they can be freed, enabling the software to
> queue new TREs. This approach enhances overall optimization.
> 
> Please let me know if you have any questions, concerns, or suggestions.

The question was why do you limit that to QCOM_I2C_GPI_NUM_MSGS_PER_IRQ.
What is the reason for that limit, etc. If you think about it, The GENI
/ I2C doesn't impose any limit on the number of messages processed in
one go (if I understand it correctly). Instead the limit comes from the
GPI DMA driver. As such, please don't add extra 'handling' to the I2C
driver. Make GPI DMA driver responsible for saying 'no more for now',
then I2C driver can setup add an interrupt flag and proceed with
submitting next messages, etc.

I really don't see a reason for additional complicated handling in the
geni driver that you've implemented. Maybe I misunderstand something. In
such a case it usually means that you have to explain the design in the
commit message / in-code comments.

-- 
With best wishes
Dmitry


Re: [PATCH v5 10/12] drm: renesas: rz-du: mipi_dsi: Add dphy_late_init() callback for RZ/V2H(P)

2025-05-21 Thread Lad, Prabhakar
Hi Laurent,

Thank you for the review.

On Tue, May 20, 2025 at 3:28 PM Laurent Pinchart
 wrote:
>
> Hi Prabhakar,
>
> Thank you for the patch.
>
> On Mon, May 12, 2025 at 07:23:28PM +0100, Prabhakar wrote:
> > From: Lad Prabhakar 
> >
> > Introduce the `dphy_late_init` callback in `rzg2l_mipi_dsi_hw_info` to
> > allow additional D-PHY register configurations after enabling data and
> > clock lanes. This is required for the RZ/V2H(P) SoC but not for the
> > RZ/G2L SoC.
> >
> > Modify `rzg2l_mipi_dsi_startup()` to invoke `dphy_late_init` if defined,
> > ensuring SoC-specific initialization is performed only when necessary.
> >
> > This change prepares for RZ/V2H(P) SoC support while maintaining
> > compatibility with existing platforms.
> >
> > Co-developed-by: Fabrizio Castro 
> > Signed-off-by: Fabrizio Castro 
> > Signed-off-by: Lad Prabhakar 
> > Reviewed-by: Biju Das 
> > ---
> > v4->v5:
> > - Added Reviewed tag from Biju
> >
> > v3->v4:
> > - No changes
> >
> > v2->v3:
> > - No changes
> >
> > v1->v2:
> > - No changes
> > ---
> >  drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 4 
> >  1 file changed, 4 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c 
> > b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > index 55a1c1b043c8..e1ce21a9ddb3 100644
> > --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > @@ -34,6 +34,7 @@ struct rzg2l_mipi_dsi;
> >
> >  struct rzg2l_mipi_dsi_hw_info {
> >   int (*dphy_init)(struct rzg2l_mipi_dsi *dsi, u64 hsfreq_millihz);
> > + void (*dphy_late_init)(struct rzg2l_mipi_dsi *dsi);
>
> As this is called at startup time I would have called it dphy_startup.
> Up to you.
>
Agreed, I will rename this to dphy_startup_late_init().

Cheers,
Prabhakar

> Reviewed-by: Laurent Pinchart 
>
> >   void (*dphy_exit)(struct rzg2l_mipi_dsi *dsi);
> >   u32 phy_reg_offset;
> >   u32 link_reg_offset;
> > @@ -320,6 +321,9 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi 
> > *dsi,
> >   txsetr = TXSETR_DLEN | TXSETR_NUMLANEUSE(dsi->lanes - 1) | 
> > TXSETR_CLEN;
> >   rzg2l_mipi_dsi_link_write(dsi, TXSETR, txsetr);
> >
> > + if (dsi->info->dphy_late_init)
> > + dsi->info->dphy_late_init(dsi);
> > +
> >   hsfreq = DIV_ROUND_CLOSEST_ULL(hsfreq_millihz, MILLI);
> >   /*
> >* Global timings characteristic depends on high speed Clock Frequency
>
> --
> Regards,
>
> Laurent Pinchart


Re: [PATCH v5 04/12] drm: renesas: rz-du: mipi_dsi: Simplify HSFREQ calculation

2025-05-21 Thread Lad, Prabhakar
Hi Laurent,

Thank you for the review.

On Tue, May 20, 2025 at 3:05 PM Laurent Pinchart
 wrote:
>
> Hi Prabhakar,
>
> Thank you for the patch.
>
> On Mon, May 12, 2025 at 07:23:22PM +0100, Prabhakar wrote:
> > From: Lad Prabhakar 
> >
> > Simplify the high-speed clock frequency (HSFREQ) calculation by removing
> > the redundant multiplication and division by 8. The updated equation:
> >
> > hsfreq = (mode->clock * bpp) / (dsi->lanes);
>
> You can drop the parentheses around the second factor. You can actuall
> drop all prentheses.
>
Agreed, I will drop the parentheses.

> >
> > produces the same result while improving readability and clarity.
> >
> > Additionally, update the comment to clarify the relationship between HS
> > clock bit frequency, HS byte clock frequency, and HSFREQ.
> >
> > Signed-off-by: Lad Prabhakar 
> > Reviewed-by: Biju Das 
> > ---
> > v4->v5:
> > - No changes
> >
> > v3->v4:
> > - No changes
> >
> > v2->v3:
> > - No changes
> >
> > v1->v2:
> > - Added Reviewed-by tag from Biju
> > ---
> >  drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c 
> > b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > index ec8baecb9ba5..c5f698cd74f1 100644
> > --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > @@ -277,10 +277,10 @@ static int rzg2l_mipi_dsi_startup(struct 
> > rzg2l_mipi_dsi *dsi,
> >*   hsclk: DSI HS Byte clock frequency (Hz)
> >*   lanes: number of data lanes
> >*
> > -  * hsclk(bit) = hsclk(byte) * 8
> > +  * hsclk(bit) = hsclk(byte) * 8 = hsfreq
> >*/
> >   bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
> > - hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes);
> > + hsfreq = (mode->clock * bpp) / dsi->lanes;
>
> You can drop the parentheses here too.
>
OK, I'll drop the parentheses.

Cheers,
Prabhakar


Re: [PATCH v4 09/30] drm/msm/dpu: get rid of DPU_CTL_ACTIVE_CFG

2025-05-21 Thread Neil Armstrong

On 20/05/2025 23:29, Dmitry Baryshkov wrote:

On Tue, May 20, 2025 at 09:57:38AM +0200, neil.armstr...@linaro.org wrote:

On 19/05/2025 18:04, Dmitry Baryshkov wrote:

From: Dmitry Baryshkov 

Continue migration to the MDSS-revision based checks and replace
DPU_CTL_ACTIVE_CFG feature bit with the core_major_ver >= 5 check.

Signed-off-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Dmitry Baryshkov 
---
   drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h  | 6 --
   drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h | 6 --
   drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h  | 6 --
   drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_3_sm6150.h  | 6 --
   drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h  | 6 --
   drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h  | 6 --
   drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h  | 3 ---
   drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h  | 1 -
   drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h  | 4 
   drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h | 1 -
   drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h  | 1 -
   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c| 2 +-
   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c| 2 +-
   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 7 ++-
   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c  | 3 +--
   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h  | 1 -
   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c  | 2 +-
   17 files changed, 6 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
index 
a0ba55ab3c894c200225fe48ec6214ae4135d059..25ba5d9bfff2b3f7a5054ae26511d05917f72d8b
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -69,7 +69,7 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
ctl->ops.setup_intf_cfg(ctl, &intf_cfg);
/* setup which pp blk will connect to this intf */
-   if (test_bit(DPU_CTL_ACTIVE_CFG, &ctl->caps->features) && 
phys_enc->hw_intf->ops.bind_pingpong_blk)
+   if (phys_enc->hw_intf->ops.bind_pingpong_blk)


Why did you drop the version test here ?


bind_pingpong_blk is only available since DPU 5.x, the same set of
hardware as the DPU having DPU_CTL_ACTIVE_CFG.



I think it deserves a comment in the code or the commit msg.

Neil



Re: [PATCH v4 03/20] rust: sizes: add constants up to SZ_2G

2025-05-21 Thread Boqun Feng
On Wed, May 21, 2025 at 03:44:58PM +0900, Alexandre Courbot wrote:
> nova-core will need to use SZ_1M, so make the remaining constants
> available.
> 
> Signed-off-by: Alexandre Courbot 

Reviewed-by: Boqun Feng 

Regards,
Boqun

> ---
>  rust/kernel/sizes.rs | 24 
>  1 file changed, 24 insertions(+)
> 
> diff --git a/rust/kernel/sizes.rs b/rust/kernel/sizes.rs
> index 
> 834c343e4170f507821b870e77afd08e2392911f..661e680d9330616478513a19fe2f87f9521516d7
>  100644
> --- a/rust/kernel/sizes.rs
> +++ b/rust/kernel/sizes.rs
> @@ -24,3 +24,27 @@
>  pub const SZ_256K: usize = bindings::SZ_256K as usize;
>  /// 0x0008
>  pub const SZ_512K: usize = bindings::SZ_512K as usize;
> +/// 0x0010
> +pub const SZ_1M: usize = bindings::SZ_1M as usize;
> +/// 0x0020
> +pub const SZ_2M: usize = bindings::SZ_2M as usize;
> +/// 0x0040
> +pub const SZ_4M: usize = bindings::SZ_4M as usize;
> +/// 0x0080
> +pub const SZ_8M: usize = bindings::SZ_8M as usize;
> +/// 0x0100
> +pub const SZ_16M: usize = bindings::SZ_16M as usize;
> +/// 0x0200
> +pub const SZ_32M: usize = bindings::SZ_32M as usize;
> +/// 0x0400
> +pub const SZ_64M: usize = bindings::SZ_64M as usize;
> +/// 0x0800
> +pub const SZ_128M: usize = bindings::SZ_128M as usize;
> +/// 0x1000
> +pub const SZ_256M: usize = bindings::SZ_256M as usize;
> +/// 0x2000
> +pub const SZ_512M: usize = bindings::SZ_512M as usize;
> +/// 0x4000
> +pub const SZ_1G: usize = bindings::SZ_1G as usize;
> +/// 0x8000
> +pub const SZ_2G: usize = bindings::SZ_2G as usize;
> 
> -- 
> 2.49.0
> 


Re: [PATCH v2] drm/panthor: Reset queue slots if termination fails

2025-05-21 Thread Liviu Dudau
On Mon, May 19, 2025 at 03:50:19PM +0100, Ashley Smith wrote:
> This fixes a bug where if we timeout after a suspend and the termination
> fails, due to waiting on a fence that will never be signalled for
> example, we do not resume the group correctly. The fix forces a reset
> for groups that are not terminated correctly.
> 
> Signed-off-by: Ashley Smith 

Reviewed-by: Liviu Dudau 

Best regards,
Liviu

> ---
> Changes in v2:
>  - Fixed syntax error
> ---
>  drivers/gpu/drm/panthor/panthor_sched.c | 11 ++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/panthor/panthor_sched.c 
> b/drivers/gpu/drm/panthor/panthor_sched.c
> index 43ee57728de5..65d8ae3dcac1 100644
> --- a/drivers/gpu/drm/panthor/panthor_sched.c
> +++ b/drivers/gpu/drm/panthor/panthor_sched.c
> @@ -2727,8 +2727,17 @@ void panthor_sched_suspend(struct panthor_device 
> *ptdev)
>* automatically terminate all active groups, so let's
>* force the state to halted here.
>*/
> - if (csg_slot->group->state != 
> PANTHOR_CS_GROUP_TERMINATED)
> + if (csg_slot->group->state != 
> PANTHOR_CS_GROUP_TERMINATED) {
>   csg_slot->group->state = 
> PANTHOR_CS_GROUP_TERMINATED;
> +
> + /* Reset the queue slots manually if the 
> termination
> +  * request failed.
> +  */
> + for (i = 0; i < group->queue_count; i++) {
> + if (group->queues[i])
> + cs_slot_reset_locked(ptdev, 
> csg_id, i);
> + }
> + }
>   slot_mask &= ~BIT(csg_id);
>   }
>   }
> 
> base-commit: 9934ab18051118385c7ea44d8e14175edbe6dc9c
> -- 
> 2.43.0
> 

-- 

| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---
¯\_(ツ)_/¯


[PATCH RESEND] drm/amd/display: Adjust prefix of dcn31_apg construct function name

2025-05-21 Thread Leonardo Gomes
From: Leonardo da Silva Gomes 

Adjust the dcn31_apg construct function name from
'apg31_construct' to 'dcn31_apg_construct'.
This helps the ftrace to detect the file by the function name.

Signed-off-by: Leonardo da Silva Gomes 
Co-developed-by: Derick Frias 
Signed-off-by: Derick Frias 
---
 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c| 2 +-
 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h| 2 +-
 drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c  | 2 +-
 .../gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c| 2 +-
 .../gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c| 2 +-
 .../gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c| 2 +-
 drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c  | 2 +-
 .../gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c| 2 +-
 drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c  | 2 +-
 .../gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c| 2 +-
 drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c  | 2 +-
 .../gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c| 2 +-
 12 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c 
b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c
index 05aac3e444b4..d1ccc9a34b2e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c
@@ -101,7 +101,7 @@ static struct apg_funcs dcn31_apg_funcs = {
.disable_apg= apg31_disable,
 };
 
-void apg31_construct(struct dcn31_apg *apg31,
+void dcn31_apg_construct(struct dcn31_apg *apg31,
struct dc_context *ctx,
uint32_t inst,
const struct dcn31_apg_registers *apg_regs,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h 
b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h
index 1b81f6773c53..54c6b62195c2 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h
@@ -100,7 +100,7 @@ struct dcn31_apg {
const struct dcn31_apg_mask *apg_mask;
 };
 
-void apg31_construct(struct dcn31_apg *apg3,
+void dcn31_apg_construct(struct dcn31_apg *apg3,
struct dc_context *ctx,
uint32_t inst,
const struct dcn31_apg_registers *apg_regs,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c 
b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
index dbfef85f..b3553ae26d7c 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
@@ -1207,7 +1207,7 @@ static struct apg *dcn31_apg_create(
if (!apg31)
return NULL;
 
-   apg31_construct(apg31, ctx, inst,
+   dcn31_apg_construct(apg31, ctx, inst,
&apg_regs[inst],
&apg_shift,
&apg_mask);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c 
b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
index 26becc4cb804..be55a3c36a78 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
@@ -1263,7 +1263,7 @@ static struct apg *dcn31_apg_create(
if (!apg31)
return NULL;
 
-   apg31_construct(apg31, ctx, inst,
+   dcn31_apg_construct(apg31, ctx, inst,
&apg_regs[inst],
&apg_shift,
&apg_mask);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c 
b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
index 6c2bb3f63be1..b9847b4bb0f3 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
@@ -1205,7 +1205,7 @@ static struct apg *dcn31_apg_create(
if (!apg31)
return NULL;
 
-   apg31_construct(apg31, ctx, inst,
+   dcn31_apg_construct(apg31, ctx, inst,
&apg_regs[inst],
&apg_shift,
&apg_mask);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c 
b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
index 568094827212..b6cf2a296ab4 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
@@ -1200,7 +1200,7 @@ static struct apg *dcn31_apg_create(
if (!apg31)
return NULL;
 
-   apg31_construct(apg31, ctx, inst,
+   dcn31_apg_construct(apg31, ctx, inst,
&apg_regs[inst],
&apg_shift,
&apg_mask);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c 
b/drive

[PATCH 2/3] drm/amdgpu: Adding amdgpu CRIU ioctl

2025-05-21 Thread David Francis
amdgpu CRIU requires an amdgpu CRIU ioctl. This ioctl
has a similar interface to the amdkfd CRIU ioctl.

The objects that can be checkpointed and restored are bos and vm
mappings. Because a single amdgpu bo can have multiple mappings.
the mappings are recorded separately.

The ioctl has two modes: PROCESS_INFO, which sends to the user
how many bos and vms to expect, and CHECKPOINT, which copies
data about bos and vms into user-provided buffers.

Restore is handled using existing amdgpu and drm ioctls.

The new ioctl lives in a new file amdgpu_criu.c with its own
header amdgpu_criu.h

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/Makefile  |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_criu.c | 247 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_criu.h |  35 
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +
 drivers/gpu/drm/amd/amdkfd/kfd_chardev.c |   2 +
 include/uapi/drm/amdgpu_drm.h|  45 +
 6 files changed, 332 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_criu.c
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_criu.h

diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile 
b/drivers/gpu/drm/amd/amdgpu/Makefile
index 87080c06e5fc..0863edcdd03f 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -63,7 +63,7 @@ amdgpu-y += amdgpu_device.o amdgpu_doorbell_mgr.o 
amdgpu_kms.o \
amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \
amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \
amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \
-   amdgpu_fw_attestation.o amdgpu_securedisplay.o \
+   amdgpu_fw_attestation.o amdgpu_securedisplay.o amdgpu_criu.o \
amdgpu_eeprom.o amdgpu_mca.o amdgpu_psp_ta.o amdgpu_lsdma.o \
amdgpu_ring_mux.o amdgpu_xcp.o amdgpu_seq64.o amdgpu_aca.o 
amdgpu_dev_coredump.o \
amdgpu_cper.o amdgpu_userq_fence.o amdgpu_eviction_fence.o
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_criu.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_criu.c
new file mode 100644
index ..dbd2d5049eb6
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_criu.c
@@ -0,0 +1,247 @@
+/* SPDX-License-Identifier: MIT */
+/*
+* Copyright 2025 Advanced Micro Devices, Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "amdgpu_criu.h"
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "amdgpu.h"
+#include "amdgpu_display.h"
+#include "amdgpu_dma_buf.h"
+#include "amdgpu_hmm.h"
+#include "amdgpu_xgmi.h"
+
+static bool is_import(struct amdgpu_bo *bo)
+{
+   if (bo->tbo.base.import_attach)
+   return &bo->tbo.base != (struct drm_gem_object 
*)bo->tbo.base.import_attach->dmabuf->priv;
+   return false;
+}
+
+static int amdgpu_criu_process_info(struct drm_device *dev, struct drm_file 
*data,
+   struct drm_amdgpu_criu_args *args)
+{
+   struct drm_gem_object *gobj;
+   int id;
+   int num_bos = 0;
+   int num_vm_mappings = 0;
+   struct amdgpu_vm *avm = &((struct amdgpu_fpriv *)data->driver_priv)->vm;
+
+   spin_lock(&data->table_lock);
+   idr_for_each_entry(&data->object_idr, gobj, id) {
+   struct amdgpu_bo *bo = gem_to_amdgpu_bo(gobj);
+   struct amdgpu_vm_bo_base *vm_bo_base;
+
+   num_bos += 1;
+
+   vm_bo_base = bo->vm_bo;
+
+   while (vm_bo_base) {
+   struct amdgpu_bo_va *bo_va = container_of(vm_bo_base, 
struct amdgpu_bo_va, base);
+   struct amdgpu_bo_va_mapping *mapping;
+
+   if (vm_bo_base->vm == avm) {
+
+   list_for_each_entry(mapping, &bo_va->invalids, 
list) {
+   num_vm_mappings += 1;
+  

[PATCH 3/3] drm/amdgpu: Allow kfd CRIU with no buffer objects

2025-05-21 Thread David Francis
The kfd CRIU checkpoint ioctl would return an error if trying
to checkpoint a process with no kfd buffer objects.

This is a normal case and should not be an error.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index a8cf2d4580cc..7aa34bd15958 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -2570,7 +2570,7 @@ static int criu_restore(struct file *filep,
 args->num_devices, args->num_bos, args->num_objects, 
args->priv_data_size);
 
if (!args->bos || !args->devices || !args->priv_data || 
!args->priv_data_size ||
-   !args->num_devices || !args->num_bos)
+   !args->num_devices)
return -EINVAL;
 
mutex_lock(&p->mutex);
-- 
2.34.1



[PATCH v5] Add CRIU support for amdgpu dmabuf

2025-05-21 Thread David Francis
(previous patches were incorrectly called v3 but were actually the 4th version)

This patch series adds support for CRIU checkpointing of processes that
share memory with the amdgpu dmabuf interface.

In this v5, the drm interfaces have been changed from creating buffer objects
with specified gem handles to changing the gem handle of an existing buffer
object. This new ioctl (AMDGPU_GEM_CHANGE_HANDLE) is in drm_gem.c

In the accompanying CRIU patch set, the sockets used by CRIU to exchange dmabuf
fds between restoring processes have been refactored to be created within the
amdgpu plugin itself.




Re: [PATCH v5 06/12] drm: renesas: rz-du: mipi_dsi: Add OF data support

2025-05-21 Thread Lad, Prabhakar
Hi Laurent,

Thank you for the review.

On Tue, May 20, 2025 at 3:22 PM Laurent Pinchart
 wrote:
>
> Hi Prabhakar,
>
> Thank you for the patch.
>
> On Mon, May 12, 2025 at 07:23:24PM +0100, Prabhakar wrote:
> > From: Lad Prabhakar 
> >
> > In preparation for adding support for the Renesas RZ/V2H(P) SoC, this patch
> > introduces a mechanism to pass SoC-specific information via OF data in the
> > DSI driver. This enables the driver to adapt dynamically to various
> > SoC-specific requirements without hardcoding configurations.
> >
> > The MIPI DSI interface on the RZ/V2H(P) SoC is nearly identical to the one
> > on the RZ/G2L SoC. While the LINK registers are shared between the two
> > SoCs, the D-PHY registers differ. Also the VCLK range differs on both these
> > SoCs. To accommodate these differences `struct rzg2l_mipi_dsi_hw_info` is
> > introduced and as now passed as OF data.
> >
> > These changes lay the groundwork for the upcoming RZ/V2H(P) SoC support by
> > allowing SoC-specific data to be passed through OF.
> >
> > Co-developed-by: Fabrizio Castro 
> > Signed-off-by: Fabrizio Castro 
> > Signed-off-by: Lad Prabhakar 
> > Reviewed-by: Biju Das 
> > ---
> > v4->v5:
> > - Dropped RZ_MIPI_DSI_FEATURE_DPHY_RST feature flag
> > - Added Reviewed tag from Biju
> >
> > v3->v4:
> > - No changes
> >
> > v2->v3:
> > - Dropped !dsi->info check in rzg2l_mipi_dsi_probe() as it is not needed.
> >
> > v1->v2:
> > - Added DPHY_RST as feature flag
> > ---
> >  .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c| 51 ++-
> >  .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  2 -
> >  2 files changed, 38 insertions(+), 15 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c 
> > b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > index 3f6988303e63..00c2bc6e9d6c 100644
> > --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > @@ -28,10 +28,23 @@
> >
> >  #include "rzg2l_mipi_dsi_regs.h"
> >
> > +struct rzg2l_mipi_dsi;
> > +
> > +struct rzg2l_mipi_dsi_hw_info {
> > + int (*dphy_init)(struct rzg2l_mipi_dsi *dsi, unsigned long hsfreq);
> > + void (*dphy_exit)(struct rzg2l_mipi_dsi *dsi);
> > + u32 phy_reg_offset;
> > + u32 link_reg_offset;
> > + unsigned long max_dclk;
> > + unsigned long min_dclk;
>
> I'd put min before max.
>
Sure, I'll swap them (and below).

Cheers,
Prabhakar

> > +};
> > +
> >  struct rzg2l_mipi_dsi {
> >   struct device *dev;
> >   void __iomem *mmio;
> >
> > + const struct rzg2l_mipi_dsi_hw_info *info;
> > +
> >   struct reset_control *rstc;
> >   struct reset_control *arstc;
> >   struct reset_control *prstc;
> > @@ -164,22 +177,22 @@ static const struct rzg2l_mipi_dsi_timings 
> > rzg2l_mipi_dsi_global_timings[] = {
> >
> >  static void rzg2l_mipi_dsi_phy_write(struct rzg2l_mipi_dsi *dsi, u32 reg, 
> > u32 data)
> >  {
> > - iowrite32(data, dsi->mmio + reg);
> > + iowrite32(data, dsi->mmio + dsi->info->phy_reg_offset + reg);
> >  }
> >
> >  static void rzg2l_mipi_dsi_link_write(struct rzg2l_mipi_dsi *dsi, u32 reg, 
> > u32 data)
> >  {
> > - iowrite32(data, dsi->mmio + LINK_REG_OFFSET + reg);
> > + iowrite32(data, dsi->mmio + dsi->info->link_reg_offset + reg);
> >  }
> >
> >  static u32 rzg2l_mipi_dsi_phy_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
> >  {
> > - return ioread32(dsi->mmio + reg);
> > + return ioread32(dsi->mmio + dsi->info->phy_reg_offset + reg);
> >  }
> >
> >  static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
> >  {
> > - return ioread32(dsi->mmio + LINK_REG_OFFSET + reg);
> > + return ioread32(dsi->mmio + dsi->info->link_reg_offset + reg);
> >  }
> >
> >  /* 
> > -
> > @@ -294,7 +307,7 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi 
> > *dsi,
> >mode->clock * MILLI, vclk_rate);
> >   hsfreq = DIV_ROUND_CLOSEST_ULL(vclk_rate * bpp, dsi->lanes);
> >
> > - ret = rzg2l_mipi_dsi_dphy_init(dsi, hsfreq);
> > + ret = dsi->info->dphy_init(dsi, hsfreq);
> >   if (ret < 0)
> >   goto err_phy;
> >
> > @@ -337,7 +350,7 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi 
> > *dsi,
> >   return 0;
> >
> >  err_phy:
> > - rzg2l_mipi_dsi_dphy_exit(dsi);
> > + dsi->info->dphy_exit(dsi);
> >   pm_runtime_put(dsi->dev);
> >
> >   return ret;
> > @@ -345,7 +358,7 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi 
> > *dsi,
> >
> >  static void rzg2l_mipi_dsi_stop(struct rzg2l_mipi_dsi *dsi)
> >  {
> > - rzg2l_mipi_dsi_dphy_exit(dsi);
> > + dsi->info->dphy_exit(dsi);
> >   pm_runtime_put(dsi->dev);
> >  }
> >
> > @@ -587,10 +600,12 @@ rzg2l_mipi_dsi_bridge_mode_valid(struct drm_bridge 
> > *bridge,
> >const struct drm_display_info *info,
> >const struct dr

Re: [PATCH v2 2/2] dma-buf: heaps: Give default CMA heap a fixed name

2025-05-21 Thread Maxime Ripard
Hi Jared,

On Thu, Apr 24, 2025 at 09:11:24AM -0700, Jared Kangas wrote:
> > >  struct cma_heap {
> > >   struct dma_heap *heap;
> > > @@ -394,15 +395,26 @@ static int __init __add_cma_heap(struct cma *cma, 
> > > const char *name)
> > >  static int __init add_default_cma_heap(void)
> > >  {
> > >   struct cma *default_cma = dev_get_cma_area(NULL);
> > > + const char *legacy_cma_name;
> > >   int ret;
> > >  
> > >   if (!default_cma)
> > >   return 0;
> > >  
> > > - ret = __add_cma_heap(default_cma, cma_get_name(default_cma));
> > > + ret = __add_cma_heap(default_cma, DEFAULT_CMA_NAME);
> > >   if (ret)
> > >   return ret;
> > >  
> > > + legacy_cma_name = cma_get_name(default_cma);
> > > +
> > > + if (IS_ENABLED(CONFIG_DMABUF_HEAPS_CMA_LEGACY) &&
> > > + strcmp(legacy_cma_name, DEFAULT_CMA_NAME)) {
> > > + ret = __add_cma_heap(default_cma, legacy_cma_name);
> > > + if (ret)
> > > + pr_warn("cma_heap: failed to add legacy heap: %pe\n",
> > > + ERR_PTR(-ret));
> > > + }
> > > +
> > 
> > It would also simplify this part, since you would always create the legacy 
> > heap.
> 
> By "always", do you mean removing the strcmp? I added this to guard
> against cases where the devicetree node's name clashed with the default
> name, given that the DT name isn't necessarily restricted to one of the
> current names in use ("linux,cma" or "default-pool"). It seems like the
> strcmp would be relevant regardless of the naming choice, but if this is
> overly cautious, I can remove it in v3.

That's not overly cautious, that's something I overlooked :)

You're totally right that we should check for that. We should probably
add a more specific error message in that case though

Maxime


signature.asc
Description: PGP signature


[PATCH v6 0/3] drm: Create a task info option for wedge events

2025-05-21 Thread André Almeida
This patchset implements a request made by Xaver Hugl about wedge events:

"I'd really like to have the PID of the client that triggered the GPU
reset, so that we can kill it if multiple resets are triggered in a
row (or switch to software rendering if it's KWin itself) and show a
user-friendly notification about why their app(s) crashed, but that
can be added later."

>From 
>https://lore.kernel.org/dri-devel/CAFZQkGwJ4qgHV8WTp2=svJ_VXhb-+Y8_VNtKB=jlsk6dqmy...@mail.gmail.com/

For testing, I've used amdgpu's debug_mask options debug_disable_soft_recovery
and debug_disable_gpu_ring_reset to test both wedge event paths in the driver.
To trigger a ring timeout, I've used this app:
https://gitlab.freedesktop.org/andrealmeid/gpu-timeout

Thanks!

Changelog:

v6:
 - Check if PID >= 0 for displaying the task info
 - s/app/task in a comment

v5:
 - Change from app to task also in structs, commit message and docs
 - Add a check for NULL or empty task name string

v4:
 - Change from APP to TASK
 - Add defines for event_string and pid_string length

v3:
 - Make comm_string and pid_string empty when there's no app info
 - Change "app that caused ..." to "app involved ..."
 - Clarify that devcoredump have more information about what happened

v2:
  - Rebased on top of drm/drm-next
  - Added new patch for documentation

André Almeida (3):
  drm: Create a task info option for wedge events
  drm/doc: Add a section about "Task information" for the wedge API
  drm/amdgpu: Make use of drm_wedge_task_info

 Documentation/gpu/drm-uapi.rst | 17 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 19 +--
 drivers/gpu/drm/amd/amdgpu/amdgpu_job.c|  6 +-
 drivers/gpu/drm/drm_drv.c  | 19 +++
 drivers/gpu/drm/i915/gt/intel_reset.c  |  3 ++-
 drivers/gpu/drm/xe/xe_device.c |  3 ++-
 include/drm/drm_device.h   |  8 
 include/drm/drm_drv.h  |  3 ++-
 8 files changed, 68 insertions(+), 10 deletions(-)

-- 
2.49.0



[PATCH v6 2/3] drm/doc: Add a section about "Task information" for the wedge API

2025-05-21 Thread André Almeida
Add a section about "Task information" for the wedge API.

Reviewed-by: Krzysztof Karas 
Reviewed-by: Raag Jadav 
Signed-off-by: André Almeida 
---
v5:
 - Change app to task in the text as well
v4:
 - Change APP to TASK
v3:
 - Change "app that caused ..." to "app involved ..."
 - Clarify that devcoredump have more information about what happened
 - Update that PID and APP will be empty if there's no app info
---
 Documentation/gpu/drm-uapi.rst | 17 +
 1 file changed, 17 insertions(+)

diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst
index 69f72e71a96e..24aa9f320ebc 100644
--- a/Documentation/gpu/drm-uapi.rst
+++ b/Documentation/gpu/drm-uapi.rst
@@ -446,6 +446,23 @@ telemetry information (devcoredump, syslog). This is 
useful because the first
 hang is usually the most critical one which can result in consequential hangs 
or
 complete wedging.
 
+Task information
+---
+
+The information about which application (if any) was involved in the device
+wedging is useful for userspace if they want to notify the user about what
+happened (e.g. the compositor display a message to the user "The 
+caused a graphical error and the system recovered") or to implement policies
+(e.g. the daemon may "ban" an task that keeps resetting the device). If the 
task
+information is available, the uevent will display as ``PID=`` and
+``TASK=``. Otherwise, ``PID`` and ``TASK`` will not appear in the
+event string.
+
+The reliability of this information is driver and hardware specific, and should
+be taken with a caution regarding it's precision. To have a big picture of what
+really happened, the devcoredump file provides should have much more detailed
+information about the device state and about the event.
+
 Consumer prerequisites
 --
 
-- 
2.49.0



[PATCH v6 1/3] drm: Create a task info option for wedge events

2025-05-21 Thread André Almeida
When a device get wedged, it might be caused by a guilty application.
For userspace, knowing which task was the cause can be useful for some
situations, like for implementing a policy, logs or for giving a chance
for the compositor to let the user know what task caused the problem.
This is an optional argument, when the task info is not available, the
PID and TASK string won't appear in the event string.

Sometimes just the PID isn't enough giving that the task might be already
dead by the time userspace will try to check what was this PID's name,
so to make the life easier also notify what's the task's name in the user
event.

Acked-by: Rodrigo Vivi  (for i915 and xe)
Reviewed-by: Krzysztof Karas 
Signed-off-by: André Almeida 
---
v6:
 - s/app/task in a comment
 - add PID >= 0 check
v5:
 - s/app/task for struct and commit message as well
 - move defines to drm_drv.c
 - validates if comm is not NULL and it's not empty
v4: s/APP/TASK
v3: Make comm_string and pid_string empty when there's no app info
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_job.c|  2 +-
 drivers/gpu/drm/drm_drv.c  | 19 +++
 drivers/gpu/drm/i915/gt/intel_reset.c  |  3 ++-
 drivers/gpu/drm/xe/xe_device.c |  3 ++-
 include/drm/drm_device.h   |  8 
 include/drm/drm_drv.h  |  3 ++-
 7 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 4d1b54f58495..d27091d5929c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -6363,7 +6363,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
atomic_set(&adev->reset_domain->reset_res, r);
 
if (!r)
-   drm_dev_wedged_event(adev_to_drm(adev), 
DRM_WEDGE_RECOVERY_NONE);
+   drm_dev_wedged_event(adev_to_drm(adev), 
DRM_WEDGE_RECOVERY_NONE, NULL);
 
return r;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index acb21fc8b3ce..a47b2eb301e5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -166,7 +166,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct 
drm_sched_job *s_job)
if (amdgpu_ring_sched_ready(ring))
drm_sched_start(&ring->sched, 0);
dev_err(adev->dev, "Ring %s reset succeeded\n", 
ring->sched.name);
-   drm_dev_wedged_event(adev_to_drm(adev), 
DRM_WEDGE_RECOVERY_NONE);
+   drm_dev_wedged_event(adev_to_drm(adev), 
DRM_WEDGE_RECOVERY_NONE, NULL);
goto exit;
}
dev_err(adev->dev, "Ring %s reset failure\n", ring->sched.name);
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 3dc7acd56b1d..db0cfa367b4e 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -538,10 +538,14 @@ static const char *drm_get_wedge_recovery(unsigned int 
opt)
}
 }
 
+#define WEDGE_STR_LEN 32
+#define PID_LEN 15
+
 /**
  * drm_dev_wedged_event - generate a device wedged uevent
  * @dev: DRM device
  * @method: method(s) to be used for recovery
+ * @info: optional information about the guilty task
  *
  * This generates a device wedged uevent for the DRM device specified by @dev.
  * Recovery @method\(s) of choice will be sent in the uevent environment as
@@ -554,13 +558,13 @@ static const char *drm_get_wedge_recovery(unsigned int 
opt)
  *
  * Returns: 0 on success, negative error code otherwise.
  */
-int drm_dev_wedged_event(struct drm_device *dev, unsigned long method)
+int drm_dev_wedged_event(struct drm_device *dev, unsigned long method,
+struct drm_wedge_task_info *info)
 {
const char *recovery = NULL;
unsigned int len, opt;
-   /* Event string length up to 28+ characters with available methods */
-   char event_string[32];
-   char *envp[] = { event_string, NULL };
+   char event_string[WEDGE_STR_LEN], pid_string[PID_LEN] = "", 
comm_string[TASK_COMM_LEN] = "";
+   char *envp[] = { event_string, NULL, NULL, NULL };
 
len = scnprintf(event_string, sizeof(event_string), "%s", "WEDGED=");
 
@@ -582,6 +586,13 @@ int drm_dev_wedged_event(struct drm_device *dev, unsigned 
long method)
drm_info(dev, "device wedged, %s\n", method == DRM_WEDGE_RECOVERY_NONE ?
 "but recovered through reset" : "needs recovery");
 
+   if (info && ((info->comm && info->comm[0] != '\0')) && (info->pid >= 
0)) {
+   snprintf(pid_string, sizeof(pid_string), "PID=%u", info->pid);
+   snprintf(comm_string, sizeof(comm_string), "TASK=%s", 
info->comm);
+   envp[1] = pid_string;
+   envp[2] = comm_string;
+   }
+
return k

[PATCH v6 3/3] drm/amdgpu: Make use of drm_wedge_task_info

2025-05-21 Thread André Almeida
To notify userspace about which task (if any) made the device get in a
wedge state, make use of drm_wedge_task_info parameter, filling it with
the task PID and name.

Signed-off-by: André Almeida 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 19 +--
 drivers/gpu/drm/amd/amdgpu/amdgpu_job.c|  6 +-
 2 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index d27091d5929c..c29c924aa506 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -6362,8 +6362,23 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
 
atomic_set(&adev->reset_domain->reset_res, r);
 
-   if (!r)
-   drm_dev_wedged_event(adev_to_drm(adev), 
DRM_WEDGE_RECOVERY_NONE, NULL);
+   if (!r) {
+   struct drm_wedge_task_info aux, *info = NULL;
+
+   if (job) {
+   struct amdgpu_task_info *ti;
+
+   ti = amdgpu_vm_get_task_info_pasid(adev, job->pasid);
+   if (ti) {
+   aux.pid = ti->pid;
+   aux.comm = ti->process_name;
+   info = &aux;
+   amdgpu_vm_put_task_info(ti);
+   }
+   }
+
+   drm_dev_wedged_event(adev_to_drm(adev), 
DRM_WEDGE_RECOVERY_NONE, info);
+   }
 
return r;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index a47b2eb301e5..5cb17e62df57 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -89,6 +89,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct 
drm_sched_job *s_job)
 {
struct amdgpu_ring *ring = to_amdgpu_ring(s_job->sched);
struct amdgpu_job *job = to_amdgpu_job(s_job);
+   struct drm_wedge_task_info aux, *info = NULL;
struct amdgpu_task_info *ti;
struct amdgpu_device *adev = ring->adev;
int idx;
@@ -127,6 +128,9 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct 
drm_sched_job *s_job)
dev_err(adev->dev,
"Process information: process %s pid %d thread %s pid 
%d\n",
ti->process_name, ti->tgid, ti->task_name, ti->pid);
+   aux.pid = ti->pid;
+   aux.comm = ti->process_name;
+   info = &aux;
amdgpu_vm_put_task_info(ti);
}
 
@@ -166,7 +170,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct 
drm_sched_job *s_job)
if (amdgpu_ring_sched_ready(ring))
drm_sched_start(&ring->sched, 0);
dev_err(adev->dev, "Ring %s reset succeeded\n", 
ring->sched.name);
-   drm_dev_wedged_event(adev_to_drm(adev), 
DRM_WEDGE_RECOVERY_NONE, NULL);
+   drm_dev_wedged_event(adev_to_drm(adev), 
DRM_WEDGE_RECOVERY_NONE, info);
goto exit;
}
dev_err(adev->dev, "Ring %s reset failure\n", ring->sched.name);
-- 
2.49.0



Re: [PATCH v4 01/20] rust: dma: expose the count and size of CoherentAllocation

2025-05-21 Thread Alexandre Courbot
On Wed May 21, 2025 at 9:43 PM JST, Boqun Feng wrote:
> On Wed, May 21, 2025 at 03:44:56PM +0900, Alexandre Courbot wrote:
>> These properties are very useful to have and should be accessible.
>> 
>> Signed-off-by: Alexandre Courbot 
>> ---
>>  rust/kernel/dma.rs | 18 ++
>>  1 file changed, 18 insertions(+)
>> 
>> diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
>> index 
>> 605e01e35715667f93297fd9ec49d8e7032e0910..2a60eefa47dfc1f836c30ee342e26c6ff3e9b13a
>>  100644
>> --- a/rust/kernel/dma.rs
>> +++ b/rust/kernel/dma.rs
>> @@ -129,6 +129,10 @@ pub mod attrs {
>>  //
>>  // Hence, find a way to revoke the device resources of a 
>> `CoherentAllocation`, but not the
>>  // entire `CoherentAllocation` including the allocated memory itself.
>> +//
>> +// # Invariants
>> +//
>> +// The size in bytes of the allocation is equal to `size_of:: * count()`.
>>  pub struct CoherentAllocation {
>>  dev: ARef,
>>  dma_handle: bindings::dma_addr_t,
>> @@ -201,6 +205,20 @@ pub fn alloc_coherent(
>>  CoherentAllocation::alloc_attrs(dev, count, gfp_flags, Attrs(0))
>>  }
>>  
>> +/// Returns the number of elements `T` in this allocation.
>> +///
>> +/// Note that this is not the size of the allocation in bytes, which is 
>> provided by
>> +/// [`Self::size`].
>> +pub fn count(&self) -> usize {
>> +self.count
>> +}
>> +
>> +/// Returns the size in bytes of this allocation.
>> +pub fn size(&self) -> usize {
>> +// As per the invariants of `CoherentAllocation`.
>> +self.count * core::mem::size_of::()
>
> I think we need a comment or even an invariant saying this multiply
> cannot overflow.

I'll add the following invariant:

`size_of:: * count` fits into a `usize`.

and refer to it here. Does it work?



[PULL] drm-intel-next-fixes

2025-05-21 Thread Joonas Lahtinen
Hi Dave & Sima,

Here goes another drm-intel-next-fixes PR towards 6.16-rc1.

Thunderbolt disconnect fix for MTL/ARL/LNL, DDI port clock fix for PTL+ and WQ
allocation error check for display init code.

Regards, Joonas

PS. CI results were for one patch more, which I reverted during review
of the automation picked patches, but results should still be valid.

***

drm-intel-next-fixes-2025-05-22:

- Fix for Thunderbolt sink disconnect on MTL/ARL/LNL
- Fix for DDI port clock select mask on PTL+
- Add error checks for alloc_ordered_workqueue() and alloc_workqueue() in 
display

The following changes since commit c4f8ac095fc91084108ec21117eb9c1fff64725d:

  Merge tag 'nova-next-v6.16-2025-05-20' of 
https://gitlab.freedesktop.org/drm/nova into drm-next (2025-05-21 05:49:31 
+1000)

are available in the Git repository at:

  https://gitlab.freedesktop.org/drm/i915/kernel.git 
tags/drm-intel-next-fixes-2025-05-22

for you to fetch changes up to f4c7baa0699b69edb6887a992283b389761e0e81:

  drm/i915/display: Add check for alloc_ordered_workqueue() and 
alloc_workqueue() (2025-05-22 09:25:57 +0300)


- Fix for Thunderbolt sink disconnect on MTL/ARL/LNL
- Fix for DDI port clock select mask on PTL+
- Add error checks for alloc_ordered_workqueue() and alloc_workqueue() in 
display


Haoxiang Li (1):
  drm/i915/display: Add check for alloc_ordered_workqueue() and 
alloc_workqueue()

Imre Deak (2):
  drm/i915/ptl: Use everywhere the correct DDI port clock select mask
  drm/i915/dp_mst: Work around Thunderbolt sink disconnect after 
SINK_COUNT_ESI read

 drivers/gpu/drm/i915/display/intel_cx0_phy.c   | 27 ---
 drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h  | 15 ---
 .../gpu/drm/i915/display/intel_display_driver.c| 30 ++
 drivers/gpu/drm/i915/display/intel_dp.c| 17 
 4 files changed, 63 insertions(+), 26 deletions(-)


Re: [PATCH v9 2/9] dma-buf: dma-heap: export declared functions

2025-05-21 Thread Jens Wiklander
On Wed, May 21, 2025 at 9:13 AM Christian König
 wrote:
>
> On 5/20/25 17:16, Jens Wiklander wrote:
> > Export the dma-buf heap functions declared in .
>
> That is what this patch does and that should be obvious by looking at it. You 
> need to explain why you do this.
>
> Looking at the rest of the series it's most likely ok, but this commit 
> message should really be improved.

I'm considering something like this for the next version:
Export the dma-buf heap functions declared in  to allow
them to be used by kernel modules. This will enable drivers like the OP-TEE
driver, to utilize these interfaces for registering and managing their
specific DMA heaps.

Thanks,
Jens

>
> Regards,
> Christian.
>
> >
> > Signed-off-by: Jens Wiklander 
> > ---
> >  drivers/dma-buf/dma-heap.c | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
> > index 3cbe87d4a464..cdddf0e24dce 100644
> > --- a/drivers/dma-buf/dma-heap.c
> > +++ b/drivers/dma-buf/dma-heap.c
> > @@ -202,6 +202,7 @@ void *dma_heap_get_drvdata(struct dma_heap *heap)
> >  {
> >   return heap->priv;
> >  }
> > +EXPORT_SYMBOL(dma_heap_get_drvdata);
> >
> >  /**
> >   * dma_heap_get_name - get heap name
> > @@ -214,6 +215,7 @@ const char *dma_heap_get_name(struct dma_heap *heap)
> >  {
> >   return heap->name;
> >  }
> > +EXPORT_SYMBOL(dma_heap_get_name);
> >
> >  /**
> >   * dma_heap_add - adds a heap to dmabuf heaps
> > @@ -303,6 +305,7 @@ struct dma_heap *dma_heap_add(const struct 
> > dma_heap_export_info *exp_info)
> >   kfree(heap);
> >   return err_ret;
> >  }
> > +EXPORT_SYMBOL(dma_heap_add);
> >
> >  static char *dma_heap_devnode(const struct device *dev, umode_t *mode)
> >  {
>


[PATCH 9/9] iosys_map: embed the is_iomem bit into the pointer.

2025-05-21 Thread Dave Airlie
From: Dave Airlie 

This reduces this struct from 16 to 8 bytes, and it gets embedded
into a lot of things.

Signed-off-by: Dave Airlie 
---
 include/linux/iosys-map.h | 30 --
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/include/linux/iosys-map.h b/include/linux/iosys-map.h
index a6c2cc9ca756..44479966ce24 100644
--- a/include/linux/iosys-map.h
+++ b/include/linux/iosys-map.h
@@ -99,29 +99,27 @@
  * iosys_map_incr(&map, len); // go to first byte after the memcpy
  */
 
+#define _IOSYS_MAP_IS_IOMEM 1
 /**
  * struct iosys_map - Pointer to IO/system memory
  * @vaddr_iomem:   The buffer's address if in I/O memory
  * @vaddr: The buffer's address if in system memory
- * @is_iomem:  True if the buffer is located in I/O memory, or false
- * otherwise.
  */
 struct iosys_map {
union {
void __iomem *_vaddr_iomem;
void *_vaddr;
};
-   bool _is_iomem;
 };
 
 static inline bool iosys_map_is_iomem(const struct iosys_map *map)
 {
-   return map->_is_iomem;
+   return ((unsigned long)map->_vaddr) & _IOSYS_MAP_IS_IOMEM;
 }
 
 static inline void __iomem *iosys_map_ioptr(const struct iosys_map *map)
 {
-   return map->_vaddr_iomem;
+   return (void __iomem *)((unsigned long)map->_vaddr_iomem & 
~_IOSYS_MAP_IS_IOMEM);
 }
 
 static inline void *iosys_map_ptr(const struct iosys_map *map)
@@ -136,7 +134,6 @@ static inline void *iosys_map_ptr(const struct iosys_map 
*map)
 #define IOSYS_MAP_INIT_VADDR(vaddr_)   \
{   \
._vaddr = (vaddr_), \
-   ._is_iomem = false, \
}
 
 /**
@@ -145,8 +142,7 @@ static inline void *iosys_map_ptr(const struct iosys_map 
*map)
  */
 #define IOSYS_MAP_INIT_VADDR_IOMEM(vaddr_iomem_)   \
{   \
-   ._vaddr_iomem = (vaddr_iomem_), \
-   ._is_iomem = true,  \
+   ._vaddr_iomem = (void __iomem *)(((unsigned long)(vaddr_iomem_) 
| _IOSYS_MAP_IS_IOMEM)), \
}
 
 /**
@@ -198,7 +194,6 @@ static inline void *iosys_map_ptr(const struct iosys_map 
*map)
 static inline void iosys_map_set_vaddr(struct iosys_map *map, void *vaddr)
 {
map->_vaddr = vaddr;
-   map->_is_iomem = false;
 }
 
 /**
@@ -211,8 +206,7 @@ static inline void iosys_map_set_vaddr(struct iosys_map 
*map, void *vaddr)
 static inline void iosys_map_set_vaddr_iomem(struct iosys_map *map,
 void __iomem *vaddr_iomem)
 {
-   map->_vaddr_iomem = vaddr_iomem;
-   map->_is_iomem = true;
+   map->_vaddr_iomem = (void __iomem *)((unsigned long)vaddr_iomem | 
_IOSYS_MAP_IS_IOMEM);
 }
 
 /**
@@ -229,12 +223,9 @@ static inline void iosys_map_set_vaddr_iomem(struct 
iosys_map *map,
 static inline bool iosys_map_is_equal(const struct iosys_map *lhs,
  const struct iosys_map *rhs)
 {
-   if (lhs->_is_iomem != rhs->_is_iomem)
+   if (lhs->_vaddr != rhs->_vaddr)
return false;
-   else if (lhs->_is_iomem)
-   return lhs->_vaddr_iomem == rhs->_vaddr_iomem;
-   else
-   return lhs->_vaddr == rhs->_vaddr;
+   return true;
 }
 
 /**
@@ -279,12 +270,7 @@ static inline bool iosys_map_is_set(const struct iosys_map 
*map)
  */
 static inline void iosys_map_clear(struct iosys_map *map)
 {
-   if (map->_is_iomem) {
-   map->_vaddr_iomem = NULL;
-   map->_is_iomem = false;
-   } else {
-   map->_vaddr = NULL;
-   }
+   map->_vaddr = NULL;
 }
 
 /**
-- 
2.49.0



[PATCH 7/9] drm: avoid accessing iosys_map internals.

2025-05-21 Thread Dave Airlie
From: Dave Airlie 

This avoids directly accessing the iosys_map internals using new interfaces.

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/drm_cache.c   | 28 +--
 drivers/gpu/drm/drm_fbdev_shmem.c |  4 +--
 drivers/gpu/drm/drm_format_helper.c   | 16 +--
 drivers/gpu/drm/sysfb/drm_sysfb_modeset.c |  2 +-
 .../gpu/drm/tests/drm_format_helper_test.c| 26 -
 5 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c
index 7051c9c909c2..8945d32d26d8 100644
--- a/drivers/gpu/drm/drm_cache.c
+++ b/drivers/gpu/drm/drm_cache.c
@@ -215,12 +215,12 @@ static void memcpy_fallback(struct iosys_map *dst,
const struct iosys_map *src,
unsigned long len)
 {
-   if (!dst->is_iomem && !src->is_iomem) {
-   memcpy(dst->vaddr, src->vaddr, len);
-   } else if (!src->is_iomem) {
-   iosys_map_memcpy_to(dst, 0, src->vaddr, len);
-   } else if (!dst->is_iomem) {
-   memcpy_fromio(dst->vaddr, src->vaddr_iomem, len);
+   if (!iosys_map_is_iomem(dst) && !iosys_map_is_iomem(src)) {
+   memcpy(iosys_map_ptr(dst), iosys_map_ptr(src), len);
+   } else if (iosys_map_is_iomem(src)) {
+   iosys_map_memcpy_to(dst, 0, iosys_map_ptr(src), len);
+   } else if (!iosys_map_is_iomem(dst)) {
+   memcpy_fromio(iosys_map_ptr(dst), iosys_map_ioptr(src), len);
} else {
/*
 * Bounce size is not performance tuned, but using a
@@ -228,8 +228,8 @@ static void memcpy_fallback(struct iosys_map *dst,
 * resorting to ioreadxx() + iowritexx().
 */
char bounce[MEMCPY_BOUNCE_SIZE];
-   void __iomem *_src = src->vaddr_iomem;
-   void __iomem *_dst = dst->vaddr_iomem;
+   void __iomem *_src = iosys_map_ioptr(src);
+   void __iomem *_dst = iosys_map_ioptr(dst);
 
while (len >= MEMCPY_BOUNCE_SIZE) {
memcpy_fromio(bounce, _src, MEMCPY_BOUNCE_SIZE);
@@ -312,12 +312,12 @@ void drm_memcpy_from_wc(struct iosys_map *dst,
}
 
if (static_branch_likely(&has_movntdqa)) {
-   __drm_memcpy_from_wc(dst->is_iomem ?
-(void __force *)dst->vaddr_iomem :
-dst->vaddr,
-src->is_iomem ?
-(void const __force *)src->vaddr_iomem :
-src->vaddr,
+   __drm_memcpy_from_wc(iosys_map_is_iomem(dst) ?
+(void __force *)iosys_map_ioptr(dst) :
+iosys_map_ptr(dst),
+iosys_map_is_iomem(src) ?
+(void const __force *)iosys_map_ioptr(src) 
:
+iosys_map_ptr(src),
 len);
return;
}
diff --git a/drivers/gpu/drm/drm_fbdev_shmem.c 
b/drivers/gpu/drm/drm_fbdev_shmem.c
index f824369baacd..d45b6826138b 100644
--- a/drivers/gpu/drm/drm_fbdev_shmem.c
+++ b/drivers/gpu/drm/drm_fbdev_shmem.c
@@ -159,7 +159,7 @@ int drm_fbdev_shmem_driver_fbdev_probe(struct drm_fb_helper 
*fb_helper,
ret = drm_client_buffer_vmap(buffer, &map);
if (ret) {
goto err_drm_client_buffer_delete;
-   } else if (drm_WARN_ON(dev, map.is_iomem)) {
+   } else if (drm_WARN_ON(dev, iosys_map_is_iomem(&map))) {
ret = -ENODEV; /* I/O memory not supported; use generic 
emulation */
goto err_drm_client_buffer_delete;
}
@@ -183,7 +183,7 @@ int drm_fbdev_shmem_driver_fbdev_probe(struct drm_fb_helper 
*fb_helper,
if (!shmem->map_wc)
info->flags |= FBINFO_READS_FAST; /* signal caching */
info->screen_size = sizes->surface_height * fb->pitches[0];
-   info->screen_buffer = map.vaddr;
+   info->screen_buffer = iosys_map_ptr(&map);
info->fix.smem_len = info->screen_size;
 
/* deferred I/O */
diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index d36e6cacc575..cccec04bec4e 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -236,13 +236,13 @@ static int drm_fb_xfrm(struct iosys_map *dst,
dst_pitch = default_dst_pitch;
 
/* 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],
- src[0].vaddr, fb, clip, 
vaddr_cached_hint, state,
+   if (iosys_map_is_iomem(&dst[0]))
+   return __drm_fb_xfrm_toio(iosys_map_ioptr(&dst[0]), 
dst_pitch[0], dst_pixs

[PATCH 4/9] drm/xe: avoid accessing internals of iosys_map

2025-05-21 Thread Dave Airlie
From: Dave Airlie 

This uses the new accessors to avoid touch iosys_map internals.

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/xe/display/intel_fbdev_fb.c |  2 +-
 drivers/gpu/drm/xe/xe_bo.c  |  8 
 drivers/gpu/drm/xe/xe_eu_stall.c|  2 +-
 drivers/gpu/drm/xe/xe_guc_pc.c  |  2 +-
 drivers/gpu/drm/xe/xe_map.h | 12 ++--
 drivers/gpu/drm/xe/xe_memirq.c  | 16 
 drivers/gpu/drm/xe/xe_oa.c  |  4 ++--
 drivers/gpu/drm/xe/xe_pt.c  |  4 ++--
 drivers/gpu/drm/xe/xe_sa.c  |  8 
 9 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c 
b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c
index e8191562d122..ad2681c90efb 100644
--- a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c
+++ b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c
@@ -101,7 +101,7 @@ int intel_fbdev_fb_fill_info(struct intel_display *display, 
struct fb_info *info
}
XE_WARN_ON(iosys_map_is_null(&obj->vmap));
 
-   info->screen_base = obj->vmap.vaddr_iomem;
+   info->screen_base = iosys_map_ioptr(&obj->vmap);
info->screen_size = obj->ttm.base.size;
 
return 0;
diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index d99d91fe8aa9..c83a54708495 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -1249,7 +1249,7 @@ int xe_bo_evict_pinned(struct xe_bo *bo)
unmap = true;
}
 
-   xe_map_memcpy_from(xe, backup->vmap.vaddr, &bo->vmap, 0,
+   xe_map_memcpy_from(xe, iosys_map_ptr(&backup->vmap), &bo->vmap, 
0,
   bo->size);
}
 
@@ -1342,7 +1342,7 @@ int xe_bo_restore_pinned(struct xe_bo *bo)
unmap = true;
}
 
-   xe_map_memcpy_to(xe, &bo->vmap, 0, backup->vmap.vaddr,
+   xe_map_memcpy_to(xe, &bo->vmap, 0, iosys_map_ptr(&backup->vmap),
 bo->size);
}
 
@@ -2226,9 +2226,9 @@ int xe_managed_bo_reinit_in_vram(struct xe_device *xe, 
struct xe_tile *tile, str
  XE_BO_FLAG_PINNED_NORESTORE);
 
xe_assert(xe, IS_DGFX(xe));
-   xe_assert(xe, !(*src)->vmap.is_iomem);
+   xe_assert(xe, !iosys_map_is_iomem(&(*src)->vmap));
 
-   bo = xe_managed_bo_create_from_data(xe, tile, (*src)->vmap.vaddr,
+   bo = xe_managed_bo_create_from_data(xe, tile, 
iosys_map_ptr(&(*src)->vmap),
(*src)->size, dst_flags);
if (IS_ERR(bo))
return PTR_ERR(bo);
diff --git a/drivers/gpu/drm/xe/xe_eu_stall.c b/drivers/gpu/drm/xe/xe_eu_stall.c
index 96732613b4b7..d8f900efac95 100644
--- a/drivers/gpu/drm/xe/xe_eu_stall.c
+++ b/drivers/gpu/drm/xe/xe_eu_stall.c
@@ -741,7 +741,7 @@ static int xe_eu_stall_stream_init(struct 
xe_eu_stall_data_stream *stream,
for_each_dss_steering(xecore, gt, group, instance) {
xecore_buf = &stream->xecore_buf[xecore];
vaddr_offset = xecore * stream->per_xecore_buf_size;
-   xecore_buf->vaddr = stream->bo->vmap.vaddr + vaddr_offset;
+   xecore_buf->vaddr = iosys_map_ptr(&stream->bo->vmap) + 
vaddr_offset;
}
return 0;
 }
diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c
index 18c623992035..c7ad56774c99 100644
--- a/drivers/gpu/drm/xe/xe_guc_pc.c
+++ b/drivers/gpu/drm/xe/xe_guc_pc.c
@@ -1068,7 +1068,7 @@ int xe_guc_pc_start(struct xe_guc_pc *pc)
goto out;
}
 
-   memset(pc->bo->vmap.vaddr, 0, size);
+   memset(iosys_map_ptr(&pc->bo->vmap), 0, size);
slpc_shared_data_write(pc, header.size, size);
 
earlier = ktime_get();
diff --git a/drivers/gpu/drm/xe/xe_map.h b/drivers/gpu/drm/xe/xe_map.h
index f62e0c8b67ab..37842c02c7f9 100644
--- a/drivers/gpu/drm/xe/xe_map.h
+++ b/drivers/gpu/drm/xe/xe_map.h
@@ -49,10 +49,10 @@ static inline u32 xe_map_read32(struct xe_device *xe, 
struct iosys_map *map)
 {
xe_device_assert_mem_access(xe);
 
-   if (map->is_iomem)
-   return readl(map->vaddr_iomem);
+   if (iosys_map_is_iomem(map))
+   return readl(iosys_map_ioptr(map));
else
-   return READ_ONCE(*(u32 *)map->vaddr);
+   return READ_ONCE(*(u32 *)iosys_map_ptr(map));
 }
 
 static inline void xe_map_write32(struct xe_device *xe, struct iosys_map *map,
@@ -60,10 +60,10 @@ static inline void xe_map_write32(struct xe_device *xe, 
struct iosys_map *map,
 {
xe_device_assert_mem_access(xe);
 
-   if (map->is_iomem)
-   writel(val, map->vaddr_iomem);
+   if (iosys_map_is_iomem(map))
+   writel(val, iosys_map_ioptr(map));
else
-   *(u32 *)map->vaddr = val;
+   *(u32 *)iosys_map_ptr(map) = val;
 }
 
 #d

[PATCH 1/9] iosys-map: add new accessor interfaces and use them internally.

2025-05-21 Thread Dave Airlie
From: Dave Airlie 

This adds accessors inlines to the iosys-map. The intent is to
roll the iomem flag into the lower bits of the vaddr eventually.

First just add accessors to move all current in-tree users over to.

Signed-off-by: Dave Airlie 
---
 include/linux/iosys-map.h | 53 +--
 1 file changed, 34 insertions(+), 19 deletions(-)

diff --git a/include/linux/iosys-map.h b/include/linux/iosys-map.h
index 4696abfd311c..5ce5df1db60a 100644
--- a/include/linux/iosys-map.h
+++ b/include/linux/iosys-map.h
@@ -114,6 +114,21 @@ struct iosys_map {
bool is_iomem;
 };
 
+static inline bool iosys_map_is_iomem(const struct iosys_map *map)
+{
+   return map->is_iomem;
+}
+
+static inline void __iomem *iosys_map_ioptr(const struct iosys_map *map)
+{
+   return map->vaddr_iomem;
+}
+
+static inline void *iosys_map_ptr(const struct iosys_map *map)
+{
+   return map->vaddr;
+}
+
 /**
  * IOSYS_MAP_INIT_VADDR - Initializes struct iosys_map to an address in system 
memory
  * @vaddr_:A system-memory address
@@ -234,9 +249,9 @@ static inline bool iosys_map_is_equal(const struct 
iosys_map *lhs,
  */
 static inline bool iosys_map_is_null(const struct iosys_map *map)
 {
-   if (map->is_iomem)
-   return !map->vaddr_iomem;
-   return !map->vaddr;
+   if (iosys_map_is_iomem(map))
+   return !iosys_map_ioptr(map);
+   return !iosys_map_ptr(map);
 }
 
 /**
@@ -286,10 +301,10 @@ static inline void iosys_map_clear(struct iosys_map *map)
 static inline void iosys_map_memcpy_to(struct iosys_map *dst, size_t 
dst_offset,
   const void *src, size_t len)
 {
-   if (dst->is_iomem)
-   memcpy_toio(dst->vaddr_iomem + dst_offset, src, len);
+   if (iosys_map_is_iomem(dst))
+   memcpy_toio(iosys_map_ioptr(dst) + dst_offset, src, len);
else
-   memcpy(dst->vaddr + dst_offset, src, len);
+   memcpy(iosys_map_ptr(dst) + dst_offset, src, len);
 }
 
 /**
@@ -306,10 +321,10 @@ static inline void iosys_map_memcpy_to(struct iosys_map 
*dst, size_t dst_offset,
 static inline void iosys_map_memcpy_from(void *dst, const struct iosys_map 
*src,
 size_t src_offset, size_t len)
 {
-   if (src->is_iomem)
-   memcpy_fromio(dst, src->vaddr_iomem + src_offset, len);
+   if (iosys_map_is_iomem(src))
+   memcpy_fromio(dst, iosys_map_ioptr(src) + src_offset, len);
else
-   memcpy(dst, src->vaddr + src_offset, len);
+   memcpy(dst, iosys_map_ptr(src) + src_offset, len);
 }
 
 /**
@@ -322,7 +337,7 @@ static inline void iosys_map_memcpy_from(void *dst, const 
struct iosys_map *src,
  */
 static inline void iosys_map_incr(struct iosys_map *map, size_t incr)
 {
-   if (map->is_iomem)
+   if (iosys_map_is_iomem(map))
map->vaddr_iomem += incr;
else
map->vaddr += incr;
@@ -341,10 +356,10 @@ static inline void iosys_map_incr(struct iosys_map *map, 
size_t incr)
 static inline void iosys_map_memset(struct iosys_map *dst, size_t offset,
int value, size_t len)
 {
-   if (dst->is_iomem)
-   memset_io(dst->vaddr_iomem + offset, value, len);
+   if (iosys_map_is_iomem(dst))
+   memset_io(iosys_map_ioptr(dst) + offset, value, len);
else
-   memset(dst->vaddr + offset, value, len);
+   memset(iosys_map_ptr(dst) + offset, value, len);
 }
 
 #ifdef CONFIG_64BIT
@@ -393,10 +408,10 @@ static inline void iosys_map_memset(struct iosys_map 
*dst, size_t offset,
  */
 #define iosys_map_rd(map__, offset__, type__) ({   
\
type__ val_;
\
-   if ((map__)->is_iomem) {
\
-   __iosys_map_rd_io(val_, (map__)->vaddr_iomem + (offset__), 
type__); \
+   if (iosys_map_is_iomem(map__)) {
\
+   __iosys_map_rd_io(val_, iosys_map_ioptr(map__) + (offset__), 
type__);   \
} else {
\
-   __iosys_map_rd_sys(val_, (map__)->vaddr + (offset__), type__);  
\
+   __iosys_map_rd_sys(val_, iosys_map_ptr(map__) + (offset__), 
type__);\
}   
\
val_;   
\
 })
@@ -415,10 +430,10 @@ static inline void iosys_map_memset(struct iosys_map 
*dst, size_t offset,
  */
 #define iosys_map_wr(map__, offset__, type__, val__) ({
\
type__ val_ = (val__);  
\
-  

[PATCH 8/9] iosys: hide internal details of implementation.

2025-05-21 Thread Dave Airlie
From: Dave Airlie 

Now hide the current implementation details, to catch any new
users entering the tree and trying to trick us up.

Signed-off-by: Dave Airlie 
---
 include/linux/iosys-map.h | 48 +++
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/include/linux/iosys-map.h b/include/linux/iosys-map.h
index 5ce5df1db60a..a6c2cc9ca756 100644
--- a/include/linux/iosys-map.h
+++ b/include/linux/iosys-map.h
@@ -108,25 +108,25 @@
  */
 struct iosys_map {
union {
-   void __iomem *vaddr_iomem;
-   void *vaddr;
+   void __iomem *_vaddr_iomem;
+   void *_vaddr;
};
-   bool is_iomem;
+   bool _is_iomem;
 };
 
 static inline bool iosys_map_is_iomem(const struct iosys_map *map)
 {
-   return map->is_iomem;
+   return map->_is_iomem;
 }
 
 static inline void __iomem *iosys_map_ioptr(const struct iosys_map *map)
 {
-   return map->vaddr_iomem;
+   return map->_vaddr_iomem;
 }
 
 static inline void *iosys_map_ptr(const struct iosys_map *map)
 {
-   return map->vaddr;
+   return map->_vaddr;
 }
 
 /**
@@ -135,8 +135,8 @@ static inline void *iosys_map_ptr(const struct iosys_map 
*map)
  */
 #define IOSYS_MAP_INIT_VADDR(vaddr_)   \
{   \
-   .vaddr = (vaddr_),  \
-   .is_iomem = false,  \
+   ._vaddr = (vaddr_), \
+   ._is_iomem = false, \
}
 
 /**
@@ -145,8 +145,8 @@ static inline void *iosys_map_ptr(const struct iosys_map 
*map)
  */
 #define IOSYS_MAP_INIT_VADDR_IOMEM(vaddr_iomem_)   \
{   \
-   .vaddr_iomem = (vaddr_iomem_),  \
-   .is_iomem = true,   \
+   ._vaddr_iomem = (vaddr_iomem_), \
+   ._is_iomem = true,  \
}
 
 /**
@@ -197,8 +197,8 @@ static inline void *iosys_map_ptr(const struct iosys_map 
*map)
  */
 static inline void iosys_map_set_vaddr(struct iosys_map *map, void *vaddr)
 {
-   map->vaddr = vaddr;
-   map->is_iomem = false;
+   map->_vaddr = vaddr;
+   map->_is_iomem = false;
 }
 
 /**
@@ -211,8 +211,8 @@ static inline void iosys_map_set_vaddr(struct iosys_map 
*map, void *vaddr)
 static inline void iosys_map_set_vaddr_iomem(struct iosys_map *map,
 void __iomem *vaddr_iomem)
 {
-   map->vaddr_iomem = vaddr_iomem;
-   map->is_iomem = true;
+   map->_vaddr_iomem = vaddr_iomem;
+   map->_is_iomem = true;
 }
 
 /**
@@ -229,12 +229,12 @@ static inline void iosys_map_set_vaddr_iomem(struct 
iosys_map *map,
 static inline bool iosys_map_is_equal(const struct iosys_map *lhs,
  const struct iosys_map *rhs)
 {
-   if (lhs->is_iomem != rhs->is_iomem)
+   if (lhs->_is_iomem != rhs->_is_iomem)
return false;
-   else if (lhs->is_iomem)
-   return lhs->vaddr_iomem == rhs->vaddr_iomem;
+   else if (lhs->_is_iomem)
+   return lhs->_vaddr_iomem == rhs->_vaddr_iomem;
else
-   return lhs->vaddr == rhs->vaddr;
+   return lhs->_vaddr == rhs->_vaddr;
 }
 
 /**
@@ -279,11 +279,11 @@ static inline bool iosys_map_is_set(const struct 
iosys_map *map)
  */
 static inline void iosys_map_clear(struct iosys_map *map)
 {
-   if (map->is_iomem) {
-   map->vaddr_iomem = NULL;
-   map->is_iomem = false;
+   if (map->_is_iomem) {
+   map->_vaddr_iomem = NULL;
+   map->_is_iomem = false;
} else {
-   map->vaddr = NULL;
+   map->_vaddr = NULL;
}
 }
 
@@ -338,9 +338,9 @@ static inline void iosys_map_memcpy_from(void *dst, const 
struct iosys_map *src,
 static inline void iosys_map_incr(struct iosys_map *map, size_t incr)
 {
if (iosys_map_is_iomem(map))
-   map->vaddr_iomem += incr;
+   map->_vaddr_iomem += incr;
else
-   map->vaddr += incr;
+   map->_vaddr += incr;
 }
 
 /**
-- 
2.49.0



Re: [PATCH 2/3] drm/amdgpu: Adding amdgpu CRIU ioctl

2025-05-21 Thread kernel test robot
Hi David,

kernel test robot noticed the following build warnings:

[auto build test WARNING on drm/drm-next]
[also build test WARNING on next-20250521]
[cannot apply to drm-exynos/exynos-drm-next linus/master v6.15-rc7]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:
https://github.com/intel-lab-lkp/linux/commits/David-Francis/drm-amdgpu-Adding-amdgpu-CRIU-ioctl/20250521-230706
base:   git://anongit.freedesktop.org/drm/drm drm-next
patch link:
https://lore.kernel.org/r/20250521140649.4058526-3-David.Francis%40amd.com
patch subject: [PATCH 2/3] drm/amdgpu: Adding amdgpu CRIU ioctl
config: arm-randconfig-002-20250522 
(https://download.01.org/0day-ci/archive/20250522/202505221029.1z5ok2nq-...@intel.com/config)
compiler: clang version 21.0.0git (https://github.com/llvm/llvm-project 
f819f46284f2a79790038e1f6649172789734ae8)
reproduce (this is a W=1 build): 
(https://download.01.org/0day-ci/archive/20250522/202505221029.1z5ok2nq-...@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot 
| Closes: 
https://lore.kernel.org/oe-kbuild-all/202505221029.1z5ok2nq-...@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/gpu/drm/amd/amdgpu/amdgpu_criu.c:160:42: warning: converting the 
>> result of '<<' to a boolean always evaluates to true 
>> [-Wtautological-constant-compare]
 160 | bo_bucket->alloc_flags = bo->flags & 
(!AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE);
 |^
   include/uapi/drm/amdgpu_drm.h:146:51: note: expanded from macro 
'AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE'
 146 | #define AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE  (1 << 9)
 |^
   1 warning generated.


vim +160 drivers/gpu/drm/amd/amdgpu/amdgpu_criu.c

   119  
   120  struct amdgpu_vm *avm = &((struct amdgpu_fpriv 
*)data->driver_priv)->vm;
   121  struct drm_amdgpu_criu_bo_bucket *bo_buckets;
   122  struct drm_amdgpu_criu_vm_bucket *vm_buckets;
   123  struct drm_gem_object *gobj;
   124  int vm_priv_index = 0;
   125  int bo_index = 0;
   126  int num_bos = 0;
   127  int fd, id, ret;
   128  
   129  spin_lock(&data->table_lock);
   130  idr_for_each_entry(&data->object_idr, gobj, id)
   131  num_bos += 1;
   132  spin_unlock(&data->table_lock);
   133  
   134  if (args->num_bos != num_bos) {
   135  ret = -EINVAL;
   136  goto exit;
   137  }
   138  
   139  bo_buckets = kvzalloc(num_bos * sizeof(*bo_buckets), 
GFP_KERNEL);
   140  if (!bo_buckets) {
   141  ret = -ENOMEM;
   142  goto free_buckets;
   143  }
   144  
   145  vm_buckets = kvzalloc(args->num_vms * sizeof(*vm_buckets), 
GFP_KERNEL);
   146  if (!vm_buckets) {
   147  ret = -ENOMEM;
   148  goto free_vms;
   149  }
   150  
   151  idr_for_each_entry(&data->object_idr, gobj, id) {
   152  struct amdgpu_bo *bo = gem_to_amdgpu_bo(gobj);
   153  struct drm_amdgpu_criu_bo_bucket *bo_bucket;
   154  struct amdgpu_vm_bo_base *vm_bo_base;
   155  
   156  bo_bucket = &bo_buckets[bo_index];
   157  
   158  bo_bucket->size = amdgpu_bo_size(bo);
   159  bo_bucket->offset = amdgpu_bo_mmap_offset(bo);
 > 160  bo_bucket->alloc_flags = bo->flags & 
 > (!AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE);
   161  bo_bucket->preferred_domains = bo->preferred_domains;
   162  
   163  if (is_import(bo))
   164  bo_bucket->flags |= 
AMDGPU_CRIU_BO_FLAG_IS_IMPORT;
   165  
   166  drm_gem_prime_handle_to_fd(dev, data, id, 0, &fd);
   167  if (fd)
   168  bo_bucket->dmabuf_fd = fd;
   169  
   170  vm_bo_base = bo->vm_bo;
   171  
   172  while (vm_bo_base) {
   173  struct amdgpu_bo_va *bo_va = 
container_of(vm_bo_base, struct amdgpu_bo_va, base);
   174  struct amdgpu_bo_va_mapping *mapping;
   175  
   176  if (vm_bo_base->vm == avm) {
   177  list_for_each_entry(mapping, 
&bo_va->invalids, list) {
   178 

Re: [PATCH v10 08/10] drm: Get rid of drm_sched_job.id

2025-05-21 Thread kernel test robot
Hi Pierre-Eric,

kernel test robot noticed the following build errors:

[auto build test ERROR on drm-xe/drm-xe-next]
[also build test ERROR on next-20250521]
[cannot apply to lwn/docs-next linus/master v6.15-rc7]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:
https://github.com/intel-lab-lkp/linux/commits/Pierre-Eric-Pelloux-Prayer/drm-debugfs-Output-client_id-in-in-drm_clients_info/20250521-235024
base:   https://gitlab.freedesktop.org/drm/xe/kernel.git drm-xe-next
patch link:
https://lore.kernel.org/r/20250521154531.10541-9-pierre-eric.pelloux-prayer%40amd.com
patch subject: [PATCH v10 08/10] drm: Get rid of drm_sched_job.id
config: i386-buildonly-randconfig-002-20250522 
(https://download.01.org/0day-ci/archive/20250522/202505221031.qxnz9ikv-...@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): 
(https://download.01.org/0day-ci/archive/20250522/202505221031.qxnz9ikv-...@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot 
| Closes: 
https://lore.kernel.org/oe-kbuild-all/202505221031.qxnz9ikv-...@intel.com/

All errors (new ones prefixed by >>):

   In file included from include/trace/define_trace.h:119,
from drivers/gpu/drm/lima/lima_trace.h:50,
from drivers/gpu/drm/lima/lima_trace.c:7:
   include/trace/../../drivers/gpu/drm/lima/lima_trace.h: In function 
'do_trace_event_raw_event_lima_task':
>> include/trace/../../drivers/gpu/drm/lima/lima_trace.h:24:46: error: 'struct 
>> drm_sched_job' has no member named 'id'
  24 | __entry->task_id = task->base.id;
 |  ^
   include/trace/trace_events.h:427:11: note: in definition of macro 
'__DECLARE_EVENT_CLASS'
 427 | { assign; }  
   \
 |   ^~
   include/trace/trace_events.h:435:23: note: in expansion of macro 'PARAMS'
 435 |   PARAMS(assign), PARAMS(print)) 
   \
 |   ^~
   include/trace/../../drivers/gpu/drm/lima/lima_trace.h:13:1: note: in 
expansion of macro 'DECLARE_EVENT_CLASS'
  13 | DECLARE_EVENT_CLASS(lima_task,
 | ^~~
   include/trace/../../drivers/gpu/drm/lima/lima_trace.h:23:9: note: in 
expansion of macro 'TP_fast_assign'
  23 | TP_fast_assign(
 | ^~
   In file included from include/trace/define_trace.h:120:
   include/trace/../../drivers/gpu/drm/lima/lima_trace.h: In function 
'do_perf_trace_lima_task':
>> include/trace/../../drivers/gpu/drm/lima/lima_trace.h:24:46: error: 'struct 
>> drm_sched_job' has no member named 'id'
  24 | __entry->task_id = task->base.id;
 |  ^
   include/trace/perf.h:51:11: note: in definition of macro 
'__DECLARE_EVENT_CLASS'
  51 | { assign; }  
   \
 |   ^~
   include/trace/perf.h:67:23: note: in expansion of macro 'PARAMS'
  67 |   PARAMS(assign), PARAMS(print)) 
   \
 |   ^~
   include/trace/../../drivers/gpu/drm/lima/lima_trace.h:13:1: note: in 
expansion of macro 'DECLARE_EVENT_CLASS'
  13 | DECLARE_EVENT_CLASS(lima_task,
 | ^~~
   include/trace/../../drivers/gpu/drm/lima/lima_trace.h:23:9: note: in 
expansion of macro 'TP_fast_assign'
  23 | TP_fast_assign(
 | ^~


vim +24 include/trace/../../drivers/gpu/drm/lima/lima_trace.h

7f60c4b9d964f6 Qiang Yu2020-03-07  12  
7f60c4b9d964f6 Qiang Yu2020-03-07  13  
DECLARE_EVENT_CLASS(lima_task,
7f60c4b9d964f6 Qiang Yu2020-03-07  14   TP_PROTO(struct 
lima_sched_task *task),
7f60c4b9d964f6 Qiang Yu2020-03-07  15   TP_ARGS(task),
7f60c4b9d964f6 Qiang Yu2020-03-07  16   TP_STRUCT__entry(
7f60c4b9d964f6 Qiang Yu2020-03-07  17   
__field(uint64_t, task_id)
7f60c4b9d964f6 Qiang Yu2020-03-07  18   
__field(unsigned int, context)
7f60c4b9d964f6 Qiang Yu2020-03-07  19   
__field(unsigned int, seqno)
7f60c4b9d964f6 Qiang Yu2020-03-07  20   __string(pipe, 
task->base.sched->name)
7f60c4b9d964f6 Qiang Yu2020-03-07  21   ),
7f

Re: [RFC 0/2] Introduce a sysfs interface for lmem information

2025-05-21 Thread Tvrtko Ursulin



On 21/05/2025 18:10, Krzysztof Niemiec wrote:

On 2025-05-21 at 09:06:43 GMT, Tvrtko Ursulin wrote:


On 20/05/2025 16:01, Joonas Lahtinen wrote:

(+ Tvrtko, Rodrigo and Jani)

Quoting Krzysztof Niemiec (2025-05-19 18:34:14)

Hi,

This series introduces a way for applications to read local memory
information via files in the sysfs. So far the only way to do this was
via i915_query ioctl. This is slightly less handy than sysfs for
external users. Additionally, the ioctl has a capability check which
limits which users of a system might use it to get information.

The goals of this series are:

  1) Introduce a simpler interface to access lmem information,
  2) Lift the CAP_PERFMON check on that information, OR provide
 the administrator with a way to optionally lift it.

The first patch introduces the general mechanism without protections.
This will effectively lift a capability check on obtaining the memory
information. The second patch introduces that check back inside the
_show() functions, but also adds a sysctl parameter allowing to override
the checks, if an administrator so decides.

I'm sending this as RFC because I have a feeling that there's no
consensus whether memory information exposed in the patch should be
protected or not. Showing it to any user is strictly speaking an info
leak, but the severity thereof might be considered not that high, so I'd
rather leave it up to discussion first.

If we decide for lifting the check, the first patch is sufficient.


Nack on that.

CPU memory footprint and GPU memory footprint have a very different
nature. This was discussed to quite a length, please refer to mailing
list archives.


If we
decide against it, the second patch protects the information by default,
but with a way to expose it as a conscious decision of the admin. I find
it a decent compromise.


No need for the added complexity if we were to add a sysfs.

If a sysfs is added, it can be made root readable by default but system
admin is free to chown or chmod the file for more relaxed access. Back
in the original discussion time, this was omitted for lack of users.


Agreed, no need to complicate with redundant access controls in the kernel.


Even now, userspace/sysadmin could already essentially use setuid helper
process that will only report the memory statistics.

So I'm not really fully convinced this is needed at all.

And if it is to be added for the convenience of usersppace, it should
probably then be considered to be a standard interface across DRM drivers
ala fdinfo or cgroups.


Cgroup visibility for device memory exists in principle although i915 hasn't
been wired up to it.

For system memory (integrated GPUs) there is some work in progress around
memcg accounting, although I am unsure if i915 would be automatically
covered or not.

Also going a step back, from MangoHUDs point of view, I don't really see why
total GPU memory is very interesting? I would have thought it is more
interesting to know how much the monitored client is using, which is already
available via fdinfo. Total memory sounds like something which it could
leave to interpretation by the entity looking at the traces. (If the
monitored client is running alone then total_free =~ total - client, and if
it isn't running alone then it doesn't matter, no?)



They use it to plot the VRAM usage so you have a rough idea of how much
of the total the client is using. [1]

[1] 
https://github.com/flightlessmango/MangoHud/blob/master/src/hud_elements.cpp#L1471-L1485


I get what it does, I just don't see the huge value in plotting the 
total. Nevertheless it is available from the memory query, that part is 
not privileged.


If the query is too cumbersome, for some reason, I could be convinced 
for a total in sysfs but the rest looks too much.


Regards,

Tvrtko


This change has been requested in these parallel issues for i915 and Xe:

https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14153
https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/4861

Thanks
Krzysztof

Krzysztof Niemiec (2):
drm/i915: Expose local memory information via sysfs
drm/i915: Add protections to sysfs local memory information

   drivers/gpu/drm/i915/i915_sysfs.c  |   6 +
   drivers/gpu/drm/i915/intel_memory_region.c | 136 +
   drivers/gpu/drm/i915/intel_memory_region.h |   3 +
   3 files changed, 145 insertions(+)

--
2.45.2
_






  1   2   >