Re: [PATCH] drm/ast: Fix soft lockup

2024-03-27 Thread Jocelyn Falempe

Hi,

Thanks for your patch.
I'm wondering how you can trigger this infinite loop ?

Also this looks like a simple fix, that can be easily backported, so I'm 
adding stable in Cc.


If Thomas has no objections, I can push it to drm-misc-fixes.

Reviewed-by: Jocelyn Falempe 

--

Jocelyn

On 25/03/2024 04:35, Jammy Huang wrote:

Avoid infinite-loop in ast_dp_set_on_off().

Signed-off-by: Jammy Huang 
---
  drivers/gpu/drm/ast/ast_dp.c | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
index ebb6d8ebd44e..1e9259416980 100644
--- a/drivers/gpu/drm/ast/ast_dp.c
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -180,6 +180,7 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on)
  {
struct ast_device *ast = to_ast_device(dev);
u8 video_on_off = on;
+   u32 i = 0;
  
  	// Video On/Off

ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE3, (u8) 
~AST_DP_VIDEO_ENABLE, on);
@@ -192,6 +193,8 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on)
ASTDP_MIRROR_VIDEO_ENABLE) != 
video_on_off) {
// wait 1 ms
mdelay(1);
+   if (++i > 200)
+   break;
}
}
  }

base-commit: b0546776ad3f332e215cebc0b063ba4351971cca




Re: [PATCH v5 00/13] drm/ast: Detect connector status for VGA and SIL164

2024-03-21 Thread Jocelyn Falempe

Hi,

Thanks for those patches, that's really a good enhancement to the ast 
driver, and fits well with the BMC virtual connector.



I've reviewed the whole series, and it looks good to me.

Reviewed-by: Jocelyn Falempe 

--

Jocelyn

On 20/03/2024 10:34, Thomas Zimmermann wrote:

Detect the status of the VGA or SIL164 conenctor by polling the DDC
channel. Update the status at runtime and flip the BMC status as well.

Patches 1 adds a missing include statement that will be required to
make later patches compile.

Patches 2 and 3 simplify the VGA and SIL164 connectors, such that no
additional data structure is required. These patches have been reviewed
before as part of the series at [1].

Patches 4 to 10 improve the I2C code that is used to retrieve the
monitor's EDID data. It's now fully managed, it acquires the necessary
lock automatically and it is called DDC, which better represents its
purpose than I2C.

Patches 11 to 13 finally implement polling. Patch 11 updates ast's
EDID code to be up-to-date. The helper drm_connector_get_modes() reads
the EDID via DDC and updates the property. No driver code is required.
Patch 12 uses a similar pattern to detect the presence of the monitor
and sets the connector status accordingly. As polling also needs to be
cleaned up, patch 13 adds the necessary helpers to do so.

Tested on AST2500 hardware and BMC output. The BMC connector now also
flips its status correctly at runtime.

[1] https://patchwork.freedesktop.org/series/104547/

v5:
- share implementation in drm_connector_helper_detect_ctx() (Maxime)
- test for DDC presence with drm_probe_ddc() (Maxime, Jani)
- perform managed cleanup of poll thread

Thomas Zimmermann (13):
   drm/ast: Include  where necessary
   drm/ast: Fail probing if DDC channel could not be initialized
   drm/ast: Remove struct ast_{vga,sil165}_connector
   drm/ast: Allocate instance of struct ast_i2c_chan with managed helpers
   drm/ast: Move DDC code to ast_ddc.{c,h}
   drm/ast: Rename struct ast_i2c_chan to struct ast_ddc
   drm/ast: Pass AST device to ast_ddc_create()
   drm/ast: Store AST device in struct ast_ddc
   drm/ast: Rename struct i2c_algo_bit_data callbacks and their
 parameters
   drm/ast: Acquire I/O-register lock in DDC code
   drm/ast: Use drm_connector_helper_get_modes()
   drm/ast: Implement polling for VGA and SIL164 connectors
   drm/ast: Automatically clean up poll helper

  drivers/gpu/drm/ast/Makefile |  10 +-
  drivers/gpu/drm/ast/{ast_i2c.c => ast_ddc.c} | 120 +--
  drivers/gpu/drm/ast/ast_ddc.h|  20 +++
  drivers/gpu/drm/ast/ast_drv.c|   1 +
  drivers/gpu/drm/ast/ast_drv.h|  39 +
  drivers/gpu/drm/ast/ast_main.c   |   1 +
  drivers/gpu/drm/ast/ast_mode.c   | 147 +--
  drivers/gpu/drm/drm_probe_helper.c   |  56 +++
  include/drm/drm_probe_helper.h   |   5 +
  9 files changed, 206 insertions(+), 193 deletions(-)
  rename drivers/gpu/drm/ast/{ast_i2c.c => ast_ddc.c} (54%)
  create mode 100644 drivers/gpu/drm/ast/ast_ddc.h





Re: [PATCH 12/43] drm/mgag200: Use fbdev-shmem

2024-03-18 Thread Jocelyn Falempe




On 18/03/2024 08:56, Thomas Zimmermann wrote:

Hi

Am 13.03.24 um 15:03 schrieb Jocelyn Falempe:

Hi,

Thanks, it looks good to me.

Reviewed-by: Jocelyn Falempe 


Thanks. Do you still have access to that broken realtime system? I 
wonder if this patch makes a difference, as there's now one large 
memcpy() less.


Hi,

Sure, I'll do some latency tests if I can get access to that server again.

Best regards,



Best regards
Thomas





Re: [PATCH v10 1/9] drm/panic: Add drm panic locking

2024-03-15 Thread Jocelyn Falempe




On 15/03/2024 16:28, John Ogness wrote:

On 2024-03-15, Jocelyn Falempe  wrote:

+static inline int drm_panic_trylock(struct drm_device *dev, unsigned long 
*flags)
+{
+   return raw_spin_trylock_irqsave(>mode_config.panic_lock, *flags);
+}


[...]


+static inline unsigned long drm_panic_lock(struct drm_device *dev)
+{
+   unsigned long flags;
+
+   raw_spin_lock_irqsave(>mode_config.panic_lock, flags);
+   return flags;
+}


I find it a bit strange that @flags is passed as an argument in the
trylock variant but returned in the lock variant. I would pass it as an
argument in both variants. Just a suggestion.


Or maybe I can do it as a macro instead of a static inline function, to 
have the same semantic as raw_spin_lock_irqsave() which modify the 
flags, without passing it as pointer, because it's also a macro.


https://elixir.bootlin.com/linux/latest/source/include/linux/spinlock.h#L296

#define drm_panic_lock(dev, flags) \
raw_spin_lock_irqsave(>mode_config.panic_lock, flags);



John Ogness



--

Jocelyn



[PATCH v10 9/9] drm/ast: Add drm_panic support

2024-03-15 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a message to
the screen when a kernel panic occurs.

v7
 * Use drm_for_each_primary_visible_plane()

v8:
 * Replace get_scanout_buffer() logic with drm_panic_set_buffer()
   (Thomas Zimmermann)
v9:
 * Revert to using get_scanout_buffer() (Sima)
 * move get_scanout_buffer() to plane helper functions

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/ast/ast_mode.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index a718646a66b8..49f2d8bd3377 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -700,12 +701,29 @@ static void 
ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,
ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x1, 0xdf, 0x20);
 }
 
+static int ast_primary_plane_helper_get_scanout_buffer(struct drm_plane *plane,
+  struct 
drm_scanout_buffer *sb)
+{
+   struct ast_plane *ast_plane = to_ast_plane(plane);
+
+   if (plane->state && plane->state->fb && ast_plane->vaddr) {
+   sb->format = plane->state->fb->format;
+   sb->width = plane->state->fb->width;
+   sb->height = plane->state->fb->height;
+   sb->pitch = plane->state->fb->pitches[0];
+   iosys_map_set_vaddr_iomem(>map, ast_plane->vaddr);
+   return 0;
+   }
+   return -ENODEV;
+}
+
 static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = {
DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
.atomic_check = ast_primary_plane_helper_atomic_check,
.atomic_update = ast_primary_plane_helper_atomic_update,
.atomic_enable = ast_primary_plane_helper_atomic_enable,
.atomic_disable = ast_primary_plane_helper_atomic_disable,
+   .get_scanout_buffer = ast_primary_plane_helper_get_scanout_buffer,
 };
 
 static const struct drm_plane_funcs ast_primary_plane_funcs = {
-- 
2.44.0



[PATCH v10 4/9] drm/panic: Add debugfs entry to test without triggering panic.

2024-03-15 Thread Jocelyn Falempe
Add a debugfs file, so you can test drm_panic without freezing
your machine. This is unsafe, and should be enabled only for
developer or tester.

To display the drm_panic screen on the device 0:
echo 1 > /sys/kernel/debug/dri/0/drm_panic_plane_0

v9:
 * Create a debugfs file for each plane in the device's debugfs
   directory. This allows to test for each plane of each GPU
   independently.

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/Kconfig |  9 
 drivers/gpu/drm/drm_panic.c | 43 -
 2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index f07ca38d3f98..6e41fbd16b3d 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -125,6 +125,15 @@ config DRM_PANIC_BACKGROUND_COLOR
depends on DRM_PANIC
default 0x00
 
+config DRM_PANIC_DEBUG
+   bool "Add a debug fs entry to trigger drm_panic"
+   depends on DRM_PANIC && DEBUG_FS
+   help
+ Add dri/[device]/drm_panic_plane_x in the kernel debugfs, to force the
+ panic handler to write the panic message to this plane scanout buffer.
+ This is unsafe and should not be enabled on a production build.
+ If in doubt, say "N".
+
 config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
 bool "Enable refcount backtrace history in the DP MST helpers"
depends on STACKTRACE_SUPPORT
diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c
index 2c3b2fffe659..cd2c7c2d1c59 100644
--- a/drivers/gpu/drm/drm_panic.c
+++ b/drivers/gpu/drm/drm_panic.c
@@ -493,6 +493,45 @@ static void drm_panic(struct kmsg_dumper *dumper, enum 
kmsg_dump_reason reason)
draw_panic_plane(plane);
 }
 
+
+/*
+ * DEBUG FS, This is currently unsafe.
+ * Create one file per plane, so it's possible to debug one plane at a time.
+ */
+#ifdef CONFIG_DRM_PANIC_DEBUG
+#include 
+
+static ssize_t debugfs_trigger_write(struct file *file, const char __user 
*user_buf,
+size_t count, loff_t *ppos)
+{
+   bool run;
+
+   if (kstrtobool_from_user(user_buf, count, ) == 0 && run) {
+   struct drm_plane *plane = file->private_data;
+
+   draw_panic_plane(plane);
+   }
+   return count;
+}
+
+static const struct file_operations dbg_drm_panic_ops = {
+   .owner = THIS_MODULE,
+   .write = debugfs_trigger_write,
+   .open = simple_open,
+};
+
+static void debugfs_register_plane(struct drm_plane *plane, int index)
+{
+   char fname[32];
+
+   snprintf(fname, 32, "drm_panic_plane_%d", index);
+   debugfs_create_file(fname, 0200, plane->dev->debugfs_root,
+   plane, _drm_panic_ops);
+}
+#else
+static void debugfs_register_plane(struct drm_plane *plane, int index) {}
+#endif /* CONFIG_DRM_PANIC_DEBUG */
+
 /**
  * drm_panic_register() - Initialize DRM panic for a device
  * @dev: the drm device on which the panic screen will be displayed.
@@ -512,8 +551,10 @@ void drm_panic_register(struct drm_device *dev)
plane->kmsg_panic.max_reason = KMSG_DUMP_PANIC;
if (kmsg_dump_register(>kmsg_panic))
drm_warn(dev, "Failed to register panic handler\n");
-   else
+   else {
+   debugfs_register_plane(plane, registered_plane);
registered_plane++;
+   }
}
if (registered_plane)
drm_info(dev, "Registered %d planes with drm panic\n", 
registered_plane);
-- 
2.44.0



[PATCH v10 8/9] drm/imx: Add drm_panic support

2024-03-15 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a user-friendly
message to the screen when a kernel panic occurs.

v7:
 * use drm_panic_gem_get_scanout_buffer() helper

v8:
 * Replace get_scanout_buffer() logic with drm_panic_set_buffer()

v9:
 * Revert to using get_scanout_buffer() (Sima)
 * move get_scanout_buffer() to plane helper functions

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c 
b/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c
index dade8b59feae..3e21d2a1a124 100644
--- a/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c
@@ -772,6 +772,12 @@ static const struct drm_plane_helper_funcs 
ipu_plane_helper_funcs = {
.atomic_disable = ipu_plane_atomic_disable,
.atomic_update = ipu_plane_atomic_update,
 };
+static const struct drm_plane_helper_funcs ipu_primary_plane_helper_funcs = {
+   .atomic_check = ipu_plane_atomic_check,
+   .atomic_disable = ipu_plane_atomic_disable,
+   .atomic_update = ipu_plane_atomic_update,
+   .get_scanout_buffer = drm_panic_gem_get_scanout_buffer,
+};
 
 bool ipu_plane_atomic_update_pending(struct drm_plane *plane)
 {
@@ -916,7 +922,10 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, 
struct ipu_soc *ipu,
ipu_plane->dma = dma;
ipu_plane->dp_flow = dp;
 
-   drm_plane_helper_add(_plane->base, _plane_helper_funcs);
+   if (type == DRM_PLANE_TYPE_PRIMARY)
+   drm_plane_helper_add(_plane->base, 
_primary_plane_helper_funcs);
+   else
+   drm_plane_helper_add(_plane->base, _plane_helper_funcs);
 
if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG)
ret = drm_plane_create_zpos_property(_plane->base, zpos, 0,
-- 
2.44.0



[PATCH v10 6/9] drm/simpledrm: Add drm_panic support

2024-03-15 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a user-friendly
message to the screen when a kernel panic occurs.

v8:
 * Replace get_scanout_buffer() with drm_panic_set_buffer()
   (Thomas Zimmermann)

v9:
 * Revert to using get_scanout_buffer() (Sima)
 * move get_scanout_buffer() to plane helper functions (Thomas Zimmermann)

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/tiny/simpledrm.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 7ce1c4617675..f498665be8c4 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #define DRIVER_NAME"simpledrm"
@@ -671,11 +672,26 @@ static void 
simpledrm_primary_plane_helper_atomic_disable(struct drm_plane *plan
drm_dev_exit(idx);
 }
 
+static int simpledrm_primary_plane_helper_get_scanout_buffer(struct drm_plane 
*plane,
+struct 
drm_scanout_buffer *sb)
+{
+   struct simpledrm_device *sdev = simpledrm_device_of_dev(plane->dev);
+
+   sb->width = sdev->mode.hdisplay;
+   sb->height = sdev->mode.vdisplay;
+   sb->format = sdev->format;
+   sb->pitch = sdev->pitch;
+   sb->map = sdev->screen_base;
+
+   return 0;
+}
+
 static const struct drm_plane_helper_funcs 
simpledrm_primary_plane_helper_funcs = {
DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
.atomic_check = simpledrm_primary_plane_helper_atomic_check,
.atomic_update = simpledrm_primary_plane_helper_atomic_update,
.atomic_disable = simpledrm_primary_plane_helper_atomic_disable,
+   .get_scanout_buffer = simpledrm_primary_plane_helper_get_scanout_buffer,
 };
 
 static const struct drm_plane_funcs simpledrm_primary_plane_funcs = {
-- 
2.44.0



[PATCH v10 7/9] drm/mgag200: Add drm_panic support

2024-03-15 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a message to
the screen when a kernel panic occurs.

v5:
 * Also check that the plane is visible and primary. (Thomas Zimmermann)

v7:
 * use drm_for_each_primary_visible_plane()

v8:
 * Replace get_scanout_buffer() logic with drm_panic_set_buffer()
   (Thomas Zimmermann)

v9:
 * Revert to using get_scanout_buffer() (Sima)
 * move get_scanout_buffer() to plane helper functions (Thomas Zimmermann)

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/mgag200/mgag200_drv.h  |  7 ++-
 drivers/gpu/drm/mgag200/mgag200_mode.c | 18 ++
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h 
b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 765e49fd8911..58a0e62eaf18 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -366,6 +366,7 @@ struct drm_crtc_state;
 struct drm_display_mode;
 struct drm_plane;
 struct drm_atomic_state;
+struct drm_scanout_buffer;
 
 extern const uint32_t mgag200_primary_plane_formats[];
 extern const size_t   mgag200_primary_plane_formats_size;
@@ -379,12 +380,16 @@ void mgag200_primary_plane_helper_atomic_enable(struct 
drm_plane *plane,
struct drm_atomic_state *state);
 void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane,
 struct drm_atomic_state 
*old_state);
+int mgag200_primary_plane_helper_get_scanout_buffer(struct drm_plane *plane,
+   struct drm_scanout_buffer 
*sb);
+
 #define MGAG200_PRIMARY_PLANE_HELPER_FUNCS \
DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, \
.atomic_check = mgag200_primary_plane_helper_atomic_check, \
.atomic_update = mgag200_primary_plane_helper_atomic_update, \
.atomic_enable = mgag200_primary_plane_helper_atomic_enable, \
-   .atomic_disable = mgag200_primary_plane_helper_atomic_disable
+   .atomic_disable = mgag200_primary_plane_helper_atomic_disable, \
+   .get_scanout_buffer = mgag200_primary_plane_helper_get_scanout_buffer
 
 #define MGAG200_PRIMARY_PLANE_FUNCS \
.update_plane = drm_atomic_helper_update_plane, \
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c 
b/drivers/gpu/drm/mgag200/mgag200_mode.c
index e17cb4c5f774..8f368ecca4d4 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mgag200_drv.h"
@@ -546,6 +547,23 @@ void mgag200_primary_plane_helper_atomic_disable(struct 
drm_plane *plane,
msleep(20);
 }
 
+int mgag200_primary_plane_helper_get_scanout_buffer(struct drm_plane *plane,
+   struct drm_scanout_buffer 
*sb)
+{
+   struct mga_device *mdev = to_mga_device(plane->dev);
+   struct iosys_map map = IOSYS_MAP_INIT_VADDR_IOMEM(mdev->vram);
+
+   if (plane->state && plane->state->fb) {
+   sb->format = plane->state->fb->format;
+   sb->width = plane->state->fb->width;
+   sb->height = plane->state->fb->height;
+   sb->pitch = plane->state->fb->pitches[0];
+   sb->map = map;
+   return 0;
+   }
+   return -ENODEV;
+}
+
 /*
  * CRTC
  */
-- 
2.44.0



[PATCH v10 5/9] drm/fb_dma: Add generic get_scanout_buffer() for drm_panic

2024-03-15 Thread Jocelyn Falempe
This was initialy done for imx6, but should work on most drivers
using drm_fb_dma_helper.

v8:
 * Replace get_scanout_buffer() logic with drm_panic_set_buffer()
   (Thomas Zimmermann)

v9:
 * go back to get_scanout_buffer()
 * move get_scanout_buffer() to plane helper functions

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/drm_fb_dma_helper.c | 47 +
 include/drm/drm_fb_dma_helper.h |  4 +++
 2 files changed, 51 insertions(+)

diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c 
b/drivers/gpu/drm/drm_fb_dma_helper.c
index 3b535ad1b07c..010327069ad4 100644
--- a/drivers/gpu/drm/drm_fb_dma_helper.c
+++ b/drivers/gpu/drm/drm_fb_dma_helper.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -148,3 +149,49 @@ void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
}
 }
 EXPORT_SYMBOL_GPL(drm_fb_dma_sync_non_coherent);
+
+#if defined(CONFIG_DRM_PANIC)
+/**
+ * @plane: DRM primary plane
+ * @drm_scanout_buffer: scanout buffer for the panic handler
+ * Returns: 0 or negative error code
+ *
+ * Generic get_scanout_buffer() implementation, for drivers that uses the
+ * drm_fb_dma_helper.
+ */
+int drm_panic_gem_get_scanout_buffer(struct drm_plane *plane,
+struct drm_scanout_buffer *sb)
+{
+   struct drm_gem_dma_object *dma_obj;
+   struct drm_framebuffer *fb;
+
+   fb = plane->state->fb;
+   /* Only support linear modifier */
+   if (fb->modifier != DRM_FORMAT_MOD_LINEAR)
+   return -ENODEV;
+
+   dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
+
+   /* Buffer should be accessible from the CPU */
+   if (dma_obj->base.import_attach)
+   return -ENODEV;
+
+   /* Buffer should be already mapped to CPU */
+   if (!dma_obj->vaddr)
+   return -ENODEV;
+
+   iosys_map_set_vaddr(>map, dma_obj->vaddr);
+   sb->format = fb->format;
+   sb->height = fb->height;
+   sb->width = fb->width;
+   sb->pitch = fb->pitches[0];
+   return 0;
+}
+#else
+int drm_panic_gem_get_scanout_buffer(struct drm_plane *plane,
+struct drm_scanout_buffer *sb)
+{
+   return -ENODEV;
+}
+#endif
+EXPORT_SYMBOL(drm_panic_gem_get_scanout_buffer);
diff --git a/include/drm/drm_fb_dma_helper.h b/include/drm/drm_fb_dma_helper.h
index d5e036c57801..61f24c2aba2f 100644
--- a/include/drm/drm_fb_dma_helper.h
+++ b/include/drm/drm_fb_dma_helper.h
@@ -7,6 +7,7 @@
 struct drm_device;
 struct drm_framebuffer;
 struct drm_plane_state;
+struct drm_scanout_buffer;
 
 struct drm_gem_dma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb,
unsigned int plane);
@@ -19,5 +20,8 @@ void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
  struct drm_plane_state *old_state,
  struct drm_plane_state *state);
 
+int drm_panic_gem_get_scanout_buffer(struct drm_plane *plane,
+struct drm_scanout_buffer *sb);
+
 #endif
 
-- 
2.44.0



[PATCH v10 3/9] drm/panic: Add support for color format conversion

2024-03-15 Thread Jocelyn Falempe
Add support for the following formats:
DRM_FORMAT_RGB565
DRM_FORMAT_RGBA5551
DRM_FORMAT_XRGB1555
DRM_FORMAT_ARGB1555
DRM_FORMAT_RGB888
DRM_FORMAT_XRGB
DRM_FORMAT_ARGB
DRM_FORMAT_XBGR
DRM_FORMAT_XRGB2101010
DRM_FORMAT_ARGB2101010

v10:
 * move and simplify the functions from the drm format helper to drm_panic

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/drm_panic.c | 272 ++--
 1 file changed, 262 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c
index faa64961c0f2..2c3b2fffe659 100644
--- a/drivers/gpu/drm/drm_panic.c
+++ b/drivers/gpu/drm/drm_panic.c
@@ -81,15 +81,155 @@ static const struct drm_panic_line logo[] = {
PANIC_LINE(" \\___)=(___/"),
 };
 
-static void drm_panic_fill32(struct iosys_map *map, unsigned int pitch,
+/*
+ * Color conversion
+ */
+
+static u16 convert_xrgb_to_rgb565(u32 pix)
+{
+   return ((pix & 0x00F8) >> 8) |
+  ((pix & 0xFC00) >> 5) |
+  ((pix & 0x00F8) >> 3);
+}
+
+static u16 convert_xrgb_to_rgba5551(u32 pix)
+{
+   return ((pix & 0x00f8) >> 8) |
+  ((pix & 0xf800) >> 5) |
+  ((pix & 0x00f8) >> 2) |
+  BIT(0); /* set alpha bit */
+}
+
+static u16 convert_xrgb_to_xrgb1555(u32 pix)
+{
+   return ((pix & 0x00f8) >> 9) |
+  ((pix & 0xf800) >> 6) |
+  ((pix & 0x00f8) >> 3);
+}
+
+static u16 convert_xrgb_to_argb1555(u32 pix)
+{
+   return BIT(15) | /* set alpha bit */
+  ((pix & 0x00f8) >> 9) |
+  ((pix & 0xf800) >> 6) |
+  ((pix & 0x00f8) >> 3);
+}
+
+static u32 convert_xrgb_to_argb(u32 pix)
+{
+   return pix | GENMASK(31, 24); /* fill alpha bits */
+}
+
+static u32 convert_xrgb_to_xbgr(u32 pix)
+{
+   return ((pix & 0x00ff) >> 16) <<  0 |
+  ((pix & 0xff00) >>  8) <<  8 |
+  ((pix & 0x00ff) >>  0) << 16 |
+  ((pix & 0xff00) >> 24) << 24;
+}
+
+static u32 convert_xrgb_to_abgr(u32 pix)
+{
+   return ((pix & 0x00ff) >> 16) <<  0 |
+  ((pix & 0xff00) >>  8) <<  8 |
+  ((pix & 0x00ff) >>  0) << 16 |
+  GENMASK(31, 24); /* fill alpha bits */
+}
+
+static u32 convert_xrgb_to_xrgb2101010(u32 pix)
+{
+   pix = ((pix & 0x00FF) << 2) |
+ ((pix & 0xFF00) << 4) |
+ ((pix & 0x00FF) << 6);
+   return pix | ((pix >> 8) & 0x00300C03);
+}
+
+static u32 convert_xrgb_to_argb2101010(u32 pix)
+{
+   pix = ((pix & 0x00FF) << 2) |
+ ((pix & 0xFF00) << 4) |
+ ((pix & 0x00FF) << 6);
+   return GENMASK(31, 30) /* set alpha bits */ | pix | ((pix >> 8) & 
0x00300C03);
+}
+
+/*
+ * convert_from_xrgb - convert one pixel from xrgb to the desired 
format
+ * @color: input color, in xrgb format
+ * @format: output format
+ *
+ * Returns:
+ * Color in the format specified, casted to u32.
+ * Or 0 if the format is not supported.
+ */
+static u32 convert_from_xrgb(u32 color, u32 format)
+{
+   switch (format) {
+   case DRM_FORMAT_RGB565:
+   return convert_xrgb_to_rgb565(color);
+   case DRM_FORMAT_RGBA5551:
+   return convert_xrgb_to_rgba5551(color);
+   case DRM_FORMAT_XRGB1555:
+   return convert_xrgb_to_xrgb1555(color);
+   case DRM_FORMAT_ARGB1555:
+   return convert_xrgb_to_argb1555(color);
+   case DRM_FORMAT_RGB888:
+   case DRM_FORMAT_XRGB:
+   return color;
+   case DRM_FORMAT_ARGB:
+   return convert_xrgb_to_argb(color);
+   case DRM_FORMAT_XBGR:
+   return convert_xrgb_to_xbgr(color);
+   case DRM_FORMAT_ABGR:
+   return convert_xrgb_to_abgr(color);
+   case DRM_FORMAT_XRGB2101010:
+   return convert_xrgb_to_xrgb2101010(color);
+   case DRM_FORMAT_ARGB2101010:
+   return convert_xrgb_to_argb2101010(color);
+   default:
+   WARN_ONCE(1, "Can't convert to %p4cc\n", );
+   return 0;
+   }
+}
+
+/*
+ * Blit & Fill
+ */
+static void drm_panic_blit16(struct iosys_map *dmap, unsigned int dpitch,
+const u8 *sbuf8, unsigned int spitch,
 unsigned int height, unsigned int width,
-u32 color)
+u16 fg16, u16 bg16)
 {
unsigned int y, x;
+   u16 val16;
 
-   

[PATCH v10 2/9] drm/panic: Add a drm panic handler

2024-03-15 Thread Jocelyn Falempe
This module displays a user friendly message when a kernel panic
occurs. It currently doesn't contain any debug information,
but that can be added later.

v2
 * Use get_scanout_buffer() instead of the drm client API.
  (Thomas Zimmermann)
 * Add the panic reason to the panic message (Nerdopolis)
 * Add an exclamation mark (Nerdopolis)

v3
 * Rework the drawing functions, to write the pixels line by line and
 to use the drm conversion helper to support other formats.
 (Thomas Zimmermann)

v4
 * Use drm_fb_r1_to_32bit for fonts (Thomas Zimmermann)
 * Remove the default y to DRM_PANIC config option (Thomas Zimmermann)
 * Add foreground/background color config option
 * Fix the bottom lines not painted if the framebuffer height
   is not a multiple of the font height.
 * Automatically register the device to drm_panic, if the function
   get_scanout_buffer exists. (Thomas Zimmermann)

v5
 * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
 * Also add drm_fb_fill() to fill area with background color.
 * Add draw_pixel_xy() API for drivers that can't provide a linear buffer.
 * Add a flush() callback for drivers that needs to synchronize the buffer.
 * Add a void *private field, so drivers can pass private data to
   draw_pixel_xy() and flush().

v6
 * Fix sparse warning for panic_msg and logo.

v7
 * Add select DRM_KMS_HELPER for the color conversion functions.

v8
 * Register directly each plane to the panic notifier (Sima)
 * Add raw_spinlock to properly handle concurrency (Sima)
 * Register plane instead of device, to avoid looping through plane
   list, and simplify code.
 * Replace get_scanout_buffer() logic with drm_panic_set_buffer()
  (Thomas Zimmermann)
 * Removed the draw_pixel_xy() API, will see later if it can be added back.

v9
 * Revert to using get_scanout_buffer() (Sima)
 * Move get_scanout_buffer() and panic_flush() to the plane helper
   functions (Thomas Zimmermann)
 * Register all planes with get_scanout_buffer() to the panic notifier
 * Use drm_panic_lock() to protect against race (Sima)

v10
 * Move blit and fill functions back in drm_panic (Thomas Zimmermann).
 * Simplify the text drawing functions.
 * Use kmsg_dumper instead of panic_notifier (Sima).

Signed-off-by: Jocelyn Falempe 
---
 Documentation/gpu/drm-kms.rst|  12 +
 drivers/gpu/drm/Kconfig  |  23 ++
 drivers/gpu/drm/Makefile |   1 +
 drivers/gpu/drm/drm_drv.c|   4 +
 drivers/gpu/drm/drm_panic.c  | 288 +++
 drivers/gpu/drm/drm_plane.c  |   1 +
 include/drm/drm_modeset_helper_vtables.h |  37 +++
 include/drm/drm_panic.h  |  52 
 include/drm/drm_plane.h  |   6 +
 9 files changed, 424 insertions(+)
 create mode 100644 drivers/gpu/drm/drm_panic.c

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 13d3627d8bc0..b64334661aeb 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -398,6 +398,18 @@ Plane Damage Tracking Functions Reference
 .. kernel-doc:: include/drm/drm_damage_helper.h
:internal:
 
+Plane Panic Feature
+---
+
+.. kernel-doc:: drivers/gpu/drm/drm_panic.c
+   :doc: overview
+
+Plane Panic Functions Reference
+---
+
+.. kernel-doc:: drivers/gpu/drm/drm_panic.c
+   :export:
+
 Display Modes Function Reference
 
 
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 16029435b750..f07ca38d3f98 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -102,6 +102,29 @@ config DRM_KMS_HELPER
help
  CRTC helpers for KMS drivers.
 
+config DRM_PANIC
+   bool "Display a user-friendly message when a kernel panic occurs"
+   depends on DRM && !FRAMEBUFFER_CONSOLE
+   select DRM_KMS_HELPER
+   select FONT_SUPPORT
+   help
+ Enable a drm panic handler, which will display a user-friendly message
+ when a kernel panic occurs. It's useful when using a user-space
+ console instead of fbcon.
+ It will only work if your graphic driver supports this feature.
+ To support Hi-DPI Display, you can enable bigger fonts like
+ FONT_TER16x32
+
+config DRM_PANIC_FOREGROUND_COLOR
+   hex "Drm panic screen foreground color, in RGB"
+   depends on DRM_PANIC
+   default 0xff
+
+config DRM_PANIC_BACKGROUND_COLOR
+   hex "Drm panic screen background color, in RGB"
+   depends on DRM_PANIC
+   default 0x00
+
 config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
 bool "Enable refcount backtrace history in the DP MST helpers"
depends on STACKTRACE_SUPPORT
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index a73c04d2d7a3..f9ca4f8fa6c5 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -88,6 +88,7 @@ drm-$(CONFIG_DRM_P

[PATCH v10 1/9] drm/panic: Add drm panic locking

2024-03-15 Thread Jocelyn Falempe
From: Daniel Vetter 

Rough sketch for the locking of drm panic printing code. The upshot of
this approach is that we can pretty much entirely rely on the atomic
commit flow, with the pair of raw_spin_lock/unlock providing any
barriers we need, without having to create really big critical
sections in code.

This also avoids the need that drivers must explicitly update the
panic handler state, which they might forget to do, or not do
consistently, and then we blow up in the worst possible times.

It is somewhat racy against a concurrent atomic update, and we might
write into a buffer which the hardware will never display. But there's
fundamentally no way to avoid that - if we do the panic state update
explicitly after writing to the hardware, we might instead write to an
old buffer that the user will barely ever see.

Note that an rcu protected deference of plane->state would give us the
the same guarantees, but it has the downside that we then need to
protect the plane state freeing functions with call_rcu too. Which
would very widely impact a lot of code and therefore doesn't seem
worth the complexity compared to a raw spinlock with very tiny
critical sections. Plus rcu cannot be used to protect access to
peek/poke registers anyway, so we'd still need it for those cases.

Peek/poke registers for vram access (or a gart pte reserved just for
panic code) are also the reason I've gone with a per-device and not
per-plane spinlock, since usually these things are global for the
entire display. Going with per-plane locks would mean drivers for such
hardware would need additional locks, which we don't want, since it
deviates from the per-console takeoverlocks design.

Longer term it might be useful if the panic notifiers grow a bit more
structure than just the absolute bare
EXPORT_SYMBOL(panic_notifier_list) - somewhat aside, why is that not
EXPORT_SYMBOL_GPL ... If panic notifiers would be more like console
drivers with proper register/unregister interfaces we could perhaps
reuse the very fancy console lock with all it's check and takeover
semantics that John Ogness is developing to fix the console_lock mess.
But for the initial cut of a drm panic printing support I don't think
we need that, because the critical sections are extremely small and
only happen once per display refresh. So generally just 60 tiny locked
sections per second, which is nothing compared to a serial console
running a 115kbaud doing really slow mmio writes for each byte. So for
now the raw spintrylock in drm panic notifier callback should be good
enough.

Another benefit of making panic notifiers more like full blown
consoles (that are used in panics only) would be that we get the two
stage design, where first all the safe outputs are used. And then the
dangerous takeover tricks are deployed (where for display drivers we
also might try to intercept any in-flight display buffer flips, which
if we race and misprogram fifos and watermarks can hang the memory
controller on some hw).

For context the actual implementation on the drm side is by Jocelyn
and this patch is meant to be combined with the overall approach in
v7 (v8 is a bit less flexible, which I think is the wrong direction):

https://lore.kernel.org/dri-devel/20240104160301.185915-1-jfale...@redhat.com/

Note that the locking is very much not correct there, hence this
separate rfc.

v2:
- fix authorship, this was all my typing
- some typo oopsies
- link to the drm panic work by Jocelyn for context

v10:
- Use spinlock_irqsave/restore (John Ogness)

Signed-off-by: Daniel Vetter 
Cc: Jocelyn Falempe 
Cc: Andrew Morton 
Cc: "Peter Zijlstra (Intel)" 
Cc: Lukas Wunner 
Cc: Petr Mladek 
Cc: Steven Rostedt 
Cc: John Ogness 
Cc: Sergey Senozhatsky 
Cc: Maarten Lankhorst 
Cc: Maxime Ripard 
Cc: Thomas Zimmermann 
Cc: David Airlie 
Cc: Daniel Vetter 
Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/drm_atomic_helper.c |   4 ++
 drivers/gpu/drm/drm_drv.c   |   1 +
 include/drm/drm_mode_config.h   |  10 +++
 include/drm/drm_panic.h | 107 
 4 files changed, 122 insertions(+)
 create mode 100644 include/drm/drm_panic.h

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 39ef0a6addeb..89dbf0ab1ba8 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -3016,6 +3017,7 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state 
*state,
  bool stall)
 {
int i, ret;
+   unsigned long flags;
struct drm_connector *connector;
struct drm_connector_state *old_conn_state, *new_conn_state;
struct drm_crtc *crtc;
@@ -3099,6 +3101,7 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state 
*state,
}
}
 
+   flags = drm_panic_lock(state->dev);
for_each_oldne

[PATCH v10 0/9] drm/panic: Add a drm panic handler

2024-03-15 Thread Jocelyn Falempe
This introduces a new drm panic handler, which displays a message when a panic 
occurs.
So when fbcon is disabled, you can still see a kernel panic.

This is one of the missing feature, when disabling VT/fbcon in the kernel:
https://www.reddit.com/r/linux/comments/10eccv9/config_vtn_in_2023/
Fbcon can be replaced by a userspace kms console, but the panic screen must be 
done in the kernel.

This is a proof of concept, and works with simpledrm, mgag200, ast, and imx.

To test it, make sure you're using one of the supported driver, and trigger a 
panic:
echo c > /proc/sysrq-trigger

or you can enable CONFIG_DRM_PANIC_DEBUG and echo 1 > 
/sys/kernel/debug/dri/0/drm_panic_plane_0


v2:
 * Use get_scanout_buffer() instead of the drm client API. (Thomas Zimmermann)
 * Add the panic reason to the panic message (Nerdopolis)
 * Add an exclamation mark (Nerdopolis)
 
v3:
 * Rework the drawing functions, to write the pixels line by line and
 to use the drm conversion helper to support other formats.
 (Thomas Zimmermann)
 
v4:
 * Fully support all simpledrm formats using drm conversion helpers
 * Rename dpanic_* to drm_panic_*, and have more coherent function name.
   (Thomas Zimmermann)
 * Use drm_fb_r1_to_32bit for fonts (Thomas Zimmermann)
 * Remove the default y to DRM_PANIC config option (Thomas Zimmermann)
 * Add foreground/background color config option
 * Fix the bottom lines not painted if the framebuffer height
   is not a multiple of the font height.
 * Automatically register the driver to drm_panic, if the function
   get_scanout_buffer() exists. (Thomas Zimmermann)
 * Add mgag200 support.
 
v5:
 * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
   (Thomas Zimmermann)
 * Also add drm_fb_fill() to fill area with background color.
 * Add draw_pixel_xy() API for drivers that can't provide a linear buffer.
 * Add a flush() callback for drivers that needs to synchronize the buffer.
 * Add a void *private field, so drivers can pass private data to
   draw_pixel_xy() and flush(). 
 * Add ast support.
 * Add experimental imx/ipuv3 support, to test on an ARM hw. (Maxime Ripard)

v6:
 * Fix sparse and __le32 warnings
 * Drop the IMX/IPUV3 experiment, it was just to show that it works also on
   ARM devices.

v7:
 * Add a check to see if the 4cc format is supported by drm_panic.
 * Add a drm/plane helper to loop over all visible primary buffer,
   simplifying the get_scanout_buffer implementations
 * Add a generic implementation for drivers that uses drm_fb_dma. (Maxime 
Ripard)
 * Add back the IMX/IPUV3 support, and use the generic implementation. (Maxime 
Ripard)

v8:
 * Directly register each plane to the panic notifier (Sima)
 * Replace get_scanout_buffer() with set_scanout_buffer() to simplify
   the locking. (Thomas Zimmermann)
 * Add a debugfs entry, to trigger the drm_panic without a real panic (Sima)
 * Fix the drm_panic Documentation, and include it in drm-kms.rst

