All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v11 0/9] drm/panic: Add a drm panic handler
@ 2024-03-28 12:03 Jocelyn Falempe
  2024-03-28 12:03 ` [PATCH v11 1/9] drm/panic: Add drm panic locking Jocelyn Falempe
                   ` (9 more replies)
  0 siblings, 10 replies; 17+ messages in thread
From: Jocelyn Falempe @ 2024-03-28 12:03 UTC (permalink / raw)
  To: dri-devel, tzimmermann, airlied, maarten.lankhorst, mripard,
	daniel, javierm, bluescreen_avenger, noralf, sui.jingfeng
  Cc: gpiccoli, 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.

It 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

There were not many comments on v10, so I think we're close to something that can be merged.
Even if this is not yet useful, it will allows to work on more driver support, and
better debug information.

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)

v11:
 * Use macro instead of inline functions for drm_panic_lock/unlock (John Ogness)


Best regards,

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/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                  | 152 ++++++
 include/drm/drm_plane.h                  |   6 +
 17 files changed, 959 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_panic.c
 create mode 100644 include/drm/drm_panic.h


base-commit: 6376eb8b911534735fec104c1a0d780e4cf3116a
-- 
2.44.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v11 1/9] drm/panic: Add drm panic locking
  2024-03-28 12:03 [PATCH v11 0/9] drm/panic: Add a drm panic handler Jocelyn Falempe
@ 2024-03-28 12:03 ` Jocelyn Falempe
  2024-04-02  2:28   ` nerdopolis
  2024-03-28 12:03 ` [PATCH v11 2/9] drm/panic: Add a drm panic handler Jocelyn Falempe
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 17+ messages in thread
From: Jocelyn Falempe @ 2024-03-28 12:03 UTC (permalink / raw)
  To: dri-devel, tzimmermann, airlied, maarten.lankhorst, mripard,
	daniel, javierm, bluescreen_avenger, noralf, sui.jingfeng
  Cc: gpiccoli, Daniel Vetter, Jocelyn Falempe, Andrew Morton,
	Peter Zijlstra (Intel),
	Lukas Wunner, Petr Mladek, Steven Rostedt, John Ogness,
	Sergey Senozhatsky, David Airlie

From: Daniel Vetter <daniel.vetter@ffwll.ch>

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-jfalempe@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)

v11:
- Use macro instead of inline functions for drm_panic_lock/unlock (John Ogness)

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Jocelyn Falempe <jfalempe@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: "Peter Zijlstra (Intel)" <peterz@infradead.org>
Cc: Lukas Wunner <lukas@wunner.de>
Cc: Petr Mladek <pmladek@suse.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: John Ogness <john.ogness@linutronix.de>
Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: David Airlie <airlied@gmail.com>
Cc: Daniel Vetter <daniel@ffwll.ch>
Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
---
 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             | 100 ++++++++++++++++++++++++++++
 4 files changed, 115 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..fb97b51b38f1 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -38,6 +38,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_panic.h>
 #include <drm/drm_print.h>
 #include <drm/drm_self_refresh_helper.h>
 #include <drm/drm_vblank.h>
@@ -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,
 		}
 	}
 
+	drm_panic_lock(state->dev, flags);
 	for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
 		WARN_ON(plane->state != old_plane_state);
 
@@ -3108,6 +3111,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, flags);
 
 	for_each_oldnew_private_obj_in_state(state, obj, old_obj_state, new_obj_state, i) {
 		WARN_ON(obj->state != old_obj_state);
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 243cacb3575c..c157500b3135 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -638,6 +638,7 @@ static int drm_dev_init(struct drm_device *dev,
 	mutex_init(&dev->filelist_mutex);
 	mutex_init(&dev->clientlist_mutex);
 	mutex_init(&dev->master_mutex);
+	raw_spin_lock_init(&dev->mode_config.panic_lock);
 
 	ret = drmm_add_action_or_reset(dev, drm_dev_init_release, NULL);
 	if (ret)
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 973119a9176b..e79f1a557a22 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -505,6 +505,16 @@ struct drm_mode_config {
 	 */
 	struct list_head plane_list;
 
+	/**
+	 * @panic_lock:
+	 *
+	 * Raw spinlock used to protect critical sections of code that access
+	 * the display hardware or modeset software state, which the panic
+	 * printing code must be protected against. See drm_panic_trylock(),
+	 * drm_panic_lock() and drm_panic_unlock().
+	 */
+	struct raw_spinlock panic_lock;
+
 	/**
 	 * @num_crtc:
 	 *
diff --git a/include/drm/drm_panic.h b/include/drm/drm_panic.h
new file mode 100644
index 000000000000..68f57710d2d1
--- /dev/null
+++ b/include/drm/drm_panic.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: GPL-2.0 or MIT */
+#ifndef __DRM_PANIC_H__
+#define __DRM_PANIC_H__
+
+#include <drm/drm_device.h>
+/*
+ * Copyright (c) 2024 Intel
+ */
+
+/**
+ * drm_panic_trylock - try to enter the panic printing critical section
+ * @dev: struct drm_device
+ * @flags: unsigned long irq flags you need to pass to the unlock() counterpart
+ *
+ * This function must be called by any panic printing code. The panic printing
+ * attempt must be aborted if the trylock fails.
+ *
+ * Panic printing code can make the following assumptions while holding the
+ * panic lock:
+ *
+ * - Anything protected by drm_panic_lock() and drm_panic_unlock() pairs is safe
+ *   to access.
+ *
+ * - Furthermore the panic printing code only registers in drm_dev_unregister()
+ *   and gets removed in drm_dev_unregister(). This allows the panic code to
+ *   safely access any state which is invariant in between these two function
+ *   calls, like the list of planes drm_mode_config.plane_list or most of the
+ *   struct drm_plane structure.
+ *
+ * Specifically thanks to the protection around plane updates in
+ * drm_atomic_helper_swap_state() the following additional guarantees hold:
+ *
+ * - It is safe to deference the drm_plane.state pointer.
+ *
+ * - Anything in struct drm_plane_state or the driver's subclass thereof which
+ *   stays invariant after the atomic check code has finished is safe to access.
+ *   Specifically this includes the reference counted pointers to framebuffer
+ *   and buffer objects.
+ *
+ * - Anything set up by drm_plane_helper_funcs.fb_prepare and cleaned up
+ *   drm_plane_helper_funcs.fb_cleanup is safe to access, as long as it stays
+ *   invariant between these two calls. This also means that for drivers using
+ *   dynamic buffer management the framebuffer is pinned, and therefer all
+ *   relevant datastructures can be accessed without taking any further locks
+ *   (which would be impossible in panic context anyway).
+ *
+ * - Importantly, software and hardware state set up by
+ *   drm_plane_helper_funcs.begin_fb_access and
+ *   drm_plane_helper_funcs.end_fb_access is not safe to access.
+ *
+ * Drivers must not make any assumptions about the actual state of the hardware,
+ * unless they explicitly protected these hardware access with drm_panic_lock()
+ * and drm_panic_unlock().
+ *
+ * Returns:
+ *
+ * 0 when failing to acquire the raw spinlock, nonzero on success.
+ */
+#define drm_panic_trylock(dev, flags) \
+	raw_spin_trylock_irqsave(&dev->mode_config.panic_lock, flags)
+
+/**
+ * drm_panic_lock - protect panic printing relevant state
+ * @dev: struct drm_device
+ * @flags: unsigned long irq flags you need to pass to the unlock() counterpart
+ *
+ * This function must be called to protect software and hardware state that the
+ * panic printing code must be able to rely on. The protected sections must be
+ * as small as possible. It uses the irqsave/irqrestore variant, and can be
+ * called from irq handler. Examples include:
+ *
+ * - Access to peek/poke or other similar registers, if that is the way the
+ *   driver prints the pixels into the scanout buffer at panic time.
+ *
+ * - Updates to pointers like drm_plane.state, allowing the panic handler to
+ *   safely deference these. This is done in drm_atomic_helper_swap_state().
+ *
+ * - An state that isn't invariant and that the driver must be able to access
+ *   during panic printing.
+ *
+ * Returns:
+ *
+ * The irqflags needed to call drm_panic_unlock().
+ */
+
+#define drm_panic_lock(dev, flags) \
+	raw_spin_lock_irqsave(&dev->mode_config.panic_lock, flags)
+
+/**
+ * drm_panic_unlock - end of the panic printing critical section
+ * @dev: struct drm_device
+ * @flags: irq flags that were returned when acquiring the lock
+ *
+ * Unlocks the raw spinlock acquired by either drm_panic_lock() or
+ * drm_panic_trylock().
+ */
+#define drm_panic_unlock(dev, flags) \
+	raw_spin_unlock_irqrestore(&dev->mode_config.panic_lock, flags)
+
+#endif /* __DRM_PANIC_H__ */
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v11 2/9] drm/panic: Add a drm panic handler
  2024-03-28 12:03 [PATCH v11 0/9] drm/panic: Add a drm panic handler Jocelyn Falempe
  2024-03-28 12:03 ` [PATCH v11 1/9] drm/panic: Add drm panic locking Jocelyn Falempe