v9:
 * Revert to using get_scanout_buffer() (Sima)
 * Move get_scanout_buffer() and panic_flush() to the plane helper
   functions (Thomas Zimmermann)
 * Register all planes with get_scanout_buffer() to the panic notifier
 * Use drm_panic_lock() to protect against race (Sima)
 * Create a debugfs file for each plane in the device's debugfs
   directory. This allows to test for each plane of each GPU
   independently.
v10:
 * Move blit and fill functions back in drm_panic (Thomas Zimmermann).
 * Simplify the text drawing functions.
 * Use kmsg_dumper instead of panic_notifier (Sima).
 * Use spinlock_irqsave/restore (John Ogness)


Daniel Vetter (1):
  drm/panic: Add drm panic locking

Jocelyn Falempe (8):
  drm/panic: Add a drm panic handler
  drm/panic: Add support for color format conversion
  drm/panic: Add debugfs entry to test without triggering panic.
  drm/fb_dma: Add generic get_scanout_buffer() for drm_panic
  drm/simpledrm: Add drm_panic support
  drm/mgag200: Add drm_panic support
  drm/imx: Add drm_panic support
  drm/ast: Add drm_panic support

 Documentation/gpu/drm-kms.rst|  12 +
 drivers/gpu/drm/Kconfig  |  32 ++
 drivers/gpu/drm/Makefile |   1 +
 drivers/gpu/drm/ast/ast_mode.c   |  18 +
 drivers/gpu/drm/drm_atomic_helper.c  |   4 +
 drivers/gpu/drm/drm_drv.c|   5 +
 drivers/gpu/drm/drm_fb_dma_helper.c  |  47 ++
 drivers/gpu/drm/drm_panic.c  | 581 +++
 drivers/gpu/drm/drm_plane.c  |   1 +
 drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c  |  11 +-
 drivers/gpu/drm/mgag200/mgag200_drv.h|   7 +-
 drivers/gpu/drm/mgag200/mgag200_mode.c   |  18 +
 drivers/gpu/drm/tiny/simpledrm.c |  16 +
 include/drm/drm_fb_dma_helper.h  |   4 +
 include/drm/drm_mode_config.h|  10 +
 include/drm/drm_modeset_helper_vtables.h |  37 ++
 include/drm/drm_panic.h  | 159 +++
 include/drm/drm_plane.h  |   6 +
 18 files changed, 967 insertions(+), 2 del

Re: [PATCH] vmwgfx: Create debugfs ttm_resource_manager entry only if needed

2024-03-14 Thread Jocelyn Falempe




On 13/03/2024 18:57, Zack Rusin wrote:

On Tue, Mar 12, 2024 at 5:36 AM Jocelyn Falempe  wrote:

[...]


Thanks! That looks great. I can push it through drm-misc-fixes.


Thanks,

I think I only forget the "drm/" in the commit title, but yes you can 
push it with this small correction.




Reviewed-by: Zack Rusin 

z



Best regards,

--

Jocelyn



Re: [PATCH 12/43] drm/mgag200: Use fbdev-shmem

2024-03-13 Thread Jocelyn Falempe

Hi,

Thanks, it looks good to me.

Reviewed-by: Jocelyn Falempe 

--

Jocelyn

On 12/03/2024 16:45, Thomas Zimmermann wrote:

Implement fbdev emulation with fbdev-shmem. Avoids the overhead of
fbdev-generic's additional shadow buffering. No functional changes.

Signed-off-by: Thomas Zimmermann 
Cc: Dave Airlie 
Cc: Thomas Zimmermann 
Cc: Jocelyn Falempe 
---
  drivers/gpu/drm/mgag200/mgag200_drv.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c 
b/drivers/gpu/drm/mgag200/mgag200_drv.c
index 573dbe256aa8b..65f2ed18b31c5 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -12,7 +12,7 @@
  #include 
  #include 
  #include 
-#include 
+#include 
  #include 
  #include 
  #include 
@@ -285,7 +285,7 @@ mgag200_pci_probe(struct pci_dev *pdev, const struct 
pci_device_id *ent)
 * FIXME: A 24-bit color depth does not work with 24 bpp on
 * G200ER. Force 32 bpp.
 */
-   drm_fbdev_generic_setup(dev, 32);
+   drm_fbdev_shmem_setup(dev, 32);
  
  	return 0;

  }




Re: [PATCH 09/43] drm/ast: Use fbdev-shmem

2024-03-13 Thread Jocelyn Falempe

Hi,

Thanks, it looks good to me.

Reviewed-by: Jocelyn Falempe 

--

Jocelyn

On 12/03/2024 16:45, Thomas Zimmermann wrote:

Implement fbdev emulation with fbdev-shmem. Avoids the overhead of
fbdev-generic's additional shadow buffering. No functional changes.

Signed-off-by: Thomas Zimmermann 
Cc: Dave Airlie 
Cc: Thomas Zimmermann 
Cc: Jocelyn Falempe 
---
  drivers/gpu/drm/ast/ast_drv.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
index 90bcb1eb9cd94..4fcab4304e176 100644
--- a/drivers/gpu/drm/ast/ast_drv.c
+++ b/drivers/gpu/drm/ast/ast_drv.c
@@ -32,7 +32,7 @@
  #include 
  #include 
  #include 
-#include 
+#include 
  #include 
  #include 
  #include 
@@ -359,7 +359,7 @@ static int ast_pci_probe(struct pci_dev *pdev, const struct 
pci_device_id *ent)
if (ret)
return ret;
  
-	drm_fbdev_generic_setup(drm, 32);

+   drm_fbdev_shmem_setup(drm, 32);
  
  	return 0;

  }




Re: [v9,5/9] drm/fb_dma: Add generic get_scanout_buffer() for drm_panic

2024-03-13 Thread Jocelyn Falempe




On 12/03/2024 17:44, Sui Jingfeng wrote:

Hi,

I'm get attracted by your patch, so I want to comment.
Please correct or ignore me if I say something wrong.

On 2024/3/7 17:14, Jocelyn Falempe wrote:

This was initialy done for imx6, but should work on most drivers
using drm_fb_dma_helper.

v8:
  * Replace get_scanout_buffer() logic with drm_panic_set_buffer()
    (Thomas Zimmermann)

v9:
  * go back to get_scanout_buffer()
  * move get_scanout_buffer() to plane helper functions

Signed-off-by: Jocelyn Falempe 
---
  drivers/gpu/drm/drm_fb_dma_helper.c | 47 +
  include/drm/drm_fb_dma_helper.h |  4 +++
  2 files changed, 51 insertions(+)

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

index 3b535ad1b07c..010327069ad4 100644
--- a/drivers/gpu/drm/drm_fb_dma_helper.c
+++ b/drivers/gpu/drm/drm_fb_dma_helper.c
@@ -15,6 +15,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -148,3 +149,49 @@ void drm_fb_dma_sync_non_coherent(struct 
drm_device *drm,

  }
  }
  EXPORT_SYMBOL_GPL(drm_fb_dma_sync_non_coherent);
+
+#if defined(CONFIG_DRM_PANIC)
+/**
+ * @plane: DRM primary plane
+ * @drm_scanout_buffer: scanout buffer for the panic handler
+ * Returns: 0 or negative error code
+ *
+ * Generic get_scanout_buffer() implementation, for drivers that uses 
the

+ * drm_fb_dma_helper.
+ */
+int drm_panic_gem_get_scanout_buffer(struct drm_plane *plane,
+ struct drm_scanout_buffer *sb)
+{
+    struct drm_gem_dma_object *dma_obj;
+    struct drm_framebuffer *fb;
+
+    fb = plane->state->fb;
+    /* Only support linear modifier */
+    if (fb->modifier != DRM_FORMAT_MOD_LINEAR)
+    return -ENODEV;



I think, the framebuffer format check clause here should be moved to the 
core layer.
For example, move this check into thedrm_panic_is_format_supported() 
function. And update the drm_panic_is_format_supported() function  to 
make it take 'struct drm_framebuffer *fb'
as argument. Because this check is needed for all implement, not driver 
specific or

implement specific.


I'm unsure about this. I think for some drivers it might be easier to 
give a memory buffer different from the plane's drm_framebuffer, and do 
their own specific things to display it. So forcing the use of a 
drm_framebuffer will remove some flexibility.




I know that some display controller support TILE format, but then you 
can try to trigger modeset
to let the display controller using linear format to display. Or, you 
can also convert local
linear buffer(with content pained) to the device specific TILED 
framebuffer, then feed TILED
framebuffer to the display controller to scanout. This is something like 
reverse the process of
resolve, but the convert program is running on the CPU.  As panic is not 
performance critical,
so it's possible. This maybe a bit more difficult, but the idea behind 
this is that the goal of
this drm_panic_gem_get_scanout_buffer() function is just to get a buffer 
scanout-able. Other
things beyond that (like format checking) can be moved to upper 
level(the caller of it). So you
don't need to modify(update) the specific implement if one day you have 
some fancy idea implemented.





Correct me if I'm wrong, but the tiled format are mostly hardware 
dependent, and I don't think we can have a generic implementation, that 
can cover multiple hardware.


I want to add support for multi-planar format like YUV for drm_panic 
later, but for tiled buffer, I think it should be easier to deactivate 
tiling on the hardware itself.



+    dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
+
+    /* Buffer should be accessible from the CPU */
+    if (dma_obj->base.import_attach)
+    return -ENODEV;
+
+    /* Buffer should be already mapped to CPU */
+    if (!dma_obj->vaddr)
+    return -ENODEV;



How about to call drm_gem_vmap_unlocked(dma_obj, >map); ?


It is not safe to call it from panic context, because it takes locks:
https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/drm_gem.c#L1212

It may lockup the panic handler, and prevent other panic routine to run 
(like kdump).
So it's better to call drm_gem_vmap_unlocked() when the driver prepares 
the buffer for the primary plane, than doing it from the panic handler.



Best regards,

--

Jocelyn






+    iosys_map_set_vaddr(>map, dma_obj->vaddr);
+    sb->format = fb->format;
+    sb->height = fb->height;
+    sb->width = fb->width;
+    sb->pitch = fb->pitches[0];
+    return 0;
+}
+#else
+int drm_panic_gem_get_scanout_buffer(struct drm_plane *plane,
+ struct drm_scanout_buffer *sb)
+{
+    return -ENODEV;
+}
+#endif
+EXPORT_SYMBOL(drm_panic_gem_get_scanout_buffer);
diff --git a/include/drm/drm_fb_dma_helper.h 
b/include/drm/drm_fb_dma_helper.h

index d5e036c57801..61f24c2aba2f 100644
--- a/include/drm/drm_fb_dma_helper.h
+++ b/include/drm/drm_fb_dma_helper

Re: [PATCH v9 0/9] drm/panic: Add a drm panic handler

2024-03-13 Thread Jocelyn Falempe




On 12/03/2024 16:16, Sui Jingfeng wrote:

Hi,


On 2024/3/7 17:14, Jocelyn Falempe wrote:
This introduces a new drm panic handler, which displays a message when 
a panic occurs.

So when fbcon is disabled, you can still see a kernel panic.

This is one of the missing feature, when disabling VT/fbcon in the 
kernel:

https://www.reddit.com/r/linux/comments/10eccv9/config_vtn_in_2023/
Fbcon can be replaced by a userspace kms console, but the panic screen 
must be done in the kernel.


This is a proof of concept, and works with simpledrm, mgag200, ast, 
and imx.


To test it, make sure you're using one of the supported driver, and 
trigger a panic:

echo c > /proc/sysrq-trigger

or you can enable CONFIG_DRM_PANIC_DEBUG and echo 1 > 
/sys/kernel/debug/dri/0/drm_panic_plane_0


Yes, the whole series works for me! I have tested with drm/loongson,
Are you willing to add a implement for drm/loongson driver?
If you do please add the fallowing code snippet info 
drm/loongson/lsdc_plane.c.

Thanks you.


Thanks for testing, and for enabling drm_panic on loongson.

My plan is to have a first version of drm_panic merged before adding 
more drivers. You will be able to send this patch when drm_panic is 
merged in drm-misc-next, and I will review it.


Best regards,

--

Jocelyn



static int
lsdc_primary_plane_get_scanout_buffer(struct drm_plane *plane,
               struct drm_scanout_buffer *scanout)
{
     struct drm_framebuffer *fb;

     if (!plane->state || !plane->state->fb)
     return -ENODEV;

     fb = plane->state->fb;
     if (fb->modifier != DRM_FORMAT_MOD_LINEAR)
     return -ENODEV;

     scanout->format = fb->format;
     scanout->width = fb->width;
     scanout->height = fb->height;
     scanout->pitch = fb->pitches[0];

     return drm_gem_vmap_unlocked(fb->obj[0], >map);
}

hook this lsdc_primary_plane_get_scanout_buffer() up to the 
.get_scanout_buffer
member of lsdc_primary_helper_funcs, and include the #include 


Thanks you in advance!





Re: [v9,3/9] drm/panic: Add a drm panic handler

2024-03-12 Thread Jocelyn Falempe




On 12/03/2024 14:18, Sui Jingfeng wrote:

Hi,



[...]



While applying you patch, there is new blank line at EOF reported, see 
below.

This is not an issue, but I want to report this to you.


Hi,

Thanks, I will remove it for the next version.

--

Jocelyn



git am ../drm-panic-Add-a-drm-panic-handler.mbox
Applying: drm/panic: Add drm panic locking
Applying: drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill
Applying: drm/panic: Add a drm panic handler
.git/rebase-apply/patch:439: new blank line at EOF.
+
warning: 1 line adds whitespace errors.
Applying: drm/panic: Add debugfs entry to test without triggering panic.
Applying: drm/fb_dma: Add generic get_scanout_buffer() for drm_panic
Applying: drm/simpledrm: Add drm_panic support
Applying: drm/mgag200: Add drm_panic support
Applying: drm/imx: Add drm_panic support
Applying: drm/ast: Add drm_panic support





Re: [v2] drm/mgag200: Add a workaround for low-latency

2024-03-12 Thread Jocelyn Falempe




On 12/03/2024 13:56, Sui Jingfeng wrote:

Hi,


Interesting patch! I know this patch already merged.
While study this patch, I have a few questions.


On 2024/2/8 17:51, Jocelyn Falempe wrote:

We found a regression in v5.10 on real-time server, using the
rt-kernel and the mgag200 driver. It's some really specialized
workload, with <10us latency expectation on isolated core.
After the v5.10, the real time tasks missed their <10us latency
when something prints on the screen (fbcon or printk)

The regression has been bisected to 2 commits:
commit 0b34d58b6c32 ("drm/mgag200: Enable caching for SHMEM pages")
commit 4862ffaec523 ("drm/mgag200: Move vmap out of commit tail")

The first one changed the system memory framebuffer from Write-Combine
to the default caching.
Before the second commit, the mgag200 driver used to unmap the
framebuffer after each frame, which implicitly does a cache flush.



I don't know why it need to do a cache flush, where is the code.
I'm asking because I want to study this technique.

Generally speaking, X86-64 platform's default page caching is cached.
And I think the cached mapping is fastest for software rendering. And
the platform guaranteed the coherency for us, right?

Because X86-64 platform(or CPU)'s write buffer is implemented on the
top of cache? I'm means that for ARM(or other) CPU, when using 
Write-combine

the data will has nothing to do with cache.


Both regressions are fixed by this commit, which restore WC mapping
for the framebuffer in system memory, and add a cache flush.


So switch back to WC probably will decrease overall performance, I think.
And the cache flush operation should not have a impact. Except X86-64's
Write-Combine is different other platform's Write-Combine?


Yes this patch is a bit weird. Usually you want your VRAM mapping to be 
Write-Combine. Here it also set the system memory framebuffer as 
Write-Combine. On most x86-64, Write Combine uses its own hardware 
buffer that is not in L1/L2/L3. So when it copies the framebuffer from 
WC system memory to VRAM, it doesn't involve the cache, and have less 
impact on latency for other tasks running on other CPU.
Also I think the cache flush is important to flush those WC buffers, so 
when the next frame comes, it won't have to wait for the buffers to be 
copied to the slow VRAM.

When running the latency tests, it's obvious that both are needed.
This is how I understand it, but I may be wrong.

--

Jocelyn





This is only needed on x86_64, for low-latency workload,
so the new kconfig DRM_MGAG200_IOBURST_WORKAROUND depends on
PREEMPT_RT and X86.

For more context, the whole thread can be found here [1]

Signed-off-by: Jocelyn Falempe 
Link: 
https://lore.kernel.org/dri-devel/20231019135655.313759-1-jfale...@redhat.com/ # 1

Acked-by: Thomas Zimmermann 






[PATCH] vmwgfx: Create debugfs ttm_resource_manager entry only if needed

2024-03-12 Thread Jocelyn Falempe
The driver creates /sys/kernel/debug/dri/0/mob_ttm even when the
corresponding ttm_resource_manager is not allocated.
This leads to a crash when trying to read from this file.

Add a check to create mob_ttm, system_mob_ttm, and gmr_ttm debug file
only when the corresponding ttm_resource_manager is allocated.

crash> bt
PID: 3133409  TASK: 8fe4834a5000  CPU: 3COMMAND: "grep"
 #0 [b954506b3b20] machine_kexec at b2a6bec3
 #1 [b954506b3b78] __crash_kexec at b2bb598a
 #2 [b954506b3c38] crash_kexec at b2bb68c1
 #3 [b954506b3c50] oops_end at b2a2a9b1
 #4 [b954506b3c70] no_context at b2a7e913
 #5 [b954506b3cc8] __bad_area_nosemaphore at b2a7ec8c
 #6 [b954506b3d10] do_page_fault at b2a7f887
 #7 [b954506b3d40] page_fault at b360116e
[exception RIP: ttm_resource_manager_debug+0x11]
RIP: c04afd11  RSP: b954506b3df0  RFLAGS: 00010246
RAX: 8fe41a6d1200  RBX:   RCX: 0940
RDX:   RSI: c04b4338  RDI: 
RBP: b954506b3e08   R8: 8fee3ffad000   R9: 
R10: 8fe41a76a000  R11: 0001  R12: 
R13: 0001  R14: 8fe5bb6f3900  R15: 8fe41a6d1200
ORIG_RAX:   CS: 0010  SS: 0018
 #8 [b954506b3e00] ttm_resource_manager_show at c04afde7 [ttm]
 #9 [b954506b3e30] seq_read at b2d8f9f3
RIP: 7f4c4eda8985  RSP: 7ffdbba9e9f8  RFLAGS: 0246
RAX: ffda  RBX: 0037e000  RCX: 7f4c4eda8985
RDX: 0037e000  RSI: 7f4c41573000  RDI: 0003
RBP: 0037e000   R8:    R9: 0037fe30
R10:   R11: 0246  R12: 7f4c41573000
R13: 0003  R14: 7f4c41572010  R15: 0003
ORIG_RAX:   CS: 0033  SS: 002b

Signed-off-by: Jocelyn Falempe 
Fixes: af4a25bbe5e7 ("drm/vmwgfx: Add debugfs entries for various ttm resource 
managers")
Cc: 
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 15 +--
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index d3e308fdfd5b..c7d90f96d16a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -1444,12 +1444,15 @@ static void vmw_debugfs_resource_managers_init(struct 
vmw_private *vmw)
root, "system_ttm");
ttm_resource_manager_create_debugfs(ttm_manager_type(>bdev, 
TTM_PL_VRAM),
root, "vram_ttm");
-   ttm_resource_manager_create_debugfs(ttm_manager_type(>bdev, 
VMW_PL_GMR),
-   root, "gmr_ttm");
-   ttm_resource_manager_create_debugfs(ttm_manager_type(>bdev, 
VMW_PL_MOB),
-   root, "mob_ttm");
-   ttm_resource_manager_create_debugfs(ttm_manager_type(>bdev, 
VMW_PL_SYSTEM),
-   root, "system_mob_ttm");
+   if (vmw->has_gmr)
+   
ttm_resource_manager_create_debugfs(ttm_manager_type(>bdev, VMW_PL_GMR),
+   root, "gmr_ttm");
+   if (vmw->has_mob) {
+   
ttm_resource_manager_create_debugfs(ttm_manager_type(>bdev, VMW_PL_MOB),
+   root, "mob_ttm");
+   
ttm_resource_manager_create_debugfs(ttm_manager_type(>bdev, VMW_PL_SYSTEM),
+   root, "system_mob_ttm");
+   }
 }
 
 static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,

base-commit: b33651a5c98dbd5a919219d8c129d0674ef74299
-- 
2.44.0



Re: [PATCH v9 1/9] drm/panic: Add drm panic locking

2024-03-08 Thread Jocelyn Falempe




On 07/03/2024 11:27, John Ogness wrote:

On 2024-03-07, Jocelyn Falempe  wrote:

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 39ef0a6addeb..c0bb91312fb2 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -38,6 +38,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -3099,6 +3100,7 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state 
*state,
}
}
  
+	drm_panic_lock(state->dev);

for_each_oldnew_plane_in_state(state, plane, old_plane_state, 
new_plane_state, i) {
WARN_ON(plane->state != old_plane_state);
  
@@ -3108,6 +3110,7 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state *state,

state->planes[i].state = old_plane_state;
plane->state = new_plane_state;
}
+   drm_panic_unlock(state->dev);


Is there a reason irqsave/irqrestore variants are not used? Maybe this
code path is too hot?


This lock will be taken for each page flip, so typically at 60Hz (or 
maybe 144Hz for gamers). I don't know what are the performance impacts 
of the irqsave/irqrestore variant.


By leaving interrupts enabled, there is the risk that a panic from
within any interrupt handler may block the drm panic handler.


The current design is that the panic handler will just use try_lock(), 
and if it can't take it, the panic screen will not be seen.
The goal is to make sure drm_panic won't crash the machine and prevent 
kdump or other panic handler to run. So there is a very small race 
chance that the panic screen won't be seen, but that's ok.


So I think in this case the drm panic handler shouldn't be blocked, as 
it only use try_lock().


Best regards,

--

Jocelyn



John Ogness





Re: [RFC] How to test panic handlers, without crashing the kernel

2024-03-07 Thread Jocelyn Falempe




On 05/03/2024 18:50, Guilherme G. Piccoli wrote:

On 05/03/2024 13:52, Jocelyn Falempe wrote:

[...]
Or maybe have two lists of panic notifiers, the safe and the destructive
list. So in case of fake panic, we can only call the safe notifiers.



I tried something like that:
https://lore.kernel.org/lkml/20220427224924.592546-1-gpicc...@igalia.com/

There were many suggestions, a completely refactor of the idea (panic
lists are not really seen as reliable things).


Thanks for sharing this, so it's much more complex than what I though.


Given that, I'm not really sure splitting in lists gonna fly; maybe
restricting the test infrastructure to drm_panic plus some paths of
panic would be enough for this debugfs interface, in principle? I mean,
to unblock your work on the drm panic stuff.


For drm_panic, I changed the way the debugfs is calling the drm_panic 
functions in the last version:

https://patchwork.freedesktop.org/patch/581845/?series=122244=9

It doesn't use the panic notifier list, but create a file for each plane 
of each device directly.
It allows to test the panic handler, not in a real panic condition, but 
that's still better than nothing.




Cheers,


Guilherme



Best regards,

--

Jocelyn



Re: [PATCH v9 2/9] drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill

2024-03-07 Thread Jocelyn Falempe

Hi,

On 07/03/2024 16:41, Thomas Zimmermann wrote:



Am 07.03.24 um 15:08 schrieb Thomas Zimmermann:

Hi

Am 07.03.24 um 10:14 schrieb Jocelyn Falempe:

This is needed for drm_panic, to draw the font, and fill
the background color, in multiple color format.


As you know, I'm not happy about this patch and the the changes do not 
reflect my easier


s/easier/earlier

review. These format helpers are supposed to serve all of DRM and not 
just the panic handler. I know that the current code isn't perfect, 
but the R1 support is a step backwards IMHO.


I suggest to the drawing routines entirely within the panic-handler 
code and maybe try to sort out things later. IIRC that's how it was in 
earlier revisions of the patchset.


Sorry I didn't change this patch in v8 and v9, I was focusing on locking 
and the overall design.
I agree to move this back to drm_panic.c, so we can merge a first 
version of drm_panic. And when a generic format converter will be ready, 
I will do the patch to use it.


Best regards,

--

Jocelyn





Best regards
Thomas



v5:
  * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
  * Also add drm_fb_fill() to fill area with background color.
v6:
  * fix __le32 conversion warning found by the kernel test bot

Signed-off-by: Jocelyn Falempe 
---
  drivers/gpu/drm/drm_format_helper.c | 432 ++--
  include/drm/drm_format_helper.h |   9 +
  2 files changed, 360 insertions(+), 81 deletions(-)

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

index b1be458ed4dd..2d9646cefc4f 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -111,6 +111,153 @@ void drm_format_conv_state_release(struct 
drm_format_conv_state *state)

  }
  EXPORT_SYMBOL(drm_format_conv_state_release);
  +static __le16 drm_format_xrgb_to_rgb565(__le32 val32)
+{
+    u16 val16;
+    u32 pix;
+
+    pix = le32_to_cpu(val32);
+    val16 = ((pix & 0x00F8) >> 8) |
+    ((pix & 0xFC00) >> 5) |
+    ((pix & 0x00F8) >> 3);
+    return cpu_to_le16(val16);
+}
+
+static __le16 drm_format_xrgb_to_rgba5551(__le32 val32)
+{
+    u16 val16;
+    u32 pix;
+
+    pix = le32_to_cpu(val32);
+    val16 = ((pix & 0x00f8) >> 8) |
+    ((pix & 0xf800) >> 5) |
+    ((pix & 0x00f8) >> 2) |
+    BIT(0); /* set alpha bit */
+    return cpu_to_le16(val16);
+}
+
+static __le16 drm_format_xrgb_to_xrgb1555(__le32 val32)
+{
+    u16 val16;
+    u32 pix;
+
+    pix = le32_to_cpu(val32);
+    val16 = ((pix & 0x00f8) >> 9) |
+    ((pix & 0xf800) >> 6) |
+    ((pix & 0x00f8) >> 3);
+    return cpu_to_le16(val16);
+}
+
+static __le16 drm_format_xrgb_to_argb1555(__le32 val32)
+{
+    u16 val16;
+    u32 pix;
+
+    pix = le32_to_cpu(val32);
+    val16 = BIT(15) | /* set alpha bit */
+    ((pix & 0x00f8) >> 9) |
+    ((pix & 0xf800) >> 6) |
+    ((pix & 0x00f8) >> 3);
+    return cpu_to_le16(val16);
+}
+
+static __le32 drm_format_xrgb_to_argb(__le32 pix)
+{
+    u32 val32;
+
+    val32 = le32_to_cpu(pix);
+    val32 |= GENMASK(31, 24); /* fill alpha bits */
+    return cpu_to_le32(val32);
+}
+
+static __le32 drm_format_xrgb_to_xbgr(__le32 pix)
+{
+    u32 val32;
+
+    val32 = le32_to_cpu(pix);
+    val32 = ((val32 & 0x00ff) >> 16) <<  0 |
+    ((val32 & 0xff00) >>  8) <<  8 |
+    ((val32 & 0x00ff) >>  0) << 16 |
+    ((val32 & 0xff00) >> 24) << 24;
+    return cpu_to_le32(val32);
+}
+
+static __le32 drm_format_xrgb_to_abgr(__le32 pix)
+{
+    u32 val32;
+
+    val32 = le32_to_cpu(pix);
+    val32 = ((val32 & 0x00ff) >> 16) <<  0 |
+    ((val32 & 0xff00) >>  8) <<  8 |
+    ((val32 & 0x00ff) >>  0) << 16 |
+    GENMASK(31, 24); /* fill alpha bits */
+    return cpu_to_le32(val32);
+}
+
+static __le32 drm_format_xrgb_to_xrgb2101010(__le32 pix)
+{
+    u32 val32;
+
+    val32 = le32_to_cpu(pix);
+    val32 = ((val32 & 0x00FF) << 2) |
+    ((val32 & 0xFF00) << 4) |
+    ((val32 & 0x00FF) << 6);
+    return cpu_to_le32(val32 | ((val32 >> 8) & 0x00300C03));
+}
+
+static __le32 drm_format_xrgb_to_argb2101010(__le32 pix)
+{
+    u32 val32;
+
+    val32 = le32_to_cpu(pix);
+    val32 = ((val32 & 0x00FF) << 2) |
+    ((val32 & 0xFF00) << 4) |
+    ((val32 & 0x00FF) << 6);
+    val32 = GENMASK(31, 30) | /* set alpha bits */
+  val32 | ((val32 >> 8) & 0x00300c03);
+    return cpu_to_le32(val32);
+}
+
+/**
+ * drm_fb_convert_from_xrgb - convert one pixel from xrgb to 
the desired format

[PATCH v9 9/9] drm/ast: Add drm_panic support

2024-03-07 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a message to
the screen when a kernel panic occurs.

v7
 * Use drm_for_each_primary_visible_plane()

v8:
 * Replace get_scanout_buffer() logic with drm_panic_set_buffer()
   (Thomas Zimmermann)
v9:
 * Revert to using get_scanout_buffer() (Sima)
 * move get_scanout_buffer() to plane helper functions

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/ast/ast_mode.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index a718646a66b8..49f2d8bd3377 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -700,12 +701,29 @@ static void 
ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,
ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x1, 0xdf, 0x20);
 }
 
+static int ast_primary_plane_helper_get_scanout_buffer(struct drm_plane *plane,
+  struct 
drm_scanout_buffer *sb)
+{
+   struct ast_plane *ast_plane = to_ast_plane(plane);
+
+   if (plane->state && plane->state->fb && ast_plane->vaddr) {
+   sb->format = plane->state->fb->format;
+   sb->width = plane->state->fb->width;
+   sb->height = plane->state->fb->height;
+   sb->pitch = plane->state->fb->pitches[0];
+   iosys_map_set_vaddr_iomem(>map, ast_plane->vaddr);
+   return 0;
+   }
+   return -ENODEV;
+}
+
 static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = {
DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
.atomic_check = ast_primary_plane_helper_atomic_check,
.atomic_update = ast_primary_plane_helper_atomic_update,
.atomic_enable = ast_primary_plane_helper_atomic_enable,
.atomic_disable = ast_primary_plane_helper_atomic_disable,
+   .get_scanout_buffer = ast_primary_plane_helper_get_scanout_buffer,
 };
 
 static const struct drm_plane_funcs ast_primary_plane_funcs = {
-- 
2.43.2



[PATCH v9 7/9] drm/mgag200: Add drm_panic support

2024-03-07 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a message to
the screen when a kernel panic occurs.

v5:
 * Also check that the plane is visible and primary. (Thomas Zimmermann)

v7:
 * use drm_for_each_primary_visible_plane()

v8:
 * Replace get_scanout_buffer() logic with drm_panic_set_buffer()
   (Thomas Zimmermann)

v9:
 * Revert to using get_scanout_buffer() (Sima)
 * move get_scanout_buffer() to plane helper functions (Thomas Zimmermann)

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/mgag200/mgag200_drv.h  |  7 ++-
 drivers/gpu/drm/mgag200/mgag200_mode.c | 18 ++
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h 
b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 765e49fd8911..58a0e62eaf18 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -366,6 +366,7 @@ struct drm_crtc_state;
 struct drm_display_mode;
 struct drm_plane;
 struct drm_atomic_state;
+struct drm_scanout_buffer;
 
 extern const uint32_t mgag200_primary_plane_formats[];
 extern const size_t   mgag200_primary_plane_formats_size;
@@ -379,12 +380,16 @@ void mgag200_primary_plane_helper_atomic_enable(struct 
drm_plane *plane,
struct drm_atomic_state *state);
 void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane,
 struct drm_atomic_state 
*old_state);
+int mgag200_primary_plane_helper_get_scanout_buffer(struct drm_plane *plane,
+   struct drm_scanout_buffer 
*sb);
+
 #define MGAG200_PRIMARY_PLANE_HELPER_FUNCS \
DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, \
.atomic_check = mgag200_primary_plane_helper_atomic_check, \
.atomic_update = mgag200_primary_plane_helper_atomic_update, \
.atomic_enable = mgag200_primary_plane_helper_atomic_enable, \
-   .atomic_disable = mgag200_primary_plane_helper_atomic_disable
+   .atomic_disable = mgag200_primary_plane_helper_atomic_disable, \
+   .get_scanout_buffer = mgag200_primary_plane_helper_get_scanout_buffer
 
 #define MGAG200_PRIMARY_PLANE_FUNCS \
.update_plane = drm_atomic_helper_update_plane, \
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c 
b/drivers/gpu/drm/mgag200/mgag200_mode.c
index e17cb4c5f774..8f368ecca4d4 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mgag200_drv.h"
@@ -546,6 +547,23 @@ void mgag200_primary_plane_helper_atomic_disable(struct 
drm_plane *plane,
msleep(20);
 }
 
+int mgag200_primary_plane_helper_get_scanout_buffer(struct drm_plane *plane,
+   struct drm_scanout_buffer 
*sb)
+{
+   struct mga_device *mdev = to_mga_device(plane->dev);
+   struct iosys_map map = IOSYS_MAP_INIT_VADDR_IOMEM(mdev->vram);
+
+   if (plane->state && plane->state->fb) {
+   sb->format = plane->state->fb->format;
+   sb->width = plane->state->fb->width;
+   sb->height = plane->state->fb->height;
+   sb->pitch = plane->state->fb->pitches[0];
+   sb->map = map;
+   return 0;
+   }
+   return -ENODEV;
+}
+
 /*
  * CRTC
  */
-- 
2.43.2



[PATCH v9 8/9] drm/imx: Add drm_panic support

2024-03-07 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a user-friendly
message to the screen when a kernel panic occurs.

v7:
 * use drm_panic_gem_get_scanout_buffer() helper

v8:
 * Replace get_scanout_buffer() logic with drm_panic_set_buffer()

v9:
 * Revert to using get_scanout_buffer() (Sima)
 * move get_scanout_buffer() to plane helper functions

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c 
b/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c
index dade8b59feae..3e21d2a1a124 100644
--- a/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c
@@ -772,6 +772,12 @@ static const struct drm_plane_helper_funcs 
ipu_plane_helper_funcs = {
.atomic_disable = ipu_plane_atomic_disable,
.atomic_update = ipu_plane_atomic_update,
 };
+static const struct drm_plane_helper_funcs ipu_primary_plane_helper_funcs = {
+   .atomic_check = ipu_plane_atomic_check,
+   .atomic_disable = ipu_plane_atomic_disable,
+   .atomic_update = ipu_plane_atomic_update,
+   .get_scanout_buffer = drm_panic_gem_get_scanout_buffer,
+};
 
 bool ipu_plane_atomic_update_pending(struct drm_plane *plane)
 {
@@ -916,7 +922,10 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, 
struct ipu_soc *ipu,
ipu_plane->dma = dma;
ipu_plane->dp_flow = dp;
 
-   drm_plane_helper_add(_plane->base, _plane_helper_funcs);
+   if (type == DRM_PLANE_TYPE_PRIMARY)
+   drm_plane_helper_add(_plane->base, 
_primary_plane_helper_funcs);
+   else
+   drm_plane_helper_add(_plane->base, _plane_helper_funcs);
 
if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG)
ret = drm_plane_create_zpos_property(_plane->base, zpos, 0,
-- 
2.43.2



[PATCH v9 6/9] drm/simpledrm: Add drm_panic support

2024-03-07 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a user-friendly
message to the screen when a kernel panic occurs.

v8:
 * Replace get_scanout_buffer() with drm_panic_set_buffer()
   (Thomas Zimmermann)

v9:
 * Revert to using get_scanout_buffer() (Sima)
 * move get_scanout_buffer() to plane helper functions (Thomas Zimmermann)

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/tiny/simpledrm.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 7ce1c4617675..f498665be8c4 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #define DRIVER_NAME"simpledrm"
@@ -671,11 +672,26 @@ static void 
simpledrm_primary_plane_helper_atomic_disable(struct drm_plane *plan
drm_dev_exit(idx);
 }
 
+static int simpledrm_primary_plane_helper_get_scanout_buffer(struct drm_plane 
*plane,
+struct 
drm_scanout_buffer *sb)
+{
+   struct simpledrm_device *sdev = simpledrm_device_of_dev(plane->dev);
+
+   sb->width = sdev->mode.hdisplay;
+   sb->height = sdev->mode.vdisplay;
+   sb->format = sdev->format;
+   sb->pitch = sdev->pitch;
+   sb->map = sdev->screen_base;
+
+   return 0;
+}
+
 static const struct drm_plane_helper_funcs 
simpledrm_primary_plane_helper_funcs = {
DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
.atomic_check = simpledrm_primary_plane_helper_atomic_check,
.atomic_update = simpledrm_primary_plane_helper_atomic_update,
.atomic_disable = simpledrm_primary_plane_helper_atomic_disable,
+   .get_scanout_buffer = simpledrm_primary_plane_helper_get_scanout_buffer,
 };
 
 static const struct drm_plane_funcs simpledrm_primary_plane_funcs = {
-- 
2.43.2



[PATCH v9 3/9] drm/panic: Add a drm panic handler

2024-03-07 Thread Jocelyn Falempe
This module displays a user friendly message when a kernel panic
occurs. It currently doesn't contain any debug information,
but that can be added later.

v2
 * Use get_scanout_buffer() instead of the drm client API.
  (Thomas Zimmermann)
 * Add the panic reason to the panic message (Nerdopolis)
 * Add an exclamation mark (Nerdopolis)

v3
 * Rework the drawing functions, to write the pixels line by line and
 to use the drm conversion helper to support other formats.
 (Thomas Zimmermann)

v4
 * Use drm_fb_r1_to_32bit for fonts (Thomas Zimmermann)
 * Remove the default y to DRM_PANIC config option (Thomas Zimmermann)
 * Add foreground/background color config option
 * Fix the bottom lines not painted if the framebuffer height
   is not a multiple of the font height.
 * Automatically register the device to drm_panic, if the function
   get_scanout_buffer exists. (Thomas Zimmermann)

v5
 * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
 * Also add drm_fb_fill() to fill area with background color.
 * Add draw_pixel_xy() API for drivers that can't provide a linear buffer.
 * Add a flush() callback for drivers that needs to synchronize the buffer.
 * Add a void *private field, so drivers can pass private data to
   draw_pixel_xy() and flush().

v6
 * Fix sparse warning for panic_msg and logo.

v7
 * Add select DRM_KMS_HELPER for the color conversion functions.

v8
 * Register directly each plane to the panic notifier (Sima)
 * Add raw_spinlock to properly handle concurrency (Sima)
 * Register plane instead of device, to avoid looping through plane
   list, and simplify code.
 * Replace get_scanout_buffer() logic with drm_panic_set_buffer()
  (Thomas Zimmermann)
 * Removed the draw_pixel_xy() API, will see later if it can be added back.

v9
 * Revert to using get_scanout_buffer() (Sima)
 * Move get_scanout_buffer() and panic_flush() to the plane helper
   functions (Thomas Zimmermann)
 * Register all planes with get_scanout_buffer() to the panic notifier
 * Use drm_panic_lock() to protect against race (Sima)

Signed-off-by: Jocelyn Falempe 
---
 Documentation/gpu/drm-kms.rst|  12 +
 drivers/gpu/drm/Kconfig  |  23 ++
 drivers/gpu/drm/Makefile |   1 +
 drivers/gpu/drm/drm_drv.c|   4 +
 drivers/gpu/drm/drm_panic.c  | 322 +++
 drivers/gpu/drm/drm_plane.c  |   1 +
 include/drm/drm_modeset_helper_vtables.h |  37 +++
 include/drm/drm_panic.h  |  52 
 include/drm/drm_plane.h  |   5 +
 9 files changed, 457 insertions(+)
 create mode 100644 drivers/gpu/drm/drm_panic.c

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 13d3627d8bc0..b64334661aeb 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -398,6 +398,18 @@ Plane Damage Tracking Functions Reference
 .. kernel-doc:: include/drm/drm_damage_helper.h
:internal:
 
+Plane Panic Feature
+---
+
+.. kernel-doc:: drivers/gpu/drm/drm_panic.c
+   :doc: overview
+
+Plane Panic Functions Reference
+---
+
+.. kernel-doc:: drivers/gpu/drm/drm_panic.c
+   :export:
+
 Display Modes Function Reference
 
 
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 16029435b750..f07ca38d3f98 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -102,6 +102,29 @@ config DRM_KMS_HELPER
help
  CRTC helpers for KMS drivers.
 
+config DRM_PANIC
+   bool "Display a user-friendly message when a kernel panic occurs"
+   depends on DRM && !FRAMEBUFFER_CONSOLE
+   select DRM_KMS_HELPER
+   select FONT_SUPPORT
+   help
+ Enable a drm panic handler, which will display a user-friendly message
+ when a kernel panic occurs. It's useful when using a user-space
+ console instead of fbcon.
+ It will only work if your graphic driver supports this feature.
+ To support Hi-DPI Display, you can enable bigger fonts like
+ FONT_TER16x32
+
+config DRM_PANIC_FOREGROUND_COLOR
+   hex "Drm panic screen foreground color, in RGB"
+   depends on DRM_PANIC
+   default 0xff
+
+config DRM_PANIC_BACKGROUND_COLOR
+   hex "Drm panic screen background color, in RGB"
+   depends on DRM_PANIC
+   default 0x00
+
 config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
 bool "Enable refcount backtrace history in the DP MST helpers"
depends on STACKTRACE_SUPPORT
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index a73c04d2d7a3..f9ca4f8fa6c5 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -88,6 +88,7 @@ drm-$(CONFIG_DRM_PRIVACY_SCREEN) += \
drm_privacy_screen.o \
drm_privacy_screen_x86.o
 drm-$(CONFIG_DRM_ACCEL) += ../../accel/drm_accel.o
+drm-$(CONFIG_DRM_PANIC) += drm

[PATCH v9 5/9] drm/fb_dma: Add generic get_scanout_buffer() for drm_panic

2024-03-07 Thread Jocelyn Falempe
This was initialy done for imx6, but should work on most drivers
using drm_fb_dma_helper.

v8:
 * Replace get_scanout_buffer() logic with drm_panic_set_buffer()
   (Thomas Zimmermann)

v9:
 * go back to get_scanout_buffer()
 * move get_scanout_buffer() to plane helper functions

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/drm_fb_dma_helper.c | 47 +
 include/drm/drm_fb_dma_helper.h |  4 +++
 2 files changed, 51 insertions(+)

diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c 
b/drivers/gpu/drm/drm_fb_dma_helper.c
index 3b535ad1b07c..010327069ad4 100644
--- a/drivers/gpu/drm/drm_fb_dma_helper.c
+++ b/drivers/gpu/drm/drm_fb_dma_helper.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -148,3 +149,49 @@ void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
}
 }
 EXPORT_SYMBOL_GPL(drm_fb_dma_sync_non_coherent);