@ 2024-03-28 12:03 ` Jocelyn Falempe
  2024-04-09  8:30   ` Thomas Zimmermann
  2024-03-28 12:03 ` [PATCH v11 3/9] drm/panic: Add support for color format conversion Jocelyn Falempe
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 17+ messages in thread
From: Jocelyn Falempe @ 2024-03-28 12:03 UTC (permalink / raw)
  To: dri-devel, tzimmermann, airlied, maarten.lankhorst, mripard,
	daniel, javierm, bluescreen_avenger, noralf, sui.jingfeng
  Cc: gpiccoli, 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 <jfalempe@redhat.com>
---
 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 +++++++++++++++++++++++
 include/drm/drm_modeset_helper_vtables.h |  37 +++
 include/drm/drm_panic.h                  |  52 ++++
 include/drm/drm_plane.h                  |   6 +
 8 files changed, 423 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 0xffffff
+
+config DRM_PANIC_BACKGROUND_COLOR
+	hex "Drm panic screen background color, in RGB"
+	depends on DRM_PANIC
+	default 0x000000
+
 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_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 c157500b3135..535b624d4c9d 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -43,6 +43,7 @@
 #include <drm/drm_file.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_mode_object.h>
+#include <drm/drm_panic.h>
 #include <drm/drm_print.h>
 #include <drm/drm_privacy_screen_machine.h>
 
@@ -944,6 +945,7 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
 		if (ret)
 			goto err_unload;
 	}
+	drm_panic_register(dev);
 
 	DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
 		 driver->name, driver->major, driver->minor,
@@ -988,6 +990,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))
diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c
new file mode 100644
index 000000000000..72b5b363bcee
--- /dev/null
+++ b/drivers/gpu/drm/drm_panic.c
@@ -0,0 +1,288 @@
+// SPDX-License-Identifier: GPL-2.0 or MIT
+/*
+ * Copyright (c) 2023 Red Hat.
+ * Author: Jocelyn Falempe <jfalempe@redhat.com>
+ * inspired by the drm_log driver from David Herrmann <dh.herrmann@gmail.com>
+ * Tux Ascii art taken from cowsay written by Tony Monroe
+ */
+
+#include <linux/font.h>
+#include <linux/iosys-map.h>
+#include <linux/kdebug.h>
+#include <linux/kmsg_dump.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <drm/drm_drv.h>
+#include <drm/drm_format_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_panic.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_print.h>
+
+
+MODULE_AUTHOR("Jocelyn Falempe");
+MODULE_DESCRIPTION("DRM panic handler");
+MODULE_LICENSE("GPL");
+
+/**
+ * DOC: overview
+ *
+ * To enable DRM panic for a driver, the primary plane must implement a
+ * get_scanout_buffer() helper function. It is then automatically registered to
+ * the drm panic handler.
+ * When a panic occurs, the get_scanout_buffer() will be called, and the driver
+ * can provide a framebuffer so the panic handler can draw the panic screen on
+ * it. The buffer provided must be linear, and use a supported color format.
+ * Optionally the driver can also provide a panic_flush() callback, that will
+ * be called after that, to send additional commands to the hardware to make the
+ * scanout buffer visible.
+ */
+
+/*
+ * This module displays a user friendly message on screen when a kernel panic
+ * occurs. This is conflicting with fbcon, so you can only enable it when fbcon
+ * is disabled.
+ * It's intended for end-user, so have minimal technical/debug information.
+ *
+ * Implementation details:
+ *
+ * It is a panic handler, so it can't take lock, allocate memory, run tasks/irq,
+ * or attempt to sleep. It's a best effort, and it may not be able to display
+ * the message in all situations (like if the panic occurs in the middle of a
+ * modesetting).
+ * It will display only one static frame, so performance optimizations are low
+ * priority as the machine is already in an unusable state.
+ */
+
+struct drm_panic_line {
+	u32 len;
+	const char *txt;
+};
+
+#define PANIC_LINE(s) {.len = sizeof(s) - 1, .txt = s}
+
+static struct drm_panic_line panic_msg[] = {
+	PANIC_LINE("KERNEL PANIC !"),
+	PANIC_LINE(""),
+	PANIC_LINE("Please reboot your computer."),
+};
+
+static const struct drm_panic_line logo[] = {
+	PANIC_LINE("     .--.        _"),
+	PANIC_LINE("    |o_o |      | |"),
+	PANIC_LINE("    |:_/ |      | |"),
+	PANIC_LINE("   //   \\ \\     |_|"),
+	PANIC_LINE("  (|     | )     _"),
+	PANIC_LINE(" /'\\_   _/`\\    (_)"),
+	PANIC_LINE(" \\___)=(___/"),
+};
+
+static void drm_panic_fill32(struct iosys_map *map, unsigned int pitch,
+			     unsigned int height, unsigned int width,
+			     u32 color)
+{
+	unsigned int y, x;
+
+	for (y = 0; y < height; y++)
+		for (x = 0; x < width; x++)
+			iosys_map_wr(map, y * pitch + x * sizeof(u32), u32, color);
+}
+
+static void drm_panic_blit32(struct iosys_map *dmap, unsigned int dpitch,
+			     const u8 *sbuf8, unsigned int spitch,
+			     unsigned int height, unsigned int width,
+			     u32 fg32, u32 bg32)
+{
+	unsigned int y, x;
+	u32 val32;
+
+	for (y = 0; y < height; y++) {
+		for (x = 0; x < width; x++) {
+			val32 = (sbuf8[(y * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg32 : bg32;
+			iosys_map_wr(dmap, y * dpitch + x * sizeof(u32), u32, val32);
+		}
+	}
+}
+
+static const u8 *get_char_bitmap(const struct font_desc *font, char c, size_t font_pitch)
+{
+	return font->data + (c * font->height) * font_pitch;
+}
+
+static unsigned int get_max_line_len(const struct drm_panic_line *lines, int len)
+{
+	int i;
+	unsigned int max = 0;
+
+	for (i = 0; i < len; i++)
+		max = max(lines[i].len, max);
+	return max;
+}
+/*
+ * Draw a text in a rectangle on a framebuffer. The text is truncated if it overflows the rectangle
+ */
+static void draw_txt_rectangle(struct drm_scanout_buffer *sb,
+				const struct font_desc *font,
+				const struct drm_panic_line *msg,
+				unsigned int msg_lines,
+				bool centered,
+				struct drm_rect *clip,
+				u32 fg_color,
+				u32 bg_color)
+{
+	int i, j;
+	const u8 *src;
+	size_t font_pitch = DIV_ROUND_UP(font->width, 8);
+	struct iosys_map dst;
+	unsigned int px_width = sb->format->cpp[0];
+	int left = 0;
+
+	msg_lines = min(msg_lines,  drm_rect_height(clip) / font->height);
+	for (i = 0; i < msg_lines; i++) {
+		size_t line_len = min(msg[i].len, drm_rect_width(clip) / font->width);
+
+		if (centered)
+			left = (drm_rect_width(clip) - (line_len * font->width)) / 2;
+
+		dst = sb->map;
+		iosys_map_incr(&dst, (clip->y1 + i * font->height) * sb->pitch +
+				     (clip->x1 + left) * px_width);
+		for (j = 0; j < line_len; j++) {
+			src = get_char_bitmap(font, msg[i].txt[j], font_pitch);
+			drm_panic_blit32(&dst, sb->pitch, src, font_pitch,
+					 font->height, font->width,
+					 fg_color, bg_color);
+			iosys_map_incr(&dst, font->width * px_width);
+		}
+	}
+}
+
+/*
+ * Draw the panic message at the center of the screen
+ */
+static void draw_panic_static(struct drm_scanout_buffer *sb)
+{
+	size_t msg_lines = ARRAY_SIZE(panic_msg);
+	size_t logo_lines = ARRAY_SIZE(logo);
+	u32 fg_color = CONFIG_DRM_PANIC_FOREGROUND_COLOR;
+	u32 bg_color = CONFIG_DRM_PANIC_BACKGROUND_COLOR;
+	const struct font_desc *font = get_default_font(sb->width, sb->height,
+							0x80808080, 0x80808080);
+	struct drm_rect r_logo, r_msg;
+
+	if (!font)
+		return;
+
+	r_logo = DRM_RECT_INIT(0, 0,
+			       get_max_line_len(logo, logo_lines) * font->width,
+			       logo_lines * font->height);
+	r_msg = DRM_RECT_INIT(0, 0,
+			      min(get_max_line_len(panic_msg, msg_lines) * font->width, sb->width),
+			      min(msg_lines * font->height, sb->height));
+
+	/* Center the panic message */
+	drm_rect_translate(&r_msg, (sb->width - r_msg.x2) / 2, (sb->height - r_msg.y2) / 2);
+
+	/* Fill with the background color, and draw text on top */
+	drm_panic_fill32(&sb->map, sb->pitch, sb->height, sb->width, bg_color);
+
+	if ((r_msg.x1 >= drm_rect_width(&r_logo) || r_msg.y1 >= drm_rect_height(&r_logo)) &&
+	     drm_rect_width(&r_logo) < sb->width && drm_rect_height(&r_logo) < sb->height) {
+		draw_txt_rectangle(sb, font, logo, logo_lines, false, &r_logo, fg_color, bg_color);
+	}
+	draw_txt_rectangle(sb, font, panic_msg, msg_lines, true, &r_msg, fg_color, bg_color);
+}
+
+/*
+ * 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.
+ */
+static bool drm_panic_is_format_supported(u32 format)
+{
+	return format == DRM_FORMAT_XRGB8888;
+}
+
+static void draw_panic_plane(struct drm_plane *plane)
+{
+	struct drm_scanout_buffer sb;
+	int ret;
+	unsigned long flags;
+
+	if (!drm_panic_trylock(plane->dev, flags))
+		return;
+
+	ret = plane->helper_private->get_scanout_buffer(plane, &sb);
+
+	if (!ret && drm_panic_is_format_supported(sb.format->format)) {
+		draw_panic_static(&sb);
+		if (plane->helper_private->panic_flush)
+			plane->helper_private->panic_flush(plane);
+	}
+	drm_panic_unlock(plane->dev, flags);
+}
+
+static struct drm_plane *to_drm_plane(struct kmsg_dumper *kd)
+{
+	return container_of(kd, struct drm_plane, kmsg_panic);
+}
+
+static void drm_panic(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason)
+{
+	struct drm_plane *plane = to_drm_plane(dumper);
+
+	if (reason == KMSG_DUMP_PANIC)
+		draw_panic_plane(plane);
+}
+
+/**
+ * drm_panic_register() - Initialize DRM panic for a device
+ * @dev: the drm device on which the panic screen will be displayed.
+ */
+void drm_panic_register(struct drm_device *dev)
+{
+	struct drm_plane *plane;
+	int registered_plane = 0;
+
+	if (!dev->mode_config.num_total_plane)
+		return;
+
+	drm_for_each_plane(plane, dev) {
+		if (!plane->helper_private || !plane->helper_private->get_scanout_buffer)
+			continue;
+		plane->kmsg_panic.dump = drm_panic;
+		plane->kmsg_panic.max_reason = KMSG_DUMP_PANIC;
+		if (kmsg_dump_register(&plane->kmsg_panic))
+			drm_warn(dev, "Failed to register panic handler\n");
+		else
+			registered_plane++;
+	}
+	if (registered_plane)
+		drm_info(dev, "Registered %d planes with drm panic\n", registered_plane);
+}
+EXPORT_SYMBOL(drm_panic_register);
+
+/**
+ * drm_panic_unregister()
+ * @dev: the drm device previously registered.
+ */
+void drm_panic_unregister(struct drm_device *dev)
+{
+	struct drm_plane *plane;
+
+	if (!dev->mode_config.num_total_plane)
+		return;
+
+	drm_for_each_plane(plane, dev) {
+		if (!plane->helper_private || !plane->helper_private->get_scanout_buffer)
+			continue;
+		kmsg_dump_unregister(&plane->kmsg_panic);
+	}
+}
+EXPORT_SYMBOL(drm_panic_unregister);
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index 881b03e4dc28..bd4752b1ce3f 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -48,6 +48,7 @@
  * To make this clear all the helper vtables are pulled together in this location here.
  */
 
+struct drm_scanout_buffer;
 struct drm_writeback_connector;
 struct drm_writeback_job;
 
@@ -1442,6 +1443,42 @@ struct drm_plane_helper_funcs {
 	 */
 	void (*atomic_async_update)(struct drm_plane *plane,
 				    struct drm_atomic_state *state);
+
+	/**
+	 * @get_scanout_buffer:
+	 *
+	 * Get the current scanout buffer, to display a 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.
+	 * The device dev->mode_config.panic_lock is taken before calling this
+	 * function, so you can safely access the plane->state
+	 * 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.
+	 * The returned scanout_buffer->map must be valid if no error code is
+	 * returned.
+	 *
+	 * Returns:
+	 *
+	 * Zero on success, negative errno on failure.
+	 */
+	int (*get_scanout_buffer)(struct drm_plane *plane,
+				  struct drm_scanout_buffer *sb);
+
+	/**
+	 * @panic_flush:
+	 *
+	 * It is used by drm_panic, and is called after the panic screen is
+	 * drawn to the scanout buffer. In this function, the driver
+	 * can send additional commands to the hardware, to make the scanout
+	 * buffer visible.
+	 * The device dev->mode_config.panic_lock is taken before calling this
+	 * function, so you can safely access the plane->state
+	 * It is called from a panic callback, and must follow its restrictions.
+	 * (no locks, no memory allocation, no sleep, no thread/workqueue, ...)
+	 */
+	void (*panic_flush)(struct drm_plane *plane);
 };
 
 /**
diff --git a/include/drm/drm_panic.h b/include/drm/drm_panic.h
index 68f57710d2d1..450f2a9e7034 100644
--- a/include/drm/drm_panic.h
+++ b/include/drm/drm_panic.h
@@ -2,11 +2,51 @@
 #ifndef __DRM_PANIC_H__
 #define __DRM_PANIC_H__
 
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/iosys-map.h>
+
 #include <drm/drm_device.h>
 /*
  * Copyright (c) 2024 Intel
  */
 
+/**
+ * struct drm_scanout_buffer - DRM scanout buffer
+ *
+ * This structure holds the information necessary for drm_panic to draw the
+ * panic screen, and display it.
+ */
+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;
+};
+
 /**
  * drm_panic_trylock - try to enter the panic printing critical section
  * @dev: struct drm_device
@@ -97,4 +137,16 @@
 #define drm_panic_unlock(dev, flags) \
 	raw_spin_unlock_irqrestore(&dev->mode_config.panic_lock, flags)
 
+#ifdef CONFIG_DRM_PANIC
+
+void drm_panic_register(struct drm_device *dev);
+void drm_panic_unregister(struct drm_device *dev);
+
+#else
+
+static inline void drm_panic_register(struct drm_device *dev) {}
+static inline void drm_panic_unregister(struct drm_device *dev) {}
+
+#endif
+
 #endif /* __DRM_PANIC_H__ */
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 641fe298052d..b9a2fc0a820d 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -25,6 +25,7 @@
 
 #include <linux/list.h>
 #include <linux/ctype.h>
+#include <linux/kmsg_dump.h>
 #include <drm/drm_mode_object.h>
 #include <drm/drm_color_mgmt.h>
 #include <drm/drm_rect.h>
@@ -779,6 +780,11 @@ struct drm_plane {
 	 * @hotspot_y_property: property to set mouse hotspot y offset.
 	 */
 	struct drm_property *hotspot_y_property;
+
+	/**
+	 * @kmsg_panic: Used to register a panic notifier for this plane
+	 */
+	struct kmsg_dumper kmsg_panic;
 };
 
 #define obj_to_plane(x) container_of(x, struct drm_plane, base)
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v11 3/9] drm/panic: Add support for color format conversion
  2024-03-28 12:03 [PATCH v11 0/9] drm/panic: Add a drm panic handler Jocelyn Falempe
  2024-03-28 12:03 ` [PATCH v11 1/9] drm/panic: Add drm panic locking Jocelyn Falempe
  2024-03-28 12:03 ` [PATCH v11 2/9] drm/panic: Add a drm panic handler Jocelyn Falempe
@ 2024-03-28 12:03 ` Jocelyn Falempe
  2024-03-28 12:03 ` [PATCH v11 4/9] drm/panic: Add debugfs entry to test without triggering panic Jocelyn Falempe
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Jocelyn Falempe @ 2024-03-28 12:03 UTC (permalink / raw)
  To: dri-devel, tzimmermann, airlied, maarten.lankhorst, mripard,
	daniel, javierm, bluescreen_avenger, noralf, sui.jingfeng
  Cc: gpiccoli, 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_XRGB8888
DRM_FORMAT_ARGB8888
DRM_FORMAT_XBGR8888
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 <jfalempe@redhat.com>
---
 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 72b5b363bcee..7761779a884b 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_xrgb8888_to_rgb565(u32 pix)
+{
+	return ((pix & 0x00F80000) >> 8) |
+	       ((pix & 0x0000FC00) >> 5) |
+	       ((pix & 0x000000F8) >> 3);
+}
+
+static u16 convert_xrgb8888_to_rgba5551(u32 pix)
+{
+	return ((pix & 0x00f80000) >> 8) |
+	       ((pix & 0x0000f800) >> 5) |
+	       ((pix & 0x000000f8) >> 2) |
+	       BIT(0); /* set alpha bit */
+}
+
+static u16 convert_xrgb8888_to_xrgb1555(u32 pix)
+{
+	return ((pix & 0x00f80000) >> 9) |
+	       ((pix & 0x0000f800) >> 6) |
+	       ((pix & 0x000000f8) >> 3);
+}
+
+static u16 convert_xrgb8888_to_argb1555(u32 pix)
+{
+	return BIT(15) | /* set alpha bit */
+	       ((pix & 0x00f80000) >> 9) |
+	       ((pix & 0x0000f800) >> 6) |
+	       ((pix & 0x000000f8) >> 3);
+}
+
+static u32 convert_xrgb8888_to_argb8888(u32 pix)
+{
+	return pix | GENMASK(31, 24); /* fill alpha bits */
+}
+
+static u32 convert_xrgb8888_to_xbgr8888(u32 pix)
+{
+	return ((pix & 0x00ff0000) >> 16) <<  0 |
+	       ((pix & 0x0000ff00) >>  8) <<  8 |
+	       ((pix & 0x000000ff) >>  0) << 16 |
+	       ((pix & 0xff000000) >> 24) << 24;
+}
+
+static u32 convert_xrgb8888_to_abgr8888(u32 pix)
+{
+	return ((pix & 0x00ff0000) >> 16) <<  0 |
+	       ((pix & 0x0000ff00) >>  8) <<  8 |
+	       ((pix & 0x000000ff) >>  0) << 16 |
+	       GENMASK(31, 24); /* fill alpha bits */
+}
+
+static u32 convert_xrgb8888_to_xrgb2101010(u32 pix)
+{
+	pix = ((pix & 0x000000FF) << 2) |
+	      ((pix & 0x0000FF00) << 4) |
+	      ((pix & 0x00FF0000) << 6);
+	return pix | ((pix >> 8) & 0x00300C03);
+}
+
+static u32 convert_xrgb8888_to_argb2101010(u32 pix)
+{
+	pix = ((pix & 0x000000FF) << 2) |
+	      ((pix & 0x0000FF00) << 4) |
+	      ((pix & 0x00FF0000) << 6);
+	return GENMASK(31, 30) /* set alpha bits */ | pix | ((pix >> 8) & 0x00300C03);
+}
+
+/*
+ * convert_from_xrgb8888 - convert one pixel from xrgb8888 to the desired format
+ * @color: input color, in xrgb8888 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_xrgb8888(u32 color, u32 format)
+{
+	switch (format) {
+	case DRM_FORMAT_RGB565:
+		return convert_xrgb8888_to_rgb565(color);
+	case DRM_FORMAT_RGBA5551:
+		return convert_xrgb8888_to_rgba5551(color);
+	case DRM_FORMAT_XRGB1555:
+		return convert_xrgb8888_to_xrgb1555(color);
+	case DRM_FORMAT_ARGB1555:
+		return convert_xrgb8888_to_argb1555(color);
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_XRGB8888:
+		return color;
+	case DRM_FORMAT_ARGB8888:
+		return convert_xrgb8888_to_argb8888(color);
+	case DRM_FORMAT_XBGR8888:
+		return convert_xrgb8888_to_xbgr8888(color);
+	case DRM_FORMAT_ABGR8888:
+		return convert_xrgb8888_to_abgr8888(color);
+	case DRM_FORMAT_XRGB2101010:
+		return convert_xrgb8888_to_xrgb2101010(color);
+	case DRM_FORMAT_ARGB2101010:
+		return convert_xrgb8888_to_argb2101010(color);
+	default:
+		WARN_ONCE(1, "Can't convert to %p4cc\n", &format);
+		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;
 
-	for (y = 0; y < height; y++)
-		for (x = 0; x < width; x++)
-			iosys_map_wr(map, y * pitch + x * sizeof(u32), u32, color);
+	for (y = 0; y < height; y++) {
+		for (x = 0; x < width; x++) {
+			val16 = (sbuf8[(y * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg16 : bg16;
+			iosys_map_wr(dmap, y * dpitch + x * sizeof(u16), u16, val16);
+		}
+	}
+}
+
+static void drm_panic_blit24(struct iosys_map *dmap, unsigned int dpitch,
+			     const u8 *sbuf8, unsigned int spitch,
+			     unsigned int height, unsigned int width,
+			     u32 fg32, u32 bg32)
+{
+	unsigned int y, x;
+	u32 val32;
+
+	for (y = 0; y < height; y++) {
+		for (x = 0; x < width; x++) {
+			u32 off = y * dpitch + x * 3;
+
+			val32 = (sbuf8[(y * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg32 : bg32;
+
+			/* write blue-green-red to output in little endianness */
+			iosys_map_wr(dmap, off, u8, (val32 & 0x000000FF) >> 0);
+			iosys_map_wr(dmap, off + 1, u8, (val32 & 0x0000FF00) >> 8);
+			iosys_map_wr(dmap, off + 2, u8, (val32 & 0x00FF0000) >> 16);
+		}
+	}
 }
 
 static void drm_panic_blit32(struct iosys_map *dmap, unsigned int dpitch,
@@ -108,6 +248,115 @@ static void drm_panic_blit32(struct iosys_map *dmap, unsigned int dpitch,
 	}
 }
 