+
+#if defined(CONFIG_DRM_PANIC)
+/**
+ * @plane: DRM primary plane
+ * @drm_scanout_buffer: scanout buffer for the panic handler
+ * Returns: 0 or negative error code
+ *
+ * Generic get_scanout_buffer() implementation, for drivers that uses the
+ * drm_fb_dma_helper.
+ */
+int drm_panic_gem_get_scanout_buffer(struct drm_plane *plane,
+struct drm_scanout_buffer *sb)
+{
+   struct drm_gem_dma_object *dma_obj;
+   struct drm_framebuffer *fb;
+
+   fb = plane->state->fb;
+   /* Only support linear modifier */
+   if (fb->modifier != DRM_FORMAT_MOD_LINEAR)
+   return -ENODEV;
+
+   dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
+
+   /* Buffer should be accessible from the CPU */
+   if (dma_obj->base.import_attach)
+   return -ENODEV;
+
+   /* Buffer should be already mapped to CPU */
+   if (!dma_obj->vaddr)
+   return -ENODEV;
+
+   iosys_map_set_vaddr(>map, dma_obj->vaddr);
+   sb->format = fb->format;
+   sb->height = fb->height;
+   sb->width = fb->width;
+   sb->pitch = fb->pitches[0];
+   return 0;
+}
+#else
+int drm_panic_gem_get_scanout_buffer(struct drm_plane *plane,
+struct drm_scanout_buffer *sb)
+{
+   return -ENODEV;
+}
+#endif
+EXPORT_SYMBOL(drm_panic_gem_get_scanout_buffer);
diff --git a/include/drm/drm_fb_dma_helper.h b/include/drm/drm_fb_dma_helper.h
index d5e036c57801..61f24c2aba2f 100644
--- a/include/drm/drm_fb_dma_helper.h
+++ b/include/drm/drm_fb_dma_helper.h
@@ -7,6 +7,7 @@
 struct drm_device;
 struct drm_framebuffer;
 struct drm_plane_state;
+struct drm_scanout_buffer;
 
 struct drm_gem_dma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb,
unsigned int plane);
@@ -19,5 +20,8 @@ void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
  struct drm_plane_state *old_state,
  struct drm_plane_state *state);
 
+int drm_panic_gem_get_scanout_buffer(struct drm_plane *plane,
+struct drm_scanout_buffer *sb);
+
 #endif
 
-- 
2.43.2



[PATCH v9 4/9] drm/panic: Add debugfs entry to test without triggering panic.

2024-03-07 Thread Jocelyn Falempe
Add a debugfs file, so you can test drm_panic without freezing
your machine. This is unsafe, and should be enabled only for
developer or tester.

To display the drm_panic screen on the device 0:
echo 1 > /sys/kernel/debug/dri/0/drm_panic_plane_0

v9:
 * Create a debugfs file for each plane in the device's debugfs
   directory. This allows to test for each plane of each GPU
   independently.

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/Kconfig |  9 +
 drivers/gpu/drm/drm_panic.c | 38 +
 2 files changed, 47 insertions(+)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index f07ca38d3f98..6e41fbd16b3d 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -125,6 +125,15 @@ config DRM_PANIC_BACKGROUND_COLOR
depends on DRM_PANIC
default 0x00
 
+config DRM_PANIC_DEBUG
+   bool "Add a debug fs entry to trigger drm_panic"
+   depends on DRM_PANIC && DEBUG_FS
+   help
+ Add dri/[device]/drm_panic_plane_x in the kernel debugfs, to force the
+ panic handler to write the panic message to this plane scanout buffer.
+ This is unsafe and should not be enabled on a production build.
+ If in doubt, say "N".
+
 config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
 bool "Enable refcount backtrace history in the DP MST helpers"
depends on STACKTRACE_SUPPORT
diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c
index 2e2a033d1267..24dc1f1a388f 100644
--- a/drivers/gpu/drm/drm_panic.c
+++ b/drivers/gpu/drm/drm_panic.c
@@ -270,6 +270,43 @@ static int drm_panic(struct notifier_block *this, unsigned 
long event,
return NOTIFY_OK;
 }
 
+
+/*
+ * DEBUG FS, This is currently unsafe.
+ * Create one file per plane, so it's possible to debug one plane at a time.
+ */
+#ifdef CONFIG_DRM_PANIC_DEBUG
+#include 
+
+static ssize_t debugfs_trigger_write(struct file *file, const char __user 
*user_buf,
+  size_t count, loff_t *ppos)
+{
+   bool run;
+
+   if (kstrtobool_from_user(user_buf, count, ) == 0 && run) {
+   struct drm_plane *plane = file->private_data;
+
+   draw_panic_plane(plane, "Test from debugfs");
+   }
+   return count;
+}
+
+static const struct file_operations dbg_drm_panic_ops = {
+   .owner = THIS_MODULE,
+   .write = debugfs_trigger_write,
+   .open = simple_open,
+};
+
+static void debugfs_register_plane(struct drm_plane *plane, int index)
+{
+   char fname[32];
+
+   snprintf(fname, 32, "drm_panic_plane_%d", index);
+   debugfs_create_file(fname, 0200, plane->dev->debugfs_root,
+   plane, _drm_panic_ops);
+}
+#endif /* CONFIG_DRM_PANIC_DEBUG */
+
 /**
  * drm_panic_register() - Initialize DRM panic for a device
  * @dev: the drm device on which the panic screen will be displayed.
@@ -291,6 +328,7 @@ void drm_panic_register(struct drm_device *dev)
   >panic_notifier)) {
drm_warn(dev, "Failed to register panic handler\n");
} else {
+   debugfs_register_plane(plane, registered_plane);
registered_plane++;
}
}
-- 
2.43.2



[PATCH v9 2/9] drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill

2024-03-07 Thread Jocelyn Falempe
This is needed for drm_panic, to draw the font, and fill
the background color, in multiple color format.

v5:
 * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
 * Also add drm_fb_fill() to fill area with background color.
v6:
 * fix __le32 conversion warning found by the kernel test bot

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/drm_format_helper.c | 432 ++--
 include/drm/drm_format_helper.h |   9 +
 2 files changed, 360 insertions(+), 81 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index b1be458ed4dd..2d9646cefc4f 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -111,6 +111,153 @@ void drm_format_conv_state_release(struct 
drm_format_conv_state *state)
 }
 EXPORT_SYMBOL(drm_format_conv_state_release);
 
+static __le16 drm_format_xrgb_to_rgb565(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = ((pix & 0x00F8) >> 8) |
+   ((pix & 0xFC00) >> 5) |
+   ((pix & 0x00F8) >> 3);
+   return cpu_to_le16(val16);
+}
+
+static __le16 drm_format_xrgb_to_rgba5551(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = ((pix & 0x00f8) >> 8) |
+   ((pix & 0xf800) >> 5) |
+   ((pix & 0x00f8) >> 2) |
+   BIT(0); /* set alpha bit */
+   return cpu_to_le16(val16);
+}
+
+static __le16 drm_format_xrgb_to_xrgb1555(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = ((pix & 0x00f8) >> 9) |
+   ((pix & 0xf800) >> 6) |
+   ((pix & 0x00f8) >> 3);
+   return cpu_to_le16(val16);
+}
+
+static __le16 drm_format_xrgb_to_argb1555(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = BIT(15) | /* set alpha bit */
+   ((pix & 0x00f8) >> 9) |
+   ((pix & 0xf800) >> 6) |
+   ((pix & 0x00f8) >> 3);
+   return cpu_to_le16(val16);
+}
+
+static __le32 drm_format_xrgb_to_argb(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 |= GENMASK(31, 24); /* fill alpha bits */
+   return cpu_to_le32(val32);
+}
+
+static __le32 drm_format_xrgb_to_xbgr(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00ff) >> 16) <<  0 |
+   ((val32 & 0xff00) >>  8) <<  8 |
+   ((val32 & 0x00ff) >>  0) << 16 |
+   ((val32 & 0xff00) >> 24) << 24;
+   return cpu_to_le32(val32);
+}
+
+static __le32 drm_format_xrgb_to_abgr(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00ff) >> 16) <<  0 |
+   ((val32 & 0xff00) >>  8) <<  8 |
+   ((val32 & 0x00ff) >>  0) << 16 |
+   GENMASK(31, 24); /* fill alpha bits */
+   return cpu_to_le32(val32);
+}
+
+static __le32 drm_format_xrgb_to_xrgb2101010(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00FF) << 2) |
+   ((val32 & 0xFF00) << 4) |
+   ((val32 & 0x00FF) << 6);
+   return cpu_to_le32(val32 | ((val32 >> 8) & 0x00300C03));
+}
+
+static __le32 drm_format_xrgb_to_argb2101010(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00FF) << 2) |
+   ((val32 & 0xFF00) << 4) |
+   ((val32 & 0x00FF) << 6);
+   val32 = GENMASK(31, 30) | /* set alpha bits */
+ val32 | ((val32 >> 8) & 0x00300c03);
+   return cpu_to_le32(val32);
+}
+
+/**
+ * drm_fb_convert_from_xrgb - convert one pixel from xrgb to the 
desired format
+ * @color: input color, in xrgb format
+ * @format: output format
+ *
+ * Returns:
+ * Color in the format specified, casted to u32.
+ * Or 0 if the format is unknown.
+ */
+u32 drm_fb_convert_from_xrgb(u32 color, u32 format)
+{
+   __le32 pix = cpu_to_le32(color);
+
+   switch (format) {
+   case DRM_FORMAT_RGB565:
+   return le16_to_cpu(drm_format_xrgb_to_rgb565(pix));
+   case DRM_FORMAT_RGBA5551:
+   return le16_to_cpu(drm_format_xrgb_to_rgba5551(pix));
+   case DRM_FORMAT_XRGB1555:
+   return le16_to_cpu(drm_format_xrgb_to_xrgb1555(pix));
+   case DRM_FORMAT_ARGB1555:
+   return le16_to_cpu(drm_format

[PATCH v9 1/9] drm/panic: Add drm panic locking

2024-03-07 Thread Jocelyn Falempe
From: Daniel Vetter 

Rough sketch for the locking of drm panic printing code. The upshot of
this approach is that we can pretty much entirely rely on the atomic
commit flow, with the pair of raw_spin_lock/unlock providing any
barriers we need, without having to create really big critical
sections in code.

This also avoids the need that drivers must explicitly update the
panic handler state, which they might forget to do, or not do
consistently, and then we blow up in the worst possible times.

It is somewhat racy against a concurrent atomic update, and we might
write into a buffer which the hardware will never display. But there's
fundamentally no way to avoid that - if we do the panic state update
explicitly after writing to the hardware, we might instead write to an
old buffer that the user will barely ever see.

Note that an rcu protected deference of plane->state would give us the
the same guarantees, but it has the downside that we then need to
protect the plane state freeing functions with call_rcu too. Which
would very widely impact a lot of code and therefore doesn't seem
worth the complexity compared to a raw spinlock with very tiny
critical sections. Plus rcu cannot be used to protect access to
peek/poke registers anyway, so we'd still need it for those cases.

Peek/poke registers for vram access (or a gart pte reserved just for
panic code) are also the reason I've gone with a per-device and not
per-plane spinlock, since usually these things are global for the
entire display. Going with per-plane locks would mean drivers for such
hardware would need additional locks, which we don't want, since it
deviates from the per-console takeoverlocks design.

Longer term it might be useful if the panic notifiers grow a bit more
structure than just the absolute bare
EXPORT_SYMBOL(panic_notifier_list) - somewhat aside, why is that not
EXPORT_SYMBOL_GPL ... If panic notifiers would be more like console
drivers with proper register/unregister interfaces we could perhaps
reuse the very fancy console lock with all it's check and takeover
semantics that John Ogness is developing to fix the console_lock mess.
But for the initial cut of a drm panic printing support I don't think
we need that, because the critical sections are extremely small and
only happen once per display refresh. So generally just 60 tiny locked
sections per second, which is nothing compared to a serial console
running a 115kbaud doing really slow mmio writes for each byte. So for
now the raw spintrylock in drm panic notifier callback should be good
enough.

Another benefit of making panic notifiers more like full blown
consoles (that are used in panics only) would be that we get the two
stage design, where first all the safe outputs are used. And then the
dangerous takeover tricks are deployed (where for display drivers we
also might try to intercept any in-flight display buffer flips, which
if we race and misprogram fifos and watermarks can hang the memory
controller on some hw).

For context the actual implementation on the drm side is by Jocelyn
and this patch is meant to be combined with the overall approach in
v7 (v8 is a bit less flexible, which I think is the wrong direction):

https://lore.kernel.org/dri-devel/20240104160301.185915-1-jfale...@redhat.com/

Note that the locking is very much not correct there, hence this
separate rfc.

v2:
- fix authorship, this was all my typing
- some typo oopsies
- link to the drm panic work by Jocelyn for context

Signed-off-by: Daniel Vetter 
Cc: Jocelyn Falempe 
Cc: Andrew Morton 
Cc: "Peter Zijlstra (Intel)" 
Cc: Lukas Wunner 
Cc: Petr Mladek 
Cc: Steven Rostedt 
Cc: John Ogness 
Cc: Sergey Senozhatsky 
Cc: Maarten Lankhorst 
Cc: Maxime Ripard 
Cc: Thomas Zimmermann 
Cc: David Airlie 
Cc: Daniel Vetter 
---
 drivers/gpu/drm/drm_atomic_helper.c |  3 +
 drivers/gpu/drm/drm_drv.c   |  1 +
 include/drm/drm_mode_config.h   | 10 +++
 include/drm/drm_panic.h | 99 +
 4 files changed, 113 insertions(+)
 create mode 100644 include/drm/drm_panic.h

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 39ef0a6addeb..c0bb91312fb2 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -3099,6 +3100,7 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state 
*state,
}
}
 
+   drm_panic_lock(state->dev);
for_each_oldnew_plane_in_state(state, plane, old_plane_state, 
new_plane_state, i) {
WARN_ON(plane->state != old_plane_state);
 
@@ -3108,6 +3110,7 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state 
*state,
state->planes[i].state = old_plane_state;
plane->state = new_plane_state;
}
+   drm_panic_unlock(state->dev);
 
for_each_oldnew_pri

[PATCH v9 0/9] drm/panic: Add a drm panic handler

2024-03-07 Thread Jocelyn Falempe


This introduces a new drm panic handler, which displays a message when a panic 
occurs.
So when fbcon is disabled, you can still see a kernel panic.

This is one of the missing feature, when disabling VT/fbcon in the kernel:
https://www.reddit.com/r/linux/comments/10eccv9/config_vtn_in_2023/
Fbcon can be replaced by a userspace kms console, but the panic screen must be 
done in the kernel.

This is a proof of concept, and works with simpledrm, mgag200, ast, and imx.

To test it, make sure you're using one of the supported driver, and trigger a 
panic:
echo c > /proc/sysrq-trigger

or you can enable CONFIG_DRM_PANIC_DEBUG and echo 1 > 
/sys/kernel/debug/dri/0/drm_panic_plane_0


v2:
 * Use get_scanout_buffer() instead of the drm client API. (Thomas Zimmermann)
 * Add the panic reason to the panic message (Nerdopolis)
 * Add an exclamation mark (Nerdopolis)
 
v3:
 * Rework the drawing functions, to write the pixels line by line and
 to use the drm conversion helper to support other formats.
 (Thomas Zimmermann)
 
v4:
 * Fully support all simpledrm formats using drm conversion helpers
 * Rename dpanic_* to drm_panic_*, and have more coherent function name.
   (Thomas Zimmermann)
 * Use drm_fb_r1_to_32bit for fonts (Thomas Zimmermann)
 * Remove the default y to DRM_PANIC config option (Thomas Zimmermann)
 * Add foreground/background color config option
 * Fix the bottom lines not painted if the framebuffer height
   is not a multiple of the font height.
 * Automatically register the driver to drm_panic, if the function
   get_scanout_buffer() exists. (Thomas Zimmermann)
 * Add mgag200 support.
 
v5:
 * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
   (Thomas Zimmermann)
 * Also add drm_fb_fill() to fill area with background color.
 * Add draw_pixel_xy() API for drivers that can't provide a linear buffer.
 * Add a flush() callback for drivers that needs to synchronize the buffer.
 * Add a void *private field, so drivers can pass private data to
   draw_pixel_xy() and flush(). 
 * Add ast support.
 * Add experimental imx/ipuv3 support, to test on an ARM hw. (Maxime Ripard)

v6:
 * Fix sparse and __le32 warnings
 * Drop the IMX/IPUV3 experiment, it was just to show that it works also on
   ARM devices.

v7:
 * Add a check to see if the 4cc format is supported by drm_panic.
 * Add a drm/plane helper to loop over all visible primary buffer,
   simplifying the get_scanout_buffer implementations
 * Add a generic implementation for drivers that uses drm_fb_dma. (Maxime 
Ripard)
 * Add back the IMX/IPUV3 support, and use the generic implementation. (Maxime 
Ripard)

v8:
 * Directly register each plane to the panic notifier (Sima)
 * Replace get_scanout_buffer() with set_scanout_buffer() to simplify
   the locking. (Thomas Zimmermann)
 * Add a debugfs entry, to trigger the drm_panic without a real panic (Sima)
 * Fix the drm_panic Documentation, and include it in drm-kms.rst

v9:
 * Revert to using get_scanout_buffer() (Sima)
 * Move get_scanout_buffer() and panic_flush() to the plane helper
   functions (Thomas Zimmermann)
 * Register all planes with get_scanout_buffer() to the panic notifier
 * Use drm_panic_lock() to protect against race (Sima)
 * Create a debugfs file for each plane in the device's debugfs
   directory. This allows to test for each plane of each GPU
   independently.

Daniel Vetter (1):
  drm/panic: Add drm panic locking

Jocelyn Falempe (8):
  drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill
  drm/panic: Add a drm panic handler
  drm/panic: Add debugfs entry to test without triggering panic.
  drm/fb_dma: Add generic get_scanout_buffer() for drm_panic
  drm/simpledrm: Add drm_panic support
  drm/mgag200: Add drm_panic support
  drm/imx: Add drm_panic support
  drm/ast: Add drm_panic support

 Documentation/gpu/drm-kms.rst|  12 +
 drivers/gpu/drm/Kconfig  |  32 ++
 drivers/gpu/drm/Makefile |   1 +
 drivers/gpu/drm/ast/ast_mode.c   |  18 +
 drivers/gpu/drm/drm_atomic_helper.c  |   3 +
 drivers/gpu/drm/drm_drv.c|   5 +
 drivers/gpu/drm/drm_fb_dma_helper.c  |  47 +++
 drivers/gpu/drm/drm_format_helper.c  | 432 ++-
 drivers/gpu/drm/drm_panic.c  | 360 +++
 drivers/gpu/drm/drm_plane.c  |   1 +
 drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c  |  11 +-
 drivers/gpu/drm/mgag200/mgag200_drv.h|   7 +-
 drivers/gpu/drm/mgag200/mgag200_mode.c   |  18 +
 drivers/gpu/drm/tiny/simpledrm.c |  16 +
 include/drm/drm_fb_dma_helper.h  |   4 +
 include/drm/drm_format_helper.h  |   9 +
 include/drm/drm_mode_config.h|  10 +
 include/drm/drm_modeset_helper_vtables.h |  37 ++
 include/drm/drm_panic.h  | 151 
 include/drm/drm_plane.h  |   5 +
 20 files changed, 1096 insertions(+), 83 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_panic.c
 create mode 100644 inclu

Re: [RFC] How to test panic handlers, without crashing the kernel

2024-03-05 Thread Jocelyn Falempe




On 05/03/2024 17:23, Michael Kelley wrote:

From: Guilherme G. Piccoli  Sent: Monday, March 4, 2024 
1:43 PM


On 04/03/2024 18:12, John Ogness wrote:

[...]

The second question is how to simulate a panic context in a
non-destructive way, so we can test the panic notifiers in CI, without
crashing the machine.


I'm wondering if a "fake panic" can be implemented that quiesces all the
other CPUs via NMI (similar to kdb) and then calls the panic
notifiers. And finally releases everything back to normal. That might
produce a fairly realistic panic situation and should be fairly
non-destructive (depending on what the notifiers do and how long they
take).



Hi Jocelyn / John,

one concern here is that the panic notifiers are kind of a no man's
land, so we can have very simple / safe ones, while others are
destructive in nature.

An example of a good behaving notifier that is destructive is the
Hyper-V one, that destroys an essential host-guest interface (called
"vmbus connection"). What happens if we trigger this one just for
testing purposes in a debugfs interface? Likely the guest would die...

[+CCing Michael Kelley here since he seems interested in panic and is
also expert in Hyper-V, just in case my example is bogus.]


The Hyper-V example is valid. After hv_panic_vmbus_unload()
is called, the VM won't be able to do any disk, network, or graphics
frame buffer I/O. There's no recovery short of restarting the VM.


Thanks for the confirmation.


Michael

[I have retired from Microsoft.  I'm still occasionally contributing
to Linux kernel work with email mhkli...@outlook.com.]



So, maybe the problem could be split in 2: the non-notifiers portion of
the panic path, and the the notifiers; maybe restricting the notifiers
you'd run is a way to circumvent the risks, like if you could pass a
list of the specific notifiers you aim to test, this could be
interesting. Let's see what the others think and thanks for your work in
the DRM panic notifier =)


Or maybe have two lists of panic notifiers, the safe and the destructive 
list. So in case of fake panic, we can only call the safe notifiers.




Cheers,


Guilherme






Re: [RFC] How to test panic handlers, without crashing the kernel

2024-03-05 Thread Jocelyn Falempe




On 04/03/2024 22:12, John Ogness wrote:

[Added printk maintainer and kdb folks]

Hi Jocelyn,

On 2024-03-01, Jocelyn Falempe  wrote:

While writing a panic handler for drm devices [1], I needed a way to
test it without crashing the machine.
So from debugfs, I called
atomic_notifier_call_chain(_notifier_list, ...), but it has the
side effect of calling all other panic notifiers registered.

So Sima suggested to move that to the generic panic code, and test all
panic notifiers with a dedicated debugfs interface.

I can move that code to kernel/, but before doing that, I would like to
know if you think that's the right way to test the panic code.


One major event that happens before the panic notifiers is
panic_other_cpus_shutdown(). This can cause special situations because
CPUs can be stopped while holding resources (such as raw spin
locks). And these are the situations that make it so tricky to have safe
and reliable notifiers. If triggered from debugfs, these situations will
never occur.

My concern is that the tests via debugfs will always succeed, but in the
real world panic notifiers are failing/hanging/exploding. IMHO useful
panic testing requires real panic'ing.


Yes, but for the drm panic, it's still useful to check that the output 
is working (ie: make sure the color format and the framebuffer address 
are good). Also I've reworked the debugfs patch, so I don't have to call 
all panic notifiers. It's now per device, so your can trigger the 
drm_panic handler on a specific GPU.




For my printk panic tests I trigger unknown NMIs while booting with
"unknown_nmi_panic". Particularly with Qemu this is quite easy and
amazingly effective at catching problems. In fact, a recent printk
series [0] fixed seven issues that were found through this method of
panic testing.


Thanks for this tip, I used to test with "echo c > /proc/sysrq-trigger" 
in the guest, but that's more permissive. I'm now testing with virsh 
inject-nmi, and drm_panic is still working.



The second question is how to simulate a panic context in a
non-destructive way, so we can test the panic notifiers in CI, without
crashing the machine.


I'm wondering if a "fake panic" can be implemented that quiesces all the
other CPUs via NMI (similar to kdb) and then calls the panic
notifiers. And finally releases everything back to normal. That might
produce a fairly realistic panic situation and should be fairly
non-destructive (depending on what the notifiers do and how long they
take).


The worst case for a panic notifier, is when the panic occurs in NMI
context, but I don't know how to simulate that. The goal would be to
find early if a panic notifier tries to sleep, or do other things that
are not allowed in a panic context.


Maybe with a new boot argument "unknown_nmi_fake_panic" that triggers
the fake panic instead?

John Ogness

[0] 
https://lore.kernel.org/lkml/20240207134103.1357162-1-john.ogn...@linutronix.de



Best regards,

--

Jocelyn



Re: [RFC] drm/panic: Add drm panic locking

2024-03-01 Thread Jocelyn Falempe

Thanks for the patch.

I think it misses to initialize the lock, so we need to add a 
raw_spin_lock_init() in the drm device initialization.


Also I'm wondering if it make sense to put that under the 
CONFIG_DRM_PANIC flag, so that if you don't enable it, panic_lock() and 
panic_unlock() would be no-op.
But that may not work if the driver uses this lock to protect some 
register access.


Best regards,

--

Jocelyn

On 01/03/2024 11:39, Daniel Vetter wrote:

Rough sketch for the locking of drm panic printing code. The upshot of
this approach is that we can pretty much entirely rely on the atomic
commit flow, with the pair of raw_spin_lock/unlock providing any
barriers we need, without having to create really big critical
sections in code.

This also avoids the need that drivers must explicitly update the
panic handler state, which they might forget to do, or not do
consistently, and then we blow up in the worst possible times.

It is somewhat racy against a concurrent atomic update, and we might
write into a buffer which the hardware will never display. But there's
fundamentally no way to avoid that - if we do the panic state update
explicitly after writing to the hardware, we might instead write to an
old buffer that the user will barely ever see.

Note that an rcu protected deference of plane->state would give us the
the same guarantees, but it has the downside that we then need to
protect the plane state freeing functions with call_rcu too. Which
would very widely impact a lot of code and therefore doesn't seem
worth the complexity compared to a raw spinlock with very tiny
critical sections. Plus rcu cannot be used to protect access to
peek/poke registers anyway, so we'd still need it for those cases.

Peek/poke registers for vram access (or a gart pte reserved just for
panic code) are also the reason I've gone with a per-device and not
per-plane spinlock, since usually these things are global for the
entire display. Going with per-plane locks would mean drivers for such
hardware would need additional locks, which we don't want, since it
deviates from the per-console takeoverlocks design.

Longer term it might be useful if the panic notifiers grow a bit more
structure than just the absolute bare
EXPORT_SYMBOL(panic_notifier_list) - somewhat aside, why is that not
EXPORT_SYMBOL_GPL ... If panic notifiers would be more like console
drivers with proper register/unregister interfaces we could perhaps
reuse the very fancy console lock with all it's check and takeover
semantics that John Ogness is developing to fix the console_lock mess.
But for the initial cut of a drm panic printing support I don't think
we need that, because the critical sections are extremely small and
only happen once per display refresh. So generally just 60 tiny locked
sections per second, which is nothing compared to a serial console
running a 115kbaud doing really slow mmio writes for each byte. So for
now the raw spintrylock in drm panic notifier callback should be good
enough.

Another benefit of making panic notifiers more like full blown
consoles (that are used in panics only) would be that we get the two
stage design, where first all the safe outputs are used. And then the
dangerous takeover tricks are deployed (where for display drivers we
also might try to intercept any in-flight display buffer flips, which
if we race and misprogram fifos and watermarks can hang the memory
controller on some hw).

For context the actual implementation on the drm side is by Jocelyn
and this patch is meant to be combined with the overall approach in
v7 (v8 is a bit less flexible, which I think is the wrong direction):

https://lore.kernel.org/dri-devel/20240104160301.185915-1-jfale...@redhat.com/

Note that the locking is very much not correct there, hence this
separate rfc.

v2:
- fix authorship, this was all my typing
- some typo oopsies
- link to the drm panic work by Jocelyn for context

Signed-off-by: Daniel Vetter 
Cc: Jocelyn Falempe 
Cc: Andrew Morton 
Cc: "Peter Zijlstra (Intel)" 
Cc: Lukas Wunner 
Cc: Petr Mladek 
Cc: Steven Rostedt 
Cc: John Ogness 
Cc: Sergey Senozhatsky 
Cc: Maarten Lankhorst 
Cc: Maxime Ripard 
Cc: Thomas Zimmermann 
Cc: David Airlie 
Cc: Daniel Vetter 
---
  drivers/gpu/drm/drm_atomic_helper.c |  3 +
  include/drm/drm_mode_config.h   | 10 +++
  include/drm/drm_panic.h | 99 +
  3 files changed, 112 insertions(+)
  create mode 100644 include/drm/drm_panic.h

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 40c2bd3e62e8..5a908c186037 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -38,6 +38,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -3086,6 +3087,7 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state 
*state,
}
}
  
+	drm_panic_lock(state->dev);

for_each_oldnew_plane_in_st

[RFC] How to test panic handlers, without crashing the kernel

2024-03-01 Thread Jocelyn Falempe

Hi,

While writing a panic handler for drm devices [1], I needed a way to 
test it without crashing the machine.
So from debugfs, I called 
atomic_notifier_call_chain(_notifier_list, ...), but it has the 
side effect of calling all other panic notifiers registered.


So Sima suggested to move that to the generic panic code, and test all 
panic notifiers with a dedicated debugfs interface.


I can move that code to kernel/, but before doing that, I would like to 
know if you think that's the right way to test the panic code.



The second question is how to simulate a panic context in a 
non-destructive way, so we can test the panic notifiers in CI, without 
crashing the machine. The worst case for a panic notifier, is when the 
panic occurs in NMI context, but I don't know how to simulate that. The 
goal would be to find early if a panic notifier tries to sleep, or do 
other things that are not allowed in a panic context.



Best regards,

--

Jocelyn

[1] https://patchwork.freedesktop.org/patch/580183/?series=122244=8



Re: [PATCH v8 5/8] drm/simpledrm: Add drm_panic support

2024-02-29 Thread Jocelyn Falempe




On 29/02/2024 12:17, Daniel Vetter wrote:

On Tue, Feb 27, 2024 at 11:04:16AM +0100, Jocelyn Falempe wrote:

Add support for the drm_panic module, which displays a user-friendly
message to the screen when a kernel panic occurs.

v8:
  * Replace get_scanout_buffer() with drm_panic_set_buffer()
(Thomas Zimmermann)

Signed-off-by: Jocelyn Falempe 
---
  drivers/gpu/drm/tiny/simpledrm.c | 17 +
  1 file changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 7ce1c4617675..a2190995354a 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -25,6 +25,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  
  #define DRIVER_NAME	"simpledrm"

@@ -735,6 +736,20 @@ static const struct drm_connector_funcs 
simpledrm_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
  };
  
+static void simpledrm_init_panic_buffer(struct drm_plane *plane)

+{
+   struct simpledrm_device *sdev = simpledrm_device_of_dev(plane->dev);
+   struct drm_framebuffer fb;
+
+   /* Fake framebuffer struct for drm_panic_set_buffer */
+   fb.width = sdev->mode.hdisplay;
+   fb.height = sdev->mode.vdisplay;
+   fb.format = sdev->format;
+   fb.pitches[0] = sdev->pitch;
+
+   drm_panic_set_buffer(plane->panic_scanout, , >screen_base);
+}
+
  static const struct drm_mode_config_funcs simpledrm_mode_config_funcs = {
.fb_create = drm_gem_fb_create_with_dirty,
.atomic_check = drm_atomic_helper_check,
@@ -945,6 +960,8 @@ static struct simpledrm_device 
*simpledrm_device_create(struct drm_driver *drv,
return ERR_PTR(ret);
drm_plane_helper_add(primary_plane, 
_primary_plane_helper_funcs);
drm_plane_enable_fb_damage_clips(primary_plane);
+   drm_panic_register(primary_plane);


Just a quick comment on this:

This does not work, the driver is not ready to handle panic calls at this
stage. Instead we need to automatically register all planes that support
panic handling in drm_dev_register(), and we need to remove them all again
in drm_dev_unregister(). Outside of these functions it is not safe to call
into driver code.


If you register the primary plane and didn't call drm_panic_set_buffer() 
yet, the panic handler will not do anything, so it should be safe.


But if we revert to using the get_scanout_buffer(), this makes sense.


At that point it might be simpler to only register one panic notifier per
drm_device, and push the loop into the panic handler again.

Cheers, Sima


+   simpledrm_init_panic_buffer(primary_plane);
  
  	/* CRTC */
  
--

2.43.0







Re: [PATCH v8 3/8] drm/panic: Add debugfs entry to test without triggering panic.

2024-02-29 Thread Jocelyn Falempe




On 29/02/2024 12:21, Daniel Vetter wrote:

On Tue, Feb 27, 2024 at 11:04:14AM +0100, Jocelyn Falempe wrote:

Add a debugfs file, so you can test drm_panic without freezing
your machine. This is unsafe, and should be enabled only for
developer or tester.

to display the drm_panic screen, just run:
echo 1 > /sys/kernel/debug/drm_panic/trigger

Signed-off-by: Jocelyn Falempe 
---
  drivers/gpu/drm/Kconfig |  9 +++
  drivers/gpu/drm/drm_panic.c | 47 +
  2 files changed, 56 insertions(+)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index c17d8a8f6877..8dcea29f595c 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -125,6 +125,15 @@ config DRM_PANIC_BACKGROUND_COLOR
depends on DRM_PANIC
default 0x00
  
+config DRM_PANIC_DEBUG

+   bool "Add a debug fs entry to trigger drm_panic"
+   depends on DRM_PANIC && DEBUG_FS
+   help
+ Add drm_panic/trigger in the kernel debugfs, to force the panic
+ handler to write the panic message to the scanout buffer. This is
+ unsafe and should not be enabled on a production build.
+ If in doubt, say "N".
+
  config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
  bool "Enable refcount backtrace history in the DP MST helpers"
depends on STACKTRACE_SUPPORT
diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c
index c9f386476ef9..c5d3f725c5f5 100644
--- a/drivers/gpu/drm/drm_panic.c
+++ b/drivers/gpu/drm/drm_panic.c
@@ -398,3 +398,50 @@ void drm_panic_unregister(struct drm_plane *plane)
  }
  EXPORT_SYMBOL(drm_panic_unregister);
  
+

+/*
+ * DEBUG, This is currently unsafe.
+ * Also it will call all panic_notifier, since there is no way to filter and
+ * only call the drm_panic notifier.
+ */
+#ifdef CONFIG_DRM_PANIC_DEBUG
+#include 
+
+static struct dentry *debug_dir;
+static struct dentry *debug_trigger;
+
+static ssize_t dbgfs_trigger_write(struct file *file, const char __user 
*user_buf,
+  size_t count, loff_t *ppos)
+{
+   bool run;
+
+   if (kstrtobool_from_user(user_buf, count, ) == 0 && run)
+   atomic_notifier_call_chain(_notifier_list, 0, "Test drm panic 
from debugfs");


Since this is just the general panic notifier it feels very misplaced in
the drm subsystem. I think moving that code into the core panic code makes
a lot more sense, then we'd also have all the right people on Cc: to
figure out how we can best recreate the correct calling context (like nmi
context or whatever) for best case simulation of panic code. John Ogness
definitely needs to see this and ack, wherever we put it.


I'm not sure it makes sense to test all panic notifiers at once.

So maybe I can write an atomic_notifier_call_chain_with_filter(), and 
filter on the callback address, so it will only call the drm_panic 
handlers ?


--

Jocelyn


-Sima


+   return count;
+}
+
+static const struct file_operations dbg_drm_panic_ops = {
+   .owner = THIS_MODULE,
+   .write = dbgfs_trigger_write,
+};
+
+static int __init debugfs_start(void)
+{
+   debug_dir = debugfs_create_dir("drm_panic", NULL);
+
+   if (IS_ERR(debug_dir))
+   return PTR_ERR(debug_dir);
+   debug_trigger = debugfs_create_file("trigger", 0200, debug_dir,
+   NULL, _drm_panic_ops);
+   return 0;
+}
+
+static void __exit debugfs_end(void)
+{
+   debugfs_remove_recursive(debug_dir);
+}
+
+module_init(debugfs_start);
+module_exit(debugfs_end);
+
+#endif
--
2.43.0







[PATCH v8 4/8] drm/fb_dma: Add generic set_scanout_buffer() for drm_panic

2024-02-27 Thread Jocelyn Falempe
This was initialy done for imx6, but should work on most drivers
using drm_fb_dma_helper.

v8:
 * Replace get_scanout_buffer() logic with drm_panic_set_buffer()
   (Thomas Zimmermann)

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/drm_fb_dma_helper.c | 37 +
 include/drm/drm_fb_dma_helper.h |  4 
 2 files changed, 41 insertions(+)

diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c 
b/drivers/gpu/drm/drm_fb_dma_helper.c
index 3b535ad1b07c..31ba71644e2b 100644
--- a/drivers/gpu/drm/drm_fb_dma_helper.c
+++ b/drivers/gpu/drm/drm_fb_dma_helper.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -148,3 +149,39 @@ void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
}
 }
 EXPORT_SYMBOL_GPL(drm_fb_dma_sync_non_coherent);
+
+#if defined(CONFIG_DRM_PANIC)
+/**
+ * drm_panic_gem_set_scanout_buffer - helper around drm_panic_set_buffer()
+ *
+ * @plane: primary plane registered to drm_panic
+ * @fb: framebuffer attached to the plane state
+ *
+ * Update plane->panic_scanout with the new framebuffer.
+ */
+void drm_panic_gem_set_scanout_buffer(struct drm_plane *plane,
+ struct drm_framebuffer *fb)
+{
+   struct drm_gem_dma_object *dma_obj;
+   struct iosys_map map;
+
+   if (!plane->panic_scanout)
+   return;
+
+   if (fb->modifier == DRM_FORMAT_MOD_LINEAR) {
+   dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
+   if (dma_obj && dma_obj->vaddr) {
+   iosys_map_set_vaddr(, dma_obj->vaddr);
+   drm_panic_set_buffer(plane->panic_scanout, fb, );
+   return;
+   }
+   }
+   drm_panic_unset_buffer(plane->panic_scanout);
+}
+#else
+void drm_panic_gem_set_scanout_buffer(struct drm_plane *plane,
+ struct drm_framebuffer *fb)
+{
+}
+#endif
+EXPORT_SYMBOL(drm_panic_gem_set_scanout_buffer);
diff --git a/include/drm/drm_fb_dma_helper.h b/include/drm/drm_fb_dma_helper.h
index d5e036c57801..9f9ec11343cd 100644
--- a/include/drm/drm_fb_dma_helper.h
+++ b/include/drm/drm_fb_dma_helper.h
@@ -7,6 +7,7 @@
 struct drm_device;
 struct drm_framebuffer;
 struct drm_plane_state;
+struct drm_scanout_buffer;
 
 struct drm_gem_dma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb,
unsigned int plane);
@@ -19,5 +20,8 @@ void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
  struct drm_plane_state *old_state,
  struct drm_plane_state *state);
 
+void drm_panic_gem_set_scanout_buffer(struct drm_plane *plane,
+struct drm_framebuffer *fb);
+
 #endif
 
-- 
2.43.0



[PATCH v8 3/8] drm/panic: Add debugfs entry to test without triggering panic.

2024-02-27 Thread Jocelyn Falempe
Add a debugfs file, so you can test drm_panic without freezing
your machine. This is unsafe, and should be enabled only for
developer or tester.

to display the drm_panic screen, just run:
echo 1 > /sys/kernel/debug/drm_panic/trigger

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/Kconfig |  9 +++
 drivers/gpu/drm/drm_panic.c | 47 +
 2 files changed, 56 insertions(+)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index c17d8a8f6877..8dcea29f595c 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -125,6 +125,15 @@ config DRM_PANIC_BACKGROUND_COLOR
depends on DRM_PANIC
default 0x00
 
+config DRM_PANIC_DEBUG
+   bool "Add a debug fs entry to trigger drm_panic"
+   depends on DRM_PANIC && DEBUG_FS
+   help
+ Add drm_panic/trigger in the kernel debugfs, to force the panic
+ handler to write the panic message to the scanout buffer. This is
+ unsafe and should not be enabled on a production build.
+ If in doubt, say "N".
+
 config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
 bool "Enable refcount backtrace history in the DP MST helpers"
depends on STACKTRACE_SUPPORT
diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c
index c9f386476ef9..c5d3f725c5f5 100644
--- a/drivers/gpu/drm/drm_panic.c
+++ b/drivers/gpu/drm/drm_panic.c
@@ -398,3 +398,50 @@ void drm_panic_unregister(struct drm_plane *plane)
 }
 EXPORT_SYMBOL(drm_panic_unregister);
 
+
+/*
+ * DEBUG, This is currently unsafe.
+ * Also it will call all panic_notifier, since there is no way to filter and
+ * only call the drm_panic notifier.
+ */
+#ifdef CONFIG_DRM_PANIC_DEBUG
+#include 
+
+static struct dentry *debug_dir;
+static struct dentry *debug_trigger;
+
+static ssize_t dbgfs_trigger_write(struct file *file, const char __user 
*user_buf,
+  size_t count, loff_t *ppos)
+{
+   bool run;
+
+   if (kstrtobool_from_user(user_buf, count, ) == 0 && run)
+   atomic_notifier_call_chain(_notifier_list, 0, "Test drm 
panic from debugfs");
+   return count;
+}
+
+static const struct file_operations dbg_drm_panic_ops = {
+   .owner = THIS_MODULE,
+   .write = dbgfs_trigger_write,
+};
+
+static int __init debugfs_start(void)
+{
+   debug_dir = debugfs_create_dir("drm_panic", NULL);
+
+   if (IS_ERR(debug_dir))
+   return PTR_ERR(debug_dir);
+   debug_trigger = debugfs_create_file("trigger", 0200, debug_dir,
+   NULL, _drm_panic_ops);
+   return 0;
+}
+
+static void __exit debugfs_end(void)
+{
+   debugfs_remove_recursive(debug_dir);
+}
+
+module_init(debugfs_start);
+module_exit(debugfs_end);
+
+#endif
-- 
2.43.0



[PATCH v8 8/8] drm/ast: Add drm_panic support

2024-02-27 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a message to
the screen when a kernel panic occurs.

v7
 * Use drm_for_each_primary_visible_plane()

v8:
 * Replace get_scanout_buffer() logic with drm_panic_set_buffer()
   (Thomas Zimmermann)

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/ast/ast_mode.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index a718646a66b8..3d6d4c71bc34 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -656,9 +657,13 @@ static void ast_primary_plane_helper_atomic_update(struct 
drm_plane *plane,
struct drm_crtc_state *crtc_state = 
drm_atomic_get_new_crtc_state(state, crtc);
struct ast_crtc_state *ast_crtc_state = 
to_ast_crtc_state(crtc_state);
struct ast_vbios_mode_info *vbios_mode_info = 
_crtc_state->vbios_mode_info;
+   struct iosys_map map;
 
ast_set_color_reg(ast, fb->format);
ast_set_vbios_color_reg(ast, fb->format, vbios_mode_info);
+
+   iosys_map_set_vaddr_iomem(, ast_plane->vaddr);
+   drm_panic_set_buffer(plane->panic_scanout, fb, );
}
 
drm_atomic_helper_damage_iter_init(, old_plane_state, plane_state);
@@ -736,6 +741,7 @@ static int ast_primary_plane_init(struct ast_device *ast)
}
drm_plane_helper_add(primary_plane, _primary_plane_helper_funcs);
drm_plane_enable_fb_damage_clips(primary_plane);
+   drm_panic_register(primary_plane);
 
return 0;
 }
-- 
2.43.0



[PATCH v8 5/8] drm/simpledrm: Add drm_panic support

2024-02-27 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a user-friendly
message to the screen when a kernel panic occurs.

v8:
 * Replace get_scanout_buffer() with drm_panic_set_buffer()
   (Thomas Zimmermann)

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/tiny/simpledrm.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 7ce1c4617675..a2190995354a 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #define DRIVER_NAME"simpledrm"
@@ -735,6 +736,20 @@ static const struct drm_connector_funcs 
simpledrm_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
+static void simpledrm_init_panic_buffer(struct drm_plane *plane)
+{
+   struct simpledrm_device *sdev = simpledrm_device_of_dev(plane->dev);
+   struct drm_framebuffer fb;
+
+   /* Fake framebuffer struct for drm_panic_set_buffer */
+   fb.width = sdev->mode.hdisplay;
+   fb.height = sdev->mode.vdisplay;
+   fb.format = sdev->format;
+   fb.pitches[0] = sdev->pitch;
+
+   drm_panic_set_buffer(plane->panic_scanout, , >screen_base);
+}
+
 static const struct drm_mode_config_funcs simpledrm_mode_config_funcs = {
.fb_create = drm_gem_fb_create_with_dirty,
.atomic_check = drm_atomic_helper_check,
@@ -945,6 +960,8 @@ static struct simpledrm_device 
*simpledrm_device_create(struct drm_driver *drv,
return ERR_PTR(ret);
drm_plane_helper_add(primary_plane, 
_primary_plane_helper_funcs);
drm_plane_enable_fb_damage_clips(primary_plane);
+   drm_panic_register(primary_plane);
+   simpledrm_init_panic_buffer(primary_plane);
 
/* CRTC */
 
-- 
2.43.0



[PATCH v8 7/8] drm/imx: Add drm_panic support

2024-02-27 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a user-friendly
message to the screen when a kernel panic occurs.

v7:
 * use drm_panic_gem_get_scanout_buffer() helper

v8:
 * Replace get_scanout_buffer() logic with drm_panic_set_buffer()

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c 
b/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c
index dade8b59feae..e820858732ec 100644
--- a/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -765,6 +766,8 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba);
ipu_idmac_lock_enable(ipu_plane->ipu_ch, num_bursts);
ipu_plane_enable(ipu_plane);
+
+   drm_panic_gem_set_scanout_buffer(plane, fb);
 }
 
 static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = {
@@ -942,6 +945,8 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, 
struct ipu_soc *ipu,
  zpos ? "overlay" : "primary", );
return ERR_PTR(ret);
}
+   if (type == DRM_PLANE_TYPE_PRIMARY)
+   drm_panic_register(_plane->base);
 
return ipu_plane;
 }
-- 
2.43.0



[PATCH v8 6/8] drm/mgag200: Add drm_panic support

2024-02-27 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a message to
the screen when a kernel panic occurs.

v5:
 * Also check that the plane is visible and primary. (Thomas Zimmermann)

v7:
 * use drm_for_each_primary_visible_plane()

v8:
 * Replace get_scanout_buffer() logic with drm_panic_set_buffer()
   (Thomas Zimmermann)

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/mgag200/mgag200_g200.c| 2 ++
 drivers/gpu/drm/mgag200/mgag200_g200eh.c  | 2 ++
 drivers/gpu/drm/mgag200/mgag200_g200eh3.c | 2 ++
 drivers/gpu/drm/mgag200/mgag200_g200er.c  | 2 ++
 drivers/gpu/drm/mgag200/mgag200_g200ev.c  | 2 ++
 drivers/gpu/drm/mgag200/mgag200_g200ew3.c | 2 ++
 drivers/gpu/drm/mgag200/mgag200_g200se.c  | 2 ++
 drivers/gpu/drm/mgag200/mgag200_g200wb.c  | 2 ++
 drivers/gpu/drm/mgag200/mgag200_mode.c| 7 +++
 9 files changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c 
b/drivers/gpu/drm/mgag200/mgag200_g200.c
index bf5d7fe525a3..1af71785733a 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mgag200_drv.h"
@@ -217,6 +218,7 @@ static int mgag200_g200_pipeline_init(struct mga_device 
*mdev)
}
drm_plane_helper_add(primary_plane, 
_g200_primary_plane_helper_funcs);
drm_plane_enable_fb_damage_clips(primary_plane);
+   drm_panic_register(primary_plane);
 
ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
_g200_crtc_funcs, NULL);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c 
b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
index fad62453a91d..759cff8480f7 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mgag200_drv.h"
@@ -216,6 +217,7 @@ static int mgag200_g200eh_pipeline_init(struct mga_device 
*mdev)
}
drm_plane_helper_add(primary_plane, 
_g200eh_primary_plane_helper_funcs);
drm_plane_enable_fb_damage_clips(primary_plane);
+   drm_panic_register(primary_plane);
 
ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
_g200eh_crtc_funcs, NULL);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c 
b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
index 0f7d8112cd49..753b3292a384 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
@@ -6,6 +6,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mgag200_drv.h"
@@ -120,6 +121,7 @@ static int mgag200_g200eh3_pipeline_init(struct mga_device 
*mdev)
}
drm_plane_helper_add(primary_plane, 
_g200eh3_primary_plane_helper_funcs);
drm_plane_enable_fb_damage_clips(primary_plane);
+   drm_panic_register(primary_plane);
 
ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
_g200eh3_crtc_funcs, NULL);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c 
b/drivers/gpu/drm/mgag200/mgag200_g200er.c
index 8d4538b71047..3dd6120bf9bb 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200er.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mgag200_drv.h"
@@ -259,6 +260,7 @@ static int mgag200_g200er_pipeline_init(struct mga_device 
*mdev)
}
drm_plane_helper_add(primary_plane, 
_g200er_primary_plane_helper_funcs);
drm_plane_enable_fb_damage_clips(primary_plane);
+   drm_panic_register(primary_plane);
 
ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
_g200er_crtc_funcs, NULL);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c 
b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
index 56e6f986bff3..28476a93c9ba 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mgag200_drv.h"
@@ -260,6 +261,7 @@ static int mgag200_g200ev_pipeline_init(struct mga_device 
*mdev)
}
drm_plane_helper_add(primary_plane, 
_g200ev_primary_plane_helper_funcs);
drm_plane_enable_fb_damage_clips(primary_plane);
+   drm_panic_register(primary_plane);
 
ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
_g200ev_crtc_funcs, NULL);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c 
b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
index 170934414d7d..f7c17bc52afc 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
@@ -6,6 +6,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mgag200_drv.h"

[PATCH v8 2/8] drm/panic: Add a drm panic handler

2024-02-27 Thread Jocelyn Falempe
This module displays a user friendly message when a kernel panic
occurs. It currently doesn't contain any debug information,
but that can be added later.

v2
 * Use get_scanout_buffer() instead of the drm client API.
  (Thomas Zimmermann)
 * Add the panic reason to the panic message (Nerdopolis)
 * Add an exclamation mark (Nerdopolis)

v3
 * Rework the drawing functions, to write the pixels line by line and
 to use the drm conversion helper to support other formats.
 (Thomas Zimmermann)

v4
 * Use drm_fb_r1_to_32bit for fonts (Thomas Zimmermann)
 * Remove the default y to DRM_PANIC config option (Thomas Zimmermann)
 * Add foreground/background color config option
 * Fix the bottom lines not painted if the framebuffer height
   is not a multiple of the font height.
 * Automatically register the device to drm_panic, if the function
   get_scanout_buffer exists. (Thomas Zimmermann)

v5
 * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
 * Also add drm_fb_fill() to fill area with background color.
 * Add draw_pixel_xy() API for drivers that can't provide a linear buffer.
 * Add a flush() callback for drivers that needs to synchronize the buffer.
 * Add a void *private field, so drivers can pass private data to
   draw_pixel_xy() and flush().

v6
 * Fix sparse warning for panic_msg and logo.

v7
 * Add select DRM_KMS_HELPER for the color conversion functions.

v8
 * Register directly each plane to the panic notifier (Sima)
 * Add raw_spinlock to properly handle concurrency (Sima)
 * Register plane instead of device, to avoid looping through plane
   list, and simplify code.
 * Replace get_scanout_buffer() logic with drm_panic_set_buffer()
  (Thomas Zimmermann)
 * Removed the draw_pixel_xy() API, will see later if it can be added back.

Signed-off-by: Jocelyn Falempe 
---
 Documentation/gpu/drm-kms.rst|  12 +
 drivers/gpu/drm/Kconfig  |  23 ++
 drivers/gpu/drm/Makefile |   1 +
 drivers/gpu/drm/drm_panic.c  | 400 +++
 drivers/gpu/drm/drm_plane.c  |   3 +
 include/drm/drm_modeset_helper_vtables.h |  11 +
 include/drm/drm_panic.h  |  37 +++
 include/drm/drm_plane.h  |  17 +
 8 files changed, 504 insertions(+)
 create mode 100644 drivers/gpu/drm/drm_panic.c
 create mode 100644 include/drm/drm_panic.h

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 13d3627d8bc0..b64334661aeb 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -398,6 +398,18 @@ Plane Damage Tracking Functions Reference
 .. kernel-doc:: include/drm/drm_damage_helper.h
:internal:
 
+Plane Panic Feature
+---
+
+.. kernel-doc:: drivers/gpu/drm/drm_panic.c
+   :doc: overview
+
+Plane Panic Functions Reference
+---
+
+.. kernel-doc:: drivers/gpu/drm/drm_panic.c
+   :export:
+
 Display Modes Function Reference
 
 
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 872edb47bb53..c17d8a8f6877 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -102,6 +102,29 @@ config DRM_KMS_HELPER
help
  CRTC helpers for KMS drivers.
 
+config DRM_PANIC
+   bool "Display a user-friendly message when a kernel panic occurs"
+   depends on DRM && !FRAMEBUFFER_CONSOLE
+   select DRM_KMS_HELPER
+   select FONT_SUPPORT
+   help
+ Enable a drm panic handler, which will display a user-friendly message
+ when a kernel panic occurs. It's useful when using a user-space
+ console instead of fbcon.
+ It will only work if your graphic driver supports this feature.
+ To support Hi-DPI Display, you can enable bigger fonts like
+ FONT_TER16x32
+
+config DRM_PANIC_FOREGROUND_COLOR
+   hex "Drm panic screen foreground color, in RGB"
+   depends on DRM_PANIC
+   default 0xff
+
+config DRM_PANIC_BACKGROUND_COLOR
+   hex "Drm panic screen background color, in RGB"
+   depends on DRM_PANIC
+   default 0x00
+
 config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
 bool "Enable refcount backtrace history in the DP MST helpers"
depends on STACKTRACE_SUPPORT
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 104b42df2e95..49905b7e333f 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -60,6 +60,7 @@ drm-$(CONFIG_DRM_PRIVACY_SCREEN) += \
drm_privacy_screen.o \
drm_privacy_screen_x86.o
 drm-$(CONFIG_DRM_ACCEL) += ../../accel/drm_accel.o
+drm-$(CONFIG_DRM_PANIC) += drm_panic.o
 obj-$(CONFIG_DRM)  += drm.o
 
 obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o
diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c
new file mode 100644
index ..c9f386476ef9
--- /dev/null
+++ b/drivers/gpu/drm/drm_panic.c
@@ -0,0 +1,40

[PATCH v8 1/8] drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill

2024-02-27 Thread Jocelyn Falempe
This is needed for drm_panic, to draw the font, and fill
the background color, in multiple color format.

v5:
 * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
 * Also add drm_fb_fill() to fill area with background color.
v6:
 * fix __le32 conversion warning found by the kernel test bot

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/drm_format_helper.c | 432 ++--
 include/drm/drm_format_helper.h |   9 +
 2 files changed, 360 insertions(+), 81 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index b1be458ed4dd..2d9646cefc4f 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -111,6 +111,153 @@ void drm_format_conv_state_release(struct 
drm_format_conv_state *state)
 }
 EXPORT_SYMBOL(drm_format_conv_state_release);
 