+/*
+ * drm_panic_blit - convert a monochrome image to a linear framebuffer
+ * @dmap: destination iosys_map
+ * @dpitch: destination pitch in bytes
+ * @sbuf8: source buffer, in monochrome format, 8 pixels per byte.
+ * @spitch: source pitch in bytes
+ * @height: height of the image to copy, in pixels
+ * @width: width of the image to copy, in pixels
+ * @fg_color: foreground color, in destination format
+ * @bg_color: background color, in destination format
+ * @pixel_width: pixel width in bytes.
+ *
+ * This can be used to draw a font character, which is a monochrome image, to a
+ * framebuffer in other supported format.
+ */
+static void drm_panic_blit(struct iosys_map *dmap, unsigned int dpitch,
+			   const u8 *sbuf8, unsigned int spitch,
+			   unsigned int height, unsigned int width,
+			   u32 fg_color, u32 bg_color,
+			   unsigned int pixel_width)
+{
+	switch (pixel_width) {
+	case 2:
+		drm_panic_blit16(dmap, dpitch, sbuf8, spitch,
+				 height, width, fg_color, bg_color);
+	break;
+	case 3:
+		drm_panic_blit24(dmap, dpitch, sbuf8, spitch,
+				 height, width, fg_color, bg_color);
+	break;
+	case 4:
+		drm_panic_blit32(dmap, dpitch, sbuf8, spitch,
+				 height, width, fg_color, bg_color);
+	break;
+	default:
+		WARN_ONCE(1, "Can't blit with pixel width %d\n", pixel_width);
+	}
+}
+
+static void drm_panic_fill16(struct iosys_map *dmap, unsigned int dpitch,
+			     unsigned int height, unsigned int width,
+			     u16 color)
+{
+	unsigned int y, x;
+
+	for (y = 0; y < height; y++)
+		for (x = 0; x < width; x++)
+			iosys_map_wr(dmap, y * dpitch + x * sizeof(u16), u16, color);
+}
+
+static void drm_panic_fill24(struct iosys_map *dmap, unsigned int dpitch,
+			     unsigned int height, unsigned int width,
+			     u32 color)
+{
+	unsigned int y, x;
+
+	for (y = 0; y < height; y++) {
+		for (x = 0; x < width; x++) {
+			unsigned int off = y * dpitch + x * 3;
+
+			/* write blue-green-red to output in little endianness */
+			iosys_map_wr(dmap, off, u8, (color & 0x000000FF) >> 0);
+			iosys_map_wr(dmap, off + 1, u8, (color & 0x0000FF00) >> 8);
+			iosys_map_wr(dmap, off + 2, u8, (color & 0x00FF0000) >> 16);
+		}
+	}
+}
+
+static void drm_panic_fill32(struct iosys_map *dmap, unsigned int dpitch,
+			     unsigned int height, unsigned int width,
+			     u32 color)
+{
+	unsigned int y, x;
+
+	for (y = 0; y < height; y++)
+		for (x = 0; x < width; x++)
+			iosys_map_wr(dmap, y * dpitch + x * sizeof(u32), u32, color);
+}
+
+/*
+ * drm_panic_fill - Fill a rectangle with a color
+ * @dmap: destination iosys_map, pointing to the top left corner of the rectangle
+ * @dpitch: destination pitch in bytes
+ * @height: height of the rectangle, in pixels
+ * @width: width of the rectangle, in pixels
+ * @color: color to fill the rectangle.
+ * @pixel_width: pixel width in bytes
+ *
+ * Fill a rectangle with a color, in a linear framebuffer.
+ */
+static void drm_panic_fill(struct iosys_map *dmap, unsigned int dpitch,
+			   unsigned int height, unsigned int width,
+			   u32 color, unsigned int pixel_width)
+{
+	switch (pixel_width) {
+	case 2:
+		drm_panic_fill16(dmap, dpitch, height, width, color);
+	break;
+	case 3:
+		drm_panic_fill24(dmap, dpitch, height, width, color);
+	break;
+	case 4:
+		drm_panic_fill32(dmap, dpitch, height, width, color);
+	break;
+	default:
+		WARN_ONCE(1, "Can't fill with pixel width %d\n", pixel_width);
+	}
+}
+
 static const u8 *get_char_bitmap(const struct font_desc *font, char c, size_t font_pitch)
 {
 	return font->data + (c * font->height) * font_pitch;
@@ -153,9 +402,9 @@ static void draw_txt_rectangle(struct drm_scanout_buffer *sb,
 				     (clip->x1 + left) * px_width);
 		for (j = 0; j < line_len; j++) {
 			src = get_char_bitmap(font, msg[i].txt[j], font_pitch);
-			drm_panic_blit32(&dst, sb->pitch, src, font_pitch,
-					 font->height, font->width,
-					 fg_color, bg_color);
+			drm_panic_blit(&dst, sb->pitch, src, font_pitch,
+				       font->height, font->width,
+				       fg_color, bg_color, px_width);
 			iosys_map_incr(&dst, font->width * px_width);
 		}
 	}