+static __le16 drm_format_xrgb_to_rgb565(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = ((pix & 0x00F8) >> 8) |
+   ((pix & 0xFC00) >> 5) |
+   ((pix & 0x00F8) >> 3);
+   return cpu_to_le16(val16);
+}
+
+static __le16 drm_format_xrgb_to_rgba5551(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = ((pix & 0x00f8) >> 8) |
+   ((pix & 0xf800) >> 5) |
+   ((pix & 0x00f8) >> 2) |
+   BIT(0); /* set alpha bit */
+   return cpu_to_le16(val16);
+}
+
+static __le16 drm_format_xrgb_to_xrgb1555(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = ((pix & 0x00f8) >> 9) |
+   ((pix & 0xf800) >> 6) |
+   ((pix & 0x00f8) >> 3);
+   return cpu_to_le16(val16);
+}
+
+static __le16 drm_format_xrgb_to_argb1555(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = BIT(15) | /* set alpha bit */
+   ((pix & 0x00f8) >> 9) |
+   ((pix & 0xf800) >> 6) |
+   ((pix & 0x00f8) >> 3);
+   return cpu_to_le16(val16);
+}
+
+static __le32 drm_format_xrgb_to_argb(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 |= GENMASK(31, 24); /* fill alpha bits */
+   return cpu_to_le32(val32);
+}
+
+static __le32 drm_format_xrgb_to_xbgr(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00ff) >> 16) <<  0 |
+   ((val32 & 0xff00) >>  8) <<  8 |
+   ((val32 & 0x00ff) >>  0) << 16 |
+   ((val32 & 0xff00) >> 24) << 24;
+   return cpu_to_le32(val32);
+}
+
+static __le32 drm_format_xrgb_to_abgr(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00ff) >> 16) <<  0 |
+   ((val32 & 0xff00) >>  8) <<  8 |
+   ((val32 & 0x00ff) >>  0) << 16 |
+   GENMASK(31, 24); /* fill alpha bits */
+   return cpu_to_le32(val32);
+}
+
+static __le32 drm_format_xrgb_to_xrgb2101010(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00FF) << 2) |
+   ((val32 & 0xFF00) << 4) |
+   ((val32 & 0x00FF) << 6);
+   return cpu_to_le32(val32 | ((val32 >> 8) & 0x00300C03));
+}
+
+static __le32 drm_format_xrgb_to_argb2101010(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00FF) << 2) |
+   ((val32 & 0xFF00) << 4) |
+   ((val32 & 0x00FF) << 6);
+   val32 = GENMASK(31, 30) | /* set alpha bits */
+ val32 | ((val32 >> 8) & 0x00300c03);
+   return cpu_to_le32(val32);
+}
+
+/**
+ * drm_fb_convert_from_xrgb - convert one pixel from xrgb to the 
desired format
+ * @color: input color, in xrgb format
+ * @format: output format
+ *
+ * Returns:
+ * Color in the format specified, casted to u32.
+ * Or 0 if the format is unknown.
+ */
+u32 drm_fb_convert_from_xrgb(u32 color, u32 format)
+{
+   __le32 pix = cpu_to_le32(color);
+
+   switch (format) {
+   case DRM_FORMAT_RGB565:
+   return le16_to_cpu(drm_format_xrgb_to_rgb565(pix));
+   case DRM_FORMAT_RGBA5551:
+   return le16_to_cpu(drm_format_xrgb_to_rgba5551(pix));
+   case DRM_FORMAT_XRGB1555:
+   return le16_to_cpu(drm_format_xrgb_to_xrgb1555(pix));
+   case DRM_FORMAT_ARGB1555:
+   return le16_to_cpu(drm_format

[RFC][PATCH v8 0/8] drm/panic: Add a drm panic handler

2024-02-27 Thread Jocelyn Falempe
This introduces a new drm panic handler, which displays a message when a panic 
occurs.
So when fbcon is disabled, you can still see a kernel panic.

This is one of the missing feature, when disabling VT/fbcon in the kernel:
https://www.reddit.com/r/linux/comments/10eccv9/config_vtn_in_2023/
Fbcon can be replaced by a userspace kms console, but the panic screen must be 
done in the kernel.

This is a proof of concept, and works with simpledrm, mgag200, ast, and imx.

To test it, make sure you're using one of the supported driver, and trigger a 
panic:
echo c > /proc/sysrq-trigger

or you can enable CONFIG_DRM_PANIC_DEBUG and echo 1 > 
/sys/kernel/debug/drm_panic/trigger


v2:
 * Use get_scanout_buffer() instead of the drm client API. (Thomas Zimmermann)
 * Add the panic reason to the panic message (Nerdopolis)
 * Add an exclamation mark (Nerdopolis)
 
v3:
 * Rework the drawing functions, to write the pixels line by line and
 to use the drm conversion helper to support other formats.
 (Thomas Zimmermann)
 
v4:
 * Fully support all simpledrm formats using drm conversion helpers
 * Rename dpanic_* to drm_panic_*, and have more coherent function name.
   (Thomas Zimmermann)
 * Use drm_fb_r1_to_32bit for fonts (Thomas Zimmermann)
 * Remove the default y to DRM_PANIC config option (Thomas Zimmermann)
 * Add foreground/background color config option
 * Fix the bottom lines not painted if the framebuffer height
   is not a multiple of the font height.
 * Automatically register the driver to drm_panic, if the function
   get_scanout_buffer() exists. (Thomas Zimmermann)
 * Add mgag200 support.
 
v5:
 * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
   (Thomas Zimmermann)
 * Also add drm_fb_fill() to fill area with background color.
 * Add draw_pixel_xy() API for drivers that can't provide a linear buffer.
 * Add a flush() callback for drivers that needs to synchronize the buffer.
 * Add a void *private field, so drivers can pass private data to
   draw_pixel_xy() and flush(). 
 * Add ast support.
 * Add experimental imx/ipuv3 support, to test on an ARM hw. (Maxime Ripard)

v6:
 * Fix sparse and __le32 warnings
 * Drop the IMX/IPUV3 experiment, it was just to show that it works also on
   ARM devices.

v7:
 * Add a check to see if the 4cc format is supported by drm_panic.
 * Add a drm/plane helper to loop over all visible primary buffer,
   simplifying the get_scanout_buffer implementations
 * Add a generic implementation for drivers that uses drm_fb_dma. (Maxime 
Ripard)
 * Add back the IMX/IPUV3 support, and use the generic implementation. (Maxime 
Ripard)

v8:
 * Directly register each plane to the panic notifier (Sima)
 * Replace get_scanout_buffer() with set_scanout_buffer() to simplify
   the locking. (Thomas Zimmermann)
 * Add a debugfs entry, to trigger the drm_panic without a real panic (Sima)
 * Fix the drm_panic Documentation, and include it in drm-kms.rst

Best regards,


Jocelyn Falempe (8):
  drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill
  drm/panic: Add a drm panic handler
  drm/panic: Add debugfs entry to test without triggering panic.
  drm/fb_dma: Add generic set_scanout_buffer() for drm_panic
  drm/simpledrm: Add drm_panic support
  drm/mgag200: Add drm_panic support
  drm/imx: Add drm_panic support
  drm/ast: Add drm_panic support

 Documentation/gpu/drm-kms.rst |  12 +
 drivers/gpu/drm/Kconfig   |  32 ++
 drivers/gpu/drm/Makefile  |   1 +
 drivers/gpu/drm/ast/ast_mode.c|   6 +
 drivers/gpu/drm/drm_fb_dma_helper.c   |  37 ++
 drivers/gpu/drm/drm_format_helper.c   | 432 +
 drivers/gpu/drm/drm_panic.c   | 447 ++
 drivers/gpu/drm/drm_plane.c   |   3 +
 drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c   |   5 +
 drivers/gpu/drm/mgag200/mgag200_g200.c|   2 +
 drivers/gpu/drm/mgag200/mgag200_g200eh.c  |   2 +
 drivers/gpu/drm/mgag200/mgag200_g200eh3.c |   2 +
 drivers/gpu/drm/mgag200/mgag200_g200er.c  |   2 +
 drivers/gpu/drm/mgag200/mgag200_g200ev.c  |   2 +
 drivers/gpu/drm/mgag200/mgag200_g200ew3.c |   2 +
 drivers/gpu/drm/mgag200/mgag200_g200se.c  |   2 +
 drivers/gpu/drm/mgag200/mgag200_g200wb.c  |   2 +
 drivers/gpu/drm/mgag200/mgag200_mode.c|   7 +
 drivers/gpu/drm/tiny/simpledrm.c  |  17 +
 include/drm/drm_fb_dma_helper.h   |   4 +
 include/drm/drm_format_helper.h   |   9 +
 include/drm/drm_modeset_helper_vtables.h  |  11 +
 include/drm/drm_panic.h   |  37 ++
 include/drm/drm_plane.h   |  17 +
 24 files changed, 1012 insertions(+), 81 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_panic.c
 create mode 100644 include/drm/drm_panic.h


base-commit: bfa4437fd3938ae2e186e7664b2db65bb8775670
-- 
2.43.0



Re: [PATCH v2] drm/mgag200: Add a workaround for low-latency

2024-02-26 Thread Jocelyn Falempe



On 08/02/2024 12:49, Thomas Zimmermann wrote:



Am 08.02.24 um 10:51 schrieb Jocelyn Falempe:

We found a regression in v5.10 on real-time server, using the
rt-kernel and the mgag200 driver. It's some really specialized
workload, with <10us latency expectation on isolated core.
After the v5.10, the real time tasks missed their <10us latency
when something prints on the screen (fbcon or printk)

The regression has been bisected to 2 commits:
commit 0b34d58b6c32 ("drm/mgag200: Enable caching for SHMEM pages")
commit 4862ffaec523 ("drm/mgag200: Move vmap out of commit tail")

The first one changed the system memory framebuffer from Write-Combine
to the default caching.
Before the second commit, the mgag200 driver used to unmap the
framebuffer after each frame, which implicitly does a cache flush.
Both regressions are fixed by this commit, which restore WC mapping
for the framebuffer in system memory, and add a cache flush.
This is only needed on x86_64, for low-latency workload,
so the new kconfig DRM_MGAG200_IOBURST_WORKAROUND depends on
PREEMPT_RT and X86.

For more context, the whole thread can be found here [1]

Signed-off-by: Jocelyn Falempe 
Link: 
https://lore.kernel.org/dri-devel/20231019135655.313759-1-jfale...@redhat.com/ # 1


Acked-by: Thomas Zimmermann 


Applied to drm-misc-next.

Thanks,

--

Jocelyn



[PATCH v2] drm/mgag200: Add a workaround for low-latency

2024-02-08 Thread Jocelyn Falempe
We found a regression in v5.10 on real-time server, using the
rt-kernel and the mgag200 driver. It's some really specialized
workload, with <10us latency expectation on isolated core.
After the v5.10, the real time tasks missed their <10us latency
when something prints on the screen (fbcon or printk)

The regression has been bisected to 2 commits:
commit 0b34d58b6c32 ("drm/mgag200: Enable caching for SHMEM pages")
commit 4862ffaec523 ("drm/mgag200: Move vmap out of commit tail")

The first one changed the system memory framebuffer from Write-Combine
to the default caching.
Before the second commit, the mgag200 driver used to unmap the
framebuffer after each frame, which implicitly does a cache flush.
Both regressions are fixed by this commit, which restore WC mapping
for the framebuffer in system memory, and add a cache flush.
This is only needed on x86_64, for low-latency workload,
so the new kconfig DRM_MGAG200_IOBURST_WORKAROUND depends on
PREEMPT_RT and X86.

For more context, the whole thread can be found here [1]

Signed-off-by: Jocelyn Falempe 
Link: 
https://lore.kernel.org/dri-devel/20231019135655.313759-1-jfale...@redhat.com/ 
# 1
---
 drivers/gpu/drm/mgag200/Kconfig| 12 
 drivers/gpu/drm/mgag200/mgag200_drv.c  | 17 +
 drivers/gpu/drm/mgag200/mgag200_mode.c |  8 
 3 files changed, 37 insertions(+)

diff --git a/drivers/gpu/drm/mgag200/Kconfig b/drivers/gpu/drm/mgag200/Kconfig
index b28c5e4828f4..5e4d48df4854 100644
--- a/drivers/gpu/drm/mgag200/Kconfig
+++ b/drivers/gpu/drm/mgag200/Kconfig
@@ -11,3 +11,15 @@ config DRM_MGAG200
 MGA G200 desktop chips and the server variants. It requires 0.3.0
 of the modesetting userspace driver, and a version of mga driver
 that will fail on KMS enabled devices.
+
+config DRM_MGAG200_IOBURST_WORKAROUND
+   bool "Disable buffer caching"
+   depends on DRM_MGAG200 && PREEMPT_RT && X86
+   help
+ Enable a workaround to avoid I/O bursts within the mgag200 driver at
+ the expense of overall display performance.
+ It restores the map_wc = true;
+   return >base;
+}
+#endif
+
 /*
  * DRM driver
  */
@@ -99,6 +113,9 @@ static const struct drm_driver mgag200_driver = {
.major = DRIVER_MAJOR,
.minor = DRIVER_MINOR,
.patchlevel = DRIVER_PATCHLEVEL,
+#if defined(CONFIG_DRM_MGAG200_IOBURST_WORKAROUND)
+   .gem_create_object = mgag200_create_object,
+#endif
DRM_GEM_SHMEM_DRIVER_OPS,
 };
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c 
b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 0eb769dd76ce..e17cb4c5f774 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -13,6 +13,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -436,6 +437,13 @@ static void mgag200_handle_damage(struct mga_device *mdev, 
const struct iosys_ma
 
iosys_map_incr(, drm_fb_clip_offset(fb->pitches[0], fb->format, 
clip));
drm_fb_memcpy(, fb->pitches, vmap, fb, clip);
+
+   /* Flushing the cache greatly improves latency on x86_64 */
+#if defined(CONFIG_DRM_MGAG200_IOBURST_WORKAROUND)
+   if (!vmap->is_iomem)
+   drm_clflush_virt_range(vmap->vaddr + clip->y1 * fb->pitches[0],
+  drm_rect_height(clip) * fb->pitches[0]);
+#endif
 }
 
 /*

base-commit: 1f36d634670d8001a45fe2f2dcae546819f9c7d8
-- 
2.43.0



Re: [PATCH] drm/mgag200: Add a workaround for low-latency

2024-02-08 Thread Jocelyn Falempe




On 07/02/2024 10:47, Thomas Zimmermann wrote:

Hi

Am 06.02.24 um 23:21 schrieb Jocelyn Falempe:

We found a regression in v5.10 on real-time server, using the
rt-kernel and the mgag200 driver. It's some really specialized
workload, with <10us latency expectation on isolated core.
After the v5.10, the real time tasks missed their <10us latency
when something prints on the screen (fbcon or printk)

The regression has been bisected to 2 commits:
commit 0b34d58b6c32 ("drm/mgag200: Enable caching for SHMEM pages")
commit 4862ffaec523 ("drm/mgag200: Move vmap out of commit tail")

The first one changed the system memory framebuffer from Write-Combine
to the default caching.
Before the second commit, the mgag200 driver used to unmap the
framebuffer after each frame, which implicitly does a cache flush.
Both regressions are fixed by this commit, which restore WC mapping
for the framebuffer in system memory, and add a cache flush.
This is only needed on x86_64, for low-latency workload,
so the new kconfig DRM_MGAG200_LATENCY_WORKAROUND depends on
PREEMPT_RT and X86.

For more context, the whole thread can be found here:
https://lore.kernel.org/dri-devel/20231019135655.313759-1-jfale...@redhat.com/


This URL should be in a Link tag below the SoB line, like this:

Link: 
https://lore.kernel.org/dri-devel/20231019135655.313759-1-jfale...@redhat.com/ # 1 You can refer to it from within the text with [1].

ok



Signed-off-by: Jocelyn Falempe 
---
  drivers/gpu/drm/mgag200/Kconfig    | 10 ++
  drivers/gpu/drm/mgag200/mgag200_drv.c  | 17 +
  drivers/gpu/drm/mgag200/mgag200_mode.c |  8 
  3 files changed, 35 insertions(+)

diff --git a/drivers/gpu/drm/mgag200/Kconfig 
b/drivers/gpu/drm/mgag200/Kconfig

index b28c5e4828f4..73e4feba743a 100644
--- a/drivers/gpu/drm/mgag200/Kconfig
+++ b/drivers/gpu/drm/mgag200/Kconfig
@@ -11,3 +11,13 @@ config DRM_MGAG200
   MGA G200 desktop chips and the server variants. It requires 0.3.0
   of the modesetting userspace driver, and a version of mga driver
   that will fail on KMS enabled devices.
+
+config DRM_MGAG200_LATENCY_WORKAROUND


Can we call this DRM_MGAG200_IOBURST_WORKAROUND? I know what you mean by 
latency, but that's not what is happening in the driver. The latency you 
refer to is the deterministic response time of your process, but the 
response time of the driver actually goes up (because of the disabled 
caching).



+    bool "Enable workaround for low latency server"


This is a 'low-latency server'. But I'd just say "Disabled buffer 
caching", so that users know what they are getting into.



+    depends on DRM_MGAG200 && PREEMPT_RT && X86
+    help
+  Enable a workaround to have better latency with mgag200 driver.


Here I'd say "Enable a workaround to avoid I/O bursts within the mgag200 
driver at the expense of overall display performance."


+  It restores the system

+  RAM as Write-Combining, and flushing the cache after each write.
+  This is only needed on x86_64 and if you want low-latency.


Maybe "This is only useful on x86_64 if you want to run processes with 
deterministic latency."


The code itself looks good to me.


Thanks, I will send a v2 with all these changes.

--

Jocelyn



Best regards
Thomas


+  If unsure, say N.
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c 
b/drivers/gpu/drm/mgag200/mgag200_drv.c

index 54fce00e2136..3fdef8b580cc 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -84,6 +84,20 @@ resource_size_t mgag200_probe_vram(void __iomem 
*mem, resource_size_t size)

  return offset - 65536;
  }
+#if defined(CONFIG_DRM_MGAG200_LATENCY_WORKAROUND)
+static struct drm_gem_object *mgag200_create_object(struct drm_device 
*dev, size_t size)

+{
+    struct drm_gem_shmem_object *shmem;
+
+    shmem = kzalloc(sizeof(*shmem), GFP_KERNEL);
+    if (!shmem)
+    return NULL;
+
+    shmem->map_wc = true;
+    return >base;
+}
+#endif
+
  /*
   * DRM driver
   */
@@ -99,6 +113,9 @@ static const struct drm_driver mgag200_driver = {
  .major = DRIVER_MAJOR,
  .minor = DRIVER_MINOR,
  .patchlevel = DRIVER_PATCHLEVEL,
+#if defined(CONFIG_DRM_MGAG200_LATENCY_WORKAROUND)
+    .gem_create_object = mgag200_create_object,
+#endif
  DRM_GEM_SHMEM_DRIVER_OPS,
  };
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c 
b/drivers/gpu/drm/mgag200/mgag200_mode.c

index 0eb769dd76ce..34ef9fb6e96c 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -13,6 +13,7 @@
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -436,6 +437,13 @@ static void mgag200_handle_damage(struct 
mga_device *mdev, const struct iosys_ma
  iosys_map_incr(, drm_fb_clip_offset(fb->pitches[0], 
fb->format, clip));

  drm_fb_memcpy(, fb->pitches,

[PATCH] drm/mgag200: Add a workaround for low-latency

2024-02-06 Thread Jocelyn Falempe
We found a regression in v5.10 on real-time server, using the
rt-kernel and the mgag200 driver. It's some really specialized
workload, with <10us latency expectation on isolated core.
After the v5.10, the real time tasks missed their <10us latency
when something prints on the screen (fbcon or printk)

The regression has been bisected to 2 commits:
commit 0b34d58b6c32 ("drm/mgag200: Enable caching for SHMEM pages")
commit 4862ffaec523 ("drm/mgag200: Move vmap out of commit tail")

The first one changed the system memory framebuffer from Write-Combine
to the default caching.
Before the second commit, the mgag200 driver used to unmap the
framebuffer after each frame, which implicitly does a cache flush.
Both regressions are fixed by this commit, which restore WC mapping
for the framebuffer in system memory, and add a cache flush.
This is only needed on x86_64, for low-latency workload,
so the new kconfig DRM_MGAG200_LATENCY_WORKAROUND depends on
PREEMPT_RT and X86.

For more context, the whole thread can be found here:
https://lore.kernel.org/dri-devel/20231019135655.313759-1-jfale...@redhat.com/

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/mgag200/Kconfig| 10 ++
 drivers/gpu/drm/mgag200/mgag200_drv.c  | 17 +
 drivers/gpu/drm/mgag200/mgag200_mode.c |  8 
 3 files changed, 35 insertions(+)

diff --git a/drivers/gpu/drm/mgag200/Kconfig b/drivers/gpu/drm/mgag200/Kconfig
index b28c5e4828f4..73e4feba743a 100644
--- a/drivers/gpu/drm/mgag200/Kconfig
+++ b/drivers/gpu/drm/mgag200/Kconfig
@@ -11,3 +11,13 @@ config DRM_MGAG200
 MGA G200 desktop chips and the server variants. It requires 0.3.0
 of the modesetting userspace driver, and a version of mga driver
 that will fail on KMS enabled devices.
+
+config DRM_MGAG200_LATENCY_WORKAROUND
+   bool "Enable workaround for low latency server"
+   depends on DRM_MGAG200 && PREEMPT_RT && X86
+   help
+ Enable a workaround to have better latency with mgag200 driver.
+ It restores the map_wc = true;
+   return >base;
+}
+#endif
+
 /*
  * DRM driver
  */
@@ -99,6 +113,9 @@ static const struct drm_driver mgag200_driver = {
.major = DRIVER_MAJOR,
.minor = DRIVER_MINOR,
.patchlevel = DRIVER_PATCHLEVEL,
+#if defined(CONFIG_DRM_MGAG200_LATENCY_WORKAROUND)
+   .gem_create_object = mgag200_create_object,
+#endif
DRM_GEM_SHMEM_DRIVER_OPS,
 };
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c 
b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 0eb769dd76ce..34ef9fb6e96c 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -13,6 +13,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -436,6 +437,13 @@ static void mgag200_handle_damage(struct mga_device *mdev, 
const struct iosys_ma
 
iosys_map_incr(, drm_fb_clip_offset(fb->pitches[0], fb->format, 
clip));
drm_fb_memcpy(, fb->pitches, vmap, fb, clip);
+
+   /* Flushing the cache greatly improves latency on x86_64 */
+#if defined(CONFIG_DRM_MGAG200_LATENCY_WORKAROUND)
+   if (!vmap->is_iomem)
+   drm_clflush_virt_range(vmap->vaddr + clip->y1 * fb->pitches[0],
+  drm_rect_height(clip) * fb->pitches[0]);
+#endif
 }
 
 /*

base-commit: 1f36d634670d8001a45fe2f2dcae546819f9c7d8
-- 
2.43.0



Re: [PATCH] drm/mgag200: Flush the cache to improve latency

2024-02-06 Thread Jocelyn Falempe




On 06/02/2024 14:33, Daniel Vetter wrote:

On Mon, Dec 11, 2023 at 10:31:28AM +0100, Jocelyn Falempe wrote:

On 06/11/2023 11:46, Jocelyn Falempe wrote:

On 23/10/2023 10:30, Jocelyn Falempe wrote:

On 20/10/2023 14:06, Thomas Zimmermann wrote:

(cc'ing lkml for feedback)

Hi Jocelyn

Am 19.10.23 um 15:55 schrieb Jocelyn Falempe:

We found a regression in v5.10 on real-time server, using the
rt-kernel and the mgag200 driver. It's some really specialized
workload, with <10us latency expectation on isolated core.
After the v5.10, the real time tasks missed their <10us latency
when something prints on the screen (fbcon or printk)


I'd like to hear the opinion of the RT-devs on this patch.
Because AFAIK we never did such a workaround in other drivers.
And AFAIK printk is a PITA anyway.


Most other drivers uses DMA, which means this workaround can't apply
to them.



IMHO if that RT system cannot handle differences in framebuffer
caching, it's under-powered. It's just a matter of time until
something else changes and the problem returns. And (honest
question) as it's an x86-64, how do they handle System
Management Mode?


I think it's not a big news, that the Matrox G200 from 1999 is
under-powered.
I was also a bit surprised that flushing the cache would have such
effect on latency. The tests we are doing can run 24h with the
workaround, without any interrupt taking more than 10us. Without the
workaround, every ~30s the interrupt failed its 10us target.





The regression has been bisected to 2 commits:
0b34d58b6c32 ("drm/mgag200: Enable caching for SHMEM pages")
4862ffaec523 ("drm/mgag200: Move vmap out of commit tail")

The first one changed the system memory framebuffer from Write-Combine
to the default caching.
Before the second commit, the mgag200 driver used to unmap the
framebuffer after each frame, which implicitly does a cache flush.
Both regressions are fixed by the following patch, which forces a
cache flush after each frame, reverting to almost v5.9 behavior.


With that second commit, we essentially never unmap an active
framebuffer console. But with commit

359c6649cd9a ("drm/gem: Implement shadow-plane {begin,
end}_fb_access with vmap")

we now again unmap the console framebuffer after the pageflip happened.

So how does the latest kernel behave wrt to the problem?


The regression was found when upgrading the server from v5.4 to
v5.14, so we didn't test with later kernels.
We will test with v6.3 (which should have 359c6649cd9a ) and see
what it gives.


I don't have a clear explanation, but testing with v6.3, and forcing the
Write Combine, doesn't fix the latency issue. So forcing the cache flush
is still needed.

Also, on some systems, they use "isolated cpu" to handle RT task, but
with a standard kernel (so without the CONFIG_PREEMPT_RT).
So I'm wondering if we can use a kernel module parameter for this,
so that users that wants to achieve low latency, can opt-in ?

something like mgag200.force_cache_flush=1 or mgag200.low_latency=1 ?


Hi,

I have now access to a server that reproduce the issue, and I was able to
test different workarounds.

So it is definitely related to the "Write Combine" mode of the mga internal
RAM. If I comment the two lines to enable wc: 
https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/mgag200/mgag200_drv.c#L150,
then the latency is <10us (but the performances are worse, from 20ms to 87ms
to draw a full frame).


Ok this is very strange, but at least it starts to make sense. Apparently
if we stream a _lot_ of writes from wb to wc memory on a cpu that results
in high latencies on other cpus. And the only way to fix that is by
artificially making the wb source suffer from cache misses by flushing
them out.


I also tried to flush the vram using:
drm_clflush_virt_range(mdev->vram + clip->y1 * fb->pitches[0],
drm_rect_height(clip) * fb->pitches[0]);
And that lower the latency to ~20us, but it's not enough.

I tried "sfence" which I though would flush the WC buffers of the CPU, but
that has no effect in practice.

I think I can send a new patch, to not map the VRAM as Write Combine, either
if CONFIG_PREEMPT_RT is set or if a module parameter is set.
What do you think is the best approach ?


I think an mgag200 module option like Dave suggested is best.

Plus the entire above debug story in the commit message, especially the
things you've figured out in your latest testing (apologies for missing
your mail from Dec, pls ping again if things get dropped like that) kinda
explains what's going on.

Still doesn't make much sense that a cpu doing a lot of wb->wc transfers
can hurt other cores like this, but at least that seems technically
plausible.

Also please link to this thread for all the details on test setup, I think
the above is enough as a summary for the commit message. But if you want
you can include all the details below too.


Thanks,

Let me send a new pa

Re: [PATCH 00/23] [RFC] drm/format-helper: Introduce drm_pixmap, font support and filling

2024-02-01 Thread Jocelyn Falempe

Hi Thomas,

Thanks for taking the time to write this series.

I find the drm_pixmap is a nice improvement, and simplifies a bit the code.

Regarding the font blit, I'm not convinced by this approach.
I don't see the benefit of using the same function between fonts and 
framebuffer copy, as it's unlikely to have 16bit or 32bit fonts in the 
kernel, or to have monochrome buffer from userspace. And the big format 
switch will dispatch to different functions, so there is almost no code 
sharing between both paths.


Also for each format supported, you now need 2 functions for 
xrgb_to_y blit, 2 functions for c1_to_y blit, and 2 
functions for fill_yy. That doesn't scale well, and there is a lot 
of duplication between those functions.


I prefer the way Noralf Thronnes has done it in [1] and only consider 
the pixel width.


[1] 
https://lore.kernel.org/dri-devel/20190311174218.51899-2-nor...@tronnes.org/


Best regards,

--

Jocelyn

On 30/01/2024 10:53, Thomas Zimmermann wrote:

This RFC patchset implements various features required for DRM panic
handling [1] and should (for now) be seen in that context.

Most of all, the patchset replaces struct drm_framebuffer with struct
drm_pixmap in the format-conversion helpers. DRM pixmap represents a
source of pixel data for the blitting operations. Patches 1 to 19
update the interface, implementation and all of the callers. These
patches could be useful even without DRM panic handling.

With struct drm_pixmap in place, patches 20 to 22 implement rudimentary
support for blitting font data. The pixmap refers to a character's glyph,
which the blit routines write to the destination memory. An example on
blitting strings is given in patch 20's commit description.

Patch 23 adds rudimentary support for fill operations. The design is
based on blitting, but blits the same color into each pixel.

[1] https://patchwork.freedesktop.org/series/122244/

Thomas Zimmermann (23):
   drm/format-helper: Add struct drm_pixmap
   drm/format-helper: Use struct drm_pixmap for drm_fb_memcpy()
   drm/format-helper: Streamline drm_fb_xfrm() implementations
   drm/format-helper: Use struct drm_pixmap internally
   drm/format-helper: Use struct drm_pixmap for drm_fb_swab()
   drm/format-helper: Use struct drm_pixmap for
 drm_fb_xrgb_to_rgb332()
   drm/format-helper: Use struct drm_pixmap for
 drm_fb_xrgb_to_rgb565()
   drm/format-helper: Use struct drm_pixmap for
 drm_fb_xrgb_to_xrgb1555()
   drm/format-helper: Use struct drm_pixmap for
 drm_fb_xrgb_to_argb1555()
   drm/format-helper: Use struct drm_pixmap for
 drm_fb_xrgb_to_rgba5551()
   drm/format-helper: Use struct drm_pixmap for
 drm_fb_xrgb_to_rgb888()
   drm/format-helper: Use struct drm_pixmap for
 drm_fb_xrgb_to_argb()
   drm/format-helper: Use struct drm_pixmap for
 drm_fb_xrgb_to_abgr()
   drm/format-helper: Use struct drm_pixmap for
 drm_fb_xrgb_to_xbgr()
   drm/format-helper: Use struct drm_pixmap for
 drm_fb_xrgb_to_xrgb2101010()
   drm/format-helper: Use struct drm_pixmap for
 drm_fb_xrgb_to_argb2101010()
   drm/format-helper: Use struct drm_pixmap for
 drm_fb_xrgb_to_gray8()
   drm/format-helper: Use struct drm_pixmap for drm_fb_xrgb_to_mono()
   drm/format-helper: Use struct drm_pixmap for drm_fb_blit()
   [DO NOT MERGE] drm/format-helper: Add font-support for DRM pixmap
   [DO NOT MERGE] drm/format-helper: Add color palette
   [DO NOT MERGE] drm/format-helper: Support blitting from C1 to XRGB
   [DO NOT MERGE] drm/format-helper: Add drm_fb_fill() to fill screen
 with color

  drivers/gpu/drm/ast/ast_mode.c|   4 +-
  drivers/gpu/drm/drm_format_helper.c   | 678 --
  drivers/gpu/drm/drm_mipi_dbi.c|   9 +-
  drivers/gpu/drm/gud/gud_pipe.c|  24 +-
  drivers/gpu/drm/hyperv/hyperv_drm_modeset.c   |   4 +-
  drivers/gpu/drm/mgag200/mgag200_mode.c|   4 +-
  drivers/gpu/drm/solomon/ssd130x.c |  12 +-
  .../gpu/drm/tests/drm_format_helper_test.c| 106 ++-
  drivers/gpu/drm/tiny/cirrus.c |   6 +-
  drivers/gpu/drm/tiny/ofdrm.c  |   6 +-
  drivers/gpu/drm/tiny/repaper.c|   4 +-
  drivers/gpu/drm/tiny/simpledrm.c  |   6 +-
  drivers/gpu/drm/tiny/st7586.c |   4 +-
  include/drm/drm_format_helper.h   | 116 ++-
  14 files changed, 678 insertions(+), 305 deletions(-)





Re: [PATCH v7 1/9] drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill

2024-01-23 Thread Jocelyn Falempe




On 23/01/2024 13:56, Thomas Zimmermann wrote:

Hi,

FYI for points 1 and 2, I'm typing up a patchset that introduces 
drm_pixmap for the source buffer. I'll post it when I have something ready.


Thanks, I didn't have time to look into this yet.

Best regards,

--

Jocelyn



Best regards
Thomas

Am 19.01.24 um 11:58 schrieb Thomas Zimmermann:

Hi

Am 17.01.24 um 17:40 schrieb Jocelyn Falempe:



On 17/01/2024 16:06, Thomas Zimmermann wrote:

Hi

Am 04.01.24 um 17:00 schrieb Jocelyn Falempe:

This is needed for drm_panic, to draw the font, and fill
the background color, in multiple color format.


TBH, I don't like this patch at all. It looks like you're 
reimplementing existing functionality for a single use case; 
specifically drm_fb_blit().


What's wrong with the existing interfaces?


I've spend considerable time to clean up the format-helper code and 
get it into shape. It's not there yet, but on its way. So I'd rather 
prefer to update the existing code for new use cases. Adding a new 
interface for a single use case is something like a leap backwards.


So let's see if we can work out something.



drm_fb_blit() is good to copy a framebuffer to another, but is 
clearly unoptimal to draw font.


1) The framebuffer data structure is only there for historical 
reasons. It should be removed from the internal implementation 
entirely. A first patch should go into this in any case. It didn't 
happened so far, as I've been busy with other work.


2) For the public API, I've long wanted to replace framebuffers with 
something more flexible, let's call it drm_pixmap


   struct drm_pixmap {
 struct drm_format_info *format
 unsigned int width, height
 unsigned int pitches[DRM_FORMAT_MAX_PLANES]
 iomap vaddr[DRM_FORMAT_MAX_PLANES]
   };

It's the essence of drm_framebuffer. Let's say there's also an init 
helper drm_pixmap_init_from_framebuffer(pix, fb) that sets up 
everything. The implementation of drm_fb_blit() would look like this:


   drm_fb_blit(...) {

 drm_pixmap pix;
 drm_pixmap_init_from_framebuffer(pix, fb)
 __drm_fb_blit_pixmap(  )
   }

That would require some changes to drivers, but it's only simple 
refactoring.


3) When looking at your patch, there's

   src = font->data + (msg->txt[i] * font->height) * src_stride;

which should be in a helper that sets up the drm_pixmap for a font 
character:


   drm_pixmap_init_from_char(pixmap, c, font_data)

where 'c' equals msg->txt[i]

The text drawing in the panic handler would do something like

   for (msg->txt[i]) {
 drm_pixmap_init_from_char(pixmap, ...)
   drm_fb_blit_pixmap(...)
   }


It handles xrgb to any rgb format, and I need monochrome to any 
rgb format.


4) You're free to add any conversion to drm_fb_blit(). It's supposed 
to handle all available format conversion. With the pixmap-related 
changes outlined above and the actual conversion code, I think that 
would already put characters on the screen.


I need to convert foreground and background color to the destination 
format, but using drm_fb_blit() to convert 1 pixel is tedious.


5) I've recently added drm_format_conv_state to the API. It is 
supposed to hold state that is required for the conversion process. I 
specifically had color palettes in mind. Please use the data 
structure. Something like that:


   struct drm_format_conv_state {
 ...
 const drm_color_lut *palette;
   }

and in the conversion code:

   void r1_to_rgb() {
 for (x < pixels) {
 rgb = state->palette[r1]
 }
   }



It also requires an additional memory buffer, and do an additional 
memory copy that we don't need at all.


6) That memcpy_to_io() not a big deal. You should pre-allocate that 
memory buffer in the panic handler and init the drm_format_conv_state 
with DRM_FORMAT_CONV_STATE_INIT_PREALLOCATED().




It also has no way to fill a region with the background color.


7) Please add a separate drm_fb_fill() implementation. If you have a 
palette in struct drm_format_conf_state, you can add a helper for each 
destination format that takes a drm_color_lut value as input.


This point is probably worth a separate discussion.



The last thing, is if I plan to add YUV support, with this 
implementation, I only need to write one function that convert one 
pixel. Otherwise I would need to add the drm_fb_r1_to_yuvxxx_line() 
and drm_fb_r1_to_yuv() boilerplate.


8) YUVs are multi-plane formats IIRC. So it's likely a bit more 
complicated.And I'm not aware of any current use case for YUV. If the 
framebuffer console doesn't support it, the panic helper probably 
won't either.


Best regards
Thomas



Best regards,









[PATCH 2/2] drm/vmwgfx: Keep a gem reference to user bos in surfaces

2024-01-22 Thread Jocelyn Falempe
From: Zack Rusin 

commit 91398b413d03660fd5828f7b4abc64e884b98069 upstream

Surfaces can be backed (i.e. stored in) memory objects (mob's) which
are created and managed by the userspace as GEM buffers. Surfaces
grab only a ttm reference which means that the gem object can
be deleted underneath us, especially in cases where prime buffer
export is used.

Make sure that all userspace surfaces which are backed by gem objects
hold a gem reference to make sure they're not deleted before vmw
surfaces are done with them, which fixes:
[ cut here ]
refcount_t: underflow; use-after-free.
WARNING: CPU: 2 PID: 2632 at lib/refcount.c:28 refcount_warn_saturate+0xfb/0x150
Modules linked in: overlay vsock_loopback vmw_vsock_virtio_transport_common 
vmw_vsock_vmci_transport vsock snd_ens1371 snd_ac97_codec ac97_bus snd_pcm 
gameport>
CPU: 2 PID: 2632 Comm: vmw_ref_count Not tainted 6.5.0-rc2-vmwgfx #1
Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference 
Platform, BIOS 6.00 11/12/2020
RIP: 0010:refcount_warn_saturate+0xfb/0x150
Code: eb 9e 0f b6 1d 8b 5b a6 01 80 fb 01 0f 87 ba e4 80 00 83 e3 01 75 89 48 
c7 c7 c0 3c f9 a3 c6 05 6f 5b a6 01 01 e8 15 81 98 ff <0f> 0b e9 6f ff ff ff 0f 
b>
RSP: 0018:bdc34344bba0 EFLAGS: 00010286
RAX:  RBX:  RCX: 0027
RDX: 960475ea1548 RSI: 0001 RDI: 960475ea1540
RBP: bdc34344bba8 R08: 0003 R09: 65646e75203a745f
R10: a5b32b20 R11: 72657466612d6573 R12: 96037d6a6400
R13: 9603484805b0 R14: 000b R15: 9603bed06060
FS:  7f5fd8520c40() GS:960475e8() knlGS:
CS:  0010 DS:  ES:  CR0: 80050033
CR2: 7f5fda755000 CR3: 00010d012005 CR4: 003706e0
Call Trace:
 
 ? show_regs+0x6e/0x80
 ? refcount_warn_saturate+0xfb/0x150
 ? __warn+0x91/0x150
 ? refcount_warn_saturate+0xfb/0x150
 ? report_bug+0x19d/0x1b0
 ? handle_bug+0x46/0x80
 ? exc_invalid_op+0x1d/0x80
 ? asm_exc_invalid_op+0x1f/0x30
 ? refcount_warn_saturate+0xfb/0x150
 drm_gem_object_handle_put_unlocked+0xba/0x110 [drm]
 drm_gem_object_release_handle+0x6e/0x80 [drm]
 drm_gem_handle_delete+0x6a/0xc0 [drm]
 ? __pfx_vmw_bo_unref_ioctl+0x10/0x10 [vmwgfx]
 vmw_bo_unref_ioctl+0x33/0x40 [vmwgfx]
 drm_ioctl_kernel+0xbc/0x160 [drm]
 drm_ioctl+0x2d2/0x580 [drm]
 ? __pfx_vmw_bo_unref_ioctl+0x10/0x10 [vmwgfx]
 ? do_vmi_munmap+0xee/0x180
 vmw_generic_ioctl+0xbd/0x180 [vmwgfx]
 vmw_unlocked_ioctl+0x19/0x20 [vmwgfx]
 __x64_sys_ioctl+0x99/0xd0
 do_syscall_64+0x5d/0x90
 ? syscall_exit_to_user_mode+0x2a/0x50
 ? do_syscall_64+0x6d/0x90
 ? handle_mm_fault+0x16e/0x2f0
 ? exit_to_user_mode_prepare+0x34/0x170
 ? irqentry_exit_to_user_mode+0xd/0x20
 ? irqentry_exit+0x3f/0x50
 ? exc_page_fault+0x8e/0x190
 entry_SYSCALL_64_after_hwframe+0x6e/0xd8
RIP: 0033:0x7f5fda51aaff
Code: 00 48 89 44 24 18 31 c0 48 8d 44 24 60 c7 04 24 10 00 00 00 48 89 44 24 
08 48 8d 44 24 20 48 89 44 24 10 b8 10 00 00 00 0f 05 <41> 89 c0 3d 00 f0 ff ff 
7>
RSP: 002b:7ffd536a4d30 EFLAGS: 0246 ORIG_RAX: 0010
RAX: ffda RBX: 7ffd536a4de0 RCX: 7f5fda51aaff
RDX: 7ffd536a4de0 RSI: 40086442 RDI: 0003
RBP: 40086442 R08: 55fa603ada50 R09: 
R10: 0001 R11: 0246 R12: 7ffd536a51b8
R13: 0003 R14: 55fa5ebb4c80 R15: 7f5fda90f040
 
---[ end trace  ]---

A lot of the analyis on the bug was done by Murray McAllister and
Ian Forbes.

Reported-by: Murray McAllister 
Cc: Ian Forbes 
Signed-off-by: Zack Rusin 
Fixes: a950b989ea29 ("drm/vmwgfx: Do not drop the reference to the handle too 
soon")
Cc:  # v6.2+
Reviewed-by: Martin Krastev 
Link: 
https://patchwork.freedesktop.org/patch/msgid/20230928041355.737635-1-z...@kde.org
Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/vmwgfx/vmwgfx_bo.c   |  5 ++---
 drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c  |  8 +++
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h  | 22 ++-
 drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c  | 10 +
 drivers/gpu/drm/vmwgfx/vmwgfx_gem.c  | 24 -
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  |  6 +++---
 drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c  |  2 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 18 
 drivers/gpu/drm/vmwgfx/vmwgfx_shader.c   |  4 ++--
 drivers/gpu/drm/vmwgfx/vmwgfx_surface.c  | 27 +++-
 10 files changed, 71 insertions(+), 55 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
index 5ac5efea1d60..c46f380d9149 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
@@ -595,7 +595,7 @@ static int vmw_user_bo_synccpu_release(struct drm_file 
*filp,
if (!(flags & drm_vmw_synccpu_allow_cs)) {
atomic_dec(_bo->cpu_writers);
}
- 

[PATCH 1/2] drm/vmwgfx: Fix possible invalid drm gem put calls

2024-01-22 Thread Jocelyn Falempe
From: Zack Rusin 

commit f9e96bf1905479f18e83a3a4c314a8dfa56ede2c upstream

vmw_bo_unreference sets the input buffer to null on exit, resulting in
null ptr deref's on the subsequent drm gem put calls.

This went unnoticed because only very old userspace would be exercising
those paths but it wouldn't be hard to hit on old distros with brand
new kernels.

Introduce a new function that abstracts unrefing of user bo's to make
the code cleaner and more explicit.

Signed-off-by: Zack Rusin 
Reported-by: Ian Forbes 
Fixes: 9ef8d83e8e25 ("drm/vmwgfx: Do not drop the reference to the handle too 
soon")
Cc:  # v6.4+
Reviewed-by: Maaz Mombasawala
Link: 
https://patchwork.freedesktop.org/patch/msgid/20230818041301.407636-1-z...@kde.org
Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/vmwgfx/vmwgfx_bo.c  | 6 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 8 
 drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 6 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 6 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c | 3 +--
 drivers/gpu/drm/vmwgfx/vmwgfx_shader.c  | 3 +--
 6 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
index ae01d22b8f84..5ac5efea1d60 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
@@ -595,10 +595,9 @@ static int vmw_user_bo_synccpu_release(struct drm_file 
*filp,
if (!(flags & drm_vmw_synccpu_allow_cs)) {
atomic_dec(_bo->cpu_writers);
}
-   ttm_bo_put(_bo->base);
+   vmw_user_bo_unref(vmw_bo);
}
 
-   drm_gem_object_put(_bo->base.base);
return ret;
 }
 
@@ -638,8 +637,7 @@ int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void 
*data,
return ret;
 
ret = vmw_user_bo_synccpu_grab(vbo, arg->flags);
-   vmw_bo_unreference();
-   drm_gem_object_put(>base.base);
+   vmw_user_bo_unref(vbo);
if (unlikely(ret != 0)) {
if (ret == -ERESTARTSYS || ret == -EBUSY)
return -EBUSY;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h 
b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 8459fab9d979..5be15732fbc5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -1600,6 +1600,14 @@ vmw_bo_reference(struct vmw_buffer_object *buf)
return buf;
 }
 
+static inline void vmw_user_bo_unref(struct vmw_buffer_object *vbo)
+{
+   if (vbo) {
+   ttm_bo_put(>base);
+   drm_gem_object_put(>base.base);
+   }
+}
+
 static inline void vmw_fifo_resource_inc(struct vmw_private *dev_priv)
 {
atomic_inc(_priv->num_fifo_resources);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 7e59469e1cb9..5a8b187619d3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -1159,8 +1159,7 @@ static int vmw_translate_mob_ptr(struct vmw_private 
*dev_priv,
return PTR_ERR(vmw_bo);
}
ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false);
-   ttm_bo_put(_bo->base);
-   drm_gem_object_put(_bo->base.base);
+   vmw_user_bo_unref(vmw_bo);
if (unlikely(ret != 0))
return ret;
 
@@ -1214,8 +1213,7 @@ static int vmw_translate_guest_ptr(struct vmw_private 
*dev_priv,
return PTR_ERR(vmw_bo);
}
ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false);
-   ttm_bo_put(_bo->base);
-   drm_gem_object_put(_bo->base.base);
+   vmw_user_bo_unref(vmw_bo);
if (unlikely(ret != 0))
return ret;
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index aab6389cb4aa..e4b2d11f2c8b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1599,10 +1599,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct 
drm_device *dev,
 
 err_out:
/* vmw_user_lookup_handle takes one ref so does new_fb */
-   if (bo) {
-   vmw_bo_unreference();
-   drm_gem_object_put(>base.base);
-   }
+   if (bo)
+   vmw_user_bo_unref(bo);
if (surface)
vmw_surface_unreference();
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
index b5b311f2a91a..327330055ae5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
@@ -457,8 +457,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data,
 
ret = vmw_overlay_update_stream(dev_priv, buf, arg, true);
 
-   vmw_bo_unreference();
-   drm_gem_object_put(>base.base);
+   vmw_user_bo_unref(buf);
 
 out_unlock:
   

[PATCH 0/2] drm/vmwgfx backport two fixes to v6.1.x branch

2024-01-22 Thread Jocelyn Falempe
Hi,

I've backported this two commits:
f9e96bf19054 drm/vmwgfx: Fix possible invalid drm gem put calls
91398b413d03 drm/vmwgfx: Keep a gem reference to user bos in surfaces

They both fixes a950b989ea29 ("drm/vmwgfx: Do not drop the reference
to the handle too soon")
which has been backported to v6.1.x branch as 0a127ac97240

There was a lot of conflicts, and as I'm not familiar with the vmwgfx
driver, it's better to review and test them.
I've run a short test, and it worked, but that's certainly not enough.

Thanks,

Zack Rusin (2):
  drm/vmwgfx: Fix possible invalid drm gem put calls
  drm/vmwgfx: Keep a gem reference to user bos in surfaces

 drivers/gpu/drm/vmwgfx/vmwgfx_bo.c   |  7 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c  |  8 +++
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h  | 20 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c  | 12 +--
 drivers/gpu/drm/vmwgfx/vmwgfx_gem.c  | 24 -
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  | 10 -
 drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c  |  3 +--
 drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 18 
 drivers/gpu/drm/vmwgfx/vmwgfx_shader.c   |  5 ++---
 drivers/gpu/drm/vmwgfx/vmwgfx_surface.c  | 27 +++-
 10 files changed, 75 insertions(+), 59 deletions(-)


base-commit: fec3b1451d5febbc9e04250f879c10f8952e6bed
-- 
2.43.0



Re: [PATCH v7 2/9] drm/panic: Add a drm panic handler

2024-01-19 Thread Jocelyn Falempe




On 12/01/2024 14:50, Daniel Vetter wrote:

On Thu, Jan 04, 2024 at 05:00:46PM +0100, Jocelyn Falempe wrote:

+/**
+ * drm_panic_init() - Initialize drm-panic subsystem
+ *
+ * register the panic notifier
+ */
+void drm_panic_init(void)
+{
+   atomic_notifier_chain_register(_notifier_list,
+  _panic_notifier);


Ok I've found another one after checking core panic code. This is the
wrong hook, we want to be a sttruct kmsg_dumper and use
kmsg_dump_register. And again once for each drm_panic_device so that we
can rely on core locking, as I've explained in the other reply.

Also because it trashes buffers from userspace I think by default we want
to only dump on panic, so KMS_DUMP_PANIC.
-Sima



I've tested this change and I don't think kmsg_dumper is the right callback.
At least with panic_notifier, you get one line on why the panic occurs. 
With kmsg_dumper you get the whole kmsg buffer, but I don't want to 
throw that at the user. And it's not possible to extract just the panic 
reason from the log.
I think the debug information should go in a QRCode, so you can actually 
report the crash somewhere, and copy/paste the backtrace and other info 
to the bug. I've a PoC for that, but I prefer to have the main drm_panic 
merged before working further on this.


Anyway it's pretty easy to change from one to the other, since the API 
are quite similar. So if we need the complete kmsg log someday, it 
should be easy to switch.


Best regards,

--

Jocelyn



Re: [PATCH v7 2/9] drm/panic: Add a drm panic handler

2024-01-18 Thread Jocelyn Falempe




On 17/01/2024 16:49, Thomas Zimmermann wrote:

Hi

Am 04.01.24 um 17:00 schrieb Jocelyn Falempe:
[...]

+    /**
+ * @get_scanout_buffer:
+ *
+ * Get the current scanout buffer, to display a panic message 
with drm_panic.
+ * The driver should do the minimum changes to provide a linear 
buffer, that

+ * can be used to display the panic screen.
+ * It is called from a panic callback, and must follow its 
restrictions.
+ * (no locks, no memory allocation, no sleep, no 
thread/workqueue, ...)
+ * It's a best effort mode, so it's expected that in some complex 
cases the

+ * panic screen won't be displayed.
+ * Some hardware cannot provide a linear buffer, so there is a 
draw_pixel_xy()
+ * callback in the struct drm_scanout_buffer that can be used in 
this case.

+ *
+ * Returns:
+ *
+ * Zero on success, negative errno on failure.
+ */
+    int (*get_scanout_buffer)(struct drm_device *dev,
+  struct drm_scanout_buffer *sb);
+


After reading through Sima's comments on (try-)locking, I'd like to 
propose a different interface: instead of having the panic handler 
search for the scanout buffer, let each driver explicitly set the 
scanout buffer after each page flip. The algorithm for mode programming 
then looks like this:


  1) Maybe clear the panic handler's buffer at the beginning of 
atomic_commit_tail, if necessary

  2) Do the mode setting as usual
  3) In the driver's atomic_flush or atomic_update, call something like

 void drm_panic_set_scanout_buffer(dev, scanout_buffer)

to set the panic handler's new output.

This avoids all the locking and the second guessing about the pipeline 
status.


I don't see an easy way of reliably showing a panic screen during a 
modeset. But during a modeset, the old scanout buffer should 
(theoretically) not disappear until the new scanout buffer is in place. 
So if the panic happens, it would blit to the old address at worst. 
Well, that assumption needs to be verified per driver.


That's an interesting approach, and I will give it a try.
I think you still need a callback in the driver, to actually send the 
data to the GPU.


Also one thing that I don't handle yet, is when there are multiple 
outputs, so we may want to set and update multiple scanout buffers ?


Best regards,

--

Jocelyn




Best regards
Thomas



  /** @major: driver major number */
  int major;
  /** @minor: driver minor number */
diff --git a/include/drm/drm_panic.h b/include/drm/drm_panic.h
new file mode 100644
index ..bcf392b6fa1b
--- /dev/null
+++ b/include/drm/drm_panic.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: GPL-2.0 or MIT */
+#ifndef __DRM_PANIC_H__
+#define __DRM_PANIC_H__
+
+/*
+ * Copyright (c) 2023 Red Hat.
+ * Author: Jocelyn Falempe 
+ */
+
+#include 
+#include 
+#include 
+
+struct drm_device;
+
+/**
+ * struct drm_scanout_buffer - DRM scanout buffer
+ *
+ * This structure holds the information necessary for drm_panic to 
draw the

+ * panic screen, and display it.
+ * If the driver can't provide a linear buffer, it must clear @map with
+ * iosys_map_clear() and provide a draw_pixel_xy() function.
+ */
+struct drm_scanout_buffer {
+    /**
+ * @format:
+ *
+ * drm format of the scanout buffer.
+ */
+    const struct drm_format_info *format;
+    /**
+ * @map:
+ *
+ * Virtual address of the scanout buffer, either in memory or iomem.
+ * The scanout buffer should be in linear format, and can be 
directly
+ * sent to the display hardware. Tearing is not an issue for the 
panic

+ * screen.
+ */
+    struct iosys_map map;
+    /**
+ * @width: Width of the scanout buffer, in pixels.
+ */
+    unsigned int width;
+    /**
+ * @height: Height of the scanout buffer, in pixels.
+ */
+    unsigned int height;
+    /**
+ * @pitch: Length in bytes between the start of two consecutive 
lines.

+ */
+    unsigned int pitch;
+    /**
+ * @private:
+ *
+ * In case the driver can't provide a linear buffer, this is a 
pointer to
+ * some private data, that will be passed when calling 
@draw_pixel_xy()

+ * and @flush()
+ */
+    void *private;
+    /**
+ * @draw_pixel_xy:
+ *
+ * In case the driver can't provide a linear buffer, this is a 
function

+ * that drm_panic will call for each pixel to draw.
+ * Color will be converted to the format specified by @format.
+ */
+    void (*draw_pixel_xy)(unsigned int x, unsigned int y, u32 color, 
void *private);

+    /**
+ * @flush:
+ *
+ * This function is called after the panic screen is drawn, 
either using
+ * the iosys_map or the draw_pixel_xy path. In this function, the 
driver

+ * can send additional commands to the hardware, to make the buffer
+ * visible.
+ */
+    void (*flush)(void *private);
+};
+
+#ifdef CONFIG_DRM_PANIC
+
+void drm_panic_init(void);
+void drm_panic_exit(void

Re: [PATCH v7 1/9] drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill

2024-01-17 Thread Jocelyn Falempe




On 17/01/2024 16:26, Jani Nikula wrote:

On Thu, 04 Jan 2024, Jocelyn Falempe  wrote:

This is needed for drm_panic, to draw the font, and fill
the background color, in multiple color format.

v5:
  * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
  * Also add drm_fb_fill() to fill area with background color.
v6:
  * fix __le32 conversion warning found by the kernel test bot

Signed-off-by: Jocelyn Falempe 
---
  drivers/gpu/drm/drm_format_helper.c | 432 ++--
  include/drm/drm_format_helper.h |   9 +
  2 files changed, 360 insertions(+), 81 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index b1be458ed4dd..8cbc2d747cff 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -111,6 +111,153 @@ void drm_format_conv_state_release(struct 
drm_format_conv_state *state)
  }
  EXPORT_SYMBOL(drm_format_conv_state_release);
  
+static inline __le16 drm_format_xrgb_to_rgb565(__le32 val32)


Please don't use inline in C files. Just let the compiler do its job.


Sure, I will remove those inline in next version.

Thanks,

--

Jocelyn



BR,
Jani.


+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = ((pix & 0x00F8) >> 8) |
+   ((pix & 0xFC00) >> 5) |
+   ((pix & 0x00F8) >> 3);
+   return cpu_to_le16(val16);
+}
+
+static inline __le16 drm_format_xrgb_to_rgba5551(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = ((pix & 0x00f8) >> 8) |
+   ((pix & 0xf800) >> 5) |
+   ((pix & 0x00f8) >> 2) |
+   BIT(0); /* set alpha bit */
+   return cpu_to_le16(val16);
+}
+
+static inline __le16 drm_format_xrgb_to_xrgb1555(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = ((pix & 0x00f8) >> 9) |
+   ((pix & 0xf800) >> 6) |
+   ((pix & 0x00f8) >> 3);
+   return cpu_to_le16(val16);
+}
+
+static inline __le16 drm_format_xrgb_to_argb1555(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = BIT(15) | /* set alpha bit */
+   ((pix & 0x00f8) >> 9) |
+   ((pix & 0xf800) >> 6) |
+   ((pix & 0x00f8) >> 3);
+   return cpu_to_le16(val16);
+}
+
+static inline __le32 drm_format_xrgb_to_argb(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 |= GENMASK(31, 24); /* fill alpha bits */
+   return cpu_to_le32(val32);
+}
+
+static inline __le32 drm_format_xrgb_to_xbgr(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00ff) >> 16) <<  0 |
+   ((val32 & 0xff00) >>  8) <<  8 |
+   ((val32 & 0x00ff) >>  0) << 16 |
+   ((val32 & 0xff00) >> 24) << 24;
+   return cpu_to_le32(val32);
+}
+
+static inline __le32 drm_format_xrgb_to_abgr(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00ff) >> 16) <<  0 |
+   ((val32 & 0xff00) >>  8) <<  8 |
+   ((val32 & 0x00ff) >>  0) << 16 |
+   GENMASK(31, 24); /* fill alpha bits */
+   return cpu_to_le32(val32);
+}
+
+static inline __le32 drm_format_xrgb_to_xrgb2101010(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00FF) << 2) |
+   ((val32 & 0xFF00) << 4) |
+   ((val32 & 0x00FF) << 6);
+   return cpu_to_le32(val32 | ((val32 >> 8) & 0x00300C03));
+}
+
+static inline __le32 drm_format_xrgb_to_argb2101010(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00FF) << 2) |
+   ((val32 & 0xFF00) << 4) |
+   ((val32 & 0x00FF) << 6);
+   val32 = GENMASK(31, 30) | /* set alpha bits */
+ val32 | ((val32 >> 8) & 0x00300c03);
+   return cpu_to_le32(val32);
+}
+
+/**
+ * drm_fb_convert_from_xrgb - convert one pixel from xrgb to the 
desired format
+ * @color: input color, in xrgb format
+ * @format: output format
+ *
+ * Returns:
+ * Color in the format specified, casted to u32.
+ * Or 0 if the format is unknown.
+ */
+u32 drm_fb_convert_from_xrgb(u32 color, u32 format)
+{
+   __le32 pix = cpu_to_le32(color);
+
+   switch (format) {
+   case DRM_FORMAT_RGB565:
+   return le16_to_cpu(drm_forma

Re: [PATCH v7 1/9] drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill

2024-01-17 Thread Jocelyn Falempe




On 17/01/2024 16:06, Thomas Zimmermann wrote:

Hi

Am 04.01.24 um 17:00 schrieb Jocelyn Falempe:

This is needed for drm_panic, to draw the font, and fill
the background color, in multiple color format.


TBH, I don't like this patch at all. It looks like you're reimplementing 
existing functionality for a single use case; specifically drm_fb_blit().


What's wrong with the existing interfaces?


drm_fb_blit() is good to copy a framebuffer to another, but is clearly 
unoptimal to draw font.
It handles xrgb to any rgb format, and I need monochrome to any rgb 
format.
I need to convert foreground and background color to the destination 
format, but using drm_fb_blit() to convert 1 pixel is tedious.


It also requires an additional memory buffer, and do an additional 
memory copy that we don't need at all.


It also has no way to fill a region with the background color.

The last thing, is if I plan to add YUV support, with this 
implementation, I only need to write one function that convert one 
pixel. Otherwise I would need to add the drm_fb_r1_to_yuvxxx_line() and 
drm_fb_r1_to_yuv() boilerplate.


Best regards,

--

Jocelyn



Best regards
Thomas



v5:
  * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
  * Also add drm_fb_fill() to fill area with background color.
v6:
  * fix __le32 conversion warning found by the kernel test bot

Signed-off-by: Jocelyn Falempe 
---
  drivers/gpu/drm/drm_format_helper.c | 432 ++--
  include/drm/drm_format_helper.h |   9 +
  2 files changed, 360 insertions(+), 81 deletions(-)

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

index b1be458ed4dd..8cbc2d747cff 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -111,6 +111,153 @@ void drm_format_conv_state_release(struct 
drm_format_conv_state *state)

  }
  EXPORT_SYMBOL(drm_format_conv_state_release);
+static inline __le16 drm_format_xrgb_to_rgb565(__le32 val32)
+{
+    u16 val16;
+    u32 pix;
+
+    pix = le32_to_cpu(val32);
+    val16 = ((pix & 0x00F8) >> 8) |
+    ((pix & 0xFC00) >> 5) |
+    ((pix & 0x00F8) >> 3);
+    return cpu_to_le16(val16);
+}
+
+static inline __le16 drm_format_xrgb_to_rgba5551(__le32 val32)
+{
+    u16 val16;
+    u32 pix;
+
+    pix = le32_to_cpu(val32);
+    val16 = ((pix & 0x00f8) >> 8) |
+    ((pix & 0xf800) >> 5) |
+    ((pix & 0x00f8) >> 2) |
+    BIT(0); /* set alpha bit */
+    return cpu_to_le16(val16);
+}
+
+static inline __le16 drm_format_xrgb_to_xrgb1555(__le32 val32)
+{
+    u16 val16;
+    u32 pix;
+
+    pix = le32_to_cpu(val32);
+    val16 = ((pix & 0x00f8) >> 9) |
+    ((pix & 0xf800) >> 6) |
+    ((pix & 0x00f8) >> 3);
+    return cpu_to_le16(val16);
+}
+
+static inline __le16 drm_format_xrgb_to_argb1555(__le32 val32)
+{
+    u16 val16;
+    u32 pix;
+
+    pix = le32_to_cpu(val32);
+    val16 = BIT(15) | /* set alpha bit */
+    ((pix & 0x00f8) >> 9) |
+    ((pix & 0xf800) >> 6) |
+    ((pix & 0x00f8) >> 3);
+    return cpu_to_le16(val16);
+}
+
+static inline __le32 drm_format_xrgb_to_argb(__le32 pix)
+{
+    u32 val32;
+
+    val32 = le32_to_cpu(pix);
+    val32 |= GENMASK(31, 24); /* fill alpha bits */
+    return cpu_to_le32(val32);
+}
+
+static inline __le32 drm_format_xrgb_to_xbgr(__le32 pix)
+{
+    u32 val32;
+
+    val32 = le32_to_cpu(pix);
+    val32 = ((val32 & 0x00ff) >> 16) <<  0 |
+    ((val32 & 0xff00) >>  8) <<  8 |
+    ((val32 & 0x00ff) >>  0) << 16 |
+    ((val32 & 0xff00) >> 24) << 24;
+    return cpu_to_le32(val32);
+}
+
+static inline __le32 drm_format_xrgb_to_abgr(__le32 pix)
+{
+    u32 val32;
+
+    val32 = le32_to_cpu(pix);
+    val32 = ((val32 & 0x00ff) >> 16) <<  0 |
+    ((val32 & 0xff00) >>  8) <<  8 |
+    ((val32 & 0x00ff) >>  0) << 16 |
+    GENMASK(31, 24); /* fill alpha bits */
+    return cpu_to_le32(val32);
+}
+
+static inline __le32 drm_format_xrgb_to_xrgb2101010(__le32 pix)
+{
+    u32 val32;
+
+    val32 = le32_to_cpu(pix);
+    val32 = ((val32 & 0x00FF) << 2) |
+    ((val32 & 0xFF00) << 4) |
+    ((val32 & 0x00FF) << 6);
+    return cpu_to_le32(val32 | ((val32 >> 8) & 0x00300C03));
+}
+
+static inline __le32 drm_format_xrgb_to_argb2101010(__le32 pix)
+{
+    u32 val32;
+
+    val32 = le32_to_cpu(pix);
+    val32 = ((val32 & 0x00FF) << 2) |
+    ((val32 & 0xFF00) << 4) |
+    ((val32 & 0x00FF) << 6);
+    val32 = GENMASK(31, 30) | /* set alpha bits */
+  val32 | ((val3

Re: [PATCH v7 5/9] drm/fb_dma: Add generic get_scanout_buffer() for drm_panic

2024-01-17 Thread Jocelyn Falempe




On 12/01/2024 14:41, Daniel Vetter wrote:

On Thu, Jan 04, 2024 at 05:00:49PM +0100, Jocelyn Falempe wrote:

This was initialy done for imx6, but should work on most drivers
using drm_fb_dma_helper.

Signed-off-by: Jocelyn Falempe 
---
  drivers/gpu/drm/drm_fb_dma_helper.c | 55 +
  include/drm/drm_fb_dma_helper.h |  4 +++
  2 files changed, 59 insertions(+)

diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c 
b/drivers/gpu/drm/drm_fb_dma_helper.c
index 3b535ad1b07c..caed2935df4f 100644
--- a/drivers/gpu/drm/drm_fb_dma_helper.c
+++ b/drivers/gpu/drm/drm_fb_dma_helper.c
@@ -15,6 +15,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -148,3 +149,57 @@ void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
}
  }
  EXPORT_SYMBOL_GPL(drm_fb_dma_sync_non_coherent);
+
+#if defined(CONFIG_DRM_PANIC)
+/**
+ * @dev: DRM device
+ * @drm_scanout_buffer: scanout buffer for the panic handler
+ * Returns: 0 or negative error code
+ *
+ * Generic get_scanout_buffer() implementation, for drivers that uses the
+ * drm_fb_dma_helper.
+ */
+int drm_panic_gem_get_scanout_buffer(struct drm_device *dev,
+struct drm_scanout_buffer *sb)
+{
+   struct drm_plane *plane;
+   struct drm_gem_dma_object *dma_obj;
+   struct drm_framebuffer *fb;
+
+   drm_for_each_primary_visible_plane(plane, dev) {


Ok that's not enough locking by far. You can't just hope that nothing
disappears while you're in a panic handler. We've been there and ended up
reliably oopsing in the panic handler itself. So you _have_ to follow the
full set of locking rules for all drm structures, or things will just get
worse at the worst possible moment.

But also, you're not allowed to do anything else than trylock, because a
panic handler might run from nmi context, and so you cannot even acquire
irq-safe spinlocks reliably.

Which means:

- You need to be safe against concurrent drm_dev_unregister. Using the
   atomic panic notifier directly for each device should take care of that
   (but maybe that stuff is still not nmi safe, not sure).

- You _have_ to use all the locks. Luckily iterating over the plane list
   doesn't need one, but you have to trylock the plane's modeset lock.
   Which means your nice iterator macro is already toast, because that
   already looks at state it's not allowed to look at without a lock. Or
   well, the plane->state pointer is no-go already.


mutex_trylock() shouldn't be called from interrupt context, and as the 
panic may occurs in irq, I can't use that.


But the panic context should guarantee that only one CPU is still running:
https://elixir.bootlin.com/linux/latest/source/kernel/panic.c#L310

So I think using mutex_is_locked() should be safe: 
https://elixir.bootlin.com/linux/latest/source/include/linux/mutex.h#L128


This will only check if the lock is not taken, but as it's not possible 
for another task to run at the same time, I think that should be good 
enough ?


The drawback, is if we want to test without crashing the kernel, then we 
need to take the locks with trylock(), (and it's safe this time), but 
the code path would be slightly different.


--

Jocelyn




Given the locking issues I'm not sure whether the
drm_for_each_primary_visible_plane iterator is going to work, you'd need
something like iter_init/next/end we have for walking the connector list.
Plus it would be very panic specific due to the trylock, so maybe

drm_for_each_visible_plane_in_panic_handler()

or something like that.

One thing I was wondering is whether we should lift this iteration over
all planes into the shared code, and move the ->get_scanout_buffer
function to the drm_plane_funcs structure instead?


+   fb = plane->state->fb;
+   /* Only support linear modifier */
+   if (fb->modifier != DRM_FORMAT_MOD_LINEAR)
+   continue;
+
+   /* Check if color format is supported */
+   if (!drm_panic_is_format_supported(fb->format->format))
+   continue;
+
+   dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
+
+   /* Buffer should be accessible from the CPU */
+   if (dma_obj->base.import_attach)


This might be a bit too restrictive, since some drivers import dma-buf
including a vmap. So just checking for ->vaddr might be better. But can be
changed later on.


+   continue;
+
+   /* Buffer should be already mapped to CPU */


I'd clarify this comment to state that vaddr is invariant over the
lifetime of the buffer and therefore needs no locking. Correct locking
that a) takes all the locks b) never ever stalls for one is absolutely
crucial for a panic handler that won't make the situation worse.


+   if (!dma_obj->vaddr)




+   continue;
+
+   iosys_map_set_vaddr(>map, dma_obj-&g

Re: [PATCH v7 2/9] drm/panic: Add a drm panic handler

2024-01-16 Thread Jocelyn Falempe




On 12/01/2024 14:31, Daniel Vetter wrote:

On Thu, Jan 04, 2024 at 05:00:46PM +0100, Jocelyn Falempe wrote:

This module displays a user friendly message when a kernel panic
occurs. It currently doesn't contain any debug information,
but that can be added later.

v2
  * Use get_scanout_buffer() instead of the drm client API.
   (Thomas Zimmermann)
  * Add the panic reason to the panic message (Nerdopolis)
  * Add an exclamation mark (Nerdopolis)

v3
  * Rework the drawing functions, to write the pixels line by line and
  to use the drm conversion helper to support other formats.
  (Thomas Zimmermann)

v4
  * Use drm_fb_r1_to_32bit for fonts (Thomas Zimmermann)
  * Remove the default y to DRM_PANIC config option (Thomas Zimmermann)
  * Add foreground/background color config option
  * Fix the bottom lines not painted if the framebuffer height
is not a multiple of the font height.
  * Automatically register the device to drm_panic, if the function
get_scanout_buffer exists. (Thomas Zimmermann)

v5
  * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
  * Also add drm_fb_fill() to fill area with background color.
  * Add draw_pixel_xy() API for drivers that can't provide a linear buffer.
  * Add a flush() callback for drivers that needs to synchronize the buffer.
  * Add a void *private field, so drivers can pass private data to
draw_pixel_xy() and flush().

v6
  * Fix sparse warning for panic_msg and logo.

v7
  * Add select DRM_KMS_HELPER for the color conversion functions.

Signed-off-by: Jocelyn Falempe 


Bunch of comments on the glue, I didn't look at the drawing function in
detail assuming that that's all working :-)


Thanks a lot for that detailed review.

-Sima


---
  drivers/gpu/drm/Kconfig |  23 +++
  drivers/gpu/drm/Makefile|   1 +
  drivers/gpu/drm/drm_drv.c   |   8 +
  drivers/gpu/drm/drm_panic.c | 369 
  include/drm/drm_drv.h   |  21 ++
  include/drm/drm_panic.h |  97 ++
  6 files changed, 519 insertions(+)
  create mode 100644 drivers/gpu/drm/drm_panic.c
  create mode 100644 include/drm/drm_panic.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 628f90ed8a9b..a8219c98c8d6 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -103,6 +103,29 @@ config DRM_KMS_HELPER
help
  CRTC helpers for KMS drivers.
  
+config DRM_PANIC

+   bool "Display a user-friendly message when a kernel panic occurs"
+   depends on DRM && !FRAMEBUFFER_CONSOLE
+   select DRM_KMS_HELPER
+   select FONT_SUPPORT
+   help
+ Enable a drm panic handler, which will display a user-friendly message
+ when a kernel panic occurs. It's useful when using a user-space
+ console instead of fbcon.
+ It will only work if your graphic driver supports this feature.
+ To support Hi-DPI Display, you can enable bigger fonts like
+ FONT_TER16x32
+
+config DRM_PANIC_FOREGROUND_COLOR
+   hex "Drm panic screen foreground color, in RGB"
+   depends on DRM_PANIC
+   default 0xff
+
+config DRM_PANIC_BACKGROUND_COLOR
+   hex "Drm panic screen background color, in RGB"
+   depends on DRM_PANIC
+   default 0x00
+
  config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
  bool "Enable refcount backtrace history in the DP MST helpers"
depends on STACKTRACE_SUPPORT
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 8ac6f4b9546e..fdf3d3fe0c78 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -60,6 +60,7 @@ drm-$(CONFIG_DRM_PRIVACY_SCREEN) += \
drm_privacy_screen.o \
drm_privacy_screen_x86.o
  drm-$(CONFIG_DRM_ACCEL) += ../../accel/drm_accel.o
+drm-$(CONFIG_DRM_PANIC) += drm_panic.o
  obj-$(CONFIG_DRM) += drm.o
  
  obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 243cacb3575c..998942e6d687 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -43,6 +43,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  
@@ -944,6 +945,9 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)

goto err_unload;
}
  
+	if (driver->get_scanout_buffer)

+   drm_panic_register(dev);
+
DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
 driver->name, driver->major, driver->minor,
 driver->patchlevel, driver->date,
@@ -987,6 +991,8 @@ void drm_dev_unregister(struct drm_device *dev)
  {
dev->registered = false;
  
+	drm_panic_unregister(dev);

+
drm_client_dev_unregister(dev);
  
  	if (drm_core_check_feature(dev, DRIVER_MODESET))

@@ -1066,6 +1072,7 @@ static void drm_core_exit(void)
unregister_chrdev(DRM_MAJ

Re: [RFC][PATCH v7 0/9] drm/panic: Add a drm panic handler

2024-01-12 Thread Jocelyn Falempe




On 12/01/2024 15:00, Daniel Vetter wrote:

On Thu, Jan 04, 2024 at 05:00:44PM +0100, Jocelyn Falempe wrote:

This introduces a new drm panic handler, which displays a message when a panic 
occurs.
So when fbcon is disabled, you can still see a kernel panic.

This is one of the missing feature, when disabling VT/fbcon in the kernel:
https://www.reddit.com/r/linux/comments/10eccv9/config_vtn_in_2023/
Fbcon can be replaced by a userspace kms console, but the panic screen must be 
done in the kernel.

This is a proof of concept, and works with simpledrm, mgag200, ast, and imx 
using a new get_scanout_buffer() api

To test it, make sure you're using the simpledrm driver, and trigger a panic:
echo c > /proc/sysrq-trigger


Uh this is not great for testing in CI, we need something better. A
drm-specific solution would be a debugfs file that triggers the panic
dumping (which is the reason we should correctly unlock all locks we've
taken too).


Yes, I already use a dumb file in debugfs to trigger the panic handler 
for development purpose. So it's a bit easier than crashing the machine.
I didn't add it in the series, because it's a bit rough, and the panic 
handler assumes there are no other thread running, and that it's the 
last frame the gpu will display before rebooting.


It gives some beautiful effect (if your driver uses double buffering, 
only one of them will be repainted with the panic screen, so it's 
flashing a bit afterward. It's also a good way to see if your driver 
uses the damage API correctly).


So I will add it in the next series.



Even better would be if the core code provides this infrastructure, so
that ideally we could exercise running from an nmi context. For the drm
testing the best we can probably do is disable local interrupts or maybe
run from a timer that immediately fires.

I think adding that test infrastructure plus an igt that exercises should
be done as part of merging the initial version. Otherwise there's just no
way we can make sure that this code doesn't immediately bitrot like all
the previous panic handlers.


ok, I will look into that. I didn't use igt yet, so I will see what I 
can do.


Cheers, Sima



v2:
  * Use get_scanout_buffer() instead of the drm client API. (Thomas Zimmermann)
  * Add the panic reason to the panic message (Nerdopolis)
  * Add an exclamation mark (Nerdopolis)
  
v3:

  * Rework the drawing functions, to write the pixels line by line and
  to use the drm conversion helper to support other formats.
  (Thomas Zimmermann)
  
v4:

  * Fully support all simpledrm formats using drm conversion helpers
  * Rename dpanic_* to drm_panic_*, and have more coherent function name.
(Thomas Zimmermann)
  * Use drm_fb_r1_to_32bit for fonts (Thomas Zimmermann)
  * Remove the default y to DRM_PANIC config option (Thomas Zimmermann)
  * Add foreground/background color config option
  * Fix the bottom lines not painted if the framebuffer height
is not a multiple of the font height.
  * Automatically register the driver to drm_panic, if the function
get_scanout_buffer() exists. (Thomas Zimmermann)
  * Add mgag200 support.
  
v5:

  * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
(Thomas Zimmermann)
  * Also add drm_fb_fill() to fill area with background color.
  * Add draw_pixel_xy() API for drivers that can't provide a linear buffer.
  * Add a flush() callback for drivers that needs to synchronize the buffer.
  * Add a void *private field, so drivers can pass private data to
draw_pixel_xy() and flush().
  * Add ast support.
  * Add experimental imx/ipuv3 support, to test on an ARM hw. (Maxime Ripard)

v6:
  * Fix sparse and __le32 warnings
  * Drop the IMX/IPUV3 experiment, it was just to show that it works also on
ARM devices.

v7:
  * Add a check to see if the 4cc format is supported by drm_panic.
  * Add a drm/plane helper to loop over all visible primary buffer,
simplifying the get_scanout_buffer implementations
  * Add a generic implementation for drivers that uses drm_fb_dma. (Maxime 
Ripard)
  * Add back the IMX/IPUV3 support, and use the generic implementation. (Maxime 
Ripard)


Best regards,

Jocelyn Falempe (9):
   drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill
   drm/panic: Add a drm panic handler
   drm/plane: Add drm_for_each_primary_visible_plane macro
   drm/panic: Add drm_panic_is_format_supported()
   drm/fb_dma: Add generic get_scanout_buffer() for drm_panic
   drm/simpledrm: Add drm_panic support
   drm/mgag200: Add drm_panic support
   drm/ast: Add drm_panic support
   drm/imx: Add drm_panic support

  drivers/gpu/drm/Kconfig  |  23 ++
  drivers/gpu/drm/Makefile |   1 +
  drivers/gpu/drm/ast/ast_drv.c|  26 +-
  drivers/gpu/drm/drm_drv.c|   8 +
  drivers/gpu/drm/drm_fb_dma_helper.c  |  55 +++
  drivers/gpu/drm/drm_format_helper.c  | 432 ++-
  drivers/gpu/drm/drm_panic.c  | 

Re: [PATCH v7 5/9] drm/fb_dma: Add generic get_scanout_buffer() for drm_panic

2024-01-12 Thread Jocelyn Falempe




On 08/01/2024 11:20, Maxime Ripard wrote:

Hi,

On Thu, Jan 04, 2024 at 05:00:49PM +0100, Jocelyn Falempe wrote:

This was initialy done for imx6, but should work on most drivers
using drm_fb_dma_helper.

Signed-off-by: Jocelyn Falempe 
---
  drivers/gpu/drm/drm_fb_dma_helper.c | 55 +
  include/drm/drm_fb_dma_helper.h |  4 +++
  2 files changed, 59 insertions(+)

diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c 
b/drivers/gpu/drm/drm_fb_dma_helper.c
index 3b535ad1b07c..caed2935df4f 100644
--- a/drivers/gpu/drm/drm_fb_dma_helper.c
+++ b/drivers/gpu/drm/drm_fb_dma_helper.c
@@ -15,6 +15,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -148,3 +149,57 @@ void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
}
  }
  EXPORT_SYMBOL_GPL(drm_fb_dma_sync_non_coherent);
+
+#if defined(CONFIG_DRM_PANIC)
+/**
+ * @dev: DRM device
+ * @drm_scanout_buffer: scanout buffer for the panic handler
+ * Returns: 0 or negative error code
+ *
+ * Generic get_scanout_buffer() implementation, for drivers that uses the
+ * drm_fb_dma_helper.
+ */
+int drm_panic_gem_get_scanout_buffer(struct drm_device *dev,
+struct drm_scanout_buffer *sb)
+{
+   struct drm_plane *plane;
+   struct drm_gem_dma_object *dma_obj;
+   struct drm_framebuffer *fb;
+
+   drm_for_each_primary_visible_plane(plane, dev) {
+   fb = plane->state->fb;
+   /* Only support linear modifier */
+   if (fb->modifier != DRM_FORMAT_MOD_LINEAR)
+   continue;
+
+   /* Check if color format is supported */
+   if (!drm_panic_is_format_supported(fb->format->format))
+   continue;
+
+   dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
+
+   /* Buffer should be accessible from the CPU */
+   if (dma_obj->base.import_attach)
+   continue;
+
+   /* Buffer should be already mapped to CPU */
+   if (!dma_obj->vaddr)
+   continue;
+
+   iosys_map_set_vaddr(>map, dma_obj->vaddr);
+   sb->format = fb->format;
+   sb->height = fb->height;
+   sb->width = fb->width;
+   sb->pitch = fb->pitches[0];
+   return 0;
+   }
+   return -ENODEV;
+}
+#else
+int drm_panic_gem_get_scanout_buffer(struct drm_device *dev,
+struct drm_scanout_buffer *sb)
+{
+   return 0;
+}
+#endif
+EXPORT_SYMBOL(drm_panic_gem_get_scanout_buffer);


Looks much better, thanks :)

I think we should be more vocal about the failure cases too. Maybe log
it through warn/pr_crit or whatever so that at least we have an idea
what went wrong in a post mortem.


Thanks for the review.
Yes I can add an error message when it fails to find a scanout buffer.


Maxime


--

Jocelyn



Re: [PATCH v7 3/9] drm/plane: Add drm_for_each_primary_visible_plane macro

2024-01-08 Thread Jocelyn Falempe

Hi checkpatch maintainers,

This patch gives me the following checkpatch error:

ERROR: Macros with complex values should be enclosed in parentheses
#30: FILE: include/drm/drm_plane.h:959:
+#define drm_for_each_primary_visible_plane(plane, dev) \
+   list_for_each_entry((plane), &(dev)->mode_config.plane_list, head) \
+   for_each_if((plane)->type == DRM_PLANE_TYPE_PRIMARY && \
+   (plane)->state && \
+   (plane)->state->fb && \
+   (plane)->state->visible)

total: 1 errors, 0 warnings, 21 lines checked

I think this requirement cannot work when you use list_for_each kind of 
macros.

Do you have any suggestion ?

Best regards,

--

Jocelyn



On 04/01/2024 17:00, Jocelyn Falempe wrote:

To support drm_panic, most drivers need to find the current primary
visible plane with a framebuffer attached.

Signed-off-by: Jocelyn Falempe 
---
  include/drm/drm_plane.h | 15 +++
  1 file changed, 15 insertions(+)

diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index c6565a6f9324..41c08a2ddf8d 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -948,6 +948,21 @@ static inline struct drm_plane *drm_plane_find(struct 
drm_device *dev,
list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) \
for_each_if (plane->type == DRM_PLANE_TYPE_OVERLAY)
  
+/**

+ * drm_for_each_primary_visible_plane - iterate over all primary visible planes
+ * @plane: the loop cursor
+ * @dev: the DRM device
+ *
+ * Iterate over all primary, visible plane, with a framebuffer.
+ * This is useful for drm_panic, to find the current scanout buffer.
+ */
+#define drm_for_each_primary_visible_plane(plane, dev) \
+   list_for_each_entry((plane), &(dev)->mode_config.plane_list, head) \
+   for_each_if((plane)->type == DRM_PLANE_TYPE_PRIMARY && \
+   (plane)->state && \
+   (plane)->state->fb && \
+   (plane)->state->visible)
+
  /**
   * drm_for_each_plane - iterate over all planes
   * @plane: the loop cursor




Re: [PATCH] drm/mgag200: Fix caching setup for remapped video memory

2024-01-05 Thread Jocelyn Falempe

Hi,

On 05/01/2024 09:25, Thomas Zimmermann wrote:

I/O video memory for the framebuffer supports write-combine caching
mode. Simplify the driver's code that sets up the caching mode.

  * Map video memory with ioremap_wc(), which automatically sets up
the PAT entry with write-combine caching.

  * Remove the now obsolete call to devm_arch_io_reserve_memtype_wc().
It is only required to mmap the video memory to user space, which the
driver doesn't do.

  * According to the PAT documentation, arch_phys_wc_add() is best
called after remapping I/O memory, so move it after ioremap.



Thanks a lot for taking some time to look at the latency issue.
This looks good to me.

Reviewed-by: Jocelyn Falempe 

--

Jocelyn



[PATCH v7 9/9] drm/imx: Add drm_panic support

2024-01-04 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a user-friendly
message to the screen when a kernel panic occurs.

v7:
 * use drm_panic_gem_get_scanout_buffer() helper

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/imx/ipuv3/imx-drm-core.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c 
b/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
index 4cfabcf7375a..d202d937d4b6 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -172,6 +173,7 @@ static const struct drm_driver imx_drm_driver = {
.major  = 1,
.minor  = 0,
.patchlevel = 0,
+   .get_scanout_buffer = drm_panic_gem_get_scanout_buffer,
 };
 
 static int compare_of(struct device *dev, void *data)
-- 
2.43.0



[PATCH v7 8/9] drm/ast: Add drm_panic support

2024-01-04 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a message to
the screen when a kernel panic occurs.

v7
 * Use drm_for_each_primary_visible_plane()

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/ast/ast_drv.c | 26 --
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
index 90bcb1eb9cd9..8ddce3d7fda9 100644
--- a/drivers/gpu/drm/ast/ast_drv.c
+++ b/drivers/gpu/drm/ast/ast_drv.c
@@ -35,6 +35,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "ast_drv.h"
@@ -48,6 +49,27 @@ module_param_named(modeset, ast_modeset, int, 0400);
  * DRM driver
  */
 
+static int ast_get_scanout_buffer(struct drm_device *dev,
+ struct drm_scanout_buffer *sb)
+{
+   struct drm_plane *plane;
+   struct ast_plane *ast_plane;
+
+   drm_for_each_primary_visible_plane(plane, dev) {
+   ast_plane = to_ast_plane(plane);
+   if (!ast_plane->vaddr)
+   continue;
+
+   sb->format = plane->state->fb->format;
+   sb->width = plane->state->fb->width;
+   sb->height = plane->state->fb->height;
+   sb->pitch = plane->state->fb->pitches[0];
+   iosys_map_set_vaddr_iomem(>map, ast_plane->vaddr);
+   return 0;
+   }
+   return -ENODEV;
+}
+
 DEFINE_DRM_GEM_FOPS(ast_fops);
 
 static const struct drm_driver ast_driver = {
@@ -62,8 +84,8 @@ static const struct drm_driver ast_driver = {
.major = DRIVER_MAJOR,
.minor = DRIVER_MINOR,
.patchlevel = DRIVER_PATCHLEVEL,
-
-   DRM_GEM_SHMEM_DRIVER_OPS
+   .get_scanout_buffer = ast_get_scanout_buffer,
+   DRM_GEM_SHMEM_DRIVER_OPS,
 };
 
 /*
-- 
2.43.0



[PATCH v7 3/9] drm/plane: Add drm_for_each_primary_visible_plane macro

2024-01-04 Thread Jocelyn Falempe
To support drm_panic, most drivers need to find the current primary
visible plane with a framebuffer attached.

Signed-off-by: Jocelyn Falempe 
---
 include/drm/drm_plane.h | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index c6565a6f9324..41c08a2ddf8d 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -948,6 +948,21 @@ static inline struct drm_plane *drm_plane_find(struct 
drm_device *dev,
list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) \
for_each_if (plane->type == DRM_PLANE_TYPE_OVERLAY)
 
+/**
+ * drm_for_each_primary_visible_plane - iterate over all primary visible planes
+ * @plane: the loop cursor
+ * @dev: the DRM device
+ *
+ * Iterate over all primary, visible plane, with a framebuffer.
+ * This is useful for drm_panic, to find the current scanout buffer.
+ */
+#define drm_for_each_primary_visible_plane(plane, dev) \
+   list_for_each_entry((plane), &(dev)->mode_config.plane_list, head) \
+   for_each_if((plane)->type == DRM_PLANE_TYPE_PRIMARY && \
+   (plane)->state && \
+   (plane)->state->fb && \
+   (plane)->state->visible)
+
 /**
  * drm_for_each_plane - iterate over all planes
  * @plane: the loop cursor
-- 
2.43.0



[PATCH v7 7/9] drm/mgag200: Add drm_panic support

2024-01-04 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a message to
the screen when a kernel panic occurs.

v5:
 * Also check that the plane is visible and primary. (Thomas Zimmermann)

v7:
 * use drm_for_each_primary_visible_plane()

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/mgag200/mgag200_drv.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c 
b/drivers/gpu/drm/mgag200/mgag200_drv.c
index 2fb18b782b05..2bf5918eadc5 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -13,10 +13,12 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mgag200_drv.h"
@@ -84,6 +86,25 @@ resource_size_t mgag200_probe_vram(void __iomem *mem, 
resource_size_t size)
return offset - 65536;
 }
 
+static int mgag200_get_scanout_buffer(struct drm_device *dev,
+ struct drm_scanout_buffer *sb)
+{
+   struct drm_plane *plane;
+   struct mga_device *mdev = to_mga_device(dev);
+   struct iosys_map map = IOSYS_MAP_INIT_VADDR_IOMEM(mdev->vram);
+
+   /* find the primary and visible plane */
+   drm_for_each_primary_visible_plane(plane, dev) {
+   sb->format = plane->state->fb->format;
+   sb->width = plane->state->fb->width;
+   sb->height = plane->state->fb->height;
+   sb->pitch = plane->state->fb->pitches[0];
+   sb->map = map;
+   return 0;
+   }
+   return -ENODEV;
+}
+
 /*
  * DRM driver
  */
@@ -99,6 +120,7 @@ static const struct drm_driver mgag200_driver = {
.major = DRIVER_MAJOR,
.minor = DRIVER_MINOR,
.patchlevel = DRIVER_PATCHLEVEL,
+   .get_scanout_buffer = mgag200_get_scanout_buffer,
DRM_GEM_SHMEM_DRIVER_OPS,
 };
 
-- 
2.43.0



[PATCH v7 6/9] drm/simpledrm: Add drm_panic support

2024-01-04 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a user-friendly
message to the screen when a kernel panic occurs.

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/tiny/simpledrm.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 7ce1c4617675..6dd2afee84d4 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #define DRIVER_NAME"simpledrm"
@@ -985,6 +986,19 @@ static struct simpledrm_device 
*simpledrm_device_create(struct drm_driver *drv,
return sdev;
 }
 
+static int simpledrm_get_scanout_buffer(struct drm_device *dev,
+   struct drm_scanout_buffer *sb)
+{
+   struct simpledrm_device *sdev = simpledrm_device_of_dev(dev);
+
+   sb->width = sdev->mode.hdisplay;
+   sb->height = sdev->mode.vdisplay;
+   sb->pitch = sdev->pitch;
+   sb->format = sdev->format;
+   sb->map = sdev->screen_base;
+   return 0;
+}
+
 /*
  * DRM driver
  */
@@ -1000,6 +1014,7 @@ static struct drm_driver simpledrm_driver = {
.minor  = DRIVER_MINOR,
.driver_features= DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,
.fops   = _fops,
+   .get_scanout_buffer = simpledrm_get_scanout_buffer,
 };
 
 /*
-- 
2.43.0



[PATCH v7 1/9] drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill

2024-01-04 Thread Jocelyn Falempe
This is needed for drm_panic, to draw the font, and fill
the background color, in multiple color format.

v5:
 * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
 * Also add drm_fb_fill() to fill area with background color.
v6:
 * fix __le32 conversion warning found by the kernel test bot

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/drm_format_helper.c | 432 ++--
 include/drm/drm_format_helper.h |   9 +
 2 files changed, 360 insertions(+), 81 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index b1be458ed4dd..8cbc2d747cff 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -111,6 +111,153 @@ void drm_format_conv_state_release(struct 
drm_format_conv_state *state)
 }
 EXPORT_SYMBOL(drm_format_conv_state_release);
 
+static inline __le16 drm_format_xrgb_to_rgb565(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = ((pix & 0x00F8) >> 8) |
+   ((pix & 0xFC00) >> 5) |
+   ((pix & 0x00F8) >> 3);
+   return cpu_to_le16(val16);
+}
+
+static inline __le16 drm_format_xrgb_to_rgba5551(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = ((pix & 0x00f8) >> 8) |
+   ((pix & 0xf800) >> 5) |
+   ((pix & 0x00f8) >> 2) |
+   BIT(0); /* set alpha bit */
+   return cpu_to_le16(val16);
+}
+
+static inline __le16 drm_format_xrgb_to_xrgb1555(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = ((pix & 0x00f8) >> 9) |
+   ((pix & 0xf800) >> 6) |
+   ((pix & 0x00f8) >> 3);
+   return cpu_to_le16(val16);
+}
+
+static inline __le16 drm_format_xrgb_to_argb1555(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = BIT(15) | /* set alpha bit */
+   ((pix & 0x00f8) >> 9) |
+   ((pix & 0xf800) >> 6) |
+   ((pix & 0x00f8) >> 3);
+   return cpu_to_le16(val16);
+}
+
+static inline __le32 drm_format_xrgb_to_argb(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 |= GENMASK(31, 24); /* fill alpha bits */
+   return cpu_to_le32(val32);
+}
+
+static inline __le32 drm_format_xrgb_to_xbgr(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00ff) >> 16) <<  0 |
+   ((val32 & 0xff00) >>  8) <<  8 |
+   ((val32 & 0x00ff) >>  0) << 16 |
+   ((val32 & 0xff00) >> 24) << 24;
+   return cpu_to_le32(val32);
+}
+
+static inline __le32 drm_format_xrgb_to_abgr(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00ff) >> 16) <<  0 |
+   ((val32 & 0xff00) >>  8) <<  8 |
+   ((val32 & 0x00ff) >>  0) << 16 |
+   GENMASK(31, 24); /* fill alpha bits */
+   return cpu_to_le32(val32);
+}
+
+static inline __le32 drm_format_xrgb_to_xrgb2101010(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00FF) << 2) |
+   ((val32 & 0xFF00) << 4) |
+   ((val32 & 0x00FF) << 6);
+   return cpu_to_le32(val32 | ((val32 >> 8) & 0x00300C03));
+}
+
+static inline __le32 drm_format_xrgb_to_argb2101010(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00FF) << 2) |
+   ((val32 & 0xFF00) << 4) |
+   ((val32 & 0x00FF) << 6);
+   val32 = GENMASK(31, 30) | /* set alpha bits */
+ val32 | ((val32 >> 8) & 0x00300c03);
+   return cpu_to_le32(val32);
+}
+
+/**
+ * drm_fb_convert_from_xrgb - convert one pixel from xrgb to the 
desired format
+ * @color: input color, in xrgb format
+ * @format: output format
+ *
+ * Returns:
+ * Color in the format specified, casted to u32.
+ * Or 0 if the format is unknown.
+ */
+u32 drm_fb_convert_from_xrgb(u32 color, u32 format)
+{
+   __le32 pix = cpu_to_le32(color);
+
+   switch (format) {
+   case DRM_FORMAT_RGB565:
+   return le16_to_cpu(drm_format_xrgb_to_rgb565(pix));
+   case DRM_FORMAT_RGBA5551:
+   return le16_to_cpu(drm_format_xrgb_to_rgba5551(pix));
+   case DRM_FORMAT_XRGB1555:
+   return le16_to_cpu(drm_format_xrgb_to_xrgb1555(pix));
+   case DRM_FORMAT

[PATCH v7 4/9] drm/panic: Add drm_panic_is_format_supported()

2024-01-04 Thread Jocelyn Falempe
So driver knows early if drm_panic will be able to display something
on the current scanout buffer.

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/drm_panic.c | 13 +
 include/drm/drm_panic.h |  4 
 2 files changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c
index 362a696ec48a..c68167cd4c08 100644
--- a/drivers/gpu/drm/drm_panic.c
+++ b/drivers/gpu/drm/drm_panic.c
@@ -348,6 +348,19 @@ void drm_panic_unregister(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_panic_unregister);
 
+/**
+ * drm_panic_is_format_supported()
+ * @format: a fourcc color code
+ * Returns: true if supported, false otherwise.
+ *
+ * Check if drm_panic will be able to use this color format.
+ */
+bool drm_panic_is_format_supported(u32 format)
+{
+   return drm_fb_convert_from_xrgb(0xff, format) != 0;
+}
+EXPORT_SYMBOL(drm_panic_is_format_supported);
+
 /**
  * drm_panic_init() - Initialize drm-panic subsystem
  *
diff --git a/include/drm/drm_panic.h b/include/drm/drm_panic.h
index bcf392b6fa1b..1549c8eb8dcc 100644
--- a/include/drm/drm_panic.h
+++ b/include/drm/drm_panic.h
@@ -84,6 +84,8 @@ void drm_panic_exit(void);
 void drm_panic_register(struct drm_device *dev);
 void drm_panic_unregister(struct drm_device *dev);
 
+bool drm_panic_is_format_supported(u32 format);
+
 #else
 
 static inline void drm_panic_init(void) {}
@@ -92,6 +94,8 @@ static inline void drm_panic_exit(void) {}
 static inline void drm_panic_register(struct drm_device *dev) {}
 static inline void drm_panic_unregister(struct drm_device *dev) {}
 
+bool drm_panic_is_format_supported(u32 format) {return false; }
+
 #endif
 
 #endif /* __DRM_PANIC_H__ */
-- 
2.43.0



[PATCH v7 5/9] drm/fb_dma: Add generic get_scanout_buffer() for drm_panic

2024-01-04 Thread Jocelyn Falempe
This was initialy done for imx6, but should work on most drivers
using drm_fb_dma_helper.

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/drm_fb_dma_helper.c | 55 +
 include/drm/drm_fb_dma_helper.h |  4 +++
 2 files changed, 59 insertions(+)

diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c 
b/drivers/gpu/drm/drm_fb_dma_helper.c
index 3b535ad1b07c..caed2935df4f 100644
--- a/drivers/gpu/drm/drm_fb_dma_helper.c
+++ b/drivers/gpu/drm/drm_fb_dma_helper.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -148,3 +149,57 @@ void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
}
 }
 EXPORT_SYMBOL_GPL(drm_fb_dma_sync_non_coherent);