@@ -177,6 +426,9 @@ static void draw_panic_static(struct drm_scanout_buffer *sb)
 	if (!font)
 		return;
 
+	fg_color = convert_from_xrgb8888(fg_color, sb->format->format);
+	bg_color = convert_from_xrgb8888(bg_color, sb->format->format);
+
 	r_logo = DRM_RECT_INIT(0, 0,
 			       get_max_line_len(logo, logo_lines) * font->width,
 			       logo_lines * font->height);
@@ -188,7 +440,7 @@ static void draw_panic_static(struct drm_scanout_buffer *sb)
 	drm_rect_translate(&r_msg, (sb->width - r_msg.x2) / 2, (sb->height - r_msg.y2) / 2);
 
 	/* Fill with the background color, and draw text on top */
-	drm_panic_fill32(&sb->map, sb->pitch, sb->height, sb->width, bg_color);
+	drm_panic_fill(&sb->map, sb->pitch, sb->height, sb->width, bg_color, sb->format->cpp[0]);
 
 	if ((r_msg.x1 >= drm_rect_width(&r_logo) || r_msg.y1 >= drm_rect_height(&r_logo)) &&
 	     drm_rect_width(&r_logo) < sb->width && drm_rect_height(&r_logo) < sb->height) {
@@ -206,7 +458,7 @@ static void draw_panic_static(struct drm_scanout_buffer *sb)
  */
 static bool drm_panic_is_format_supported(u32 format)
 {
-	return format == DRM_FORMAT_XRGB8888;
+	return convert_from_xrgb8888(0xffffff, format) != 0;
 }
 
 static void draw_panic_plane(struct drm_plane *plane)
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v11 4/9] drm/panic: Add debugfs entry to test without triggering panic.
  2024-03-28 12:03 [PATCH v11 0/9] drm/panic: Add a drm panic handler Jocelyn Falempe
                   ` (2 preceding siblings ...)
  2024-03-28 12:03 ` [PATCH v11 3/9] drm/panic: Add support for color format conversion Jocelyn Falempe
@ 2024-03-28 12:03 ` Jocelyn Falempe
  2024-03-28 12:03 ` [PATCH v11 5/9] drm/fb_dma: Add generic get_scanout_buffer() for drm_panic Jocelyn Falempe
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Jocelyn Falempe @ 2024-03-28 12:03 UTC (permalink / raw)
  To: dri-devel, tzimmermann, airlied, maarten.lankhorst, mripard,
	daniel, javierm, bluescreen_avenger, noralf, sui.jingfeng
  Cc: gpiccoli, 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 <jfalempe@redhat.com>
---
 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 0x000000
 
+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 7761779a884b..b75e90da7f39 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 <linux/debugfs.h>
+
+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, &run) == 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, &dbg_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(&plane->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


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v11 5/9] drm/fb_dma: Add generic get_scanout_buffer() for drm_panic
  2024-03-28 12:03 [PATCH v11 0/9] drm/panic: Add a drm panic handler Jocelyn Falempe
                   ` (3 preceding siblings ...)
  2024-03-28 12:03 ` [PATCH v11 4/9] drm/panic: Add debugfs entry to test without triggering panic Jocelyn Falempe
@ 2024-03-28 12:03 ` Jocelyn Falempe
  2024-04-09  8:21   ` Thomas Zimmermann
  2024-03-28 12:03 ` [PATCH v11 6/9] drm/simpledrm: Add drm_panic support Jocelyn Falempe
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 17+ messages in thread
From: Jocelyn Falempe @ 2024-03-28 12:03 UTC (permalink / raw)
  To: dri-devel, tzimmermann, airlied, maarten.lankhorst, mripard,
	daniel, javierm, bluescreen_avenger, noralf, sui.jingfeng
  Cc: gpiccoli, 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 <jfalempe@redhat.com>
---
 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 <drm/drm_framebuffer.h>
 #include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_panic.h>
 #include <drm/drm_plane.h>
 #include <linux/dma-mapping.h>
 #include <linux/module.h>
@@ -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(&sb->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


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v11 6/9] drm/simpledrm: Add drm_panic support
  2024-03-28 12:03 [PATCH v11 0/9] drm/panic: Add a drm panic handler Jocelyn Falempe
                   ` (4 preceding siblings ...)
  2024-03-28 12:03 ` [PATCH v11 5/9] drm/fb_dma: Add generic get_scanout_buffer() for drm_panic Jocelyn Falempe
@ 2024-03-28 12:03 ` Jocelyn Falempe
  2024-03-28 12:03 ` [PATCH v11 7/9] drm/mgag200: " Jocelyn Falempe
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Jocelyn Falempe @ 2024-03-28 12:03 UTC (permalink / raw)
  To: dri-devel, tzimmermann, airlied, maarten.lankhorst, mripard,
	daniel, javierm, bluescreen_avenger, noralf, sui.jingfeng
  Cc: gpiccoli, 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 <jfalempe@redhat.com>
---
 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 <drm/drm_gem_shmem_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_panic.h>
 #include <drm/drm_probe_helper.h>
 
 #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


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v11 7/9] drm/mgag200: Add drm_panic support
  2024-03-28 12:03 [PATCH v11 0/9] drm/panic: Add a drm panic handler Jocelyn Falempe
                   ` (5 preceding siblings ...)
  2024-03-28 12:03 ` [PATCH v11 6/9] drm/simpledrm: Add drm_panic support Jocelyn Falempe
@ 2024-03-28 12:03 ` Jocelyn Falempe
  2024-03-28 12:03 ` [PATCH v11 8/9] drm/imx: " Jocelyn Falempe
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Jocelyn Falempe @ 2024-03-28 12:03 UTC (permalink / raw)
  To: dri-devel, tzimmermann, airlied, maarten.lankhorst, mripard,
	daniel, javierm, bluescreen_avenger, noralf, sui.jingfeng
  Cc: gpiccoli, 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 <jfalempe@redhat.com>
---
 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 <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_panic.h>
 #include <drm/drm_print.h>
 
 #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


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v11 8/9] drm/imx: Add drm_panic support
  2024-03-28 12:03 [PATCH v11 0/9] drm/panic: Add a drm panic handler Jocelyn Falempe
                   ` (6 preceding siblings ...)
  2024-03-28 12:03 ` [PATCH v11 7/9] drm/mgag200: " Jocelyn Falempe
@ 2024-03-28 12:03 ` Jocelyn Falempe
  2024-03-28 12:03 ` [PATCH v11 9/9] drm/ast: " Jocelyn Falempe
  2024-04-09  8:33 ` [PATCH v11 0/9] drm/panic: Add a drm panic handler Thomas Zimmermann
  9 siblings, 0 replies; 17+ messages in thread