+
+#if defined(CONFIG_DRM_PANIC)
+/**
+ * @dev: DRM device
+ * @drm_scanout_buffer: scanout buffer for the panic handler
+ * Returns: 0 or negative error code
+ *
+ * Generic get_scanout_buffer() implementation, for drivers that uses the
+ * drm_fb_dma_helper.
+ */
+int drm_panic_gem_get_scanout_buffer(struct drm_device *dev,
+struct drm_scanout_buffer *sb)
+{
+   struct drm_plane *plane;
+   struct drm_gem_dma_object *dma_obj;
+   struct drm_framebuffer *fb;
+
+   drm_for_each_primary_visible_plane(plane, dev) {
+   fb = plane->state->fb;
+   /* Only support linear modifier */
+   if (fb->modifier != DRM_FORMAT_MOD_LINEAR)
+   continue;
+
+   /* Check if color format is supported */
+   if (!drm_panic_is_format_supported(fb->format->format))
+   continue;
+
+   dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
+
+   /* Buffer should be accessible from the CPU */
+   if (dma_obj->base.import_attach)
+   continue;
+
+   /* Buffer should be already mapped to CPU */
+   if (!dma_obj->vaddr)
+   continue;
+
+   iosys_map_set_vaddr(>map, dma_obj->vaddr);
+   sb->format = fb->format;
+   sb->height = fb->height;
+   sb->width = fb->width;
+   sb->pitch = fb->pitches[0];
+   return 0;
+   }
+   return -ENODEV;
+}
+#else
+int drm_panic_gem_get_scanout_buffer(struct drm_device *dev,
+struct drm_scanout_buffer *sb)
+{
+   return 0;
+}
+#endif
+EXPORT_SYMBOL(drm_panic_gem_get_scanout_buffer);
diff --git a/include/drm/drm_fb_dma_helper.h b/include/drm/drm_fb_dma_helper.h
index d5e036c57801..2ae432865079 100644
--- a/include/drm/drm_fb_dma_helper.h
+++ b/include/drm/drm_fb_dma_helper.h
@@ -7,6 +7,7 @@
 struct drm_device;
 struct drm_framebuffer;
 struct drm_plane_state;