From: Jocelyn Falempe @ 2024-03-28 12:03 UTC (permalink / raw)
  To: dri-devel, tzimmermann, airlied, maarten.lankhorst, mripard,
	daniel, javierm, bluescreen_avenger, noralf, sui.jingfeng
  Cc: gpiccoli, 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 <jfalempe@redhat.com>
---
 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(&ipu_plane->base, &ipu_plane_helper_funcs);
+	if (type == DRM_PLANE_TYPE_PRIMARY)
+		drm_plane_helper_add(&ipu_plane->base, &ipu_primary_plane_helper_funcs);
+	else
+		drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs);
 
 	if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG)
 		ret = drm_plane_create_zpos_property(&ipu_plane->base, zpos, 0,
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v11 9/9] drm/ast: Add drm_panic support
  2024-03-28 12:03 [PATCH v11 0/9] drm/panic: Add a drm panic handler Jocelyn Falempe
                   ` (7 preceding siblings ...)
  2024-03-28 12:03 ` [PATCH v11 8/9] drm/imx: " Jocelyn Falempe
@ 2024-03-28 12:03 ` Jocelyn Falempe
  2024-04-09  8:33 ` [PATCH v11 0/9] drm/panic: Add a drm panic handler Thomas Zimmermann
  9 siblings, 0 replies; 17+ messages in thread
From: Jocelyn Falempe @ 2024-03-28 12:03 UTC (permalink / raw)
  To: dri-devel, tzimmermann, airlied, maarten.lankhorst, mripard,
	daniel, javierm, bluescreen_avenger, noralf, sui.jingfeng
  Cc: gpiccoli, 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 <jfalempe@redhat.com>
Acked-by: Sui Jingfeng <sui.jingfeng@linux.dev>
Tested-by: Sui Jingfeng <sui.jingfeng@linux.dev>
---
 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 <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_gem_shmem_helper.h>
 #include <drm/drm_managed.h>
+#include <drm/drm_panic.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
 
@@ -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(&sb->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


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH v11 1/9] drm/panic: Add drm panic locking
  2024-03-28 12:03 ` [PATCH v11 1/9] drm/panic: Add drm panic locking Jocelyn Falempe
@ 2024-04-02  2:28   ` nerdopolis
  0 siblings, 0 replies; 17+ messages in thread
From: nerdopolis @ 2024-04-02  2:28 UTC (permalink / raw)
  To: dri-devel, tzimmermann, airlied, maarten.lankhorst, mripard,
	daniel, javierm, noralf, sui.jingfeng, Jocelyn Falempe
  Cc: gpiccoli, Daniel Vetter, Andrew Morton, Peter Zijlstra (Intel),
	Lukas Wunner, Petr Mladek, Steven Rostedt, John Ogness,
	Sergey Senozhatsky

[-- Attachment #1: Type: text/plain, Size: 12107 bytes --]

On Thursday, March 28, 2024 8:03:43 AM EDT Jocelyn Falempe wrote:
> From: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> 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-jfalempe@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)
> 
> v11:
> - Use macro instead of inline functions for drm_panic_lock/unlock (John Ogness)
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Jocelyn Falempe <jfalempe@redhat.com>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: "Peter Zijlstra (Intel)" <peterz@infradead.org>
> Cc: Lukas Wunner <lukas@wunner.de>
> Cc: Petr Mladek <pmladek@suse.com>
> Cc: Steven Rostedt <rostedt@goodmis.org>
> Cc: John Ogness <john.ogness@linutronix.de>
> Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Cc: Maxime Ripard <mripard@kernel.org>
> Cc: Thomas Zimmermann <tzimmermann@suse.de>
> Cc: David Airlie <airlied@gmail.com>
> Cc: Daniel Vetter <daniel@ffwll.ch>
> Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
> ---
>  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             | 100 ++++++++++++++++++++++++++++
>  4 files changed, 115 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..fb97b51b38f1 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -38,6 +38,7 @@
>  #include <drm/drm_drv.h>
>  #include <drm/drm_framebuffer.h>
>  #include <drm/drm_gem_atomic_helper.h>
> +#include <drm/drm_panic.h>
>  #include <drm/drm_print.h>
>  #include <drm/drm_self_refresh_helper.h>
>  #include <drm/drm_vblank.h>
> @@ -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,
>          }
>      }
>  
> +    drm_panic_lock(state->dev, flags);
>      for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
>          WARN_ON(plane->state != old_plane_state);
>  
> @@ -3108,6 +3111,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, flags);
>  
>      for_each_oldnew_private_obj_in_state(state, obj, old_obj_state, new_obj_state, i) {
>          WARN_ON(obj->state != old_obj_state);
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index 243cacb3575c..c157500b3135 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -638,6 +638,7 @@ static int drm_dev_init(struct drm_device *dev,
>      mutex_init(&dev->filelist_mutex);
>      mutex_init(&dev->clientlist_mutex);
>      mutex_init(&dev->master_mutex);
> +    raw_spin_lock_init(&dev->mode_config.panic_lock);
>  
>      ret = drmm_add_action_or_reset(dev, drm_dev_init_release, NULL);
>      if (ret)
> diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
> index 973119a9176b..e79f1a557a22 100644
> --- a/include/drm/drm_mode_config.h
> +++ b/include/drm/drm_mode_config.h
> @@ -505,6 +505,16 @@ struct drm_mode_config {
>      */
>      struct list_head plane_list;
>  
> +    /**
> +    * @panic_lock:
> +    *
> +    * Raw spinlock used to protect critical sections of code that access
> +    * the display hardware or modeset software state, which the panic
> +    * printing code must be protected against. See drm_panic_trylock(),
> +    * drm_panic_lock() and drm_panic_unlock().
> +    */
> +    struct raw_spinlock panic_lock;
> +
>      /**
>      * @num_crtc:
>      *
> diff --git a/include/drm/drm_panic.h b/include/drm/drm_panic.h
> new file mode 100644
> index 000000000000..68f57710d2d1
> --- /dev/null
> +++ b/include/drm/drm_panic.h
> @@ -0,0 +1,100 @@
> +/* SPDX-License-Identifier: GPL-2.0 or MIT */
> +#ifndef __DRM_PANIC_H__
> +#define __DRM_PANIC_H__
> +
> +#include <drm/drm_device.h>
> +/*
> + * Copyright (c) 2024 Intel
> + */
> +
> +/**
> + * drm_panic_trylock - try to enter the panic printing critical section
> + * @dev: struct drm_device
> + * @flags: unsigned long irq flags you need to pass to the unlock() counterpart
> + *
> + * This function must be called by any panic printing code. The panic printing
> + * attempt must be aborted if the trylock fails.
> + *
> + * Panic printing code can make the following assumptions while holding the
> + * panic lock:
> + *
> + * - Anything protected by drm_panic_lock() and drm_panic_unlock() pairs is safe
> + *   to access.
> + *
> + * - Furthermore the panic printing code only registers in drm_dev_unregister()
> + *   and gets removed in drm_dev_unregister(). This allows the panic code to
> + *   safely access any state which is invariant in between these two function
> + *   calls, like the list of planes drm_mode_config.plane_list or most of the
> + *   struct drm_plane structure.
> + *
> + * Specifically thanks to the protection around plane updates in
> + * drm_atomic_helper_swap_state() the following additional guarantees hold:
> + *
> + * - It is safe to deference the drm_plane.state pointer.
> + *
> + * - Anything in struct drm_plane_state or the driver's subclass thereof which
> + *   stays invariant after the atomic check code has finished is safe to access.
> + *   Specifically this includes the reference counted pointers to framebuffer
> + *   and buffer objects.
> + *
> + * - Anything set up by drm_plane_helper_funcs.fb_prepare and cleaned up
> + *   drm_plane_helper_funcs.fb_cleanup is safe to access, as long as it stays
> + *   invariant between these two calls. This also means that for drivers using
> + *   dynamic buffer management the framebuffer is pinned, and therefer all
> + *   relevant datastructures can be accessed without taking any further locks
> + *   (which would be impossible in panic context anyway).
> + *
> + * - Importantly, software and hardware state set up by
> + *   drm_plane_helper_funcs.begin_fb_access and
> + *   drm_plane_helper_funcs.end_fb_access is not safe to access.
> + *
> + * Drivers must not make any assumptions about the actual state of the hardware,
> + * unless they explicitly protected these hardware access with drm_panic_lock()
> + * and drm_panic_unlock().
> + *
> + * Returns:
> + *
> + * 0 when failing to acquire the raw spinlock, nonzero on success.
> + */
> +#define drm_panic_trylock(dev, flags) \
> +    raw_spin_trylock_irqsave(&dev->mode_config.panic_lock, flags)
> +
> +/**
> + * drm_panic_lock - protect panic printing relevant state
> + * @dev: struct drm_device
> + * @flags: unsigned long irq flags you need to pass to the unlock() counterpart
> + *
> + * This function must be called to protect software and hardware state that the
> + * panic printing code must be able to rely on. The protected sections must be
> + * as small as possible. It uses the irqsave/irqrestore variant, and can be
> + * called from irq handler. Examples include:
> + *
> + * - Access to peek/poke or other similar registers, if that is the way the
> + *   driver prints the pixels into the scanout buffer at panic time.
> + *
> + * - Updates to pointers like drm_plane.state, allowing the panic handler to
> + *   safely deference these. This is done in drm_atomic_helper_swap_state().
> + *
> + * - An state that isn't invariant and that the driver must be able to access
> + *   during panic printing.
> + *
> + * Returns:
> + *
> + * The irqflags needed to call drm_panic_unlock().
> + */
> +
> +#define drm_panic_lock(dev, flags) \
> +    raw_spin_lock_irqsave(&dev->mode_config.panic_lock, flags)
> +
> +/**
> + * drm_panic_unlock - end of the panic printing critical section
> + * @dev: struct drm_device
> + * @flags: irq flags that were returned when acquiring the lock
> + *
> + * Unlocks the raw spinlock acquired by either drm_panic_lock() or
> + * drm_panic_trylock().
> + */
> +#define drm_panic_unlock(dev, flags) \
> +    raw_spin_unlock_irqrestore(&dev->mode_config.panic_lock, flags)
> +
> +#endif /* __DRM_PANIC_H__ */
> 


I can't offer much feedback, except that I have tested this in QEMU with SimpleDRM and it works great
 
Thanks!

[-- Attachment #2: Type: text/html, Size: 34318 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v11 5/9] drm/fb_dma: Add generic get_scanout_buffer() for drm_panic
  2024-03-28 12:03 ` [PATCH v11 5/9] drm/fb_dma: Add generic get_scanout_buffer() for drm_panic Jocelyn Falempe
@ 2024-04-09  8:21   ` Thomas Zimmermann
  2024-04-09 14:13     ` Jocelyn Falempe
  0 siblings, 1 reply; 17+ messages in thread
From: Thomas Zimmermann @ 2024-04-09  8:21 UTC (permalink / raw)
  To: Jocelyn Falempe, dri-devel, airlied, maarten.lankhorst, mripard,
	daniel, javierm, bluescreen_avenger, noralf, sui.jingfeng
  Cc: gpiccoli

Hi

Am 28.03.24 um 13:03 schrieb 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 <jfalempe@redhat.com>
> ---
>   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 <drm/drm_framebuffer.h>
>   #include <drm/drm_gem_dma_helper.h>
>   #include <drm/drm_gem_framebuffer_helper.h>
> +#include <drm/drm_panic.h>
>   #include <drm/drm_plane.h>
>   #include <linux/dma-mapping.h>
>   #include <linux/module.h>
> @@ -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)

I would not bother with CONFIG_DRM_PANIC for now and make the helper 
generally available.

> +/**
> + * @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)

It's neither really a function for panic handling nor a GEM function. 
This helper needs to be called drm_fb_dma_get_scanout_buffer() IMHO.

> +{
> +	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(&sb->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
>   

-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v11 2/9] drm/panic: Add a drm panic handler
  2024-03-28 12:03 ` [PATCH v11 2/9] drm/panic: Add a drm panic handler Jocelyn Falempe
@ 2024-04-09  8:30   ` Thomas Zimmermann
  2024-04-09 14:11     ` Jocelyn Falempe
  0 siblings, 1 reply; 17+ messages in thread
From: Thomas Zimmermann @ 2024-04-09  8:30 UTC (permalink / raw)
  To: Jocelyn Falempe, dri-devel, airlied, maarten.lankhorst, mripard,
	daniel, javierm, bluescreen_avenger, noralf, sui.jingfeng
  Cc: gpiccoli

Hi

Am 28.03.24 um 13:03 schrieb Jocelyn Falempe:
> +/**
> + * struct drm_scanout_buffer - DRM scanout buffer
> + *
> + * This structure holds the information necessary for drm_panic to draw the
> + * panic screen, and display it.
> + */
> +struct drm_scanout_buffer {
> +	/**
> +	 * @format:
> +	 *
> +	 * drm format of the scanout buffer.
> +	 */
> +	const struct drm_format_info *format;

Newline here and among the other fields please.

> +	/**
> +	 * @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;

I would make this an array of DRM_FORMAT_MAX_PLANES. Its functionality 
is then equivalent to the fields in struct drm_framebuffer. Supporting 
multiple color planes is the general expectation in the DRM code, even 
if not all parts actually implement it. In the panic code, you simply 
test that the scan-out format has only a single plane.

   struct iosys_map map[DRM_FORMAT_MAX_PLANES]


> +	/**
> +	 * @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;

Also use an array of DRM_FORMAT_MAX_PLANES.

> +};

This data structure looks like something I could use for the 
shadow-plane helpers. Expect it to be moved elsewhere at some point.

Best regards
Thomas


-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v11 0/9] drm/panic: Add a drm panic handler
  2024-03-28 12:03 [PATCH v11 0/9] drm/panic: Add a drm panic handler Jocelyn Falempe
                   ` (8 preceding siblings ...)
  2024-03-28 12:03 ` [PATCH v11 9/9] drm/ast: " Jocelyn Falempe
@ 2024-04-09  8:33 ` Thomas Zimmermann
  9 siblings, 0 replies; 17+ messages in thread
From: Thomas Zimmermann @ 2024-04-09  8:33 UTC (permalink / raw)
  To: Jocelyn Falempe, dri-devel, airlied, maarten.lankhorst, mripard,
	daniel, javierm, bluescreen_avenger, noralf, sui.jingfeng
  Cc: gpiccoli

Hi,

for patches 6, 7, and 9

Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>

Best regards
Thomas

Am 28.03.24 um 13:03 schrieb 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.
>
> It 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
>
> There were not many comments on v10, so I think we're close to something that can be merged.
> Even if this is not yet useful, it will allows to work on more driver support, and
> better debug information.
>
> 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)
>
> v11:
>   * Use macro instead of inline functions for drm_panic_lock/unlock (John Ogness)
>
>
> Best regards,
>
> 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/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                  | 152 ++++++
>   include/drm/drm_plane.h                  |   6 +
>   17 files changed, 959 insertions(+), 2 deletions(-)
>   create mode 100644 drivers/gpu/drm/drm_panic.c
>   create mode 100644 include/drm/drm_panic.h
>
>
> base-commit: 6376eb8b911534735fec104c1a0d780e4cf3116a

-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v11 2/9] drm/panic: Add a drm panic handler
  2024-04-09  8:30   ` Thomas Zimmermann
@ 2024-04-09 14:11     ` Jocelyn Falempe
  2024-04-10  8:13       ` Thomas Zimmermann
  0 siblings, 1 reply; 17+ messages in thread
From: Jocelyn Falempe @ 2024-04-09 14:11 UTC (permalink / raw)
  To: Thomas Zimmermann, dri-devel, airlied, maarten.lankhorst,
	mripard, daniel, javierm, bluescreen_avenger, noralf,
	sui.jingfeng
  Cc: gpiccoli

Hi,

On 09/04/2024 10:30, Thomas Zimmermann wrote:
> Hi
> 
> Am 28.03.24 um 13:03 schrieb Jocelyn Falempe:
>> +/**
>> + * struct drm_scanout_buffer - DRM scanout buffer
>> + *
>> + * This structure holds the information necessary for drm_panic to 
>> draw the
>> + * panic screen, and display it.
>> + */
>> +struct drm_scanout_buffer {
>> +    /**
>> +     * @format:
>> +     *
>> +     * drm format of the scanout buffer.
>> +     */
>> +    const struct drm_format_info *format;
> 
> Newline here and among the other fields please.

Done in v12.
> 
>> +    /**
>> +     * @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;
> 
> I would make this an array of DRM_FORMAT_MAX_PLANES. Its functionality 
> is then equivalent to the fields in struct drm_framebuffer. Supporting 
> multiple color planes is the general expectation in the DRM code, even 
> if not all parts actually implement it. In the panic code, you simply 
> test that the scan-out format has only a single plane.
> 
>    struct iosys_map map[DRM_FORMAT_MAX_PLANES]
> 
Sure, that was on my todo list, done in v12.
> 
>> +    /**
>> +     * @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;
> 
> Also use an array of DRM_FORMAT_MAX_PLANES.
> 
>> +};
> 
> This data structure looks like something I could use for the 
> shadow-plane helpers. Expect it to be moved elsewhere at some point.

Yes, this can even be part of the struct drm_framebuffer.
> 
> Best regards
> Thomas
> 
> 

Thanks for the reviews,

-- 

Jocelyn


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v11 5/9] drm/fb_dma: Add generic get_scanout_buffer() for drm_panic
  2024-04-09  8:21   ` Thomas Zimmermann
@ 2024-04-09 14:13     ` Jocelyn Falempe
  0 siblings, 0 replies; 17+ messages in thread
From: Jocelyn Falempe @ 2024-04-09 14:13 UTC (permalink / raw)
  To: Thomas Zimmermann, dri-devel, airlied, maarten.lankhorst,
	mripard, daniel, javierm, bluescreen_avenger, noralf,
	sui.jingfeng
  Cc: gpiccoli



On 09/04/2024 10:21, Thomas Zimmermann wrote:
> Hi
> 
> Am 28.03.24 um 13:03 schrieb 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 <jfalempe@redhat.com>
>> ---
>>   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 <drm/drm_framebuffer.h>
>>   #include <drm/drm_gem_dma_helper.h>
>>   #include <drm/drm_gem_framebuffer_helper.h>
>> +#include <drm/drm_panic.h>
>>   #include <drm/drm_plane.h>
>>   #include <linux/dma-mapping.h>
>>   #include <linux/module.h>
>> @@ -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)
> 
> I would not bother with CONFIG_DRM_PANIC for now and make the helper 
> generally available.

yes, that's a small function, let's keep it simple.
Done in v12
> 
>> +/**
>> + * @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)
> 
> It's neither really a function for panic handling nor a GEM function. 
> This helper needs to be called drm_fb_dma_get_scanout_buffer() IMHO.
> 
I agree, it matches the other functions prefixes in this file.
Done in v12

>> +{
>> +    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(&sb->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
> 

Thanks for the reviews,

-- 

Jocelyn


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v11 2/9] drm/panic: Add a drm panic handler
  2024-04-09 14:11     ` Jocelyn Falempe
@ 2024-04-10  8:13       ` Thomas Zimmermann
  0 siblings, 0 replies; 17+ messages in thread
From: Thomas Zimmermann @ 2024-04-10  8:13 UTC (permalink / raw)
  To: Jocelyn Falempe, dri-devel, airlied, maarten.lankhorst, mripard,
	daniel, javierm, bluescreen_avenger, noralf, sui.jingfeng
  Cc: gpiccoli

Hi

Am 09.04.24 um 16:11 schrieb Jocelyn Falempe:
> Hi,
>
> On 09/04/2024 10:30, Thomas Zimmermann wrote:
>> Hi
>>
>> Am 28.03.24 um 13:03 schrieb Jocelyn Falempe:
>>> +/**
>>> + * struct drm_scanout_buffer - DRM scanout buffer
>>> + *
>>> + * This structure holds the information necessary for drm_panic to 
>>> draw the
>>> + * panic screen, and display it.
>>> + */
>>> +struct drm_scanout_buffer {
>>> +    /**
>>> +     * @format:
>>> +     *
>>> +     * drm format of the scanout buffer.
>>> +     */
>>> +    const struct drm_format_info *format;
>>
>> Newline here and among the other fields please.
>
> Done in v12.
>>
>>> +    /**
>>> +     * @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;
>>
>> I would make this an array of DRM_FORMAT_MAX_PLANES. Its 
>> functionality is then equivalent to the fields in struct 
>> drm_framebuffer. Supporting multiple color planes is the general 
>> expectation in the DRM code, even if not all parts actually implement 
>> it. In the panic code, you simply test that the scan-out format has 
>> only a single plane.
>>
>>    struct iosys_map map[DRM_FORMAT_MAX_PLANES]
>>
> Sure, that was on my todo list, done in v12.
>>
>>> +    /**
>>> +     * @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;
>>
>> Also use an array of DRM_FORMAT_MAX_PLANES.
>>
>>> +};
>>
>> This data structure looks like something I could use for the 
>> shadow-plane helpers. Expect it to be moved elsewhere at some point.
>
> Yes, this can even be part of the struct drm_framebuffer.

Please not. These are two separate things (even though they look very 
similar).

Best regards
Thomas

>>
>> Best regards
>> Thomas
>>
>>
>
> Thanks for the reviews,
>

-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2024-04-10  8:13 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-28 12:03 [PATCH v11 0/9] drm/panic: Add a drm panic handler Jocelyn Falempe
2024-03-28 12:03 ` [PATCH v11 1/9] drm/panic: Add drm panic locking Jocelyn Falempe
2024-04-02  2:28   ` nerdopolis
2024-03-28 12:03 ` [PATCH v11 2/9] drm/panic: Add a drm panic handler Jocelyn Falempe
2024-04-09  8:30   ` Thomas Zimmermann
2024-04-09 14:11     ` Jocelyn Falempe
2024-04-10  8:13       ` Thomas Zimmermann
2024-03-28 12:03 ` [PATCH v11 3/9] drm/panic: Add support for color format conversion Jocelyn Falempe
2024-03-28 12:03 ` [PATCH v11 4/9] drm/panic: Add debugfs entry to test without triggering panic Jocelyn Falempe
2024-03-28 12:03 ` [PATCH v11 5/9] drm/fb_dma: Add generic get_scanout_buffer() for drm_panic Jocelyn Falempe
2024-04-09  8:21   ` Thomas Zimmermann
2024-04-09 14:13     ` Jocelyn Falempe
2024-03-28 12:03 ` [PATCH v11 6/9] drm/simpledrm: Add drm_panic support Jocelyn Falempe
2024-03-28 12:03 ` [PATCH v11 7/9] drm/mgag200: " Jocelyn Falempe
2024-03-28 12:03 ` [PATCH v11 8/9] drm/imx: " Jocelyn Falempe
2024-03-28 12:03 ` [PATCH v11 9/9] drm/ast: " Jocelyn Falempe
2024-04-09  8:33 ` [PATCH v11 0/9] drm/panic: Add a drm panic handler Thomas Zimmermann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.