+struct drm_scanout_buffer;
 
 struct drm_gem_dma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb,
unsigned int plane);
@@ -19,5 +20,8 @@ void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
  struct drm_plane_state *old_state,
  struct drm_plane_state *state);
 
+int drm_panic_gem_get_scanout_buffer(struct drm_device *dev,
+struct drm_scanout_buffer *sb);
+
 #endif
 
-- 
2.43.0



[PATCH v7 2/9] drm/panic: Add a drm panic handler

2024-01-04 Thread Jocelyn Falempe
This module displays a user friendly message when a kernel panic
occurs. It currently doesn't contain any debug information,
but that can be added later.

v2
 * Use get_scanout_buffer() instead of the drm client API.
  (Thomas Zimmermann)
 * Add the panic reason to the panic message (Nerdopolis)
 * Add an exclamation mark (Nerdopolis)

v3
 * Rework the drawing functions, to write the pixels line by line and
 to use the drm conversion helper to support other formats.
 (Thomas Zimmermann)

v4
 * Use drm_fb_r1_to_32bit for fonts (Thomas Zimmermann)
 * Remove the default y to DRM_PANIC config option (Thomas Zimmermann)
 * Add foreground/background color config option
 * Fix the bottom lines not painted if the framebuffer height
   is not a multiple of the font height.
 * Automatically register the device to drm_panic, if the function
   get_scanout_buffer exists. (Thomas Zimmermann)

v5
 * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
 * Also add drm_fb_fill() to fill area with background color.
 * Add draw_pixel_xy() API for drivers that can't provide a linear buffer.
 * Add a flush() callback for drivers that needs to synchronize the buffer.
 * Add a void *private field, so drivers can pass private data to
   draw_pixel_xy() and flush().

v6
 * Fix sparse warning for panic_msg and logo.

v7
 * Add select DRM_KMS_HELPER for the color conversion functions.

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/Kconfig |  23 +++
 drivers/gpu/drm/Makefile|   1 +
 drivers/gpu/drm/drm_drv.c   |   8 +
 drivers/gpu/drm/drm_panic.c | 369 
 include/drm/drm_drv.h   |  21 ++
 include/drm/drm_panic.h |  97 ++
 6 files changed, 519 insertions(+)
 create mode 100644 drivers/gpu/drm/drm_panic.c
 create mode 100644 include/drm/drm_panic.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 628f90ed8a9b..a8219c98c8d6 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -103,6 +103,29 @@ config DRM_KMS_HELPER
help
  CRTC helpers for KMS drivers.
 
+config DRM_PANIC
+   bool "Display a user-friendly message when a kernel panic occurs"
+   depends on DRM && !FRAMEBUFFER_CONSOLE
+   select DRM_KMS_HELPER
+   select FONT_SUPPORT
+   help
+ Enable a drm panic handler, which will display a user-friendly message
+ when a kernel panic occurs. It's useful when using a user-space
+ console instead of fbcon.
+ It will only work if your graphic driver supports this feature.
+ To support Hi-DPI Display, you can enable bigger fonts like
+ FONT_TER16x32
+
+config DRM_PANIC_FOREGROUND_COLOR
+   hex "Drm panic screen foreground color, in RGB"
+   depends on DRM_PANIC
+   default 0xff
+
+config DRM_PANIC_BACKGROUND_COLOR
+   hex "Drm panic screen background color, in RGB"
+   depends on DRM_PANIC
+   default 0x00
+
 config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
 bool "Enable refcount backtrace history in the DP MST helpers"
depends on STACKTRACE_SUPPORT
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 8ac6f4b9546e..fdf3d3fe0c78 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -60,6 +60,7 @@ drm-$(CONFIG_DRM_PRIVACY_SCREEN) += \
drm_privacy_screen.o \
drm_privacy_screen_x86.o
 drm-$(CONFIG_DRM_ACCEL) += ../../accel/drm_accel.o
+drm-$(CONFIG_DRM_PANIC) += drm_panic.o
 obj-$(CONFIG_DRM)  += drm.o
 
 obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 243cacb3575c..998942e6d687 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -944,6 +945,9 @@ int drm_dev_register(struct drm_device *dev, unsigned long 
flags)
goto err_unload;
}
 
+   if (driver->get_scanout_buffer)
+   drm_panic_register(dev);
+
DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
 driver->name, driver->major, driver->minor,
 driver->patchlevel, driver->date,
@@ -987,6 +991,8 @@ void drm_dev_unregister(struct drm_device *dev)
 {
dev->registered = false;
 
+   drm_panic_unregister(dev);
+
drm_client_dev_unregister(dev);
 
if (drm_core_check_feature(dev, DRIVER_MODESET))
@@ -1066,6 +1072,7 @@ static void drm_core_exit(void)
unregister_chrdev(DRM_MAJOR, "drm");
debugfs_remove(drm_debugfs_root);
drm_sysfs_destroy();
+   drm_panic_exit();
idr_destroy(_minors_idr);
drm_connector_ida_destroy();
 }
@@ -1077,6 +1084,7 @@ static int __init drm_core_init(void)
drm_connector_ida_init();
idr_init(_minors_idr);

[RFC][PATCH v7 0/9] drm/panic: Add a drm panic handler

2024-01-04 Thread Jocelyn Falempe
This introduces a new drm panic handler, which displays a message when a panic 
occurs.
So when fbcon is disabled, you can still see a kernel panic.

This is one of the missing feature, when disabling VT/fbcon in the kernel:
https://www.reddit.com/r/linux/comments/10eccv9/config_vtn_in_2023/
Fbcon can be replaced by a userspace kms console, but the panic screen must be 
done in the kernel.

This is a proof of concept, and works with simpledrm, mgag200, ast, and imx 
using a new get_scanout_buffer() api

To test it, make sure you're using the simpledrm driver, and trigger a panic:
echo c > /proc/sysrq-trigger

v2:
 * Use get_scanout_buffer() instead of the drm client API. (Thomas Zimmermann)
 * Add the panic reason to the panic message (Nerdopolis)
 * Add an exclamation mark (Nerdopolis)
 
v3:
 * Rework the drawing functions, to write the pixels line by line and
 to use the drm conversion helper to support other formats.
 (Thomas Zimmermann)
 
v4:
 * Fully support all simpledrm formats using drm conversion helpers
 * Rename dpanic_* to drm_panic_*, and have more coherent function name.
   (Thomas Zimmermann)
 * Use drm_fb_r1_to_32bit for fonts (Thomas Zimmermann)
 * Remove the default y to DRM_PANIC config option (Thomas Zimmermann)
 * Add foreground/background color config option
 * Fix the bottom lines not painted if the framebuffer height
   is not a multiple of the font height.
 * Automatically register the driver to drm_panic, if the function
   get_scanout_buffer() exists. (Thomas Zimmermann)
 * Add mgag200 support.
 
v5:
 * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
   (Thomas Zimmermann)
 * Also add drm_fb_fill() to fill area with background color.
 * Add draw_pixel_xy() API for drivers that can't provide a linear buffer.
 * Add a flush() callback for drivers that needs to synchronize the buffer.
 * Add a void *private field, so drivers can pass private data to
   draw_pixel_xy() and flush(). 
 * Add ast support.
 * Add experimental imx/ipuv3 support, to test on an ARM hw. (Maxime Ripard)

v6:
 * Fix sparse and __le32 warnings
 * Drop the IMX/IPUV3 experiment, it was just to show that it works also on
   ARM devices.

v7:
 * Add a check to see if the 4cc format is supported by drm_panic.
 * Add a drm/plane helper to loop over all visible primary buffer,
   simplifying the get_scanout_buffer implementations
 * Add a generic implementation for drivers that uses drm_fb_dma. (Maxime 
Ripard)
 * Add back the IMX/IPUV3 support, and use the generic implementation. (Maxime 
Ripard)


Best regards,

Jocelyn Falempe (9):
  drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill
  drm/panic: Add a drm panic handler
  drm/plane: Add drm_for_each_primary_visible_plane macro
  drm/panic: Add drm_panic_is_format_supported()
  drm/fb_dma: Add generic get_scanout_buffer() for drm_panic
  drm/simpledrm: Add drm_panic support
  drm/mgag200: Add drm_panic support
  drm/ast: Add drm_panic support
  drm/imx: Add drm_panic support

 drivers/gpu/drm/Kconfig  |  23 ++
 drivers/gpu/drm/Makefile |   1 +
 drivers/gpu/drm/ast/ast_drv.c|  26 +-
 drivers/gpu/drm/drm_drv.c|   8 +
 drivers/gpu/drm/drm_fb_dma_helper.c  |  55 +++
 drivers/gpu/drm/drm_format_helper.c  | 432 ++-
 drivers/gpu/drm/drm_panic.c  | 382 
 drivers/gpu/drm/imx/ipuv3/imx-drm-core.c |   2 +
 drivers/gpu/drm/mgag200/mgag200_drv.c|  22 ++
 drivers/gpu/drm/tiny/simpledrm.c |  15 +
 include/drm/drm_drv.h|  21 ++
 include/drm/drm_fb_dma_helper.h  |   4 +
 include/drm/drm_format_helper.h  |   9 +
 include/drm/drm_panic.h  | 101 ++
 include/drm/drm_plane.h  |  15 +
 15 files changed, 1033 insertions(+), 83 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_panic.c
 create mode 100644 include/drm/drm_panic.h


base-commit: 50a3c772bd927dd409c484832ddd9f6bf00b7389
-- 
2.43.0



Re: [PATCH v3 4/4] drm/ssd130x: Add support for the SSD133x OLED controller family

2023-12-22 Thread Jocelyn Falempe




On 19/12/2023 21:34, Javier Martinez Canillas wrote:

The Solomon SSD133x controllers (such as the SSD1331) are used by RGB dot
matrix OLED panels, add a modesetting pipeline to support the chip family.

The SSD133x controllers support 256 (8-bit) and 65k (16-bit) color depths
but only the former is implemented for now. This is because the 256 color
depth format matches a fourcc code already present in DRM (RGB8), but the
65k pixel format does not match the existing RG16 fourcc code format.

Instead of a R:G:B 5:6:5, the controller expects the 16-bit pixels to be
R:G:B 6:5:6, and so a new fourcc needs to be added to support this format.


small typo here, R:G:B 6:5:6 => that's 17 bits

other than that, it looks good to me, feel free to add:
Reviewed-by: Jocelyn Falempe 



Signed-off-by: Javier Martinez Canillas 
---

(no changes since v1)

  drivers/gpu/drm/solomon/ssd130x-i2c.c |   5 +
  drivers/gpu/drm/solomon/ssd130x-spi.c |   7 +
  drivers/gpu/drm/solomon/ssd130x.c | 370 ++
  drivers/gpu/drm/solomon/ssd130x.h |   5 +-
  4 files changed, 386 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/solomon/ssd130x-i2c.c 
b/drivers/gpu/drm/solomon/ssd130x-i2c.c
index f2ccab9c06d9..a047dbec4e48 100644
--- a/drivers/gpu/drm/solomon/ssd130x-i2c.c
+++ b/drivers/gpu/drm/solomon/ssd130x-i2c.c
@@ -105,6 +105,11 @@ static const struct of_device_id ssd130x_of_match[] = {
.compatible = "solomon,ssd1327",
.data = _variants[SSD1327_ID],
},
+   /* ssd133x family */
+   {
+   .compatible = "solomon,ssd1331",
+   .data = _variants[SSD1331_ID],
+   },
{ /* sentinel */ }
  };
  MODULE_DEVICE_TABLE(of, ssd130x_of_match);
diff --git a/drivers/gpu/drm/solomon/ssd130x-spi.c 
b/drivers/gpu/drm/solomon/ssd130x-spi.c
index 84e035a7ab3f..84bfde31d172 100644
--- a/drivers/gpu/drm/solomon/ssd130x-spi.c
+++ b/drivers/gpu/drm/solomon/ssd130x-spi.c
@@ -142,6 +142,11 @@ static const struct of_device_id ssd130x_of_match[] = {
.compatible = "solomon,ssd1327",
.data = _variants[SSD1327_ID],
},
+   /* ssd133x family */
+   {
+   .compatible = "solomon,ssd1331",
+   .data = _variants[SSD1331_ID],
+   },
{ /* sentinel */ }
  };
  MODULE_DEVICE_TABLE(of, ssd130x_of_match);
@@ -166,6 +171,8 @@ static const struct spi_device_id ssd130x_spi_table[] = {
{ "ssd1322", SSD1322_ID },
{ "ssd1325", SSD1325_ID },
{ "ssd1327", SSD1327_ID },
+   /* ssd133x family */
+   { "ssd1331", SSD1331_ID },
{ /* sentinel */ }
  };
  MODULE_DEVICE_TABLE(spi, ssd130x_spi_table);
diff --git a/drivers/gpu/drm/solomon/ssd130x.c 
b/drivers/gpu/drm/solomon/ssd130x.c
index bef293922b98..447d0c7c88c6 100644
--- a/drivers/gpu/drm/solomon/ssd130x.c
+++ b/drivers/gpu/drm/solomon/ssd130x.c
@@ -119,6 +119,26 @@
  #define SSD130X_SET_VCOMH_VOLTAGE 0xbe
  #define SSD132X_SET_FUNCTION_SELECT_B 0xd5
  
+/* ssd133x commands */

+#define SSD133X_SET_COL_RANGE  0x15
+#define SSD133X_SET_ROW_RANGE  0x75
+#define SSD133X_CONTRAST_A 0x81
+#define SSD133X_CONTRAST_B 0x82
+#define SSD133X_CONTRAST_C 0x83
+#define SSD133X_SET_MASTER_CURRENT 0x87
+#define SSD132X_SET_PRECHARGE_A0x8a
+#define SSD132X_SET_PRECHARGE_B0x8b
+#define SSD132X_SET_PRECHARGE_C0x8c
+#define SSD133X_SET_DISPLAY_START  0xa1
+#define SSD133X_SET_DISPLAY_OFFSET 0xa2
+#define SSD133X_SET_DISPLAY_NORMAL 0xa4
+#define SSD133X_SET_MASTER_CONFIG  0xad
+#define SSD133X_POWER_SAVE_MODE0xb0
+#define SSD133X_PHASES_PERIOD  0xb1
+#define SSD133X_SET_CLOCK_FREQ 0xb3
+#define SSD133X_SET_PRECHARGE_VOLTAGE  0xbb
+#define SSD133X_SET_VCOMH_VOLTAGE  0xbe
+
  #define MAX_CONTRAST 255
  
  const struct ssd130x_deviceinfo ssd130x_variants[] = {

@@ -180,6 +200,12 @@ const struct ssd130x_deviceinfo ssd130x_variants[] = {
.default_width = 128,
.default_height = 128,
.family_id = SSD132X_FAMILY,
+   },
+   /* ssd133x family */
+   [SSD1331_ID] = {
+   .default_width = 96,
+   .default_height = 64,
+   .family_id = SSD133X_FAMILY,
}
  };
  EXPORT_SYMBOL_NS_GPL(ssd130x_variants, DRM_SSD130X);
@@ -589,6 +615,117 @@ static int ssd132x_init(struct ssd130x_device *ssd130x)
return 0;
  }
  
+static int ssd133x_init(struct ssd130x_device *ssd130x)

+{
+   int ret;
+
+   /* Set color A contrast */
+   ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_CONTRAST_A, 0x91);
+   if (re

Re: [PATCH] drm/mgag200: Fix gamma lut not initialized for G200ER, G200EV, G200SE

2023-12-20 Thread Jocelyn Falempe

I just merged it to drm-misc-fixes:

https://cgit.freedesktop.org/drm/drm-misc/commit/?h=drm-misc-fixes=11f9eb899ecc8c02b769cf8d2532ba12786a7af7

Thanks,

--

Jocelyn



Re: [PATCH] drm/mgag200: Fix gamma lut not initialized for G200ER, G200EV, G200SE

2023-12-18 Thread Jocelyn Falempe




On 18/12/2023 12:31, Thomas Zimmermann wrote:

Hi

Am 14.12.23 um 17:38 schrieb Jocelyn Falempe:

When mgag200 switched from simple KMS to regular atomic helpers,
the initialization of the gamma settings was lost.
This leads to a black screen, if the bios/uefi doesn't use the same
pixel color depth.
This has been fixed with commit ad81e23426a6 ("drm/mgag200: Fix gamma
lut not initialized.") for most G200, but G200ER, G200EV, G200SE use
their own version of crtc_helper_atomic_enable() and need to be fixed
too.

Fixes: 1baf9127c482 ("drm/mgag200: Replace simple-KMS with regular 
atomic helpers")

Cc:  #v6.1+
Reported-by: Roger Sewell 
Suggested-by: Roger Sewell 
Signed-off-by: Jocelyn Falempe 
---
  drivers/gpu/drm/mgag200/mgag200_drv.h    |  4 
  drivers/gpu/drm/mgag200/mgag200_g200er.c |  2 ++
  drivers/gpu/drm/mgag200/mgag200_g200ev.c |  2 ++
  drivers/gpu/drm/mgag200/mgag200_g200se.c |  2 ++
  drivers/gpu/drm/mgag200/mgag200_mode.c   | 26 ++--
  5 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h 
b/drivers/gpu/drm/mgag200/mgag200_drv.h

index 57c7edcab602..ed90a92b5fcd 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -392,6 +392,10 @@ void 
mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane,

  .destroy = drm_plane_cleanup, \
  DRM_GEM_SHADOW_PLANE_FUNCS
+void mgag200_crtc_set_gamma(struct mga_device *mdev,
+    const struct drm_format_info *format,
+    struct drm_property_blob *gamma_lut);
+
  enum drm_mode_status mgag200_crtc_helper_mode_valid(struct drm_crtc 
*crtc,

  const struct drm_display_mode *mode);
  int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct 
drm_atomic_state *new_state);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c 
b/drivers/gpu/drm/mgag200/mgag200_g200er.c

index bce267e0f7de..38815cb94c61 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200er.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c
@@ -202,6 +202,8 @@ static void 
mgag200_g200er_crtc_helper_atomic_enable(struct drm_crtc *crtc,

  mgag200_g200er_reset_tagfifo(mdev);
+    mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut);
+
  mgag200_enable_display(mdev);
  if (funcs->enable_vidrst)
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c 
b/drivers/gpu/drm/mgag200/mgag200_g200ev.c

index ac957f42abe1..e698a3a499bf 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
@@ -203,6 +203,8 @@ static void 
mgag200_g200ev_crtc_helper_atomic_enable(struct drm_crtc *crtc,

  mgag200_g200ev_set_hiprilvl(mdev);
+    mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut);
+
  mgag200_enable_display(mdev);
  if (funcs->enable_vidrst)
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c 
b/drivers/gpu/drm/mgag200/mgag200_g200se.c

index bd6e573c9a1a..7e4ea0046a6b 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200se.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c
@@ -334,6 +334,8 @@ static void 
mgag200_g200se_crtc_helper_atomic_enable(struct drm_crtc *crtc,

  mgag200_g200se_set_hiprilvl(mdev, adjusted_mode, format);
+    mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut);
+
  mgag200_enable_display(mdev);
  if (funcs->enable_vidrst)
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c 
b/drivers/gpu/drm/mgag200/mgag200_mode.c

index af3ce5a6a636..d2a04b317232 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -65,9 +65,9 @@ static void mgag200_crtc_set_gamma_linear(struct 
mga_device *mdev,

  }
  }
-static void mgag200_crtc_set_gamma(struct mga_device *mdev,
-   const struct drm_format_info *format,
-   struct drm_color_lut *lut)
+static void mgag200_crtc_set_gamma_table(struct mga_device *mdev,
+ const struct drm_format_info *format,
+ struct drm_color_lut *lut)
  {
  int i;
@@ -103,6 +103,16 @@ static void mgag200_crtc_set_gamma(struct 
mga_device *mdev,

  }
  }
+void mgag200_crtc_set_gamma(struct mga_device *mdev,
+    const struct drm_format_info *format,
+    struct drm_property_blob *gamma_lut)
+{
+    if (gamma_lut)
+    mgag200_crtc_set_gamma_table(mdev, format, gamma_lut->data);
+    else
+    mgag200_crtc_set_gamma_linear(mdev, format);
+}


Please keep this open-coded its callers. With that changed

Reviewed-by: Thomas Zimmermann 


Thanks for the review, yes I will change that.
If no other comments, I will push it to drm-misc-fixes tomorrow.

--

Jocelyn



+
  static inline void mga_wait_vsync(struct mga_device *mdev)
  {
  unsigned long timeout = jiffies + HZ/10;
@@ -616,10 +626,7 @@ void mgag200_crtc_helper_atomic_flush(struct 
drm_crtc *crtc, struct drm_atomic_s

  if (crtc_state-

[PATCH] drm/mgag200: Fix gamma lut not initialized for G200ER, G200EV, G200SE

2023-12-14 Thread Jocelyn Falempe
When mgag200 switched from simple KMS to regular atomic helpers,
the initialization of the gamma settings was lost.
This leads to a black screen, if the bios/uefi doesn't use the same
pixel color depth.
This has been fixed with commit ad81e23426a6 ("drm/mgag200: Fix gamma
lut not initialized.") for most G200, but G200ER, G200EV, G200SE use
their own version of crtc_helper_atomic_enable() and need to be fixed
too.

Fixes: 1baf9127c482 ("drm/mgag200: Replace simple-KMS with regular atomic 
helpers")
Cc:  #v6.1+
Reported-by: Roger Sewell 
Suggested-by: Roger Sewell 
Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/mgag200/mgag200_drv.h|  4 
 drivers/gpu/drm/mgag200/mgag200_g200er.c |  2 ++
 drivers/gpu/drm/mgag200/mgag200_g200ev.c |  2 ++
 drivers/gpu/drm/mgag200/mgag200_g200se.c |  2 ++
 drivers/gpu/drm/mgag200/mgag200_mode.c   | 26 ++--
 5 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h 
b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 57c7edcab602..ed90a92b5fcd 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -392,6 +392,10 @@ void mgag200_primary_plane_helper_atomic_disable(struct 
drm_plane *plane,
.destroy = drm_plane_cleanup, \
DRM_GEM_SHADOW_PLANE_FUNCS
 
+void mgag200_crtc_set_gamma(struct mga_device *mdev,
+   const struct drm_format_info *format,
+   struct drm_property_blob *gamma_lut);
+
 enum drm_mode_status mgag200_crtc_helper_mode_valid(struct drm_crtc *crtc,
const struct 
drm_display_mode *mode);
 int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct 
drm_atomic_state *new_state);
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c 
b/drivers/gpu/drm/mgag200/mgag200_g200er.c
index bce267e0f7de..38815cb94c61 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200er.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c
@@ -202,6 +202,8 @@ static void mgag200_g200er_crtc_helper_atomic_enable(struct 
drm_crtc *crtc,
 
mgag200_g200er_reset_tagfifo(mdev);
 
+   mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut);
+
mgag200_enable_display(mdev);
 
if (funcs->enable_vidrst)
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c 
b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
index ac957f42abe1..e698a3a499bf 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
@@ -203,6 +203,8 @@ static void mgag200_g200ev_crtc_helper_atomic_enable(struct 
drm_crtc *crtc,
 
mgag200_g200ev_set_hiprilvl(mdev);
 
+   mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut);
+
mgag200_enable_display(mdev);
 
if (funcs->enable_vidrst)
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c 
b/drivers/gpu/drm/mgag200/mgag200_g200se.c
index bd6e573c9a1a..7e4ea0046a6b 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200se.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c
@@ -334,6 +334,8 @@ static void mgag200_g200se_crtc_helper_atomic_enable(struct 
drm_crtc *crtc,
 
mgag200_g200se_set_hiprilvl(mdev, adjusted_mode, format);
 
+   mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut);
+
mgag200_enable_display(mdev);
 
if (funcs->enable_vidrst)
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c 
b/drivers/gpu/drm/mgag200/mgag200_mode.c
index af3ce5a6a636..d2a04b317232 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -65,9 +65,9 @@ static void mgag200_crtc_set_gamma_linear(struct mga_device 
*mdev,
}
 }
 
-static void mgag200_crtc_set_gamma(struct mga_device *mdev,
-  const struct drm_format_info *format,
-  struct drm_color_lut *lut)
+static void mgag200_crtc_set_gamma_table(struct mga_device *mdev,
+const struct drm_format_info *format,
+struct drm_color_lut *lut)
 {
int i;
 
@@ -103,6 +103,16 @@ static void mgag200_crtc_set_gamma(struct mga_device *mdev,
}
 }
 
+void mgag200_crtc_set_gamma(struct mga_device *mdev,
+   const struct drm_format_info *format,
+   struct drm_property_blob *gamma_lut)
+{
+   if (gamma_lut)
+   mgag200_crtc_set_gamma_table(mdev, format, gamma_lut->data);
+   else
+   mgag200_crtc_set_gamma_linear(mdev, format);
+}
+
 static inline void mga_wait_vsync(struct mga_device *mdev)
 {
unsigned long timeout = jiffies + HZ/10;
@@ -616,10 +626,7 @@ void mgag200_crtc_helper_atomic_flush(struct drm_crtc 
*crtc, struct drm_atomic_s
if (crtc_state->enable && crtc_state->color_mgmt_changed) {
const struct drm_format_info *format = 
mgag200_crtc_sta

Re: [PATCH v5 6/6] drm/imx: Add drm_panic support

2023-12-14 Thread Jocelyn Falempe




On 14/12/2023 14:48, Maxime Ripard wrote:

Hi,

On Fri, Nov 03, 2023 at 03:53:30PM +0100, Jocelyn Falempe wrote:

Proof of concept to add drm_panic support on an arm based GPU.
I've tested it with X11/llvmpipe, because I wasn't able to have
3d rendering with etnaviv on my imx6 board.

Signed-off-by: Jocelyn Falempe 


Like I said in the v6, this shouldn't be dropped because it also kind of
documents and shows what we are expecting from a "real" driver.


Ok, I can bring it back in v7.




---
  drivers/gpu/drm/imx/ipuv3/imx-drm-core.c | 30 
  1 file changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c 
b/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
index 4a866ac60fff..db24b4976c61 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
@@ -10,6 +10,7 @@
  #include 
  #include 
  #include 
+#include 
  
  #include 
  
@@ -17,9 +18,12 @@

  #include 
  #include 
  #include 
+#include 
+#include 
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -160,6 +164,31 @@ static int imx_drm_dumb_create(struct drm_file *file_priv,
return ret;
  }
  
+static int imx_drm_get_scanout_buffer(struct drm_device *dev,

+ struct drm_scanout_buffer *sb)
+{
+   struct drm_plane *plane;
+   struct drm_gem_dma_object *dma_obj;
+
+   drm_for_each_plane(plane, dev) {
+   if (!plane->state || !plane->state->fb || 
!plane->state->visible ||
+   plane->type != DRM_PLANE_TYPE_PRIMARY)
+   continue;
+
+   dma_obj = drm_fb_dma_get_gem_obj(plane->state->fb, 0);
+   if (!dma_obj->vaddr)
+   continue;
+
+   iosys_map_set_vaddr(>map, dma_obj->vaddr);
+   sb->format = plane->state->fb->format;


Planes can be using a framebuffer in one of the numerous YUV format the
driver advertises.


+   sb->height = plane->state->fb->height;
+   sb->width = plane->state->fb->width;
+   sb->pitch = plane->state->fb->pitches[0];


And your code assumes that the buffer will be large enough for an RGB
buffer, which probably isn't the case for a single-planar YUV format,
and certainly not the case for a multi-planar one.


Yes, this code is a bit hacky, and on my test setup the framebuffer was 
in RGB, so I didn't handle other formats.
Also it should be possible to add YUV format later, but I would like to 
have a minimal drm_panic merged, before adding more features.


When the driver gives back its current framebuffer, the code should check:

   * If the buffer backed by an actual buffer (and not a dma-buf handle)


Regarding the struct drm_framebuffer, I'm not sure how do you 
differentiate an actual buffer from a dma-buf handle ?



   * If the buffer is mappable by the CPU


If "dma_obj->vaddr" is not null, then it's already mapped by the CPU right ?

   * If the buffer is in a format that the panic code can handle
   * If the buffer uses a linear modifier


Yes, that must be checked too.



Failing that, your code cannot work at the moment. We need to be clear
about that and "gracefully" handle things instead of going forward and
writing pixels to places we might not be able to write to.

Which kind of makes me think, why do we need to involve the driver at
all there?

If in the panic code, we're going over all enabled CRTCs, finding the
primary plane currently setup for them and getting the drm_framebuffer
assigned to them, it should be enough to get us all the informations we
need, right?


Yes, I think I can do a generic implementation for the drivers using the 
drm_gem_dma helper like imx6.
But for simpledrm, ast, or mgag200, I need to retrieve the VRAM address, 
because it's not in the drm_framebuffer struct, so they won't be able to 
use this generic implementation.




Maxime


Thanks for the review,

--

Jocelyn



Re: [PATCH] drm/mgag200: Flush the cache to improve latency

2023-12-11 Thread Jocelyn Falempe

On 06/11/2023 11:46, Jocelyn Falempe wrote:

On 23/10/2023 10:30, Jocelyn Falempe wrote:

On 20/10/2023 14:06, Thomas Zimmermann wrote:

(cc'ing lkml for feedback)

Hi Jocelyn

Am 19.10.23 um 15:55 schrieb Jocelyn Falempe:

We found a regression in v5.10 on real-time server, using the
rt-kernel and the mgag200 driver. It's some really specialized
workload, with <10us latency expectation on isolated core.
After the v5.10, the real time tasks missed their <10us latency
when something prints on the screen (fbcon or printk)


I'd like to hear the opinion of the RT-devs on this patch. Because 
AFAIK we never did such a workaround in other drivers. And AFAIK 
printk is a PITA anyway.


Most other drivers uses DMA, which means this workaround can't apply 
to them.




IMHO if that RT system cannot handle differences in framebuffer 
caching, it's under-powered. It's just a matter of time until 
something else changes and the problem returns. And (honest question) 
as it's an x86-64, how do they handle System Management Mode?


I think it's not a big news, that the Matrox G200 from 1999 is 
under-powered.
I was also a bit surprised that flushing the cache would have such 
effect on latency. The tests we are doing can run 24h with the 
workaround, without any interrupt taking more than 10us. Without the 
workaround, every ~30s the interrupt failed its 10us target.






The regression has been bisected to 2 commits:
0b34d58b6c32 ("drm/mgag200: Enable caching for SHMEM pages")
4862ffaec523 ("drm/mgag200: Move vmap out of commit tail")

The first one changed the system memory framebuffer from Write-Combine
to the default caching.
Before the second commit, the mgag200 driver used to unmap the
framebuffer after each frame, which implicitly does a cache flush.
Both regressions are fixed by the following patch, which forces a
cache flush after each frame, reverting to almost v5.9 behavior.


With that second commit, we essentially never unmap an active 
framebuffer console. But with commit


359c6649cd9a ("drm/gem: Implement shadow-plane {begin, end}_fb_access 
with vmap")


we now again unmap the console framebuffer after the pageflip happened.

So how does the latest kernel behave wrt to the problem?


The regression was found when upgrading the server from v5.4 to v5.14, 
so we didn't test with later kernels.
We will test with v6.3 (which should have 359c6649cd9a ) and see what 
it gives.


I don't have a clear explanation, but testing with v6.3, and forcing the 
Write Combine, doesn't fix the latency issue. So forcing the cache flush 
is still needed.


Also, on some systems, they use "isolated cpu" to handle RT task, but 
with a standard kernel (so without the CONFIG_PREEMPT_RT).

So I'm wondering if we can use a kernel module parameter for this,
so that users that wants to achieve low latency, can opt-in ?

something like mgag200.force_cache_flush=1 or mgag200.low_latency=1 ?


Hi,

I have now access to a server that reproduce the issue, and I was able 
to test different workarounds.


So it is definitely related to the "Write Combine" mode of the mga 
internal RAM. If I comment the two lines to enable wc: 
https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/mgag200/mgag200_drv.c#L150, 
then the latency is <10us (but the performances are worse, from 20ms to 
87ms to draw a full frame).


I also tried to flush the vram using:
drm_clflush_virt_range(mdev->vram + clip->y1 * fb->pitches[0], 
drm_rect_height(clip) * fb->pitches[0]);

And that lower the latency to ~20us, but it's not enough.

I tried "sfence" which I though would flush the WC buffers of the CPU, 
but that has no effect in practice.


I think I can send a new patch, to not map the VRAM as Write Combine, 
either if CONFIG_PREEMPT_RT is set or if a module parameter is set.

What do you think is the best approach ?



My tests setup:

I either flood the console with "cat /dev/urandom | base64" from the 
BMC, or write to fb0 with "while true; do dd if=/dev/urandom of=/dev/fb0 
; done"


then I run:

cd /sys/kernel/debug/tracing
echo 0 > tracing_on
echo 95 > hwlat_detector/width
echo hwlat > current_tracer
echo 10 > tracing_thresh
echo 1 > tracing_on
sleep 300
cat trace
echo 0 > tracing_on
echo nop > current_tracer


Test Results:

V6.6 (~40us latency)

# tracer: hwlat
#
# entries-in-buffer/entries-written: 6/6   #P:56
#
#_-=> irqs-off/BH-disabled
#   / _=> need-resched
#  | / _---=> hardirq/softirq
#  || / _--=> preempt-depth
#  ||| / _-=> migrate-disable
#   / delay
#   TASK-PID CPU#  |  TIMESTAMP  FUNCTION
#  | | |   | | |
   <...>-8795[001] dn...   613

[PATCH v6 3/5] drm/simpledrm: Add drm_panic support

2023-12-05 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a user-friendly
message to the screen when a kernel panic occurs.

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/tiny/simpledrm.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 34bbbd7b53dd..41eea078294b 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -986,6 +987,19 @@ static struct simpledrm_device 
*simpledrm_device_create(struct drm_driver *drv,
return sdev;
 }
 
+static int simpledrm_get_scanout_buffer(struct drm_device *dev,
+   struct drm_scanout_buffer *sb)
+{
+   struct simpledrm_device *sdev = simpledrm_device_of_dev(dev);
+
+   sb->width = sdev->mode.hdisplay;
+   sb->height = sdev->mode.vdisplay;
+   sb->pitch = sdev->pitch;
+   sb->format = sdev->format;
+   sb->map = sdev->screen_base;
+   return 0;
+}
+
 /*
  * DRM driver
  */
@@ -1001,6 +1015,7 @@ static struct drm_driver simpledrm_driver = {
.minor  = DRIVER_MINOR,
.driver_features= DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,
.fops   = _fops,
+   .get_scanout_buffer = simpledrm_get_scanout_buffer,
 };
 
 /*
-- 
2.42.0



[PATCH v6 4/5] drm/mgag200: Add drm_panic support

2023-12-05 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a message to
the screen when a kernel panic occurs.

v5:
 * Also check that the plane is visible and primary. (Thomas Zimmermann)

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/mgag200/mgag200_drv.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c 
b/drivers/gpu/drm/mgag200/mgag200_drv.c
index 2fb18b782b05..c79f3d9ee39a 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -13,10 +13,12 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mgag200_drv.h"
@@ -84,6 +86,28 @@ resource_size_t mgag200_probe_vram(void __iomem *mem, 
resource_size_t size)
return offset - 65536;
 }
 
+static int mgag200_get_scanout_buffer(struct drm_device *dev,
+ struct drm_scanout_buffer *sb)
+{
+   struct drm_plane *plane;
+   struct mga_device *mdev = to_mga_device(dev);
+   struct iosys_map map = IOSYS_MAP_INIT_VADDR_IOMEM(mdev->vram);
+
+   /* find the primary and visible plane */
+   drm_for_each_plane(plane, dev) {
+   if (!plane->state || !plane->state->visible || 
!plane->state->fb ||
+   plane->type != DRM_PLANE_TYPE_PRIMARY)
+   continue;
+   sb->format = plane->state->fb->format;
+   sb->width = plane->state->fb->width;
+   sb->height = plane->state->fb->height;
+   sb->pitch = plane->state->fb->pitches[0];
+   sb->map = map;
+   return 0;
+   }
+   return -ENODEV;
+}
+
 /*
  * DRM driver
  */
@@ -99,6 +123,7 @@ static const struct drm_driver mgag200_driver = {
.major = DRIVER_MAJOR,
.minor = DRIVER_MINOR,
.patchlevel = DRIVER_PATCHLEVEL,
+   .get_scanout_buffer = mgag200_get_scanout_buffer,
DRM_GEM_SHMEM_DRIVER_OPS,
 };
 
-- 
2.42.0



[PATCH v6 5/5] drm/ast: Add drm_panic support

2023-12-05 Thread Jocelyn Falempe
Add support for the drm_panic module, which displays a message to
the screen when a kernel panic occurs.

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/ast/ast_drv.c | 29 +++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
index 90bcb1eb9cd9..bb49e89dbd3c 100644
--- a/drivers/gpu/drm/ast/ast_drv.c
+++ b/drivers/gpu/drm/ast/ast_drv.c
@@ -35,6 +35,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "ast_drv.h"
@@ -48,6 +49,30 @@ module_param_named(modeset, ast_modeset, int, 0400);
  * DRM driver
  */
 
+static int ast_get_scanout_buffer(struct drm_device *dev,
+ struct drm_scanout_buffer *sb)
+{
+   struct drm_plane *plane;
+   struct ast_plane *ast_plane;
+
+   drm_for_each_plane(plane, dev) {
+   if (!plane->state || !plane->state->visible || 
!plane->state->fb ||
+   plane->type != DRM_PLANE_TYPE_PRIMARY)
+   continue;
+   ast_plane = to_ast_plane(plane);
+   if (!ast_plane->vaddr)
+   continue;
+
+   sb->format = plane->state->fb->format;
+   sb->width = plane->state->fb->width;
+   sb->height = plane->state->fb->height;
+   sb->pitch = plane->state->fb->pitches[0];
+   iosys_map_set_vaddr_iomem(>map, ast_plane->vaddr);
+   return 0;
+   }
+   return -ENODEV;
+}
+
 DEFINE_DRM_GEM_FOPS(ast_fops);
 
 static const struct drm_driver ast_driver = {
@@ -62,8 +87,8 @@ static const struct drm_driver ast_driver = {
.major = DRIVER_MAJOR,
.minor = DRIVER_MINOR,
.patchlevel = DRIVER_PATCHLEVEL,
-
-   DRM_GEM_SHMEM_DRIVER_OPS
+   .get_scanout_buffer = ast_get_scanout_buffer,
+   DRM_GEM_SHMEM_DRIVER_OPS,
 };
 
 /*
-- 
2.42.0



[PATCH v6 2/5] drm/panic: Add a drm panic handler

2023-12-05 Thread Jocelyn Falempe
This module displays a user friendly message when a kernel panic
occurs. It currently doesn't contain any debug information,
but that can be added later.

v2
 * Use get_scanout_buffer() instead of the drm client API.
  (Thomas Zimmermann)
 * Add the panic reason to the panic message (Nerdopolis)
 * Add an exclamation mark (Nerdopolis)

v3
 * Rework the drawing functions, to write the pixels line by line and
 to use the drm conversion helper to support other formats.
 (Thomas Zimmermann)

v4
 * Use drm_fb_r1_to_32bit for fonts (Thomas Zimmermann)
 * Remove the default y to DRM_PANIC config option (Thomas Zimmermann)
 * Add foreground/background color config option
 * Fix the bottom lines not painted if the framebuffer height
   is not a multiple of the font height.
 * Automatically register the device to drm_panic, if the function
   get_scanout_buffer exists. (Thomas Zimmermann)

v5
 * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
 * Also add drm_fb_fill() to fill area with background color.
 * Add draw_pixel_xy() API for drivers that can't provide a linear buffer.
 * Add a flush() callback for drivers that needs to synchronize the buffer.
 * Add a void *private field, so drivers can pass private data to
   draw_pixel_xy() and flush().

v6
 * Fix sparse warning for panic_msg and logo

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/Kconfig |  22 +++
 drivers/gpu/drm/Makefile|   1 +
 drivers/gpu/drm/drm_drv.c   |   8 +
 drivers/gpu/drm/drm_panic.c | 368 
 include/drm/drm_drv.h   |  21 ++
 include/drm/drm_panic.h |  96 ++
 6 files changed, 516 insertions(+)
 create mode 100644 drivers/gpu/drm/drm_panic.c
 create mode 100644 include/drm/drm_panic.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index b7abd436455f..6bf7a5b2f288 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -103,6 +103,28 @@ config DRM_KMS_HELPER
help
  CRTC helpers for KMS drivers.
 
+config DRM_PANIC
+   bool "Display a user-friendly message when a kernel panic occurs"
+   depends on DRM && !FRAMEBUFFER_CONSOLE
+   select FONT_SUPPORT
+   help
+ Enable a drm panic handler, which will display a user-friendly message
+ when a kernel panic occurs. It's useful when using a user-space
+ console instead of fbcon.
+ It will only work if your graphic driver supports this feature.
+ To support Hi-DPI Display, you can enable bigger fonts like
+ FONT_TER16x32
+
+config DRM_PANIC_FOREGROUND_COLOR
+   hex "Drm panic screen foreground color, in RGB"
+   depends on DRM_PANIC
+   default 0xff
+
+config DRM_PANIC_BACKGROUND_COLOR
+   hex "Drm panic screen background color, in RGB"
+   depends on DRM_PANIC
+   default 0x00
+
 config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
 bool "Enable refcount backtrace history in the DP MST helpers"
depends on STACKTRACE_SUPPORT
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index b4cb0835620a..100e7cfad3b9 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -73,6 +73,7 @@ drm-$(CONFIG_DRM_PRIVACY_SCREEN) += \
drm_privacy_screen_x86.o
 drm-$(CONFIG_DRM_ACCEL) += ../../accel/drm_accel.o
 obj-$(CONFIG_DRM)  += drm.o
+drm-$(CONFIG_DRM_PANIC) += drm_panic.o
 
 obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o
 
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 3c835c99daad..897146fbda25 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -955,6 +956,9 @@ int drm_dev_register(struct drm_device *dev, unsigned long 
flags)
goto err_unload;
}
 
+   if (driver->get_scanout_buffer)
+   drm_panic_register(dev);
+
DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
 driver->name, driver->major, driver->minor,
 driver->patchlevel, driver->date,
@@ -1001,6 +1005,8 @@ void drm_dev_unregister(struct drm_device *dev)
 
dev->registered = false;
 
+   drm_panic_unregister(dev);
+
drm_client_dev_unregister(dev);
 
if (drm_core_check_feature(dev, DRIVER_MODESET))
@@ -1083,6 +1089,7 @@ static void drm_core_exit(void)
unregister_chrdev(DRM_MAJOR, "drm");
debugfs_remove(drm_debugfs_root);
drm_sysfs_destroy();
+   drm_panic_exit();
idr_destroy(_minors_idr);
drm_connector_ida_destroy();
 }
@@ -1094,6 +1101,7 @@ static int __init drm_core_init(void)
drm_connector_ida_init();
idr_init(_minors_idr);
drm_memcpy_init_early();
+   drm_panic_init();
 
ret = drm_sysfs_init();
if (ret < 0) {
diff --git a/drive

[PATCH v6 1/5] drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill

2023-12-05 Thread Jocelyn Falempe
This is needed for drm_panic, to draw the font, and fill
the background color, in multiple color format.

v5:
 * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
 * Also add drm_fb_fill() to fill area with background color.
v6:
 * fix __le32 conversion warning found by the kernel test bot

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/drm_format_helper.c | 431 ++--
 include/drm/drm_format_helper.h |   9 +
 2 files changed, 359 insertions(+), 81 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index b1be458ed4dd..38a3c38f5d84 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -111,6 +111,152 @@ void drm_format_conv_state_release(struct 
drm_format_conv_state *state)
 }
 EXPORT_SYMBOL(drm_format_conv_state_release);
 
+static inline __le16 drm_format_xrgb_to_rgb565(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = ((pix & 0x00F8) >> 8) |
+   ((pix & 0xFC00) >> 5) |
+   ((pix & 0x00F8) >> 3);
+   return cpu_to_le16(val16);
+}
+
+static inline __le16 drm_format_xrgb_to_rgba5551(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = ((pix & 0x00f8) >> 8) |
+   ((pix & 0xf800) >> 5) |
+   ((pix & 0x00f8) >> 2) |
+   BIT(0); /* set alpha bit */
+   return cpu_to_le16(val16);
+}
+
+static inline __le16 drm_format_xrgb_to_xrgb1555(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = ((pix & 0x00f8) >> 9) |
+   ((pix & 0xf800) >> 6) |
+   ((pix & 0x00f8) >> 3);
+   return cpu_to_le16(val16);
+}
+
+static inline __le16 drm_format_xrgb_to_argb1555(__le32 val32)
+{
+   u16 val16;
+   u32 pix;
+
+   pix = le32_to_cpu(val32);
+   val16 = BIT(15) | /* set alpha bit */
+   ((pix & 0x00f8) >> 9) |
+   ((pix & 0xf800) >> 6) |
+   ((pix & 0x00f8) >> 3);
+   return cpu_to_le16(val16);
+}
+
+static inline __le32 drm_format_xrgb_to_argb(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 |= GENMASK(31, 24); /* fill alpha bits */
+   return cpu_to_le32(val32);
+}
+
+static inline __le32 drm_format_xrgb_to_xbgr(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00ff) >> 16) <<  0 |
+   ((val32 & 0xff00) >>  8) <<  8 |
+   ((val32 & 0x00ff) >>  0) << 16 |
+   ((val32 & 0xff00) >> 24) << 24;
+   return cpu_to_le32(val32);
+}
+
+static inline __le32 drm_format_xrgb_to_abgr(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00ff) >> 16) <<  0 |
+   ((val32 & 0xff00) >>  8) <<  8 |
+   ((val32 & 0x00ff) >>  0) << 16 |
+   GENMASK(31, 24); /* fill alpha bits */
+   return cpu_to_le32(val32);
+}
+
+static inline __le32 drm_format_xrgb_to_xrgb2101010(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00FF) << 2) |
+   ((val32 & 0xFF00) << 4) |
+   ((val32 & 0x00FF) << 6);
+   return cpu_to_le32(val32 | ((val32 >> 8) & 0x00300C03));
+}
+
+static inline __le32 drm_format_xrgb_to_argb2101010(__le32 pix)
+{
+   u32 val32;
+
+   val32 = le32_to_cpu(pix);
+   val32 = ((val32 & 0x00FF) << 2) |
+   ((val32 & 0xFF00) << 4) |
+   ((val32 & 0x00FF) << 6);
+   val32 = GENMASK(31, 30) | /* set alpha bits */
+ val32 | ((val32 >> 8) & 0x00300c03);
+   return cpu_to_le32(val32);
+}
+
+/**
+ * drm_fb_convert_from_xrgb - convert one pixel from xrgb to the 
desired format
+ * @color: input color, in xrgb format
+ * @format: output format
+ *
+ * Returns:
+ * Color in the format specified, casted to u32.
+ */
+u32 drm_fb_convert_from_xrgb(u32 color, u32 format)
+{
+   __le32 pix = cpu_to_le32(color);
+
+   switch (format) {
+   case DRM_FORMAT_RGB565:
+   return le16_to_cpu(drm_format_xrgb_to_rgb565(pix));
+   case DRM_FORMAT_RGBA5551:
+   return le16_to_cpu(drm_format_xrgb_to_rgba5551(pix));
+   case DRM_FORMAT_XRGB1555:
+   return le16_to_cpu(drm_format_xrgb_to_xrgb1555(pix));
+   case DRM_FORMAT_ARGB1555:
+

[RFC][PATCH v6 0/5] drm/panic: Add a drm panic handler

2023-12-05 Thread Jocelyn Falempe
drm/panic: Add a drm panic handler

This introduces a new drm panic handler, which displays a message when a panic 
occurs.
So when fbcon is disabled, you can still see a kernel panic.

This is one of the missing feature, when disabling VT/fbcon in the kernel:
https://www.reddit.com/r/linux/comments/10eccv9/config_vtn_in_2023/
Fbcon can be replaced by a userspace kms console, but the panic screen must be 
done in the kernel.

This is a proof of concept, and works with simpledrm and mgag200, using a new 
get_scanout_buffer() api

To test it, make sure you're using the simpledrm driver, and trigger a panic:
echo c > /proc/sysrq-trigger

v2:
 * Use get_scanout_buffer() instead of the drm client API. (Thomas Zimmermann)
 * Add the panic reason to the panic message (Nerdopolis)
 * Add an exclamation mark (Nerdopolis)
 
v3:
 * Rework the drawing functions, to write the pixels line by line and
 to use the drm conversion helper to support other formats.
 (Thomas Zimmermann)
 
v4:
 * Fully support all simpledrm formats using drm conversion helpers
 * Rename dpanic_* to drm_panic_*, and have more coherent function name.
   (Thomas Zimmermann)
 * Use drm_fb_r1_to_32bit for fonts (Thomas Zimmermann)
 * Remove the default y to DRM_PANIC config option (Thomas Zimmermann)
 * Add foreground/background color config option
 * Fix the bottom lines not painted if the framebuffer height
   is not a multiple of the font height.
 * Automatically register the driver to drm_panic, if the function
   get_scanout_buffer() exists. (Thomas Zimmermann)
 * Add mgag200 support.
 
v5:
 * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
   (Thomas Zimmermann)
 * Also add drm_fb_fill() to fill area with background color.
 * Add draw_pixel_xy() API for drivers that can't provide a linear buffer.
 * Add a flush() callback for drivers that needs to synchronize the buffer.
 * Add a void *private field, so drivers can pass private data to
   draw_pixel_xy() and flush(). 
 * Add ast support.
 * Add experimental imx/ipuv3 support, to test on an ARM hw. (Maxime Ripard)

v6:
 * Fix sparse and __le32 warnings
 * Drop the IMX/IPUV3 experiment, it was just to show that it works also on ARM 
devices.

With mgag200 support, I was able to test that the xrgb to rgb565 conversion 
is working.

IMX/IPUV3 support is not complete, I wasn't able to have etnaviv working on my 
board.
But it shows that it can still work on ARM with DMA buffer in this case.

Best regards,

Jocelyn Falempe (5):
  drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill
  drm/panic: Add a drm panic handler
  drm/simpledrm: Add drm_panic support
  drm/mgag200: Add drm_panic support
  drm/ast: Add drm_panic support

 drivers/gpu/drm/Kconfig   |  22 ++
 drivers/gpu/drm/Makefile  |   1 +
 drivers/gpu/drm/ast/ast_drv.c |  29 +-
 drivers/gpu/drm/drm_drv.c |   8 +
 drivers/gpu/drm/drm_format_helper.c   | 431 +-
 drivers/gpu/drm/drm_panic.c   | 368 ++
 drivers/gpu/drm/mgag200/mgag200_drv.c |  25 ++
 drivers/gpu/drm/tiny/simpledrm.c  |  15 +
 include/drm/drm_drv.h |  21 ++
 include/drm/drm_format_helper.h   |   9 +
 include/drm/drm_panic.h   |  96 ++
 11 files changed, 942 insertions(+), 83 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_panic.c
 create mode 100644 include/drm/drm_panic.h


base-commit: d0b3c318e04cc6c4e2a3c30ee0f6f619aa8d0db5
-- 
2.42.0



Re: [PATCH] drm/ast: Disconnect BMC if physical connector is connected

2023-11-16 Thread Jocelyn Falempe

On 16/11/2023 14:02, Thomas Zimmermann wrote:

Many user-space compositors fail with mode setting if a CRTC has
more than one connected connector. This is the case with the BMC
on Aspeed systems. Work around this problem by setting the BMC's
connector status to disconnected when the physical connector has
a display attached. This way compositors will only see one connected
connector at a time; either the physical one or the BMC.



Thanks for the patch.
I can't test it because I don't have physical access to a machine with 
aspeed GPU, but it looks good to me.


Reviewed-by: Jocelyn Falempe 

--

Jocelyn



Re: Incomplete stable drm/ast backport - screen freeze on boot

2023-11-14 Thread Jocelyn Falempe

On 13/11/2023 17:37, Sasha Levin wrote:

On Mon, Nov 13, 2023 at 10:49:01AM +0100, Thomas Zimmermann wrote:

(cc: gregkh)

Hi Jocelyn

Am 13.11.23 um 10:36 schrieb Jocelyn Falempe:

On 13/11/2023 09:34, Keno Fischer wrote:

Greetings,

When connected to a remote machine via the BMC KVM functionality,
I am experiencing screen freezes on boot when using 6.5 stable,
but not master.

The BMC on the machine in question is an ASpeed AST2600.
A quick bisect shows the problematic commit to be 2fb9667
("drm/ast: report connection status on Display Port.").
This is commit f81bb0ac upstream.

I believe the problem is that the previous commit in the series
e329cb5 ("drm/ast: Add BMC virtual connector")
was not backported to the stable branch.
As a consequence, it appears that the more accurate DP state detection
is causing the kernel to believe that no display is connected,
even when the BMC's virtual display is in fact in use.
A cherry-pick of e329cb5 onto the stable branch resolves the issue.


Yes, you're right this two patches must be backported together.

I'm sorry I didn't pay enough attention, that only one of the two was 
picked up for the stable branch.


Is it possible to backport e329cb5 to the stable branch, or should I 
push it to drm-misc-fixes ?


I think stable, which is in cc, will pick up commit e329cb5 
semi-automatically now. Otherwise, maybe ping gregkh in a few days 
about it.


I thikn it would be more appropriate to revert 2fb9667, as e329cb5
doesn't look like -stable material. I'll go ahead and do that.

Ok, that's the best thing to do, as Thomas also found that userspace can 
be confused by the new BMC virtual connector, so it's safer to revert.


Thanks,

--

Jocelyn



Re: [PATCH 00/10] drm/ast: Detect device type before init

2023-11-13 Thread Jocelyn Falempe

On 13/11/2023 09:50, Thomas Zimmermann wrote:

Detecting the ast device's chipset type and configuration mode
involves several registers, DT properties and possibly POSTing
parts of the chip. It is preferable to do this before initializing
the DRM driver, so that that each chip type can have an individual
setup code.

The patchset addresses the problem by moving all early detection
code before the allocation of the ast device.

Patch one gets a lock out of the way. The lock is only relevant
for mode setting. Move it there.

Patches 2 and 3 rework the detection of the correct I/O memory
ranges. It is now self-contained, more readable and works without
an instance of struct ast_device.

Patches 4 to 7 rework the setup of various registers that are
required for detection. Access helpers for I/O can now operate
without an instance of struct ast_device. The setup functions
operate on the I/O ranges that have been made available with
patch 3, but again without struct ast_device.

With the detection's internals done, patches 8 and 9 rework the
chip's and config-mode's detection code to operate without struct
ast_device as well.

Finally, patch 10 moves the detection code into the PCI probe
function. it runs before any of the DRM device code. The fucntion
for creating an ast device, ast_device_create(), receives the
detected I/O memory ranges, chip type and configuration mode.

This cleans up the detection code. There is more chip-specific
code in other parts of the driver. In a later patch, the ast device
setup can be split up so that each chip type gets its own code
path that does not interfere with other chips.

Tested on AST1100 and AST2100.

Thomas Zimmermann (10):
   drm/ast: Turn ioregs_lock to modeset_lock
   drm/ast: Rework I/O register setup
   drm/ast: Retrieve I/O-memory ranges without ast device
   drm/ast: Add I/O helpers without ast device
   drm/ast: Enable VGA without ast device instance
   drm/ast: Enable MMIO without ast device instance
   drm/ast: Partially implement POST without ast device instance
   drm/ast: Add enum ast_config_mode
   drm/ast: Detect ast device type and config mode without ast device
   drm/ast: Move detection code into PCI probe helper

  drivers/gpu/drm/ast/ast_drv.c  | 261 -
  drivers/gpu/drm/ast/ast_drv.h  | 101 +
  drivers/gpu/drm/ast/ast_main.c | 244 ++
  drivers/gpu/drm/ast/ast_mode.c |  26 ++--
  drivers/gpu/drm/ast/ast_post.c |  73 +
  drivers/gpu/drm/ast/ast_reg.h  |  12 +-
  6 files changed, 411 insertions(+), 306 deletions(-)


base-commit: b7816c393496dc4497c1327310821407f7171d8b
prerequisite-patch-id: 0aa359f6144c4015c140c8a6750be19099c676fb
prerequisite-patch-id: c67e5d886a47b7d0266d81100837557fda34cb24
prerequisite-patch-id: cbc453ee02fae02af22fbfdce56ab732c7a88c36


I've reviewed the whole series, and I have only a minor comment on patch 
9. That's a good thing to move the chip detection to its own functions, 
and will allow further refactoring later.



For the whole series:
Reviewed-by: Jocelyn Falempe 

--

Jocelyn



Re: [PATCH 09/10] drm/ast: Detect ast device type and config mode without ast device

2023-11-13 Thread Jocelyn Falempe

On 13/11/2023 09:50, Thomas Zimmermann wrote:

Return the ast chip and config in the detection function's parameters
instead of storing them directly in the ast device instance.

Signed-off-by: Thomas Zimmermann 
---
  drivers/gpu/drm/ast/ast_main.c | 104 ++---
  1 file changed, 57 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index f100df8d74f71..331a9a861153b 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -76,25 +76,27 @@ static void ast_open_key(void __iomem *ioregs)
__ast_write8_i(ioregs, AST_IO_VGACRI, 0x80, AST_IO_VGACR80_PASSWORD);
  }
  
-static int ast_device_config_init(struct ast_device *ast)

+static int ast_detect_chip(struct pci_dev *pdev,
+  void __iomem *regs, void __iomem *ioregs,
+  enum ast_chip *chip_out,
+  enum ast_config_mode *config_mode_out)
  {
-   struct drm_device *dev = >base;
-   struct pci_dev *pdev = to_pci_dev(dev->dev);
-   struct device_node *np = dev->dev->of_node;
+   struct device *dev = >dev;
+   struct device_node *np = dev->of_node;
+   enum ast_config_mode config_mode = ast_use_defaults;
uint32_t scu_rev = 0x;
+   enum ast_chip chip;
u32 data;
-   u8 jregd0, jregd1;
+   u8 vgacrd0, vgacrd1;
  
  	/*

 * Find configuration mode and read SCU revision
 */
  
-	ast->config_mode = ast_use_defaults;

-
/* Check if we have device-tree properties */
if (np && !of_property_read_u32(np, "aspeed,scu-revision-id", )) {
/* We do, disable P2A access */
-   ast->config_mode = ast_use_dt;
+   config_mode = ast_use_dt;
scu_rev = data;
} else if (pdev->device == PCI_CHIP_AST2000) { // Not all families have 
a P2A bridge
/*
@@ -102,9 +104,9 @@ static int ast_device_config_init(struct ast_device *ast)
 * is disabled. We force using P2A if VGA only mode bit
 * is set D[7]
 */
-   jregd0 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);
-   jregd1 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, 0xff);
-   if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) {
+   vgacrd0 = __ast_read8_i(ioregs, AST_IO_VGACRI, 0xd0);
+   vgacrd1 = __ast_read8_i(ioregs, AST_IO_VGACRI, 0xd1);
+   if (!(vgacrd0 & 0x80) || !(vgacrd1 & 0x10)) {
  
  			/*

 * We have a P2A bridge and it is enabled.
@@ -112,32 +114,32 @@ static int ast_device_config_init(struct ast_device *ast)
  
  			/* Patch AST2500/AST2510 */

if ((pdev->revision & 0xf0) == 0x40) {
-   if (!(jregd0 & AST_VRAM_INIT_STATUS_MASK))
-   ast_patch_ahb_2500(ast->regs);
+   if (!(vgacrd0 & AST_VRAM_INIT_STATUS_MASK))
+   ast_patch_ahb_2500(regs);
}
  
  			/* Double check that it's actually working */

-   data = ast_read32(ast, 0xf004);
+   data = __ast_read32(regs, 0xf004);
if ((data != 0x) && (data != 0x00)) {
-   ast->config_mode = ast_use_p2a;
+   config_mode = ast_use_p2a;
  
  /* Read SCU7c (silicon revision register) */

-   ast_write32(ast, 0xf004, 0x1e6e);
-   ast_write32(ast, 0xf000, 0x1);
-   scu_rev = ast_read32(ast, 0x1207c);
+   __ast_write32(regs, 0xf004, 0x1e6e);
+   __ast_write32(regs, 0xf000, 0x1);
+   scu_rev = __ast_read32(regs, 0x1207c);
}
}
}
  
-	switch (ast->config_mode) {

+   switch (config_mode) {
case ast_use_defaults:
-   drm_info(dev, "Using default configuration\n");
+   dev_info(dev, "Using default configuration\n");
break;
case ast_use_dt:
-   drm_info(dev, "Using device-tree for configuration\n");
+   dev_info(dev, "Using device-tree for configuration\n");
break;
case ast_use_p2a:
-   drm_info(dev, "Using P2A bridge for configuration\n");
+   dev_info(dev, "Using P2A bridge for configuration\n");
break;
}
  
@@ -146,63 +148,66 @@ static int ast_device_config_init(struct ast_device *ast)

 */
  
  	if (pdev->revision >= 0x50) {

-   ast->chip = AST2600;
-   drm_info(dev, "AST 2600 detected\n");
+   chip = AST2600;
+   dev_info(dev, "AST 2600 detected\n");


Adding a 

Re: Incomplete stable drm/ast backport - screen freeze on boot

2023-11-13 Thread Jocelyn Falempe

On 13/11/2023 09:34, Keno Fischer wrote:

Greetings,

When connected to a remote machine via the BMC KVM functionality,
I am experiencing screen freezes on boot when using 6.5 stable,
but not master.

The BMC on the machine in question is an ASpeed AST2600.
A quick bisect shows the problematic commit to be 2fb9667
("drm/ast: report connection status on Display Port.").
This is commit f81bb0ac upstream.

I believe the problem is that the previous commit in the series
e329cb5 ("drm/ast: Add BMC virtual connector")
was not backported to the stable branch.
As a consequence, it appears that the more accurate DP state detection
is causing the kernel to believe that no display is connected,
even when the BMC's virtual display is in fact in use.
A cherry-pick of e329cb5 onto the stable branch resolves the issue.


Yes, you're right this two patches must be backported together.

I'm sorry I didn't pay enough attention, that only one of the two was 
picked up for the stable branch.


Is it possible to backport e329cb5 to the stable branch, or should I 
push it to drm-misc-fixes ?


Best regards,

--

Jocelyn



Cheers,
Keno





Re: BUG in drm_kms_helper_poll_enable() fixed by reverting "drm/ast: report connection status on Display Port."

2023-11-09 Thread Jocelyn Falempe
e/drivers/gpu/drm/drm_probe_helper.c#L908

So I'm not sure why it fails in this case.



If I revert commit f81bb0ac7872893241319ea82504956676ef02fd
("drm/ast: report connection status on Display Port."), the splat
goes away:

[   60.603837] input: OpenBMC virtual_input as 
/devices/pci:00/:00:07.1/:02:00.4/usb3/3-2/3-2.6/3-2.6:1.0/0003:1D6B:0104.0002/input/input4

[   60.651733] ast :c2:00.0: vgaarb: deactivate vga console
[   60.659978]  4k 16711104 large 0 gb 0 x 
1303[88897000-8880a7ffe000] miss 383488

[   60.669321] ok.
[   60.670497] ast :c2:00.0: [drm] Using default configuration
[   60.677894] ast :c2:00.0: [drm] AST 2600 detected
[   60.683545] ast :c2:00.0: [drm] Using ASPEED DisplayPort transmitter
[   60.685381] hid-generic 0003:1D6B:0104.0002: input,hidraw0: USB HID 
v1.01 Keyboard [OpenBMC virtual_input] on usb-:02:00.4-2.6/input0
[   60.691032] ast :c2:00.0: [drm] dram MCLK=396 Mhz type=1 
bus_width=16
[   60.697172] [drm] Initialized ast 0.1.0 20120228 for :c2:00.0 on 
minor 0

[   60.729565] fbcon: astdrmfb (fb0) is primary device
[   60.729570] fbcon: Deferring console take-over
[   60.741322] ast :c2:00.0: [drm] fb0: astdrmfb frame buffer device
[   60.928226] ast :c2:00.0: vgaarb: deactivate vga console
[   60.940376] input: OpenBMC virtual_input as 
/devices/pci:00/:00:07.1/:02:00.4/usb3/3-2/3-2.6/3-2.6:1.0/0003:1D6B:0104.0002/input/input5

[   60.965436] ast :c2:00.0: [drm] Using default configuration
[   60.972051] ast :c2:00.0: [drm] AST 2600 detected
[   60.977698] ast :c2:00.0: [drm] Using ASPEED DisplayPort transmitter
[   60.985181] ast :c2:00.0: [drm] dram MCLK=396 Mhz type=1 
bus_width=16
[   61.56] [drm] Initialized ast 0.1.0 20120228 for :c2:00.0 on 
minor 0

[   61.013486] fbcon: Deferring console take-over
[   61.016918] hid-generic 0003:1D6B:0104.0002: input,hidraw0: USB HID 
v1.01 Keyboard [OpenBMC virtual_input] on usb-:02:00.4-2.6/input0

[   61.018454] ast :c2:00.0: [drm] fb0: astdrmfb frame buffer device
[   61.040853] input: OpenBMC virtual_input as 
/devices/pci:00/:00:07.1/:02:00.4/usb3/3-2/3-2.6/3-2.6:1.1/0003:1D6B:0104.0004/input/input6
[   61.059112] hid-generic 0003:1D6B:0104.0004: input,hidraw1: USB HID 
v1.01 Mouse [OpenBMC virtual_input] on usb-:02:00.4-2.6/input1
[   61.358397] input: OpenBMC virtual_input as 
/devices/pci:00/:00:07.1/:02:00.4/usb3/3-2/3-2.6/3-2.6:1.1/0003:1D6B:0104.0004/input/input7
[   61.376885] hid-generic 0003:1D6B:0104.0004: input,hidraw1: USB HID 
v1.01 Mouse [OpenBMC virtual_input] on usb-:02:00.4-2.6/input1


This has happened before when drm_kms_helper_poll_init() was added
to an ast connector_init(), see:


The crash was in the detect() callback for that previous case.
This time it crashes when setting the timer, but they still look very 
similar, thanks for pointing this.


commit 595cb5e0b832a3e100cbbdefef797b0c27bf725a
Author: Kim Phillips 
Date:   Thu Oct 21 10:30:06 2021 -0500

     Revert "drm/ast: Add detect function support"

I'm willing to test any proposed changes, esp. if it means
not reverting this commit, too, because that will only likely
lead to yet another BUG instance if/when another poll_init() gets
added in the future.  Should the FIXME described in
reschedule_output_poll_work() be addressed?



This fixme just change the timer interval from 10s to 1s, so it 
shouldn't explain this crash.


Can you test with the attached patch ? I want to see if the detect 
callback is called, and also make sure the delayed_work struct is 
properly initialized.




Thanks,

Kim


Best regards,

--

Jocelyn
From 0a9f2d81af1087ab3648206dfce160639385a6b6 Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe 
Date: Thu, 9 Nov 2023 14:39:22 +0100
Subject: [PATCH] drm/probe-helper: Add debug for AST poll bug

Signed-off-by: Jocelyn Falempe 
---
 drivers/gpu/drm/drm_probe_helper.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index 3f479483d7d8..9aa95791891a 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -753,6 +753,8 @@ static void output_poll_execute(struct work_struct *work)
 	bool repoll = false, changed;
 	u64 old_epoch_counter;
 
+	pr_info("ASTDEBUG poll execute delayed_work %p, drm_dev %p\n", delayed_work, dev);
+
 	if (!dev->mode_config.poll_enabled)
 		return;
 
@@ -910,6 +912,8 @@ void drm_kms_helper_poll_init(struct drm_device *dev)
 	INIT_DELAYED_WORK(>mode_config.output_poll_work, output_poll_execute);
 	dev->mode_config.poll_enabled = true;
 
+	pr_info("ASTDEBUG poll init delayed work %p timer %p drm_dev %p timer flag 0x%0x\n", >mode_config.output_poll_work, >mode_config.output_poll_work.timer, dev, dev->mode_config.output_poll_work.timer.flags);
+
 	drm_kms_helper_poll_enable(dev);
 }
 EXPORT_SYMBOL(drm_kms_helper_poll_init);
-- 
2.41.0



Re: [PATCH] drm/mgag200: Flush the cache to improve latency

2023-11-06 Thread Jocelyn Falempe

On 23/10/2023 10:30, Jocelyn Falempe wrote:

On 20/10/2023 14:06, Thomas Zimmermann wrote:

(cc'ing lkml for feedback)

Hi Jocelyn

Am 19.10.23 um 15:55 schrieb Jocelyn Falempe:

We found a regression in v5.10 on real-time server, using the
rt-kernel and the mgag200 driver. It's some really specialized
workload, with <10us latency expectation on isolated core.
After the v5.10, the real time tasks missed their <10us latency
when something prints on the screen (fbcon or printk)


I'd like to hear the opinion of the RT-devs on this patch. Because 
AFAIK we never did such a workaround in other drivers. And AFAIK 
printk is a PITA anyway.


Most other drivers uses DMA, which means this workaround can't apply to 
them.




IMHO if that RT system cannot handle differences in framebuffer 
caching, it's under-powered. It's just a matter of time until 
something else changes and the problem returns. And (honest question) 
as it's an x86-64, how do they handle System Management Mode?


I think it's not a big news, that the Matrox G200 from 1999 is 
under-powered.
I was also a bit surprised that flushing the cache would have such 
effect on latency. The tests we are doing can run 24h with the 
workaround, without any interrupt taking more than 10us. Without the 
workaround, every ~30s the interrupt failed its 10us target.






The regression has been bisected to 2 commits:
0b34d58b6c32 ("drm/mgag200: Enable caching for SHMEM pages")
4862ffaec523 ("drm/mgag200: Move vmap out of commit tail")

The first one changed the system memory framebuffer from Write-Combine
to the default caching.
Before the second commit, the mgag200 driver used to unmap the
framebuffer after each frame, which implicitly does a cache flush.
Both regressions are fixed by the following patch, which forces a
cache flush after each frame, reverting to almost v5.9 behavior.


With that second commit, we essentially never unmap an active 
framebuffer console. But with commit


359c6649cd9a ("drm/gem: Implement shadow-plane {begin, end}_fb_access 
with vmap")


we now again unmap the console framebuffer after the pageflip happened.

So how does the latest kernel behave wrt to the problem?


The regression was found when upgrading the server from v5.4 to v5.14, 
so we didn't test with later kernels.
We will test with v6.3 (which should have 359c6649cd9a ) and see what it 
gives.


I don't have a clear explanation, but testing with v6.3, and forcing the 
Write Combine, doesn't fix the latency issue. So forcing the cache flush 
is still needed.


Also, on some systems, they use "isolated cpu" to handle RT task, but 
with a standard kernel (so without the CONFIG_PREEMPT_RT).

So I'm wondering if we can use a kernel module parameter for this,
so that users that wants to achieve low latency, can opt-in ?

something like mgag200.force_cache_flush=1 or mgag200.low_latency=1 ?

Best regards,

--

Jocelyn




This is necessary only if you have strong realtime constraints, so I
put the cache flush under the CONFIG_PREEMPT_RT config flag.
Also clflush is only availabe on x86, (and this issue has only been
reproduced on x86_64) so it's also under the CONFIG_X86 config flag.

Fixes: 0b34d58b6c32 ("drm/mgag200: Enable caching for SHMEM pages")
Fixes: 4862ffaec523 ("drm/mgag200: Move vmap out of commit tail")
Signed-off-by: Jocelyn Falempe 
---
  drivers/gpu/drm/mgag200/mgag200_mode.c | 5 +
  1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c 
b/drivers/gpu/drm/mgag200/mgag200_mode.c

index af3ce5a6a636..11660cd29cea 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -13,6 +13,7 @@
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -436,6 +437,10 @@ static void mgag200_handle_damage(struct 
mga_device *mdev, const struct iosys_ma
  iosys_map_incr(, drm_fb_clip_offset(fb->pitches[0], 
fb->format, clip));

  drm_fb_memcpy(, fb->pitches, vmap, fb, clip);
+    /* On RT systems, flushing the cache reduces the latency for 
other RT tasks */

+#if defined(CONFIG_X86) && defined(CONFIG_PREEMPT_RT)
+    drm_clflush_virt_range(vmap, fb->height * fb->pitches[0]);
+#endif


Your second commit is part of a larger patchset that updates several 
drivers. They might all be affected. So if anything, the patch should 
go here before the unmap call:


https://elixir.bootlin.com/linux/v6.5/source/drivers/gpu/drm/drm_gem_atomic_helper.c#L377

The regression was found only with G200 currently, so I don't want to 
apply it blindly on other drivers.


Thanks for your help,

Best regards,





Re: [PATCH] drm/ast: use managed devres functions

2023-11-03 Thread Jocelyn Falempe

On 30/10/2023 10:50, Philipp Stanner wrote:

Currently, tha ast-driver just maps the PCI-dev's regions with
pcim_iomap(). It does not actually reserve the regions exclusively
with, e.g., pci_request_regions().

Replace the calls to pcim_iomap() with ones to pcim_iomap_regions() to
reserve and map the regions simultaneously.

Suggested-by: Thomas Zimmermann 
Signed-off-by: Philipp Stanner 
---
¡Hola!
I picked up the memory-region-request-task from the DRM-TODO-List [1]
and began with this driver.

Please have a first look. I wasn't entirely sure about -ENOMEM... for
example, as far as my understanding goes, it should not be able to fail
anyways in the second call.


Yes, you can remove these checks, other drivers don't do it:
https://elixir.bootlin.com/linux/latest/source/arch/x86/platform/intel-mid/pwr.c#L372



I don't have the server-hardware, thus, can't test it on a physical
machine.


I've done a quick check on an AST2600, and it works.


Please tell me what you think.


That's a good patch, thanks for your contribution.

I'll wait for Thomas review, and with the checks removed, I can help 
push it to drm-misc-next.




P.

[1] 
https://dri.freedesktop.org/docs/drm/gpu/todo.html#request-memory-regions-in-all-drivers
---
  drivers/gpu/drm/ast/ast_main.c | 15 +++
  1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index dae365ed3969..1004c6628938 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -444,9 +444,13 @@ struct ast_device *ast_device_create(const struct 
drm_driver *drv,
if (ret)
return ERR_PTR(ret);
  
-	ast->regs = pcim_iomap(pdev, 1, 0);

+   ret = pcim_iomap_regions(pdev, BIT(1), 0);
+   if (ret)
+   return ERR_PTR(ret);
+
+   ast->regs = pcim_iomap_table(pdev)[1];
if (!ast->regs)
-   return ERR_PTR(-EIO);
+   return ERR_PTR(-ENOMEM);

You can remove this check.


  
  	/*

 * After AST2500, MMIO is enabled by default, and it should be adopted
@@ -461,9 +465,12 @@ struct ast_device *ast_device_create(const struct 
drm_driver *drv,
  
  	/* "map" IO regs if the above hasn't done so already */

if (!ast->ioregs) {
-   ast->ioregs = pcim_iomap(pdev, 2, 0);
+   ret = pcim_iomap_regions(pdev, BIT(2), 0);
+   if (ret)
+   return ERR_PTR(ret);
+   ast->ioregs = pcim_iomap_table(pdev)[2];
if (!ast->ioregs)
-   return ERR_PTR(-EIO);
+   return ERR_PTR(-ENOMEM);

you can remove this check too.

}
  
  	if (!ast_is_vga_enabled(dev)) {


--

Jocelyn



<    1   2   3   4   5   6   >