.../amd/display/amdgpu_dm/amdgpu_dm_plane.c | 137 +++++++++++++++++- .../amd/display/dc/hubp/dcn30/dcn30_hubp.c | 17 +++ .../amd/display/dc/hubp/dcn30/dcn30_hubp.h | 2 + drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h | 1 + 4 files changed, 155 insertions(+), 2 deletions(-)
Add support for the drm_panic module, which displays a pretty user
friendly message on the screen when a Linux kernel panic occurs.
It should work on all readeon using amdgpu_dm_plane.c, when the
framebuffer is linear (like when in a VT). For tiled framebuffer, it
will only work on radeon with dcn30. It should be easy to add support
for dcn20 or dcn31, but I can't test it.
I've tested it on a Radeon W6400 pro.
Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
---
.../amd/display/amdgpu_dm/amdgpu_dm_plane.c | 137 +++++++++++++++++-
.../amd/display/dc/hubp/dcn30/dcn30_hubp.c | 17 +++
.../amd/display/dc/hubp/dcn30/dcn30_hubp.h | 2 +
drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h | 1 +
4 files changed, 155 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index 25f63b2e7a8e2..a62b197ab6833 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -26,7 +26,9 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_blend.h>
+#include "drm/drm_framebuffer.h"
#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_panic.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_fourcc.h>
@@ -36,6 +38,7 @@
#include "amdgpu_display.h"
#include "amdgpu_dm_trace.h"
#include "amdgpu_dm_plane.h"
+#include "bif/bif_4_1_d.h"
#include "gc/gc_11_0_0_offset.h"
#include "gc/gc_11_0_0_sh_mask.h"
@@ -1420,6 +1423,125 @@ static void amdgpu_dm_plane_atomic_async_update(struct drm_plane *plane,
amdgpu_dm_plane_handle_cursor_update(plane, old_state);
}
+/* panic_bo is set in amdgpu_dm_plane_get_scanout_buffer() and only used in amdgpu_dm_set_pixel()
+ * they are called from the panic handler, and no race condition can occurs.
+ */
+static struct amdgpu_bo *panic_abo;
+
+/* Use the indirect MMIO to write each pixel to the GPU VRAM,
+ * This is a simplified version of amdgpu_device_mm_access()
+ */
+static void amdgpu_dm_set_pixel(struct drm_scanout_buffer *sb,
+ unsigned int x,
+ unsigned int y,
+ u32 color)
+{
+ struct amdgpu_res_cursor cursor;
+ unsigned long offset;
+ struct amdgpu_bo *abo = panic_abo;
+ struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev);
+ uint32_t tmp;
+
+ offset = x * 4 + y * sb->pitch[0];
+ amdgpu_res_first(abo->tbo.resource, offset, 4, &cursor);
+
+ tmp = cursor.start >> 31;
+ WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t) cursor.start) | 0x80000000);
+ if (tmp != 0xffffffff)
+ WREG32_NO_KIQ(mmMM_INDEX_HI, tmp);
+ WREG32_NO_KIQ(mmMM_DATA, color);
+}
+
+static int amdgpu_dm_plane_disable_tiling(struct dc_plane_state *dc_plane_state)
+{
+ struct dc_state *dc_state;
+ int i;
+
+ if (!dc_plane_state)
+ return -EINVAL;
+
+ dc_state = dc_plane_state->ctx->dc->current_state;
+ if (!dc_state)
+ return -EINVAL;
+
+ for (i = 0; i < dc_plane_state->ctx->dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx = &dc_state->res_ctx.pipe_ctx[i];
+ struct hubp *hubp;
+
+ if (!pipe_ctx)
+ continue;
+
+ hubp = pipe_ctx->plane_res.hubp;
+ if (!hubp)
+ continue;
+
+ if (!hubp->funcs->hubp_clear_tiling)
+ return -EINVAL;
+
+ hubp->funcs->hubp_clear_tiling(hubp);
+ hubp->funcs->hubp_program_surface_flip_and_addr(hubp,
+ &dc_plane_state->address,
+ dc_plane_state->flip_immediate);
+ }
+ return 0;
+}
+
+static int amdgpu_dm_plane_get_scanout_buffer(struct drm_plane *plane,
+ struct drm_scanout_buffer *sb)
+{
+ struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane->state);
+ struct amdgpu_bo *abo;
+ struct drm_framebuffer *fb = plane->state->fb;
+
+ if (!fb)
+ return -EINVAL;
+
+ DRM_DEBUG_KMS("Framebuffer %dx%d %p4cc\n", fb->width, fb->height, &fb->format->format);
+
+ abo = gem_to_amdgpu_bo(fb->obj[0]);
+ if (!abo)
+ return -EINVAL;
+
+ /* disable tiling */
+ if (fb->modifier && amdgpu_dm_plane_disable_tiling(dm_plane_state->dc_state))
+ return -EINVAL;
+
+ sb->width = fb->width;
+ sb->height = fb->height;
+ /* Use the generic linear format, because we just disabled tiling */
+ sb->format = drm_format_info(fb->format->format);
+ if (!sb->format)
+ return -EINVAL;
+
+ sb->pitch[0] = fb->pitches[0];
+
+ if (abo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) {
+ if (abo->tbo.resource->mem_type != TTM_PL_VRAM) {
+ DRM_WARN("amdgpu panic, framebuffer not in VRAM\n");
+ return -EINVAL;
+ }
+ /* Only handle 32bits format, to simplify mmio access */
+ if (fb->format->cpp[0] != 4) {
+ DRM_WARN("amdgpu panic, pixel format is not 32bits\n");
+ return -EINVAL;
+ }
+ sb->set_pixel = amdgpu_dm_set_pixel;
+ panic_abo = abo;
+ return 0;
+ }
+ if (!abo->kmap.virtual &&
+ ttm_bo_kmap(&abo->tbo, 0, PFN_UP(abo->tbo.base.size), &abo->kmap)) {
+ DRM_WARN("amdgpu bo map failed, panic won't be displayed\n");
+ return -ENOMEM;
+ }
+ if (abo->kmap.bo_kmap_type & TTM_BO_MAP_IOMEM_MASK)
+ iosys_map_set_vaddr_iomem(&sb->map[0], abo->kmap.virtual);
+ else
+ iosys_map_set_vaddr(&sb->map[0], abo->kmap.virtual);
+
+ return 0;
+}
+
static const struct drm_plane_helper_funcs dm_plane_helper_funcs = {
.prepare_fb = amdgpu_dm_plane_helper_prepare_fb,
.cleanup_fb = amdgpu_dm_plane_helper_cleanup_fb,
@@ -1428,6 +1550,15 @@ static const struct drm_plane_helper_funcs dm_plane_helper_funcs = {
.atomic_async_update = amdgpu_dm_plane_atomic_async_update
};
+static const struct drm_plane_helper_funcs dm_primary_plane_helper_funcs = {
+ .prepare_fb = amdgpu_dm_plane_helper_prepare_fb,
+ .cleanup_fb = amdgpu_dm_plane_helper_cleanup_fb,
+ .atomic_check = amdgpu_dm_plane_atomic_check,
+ .atomic_async_check = amdgpu_dm_plane_atomic_async_check,
+ .atomic_async_update = amdgpu_dm_plane_atomic_async_update,
+ .get_scanout_buffer = amdgpu_dm_plane_get_scanout_buffer,
+};
+
static void amdgpu_dm_plane_drm_plane_reset(struct drm_plane *plane)
{
struct dm_plane_state *amdgpu_state = NULL;
@@ -1854,7 +1985,10 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
plane->type != DRM_PLANE_TYPE_CURSOR)
drm_plane_enable_fb_damage_clips(plane);
- drm_plane_helper_add(plane, &dm_plane_helper_funcs);
+ if (plane->type == DRM_PLANE_TYPE_PRIMARY)
+ drm_plane_helper_add(plane, &dm_primary_plane_helper_funcs);
+ else
+ drm_plane_helper_add(plane, &dm_plane_helper_funcs);
#ifdef AMD_PRIVATE_COLOR
dm_atomic_plane_attach_color_mgmt_properties(dm, plane);
@@ -1876,4 +2010,3 @@ bool amdgpu_dm_plane_is_video_format(uint32_t format)
return false;
}
-
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c
index 60a64d2903527..3b16c3cda2c3e 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c
@@ -334,6 +334,22 @@ void hubp3_program_tiling(
}
+void hubp3_clear_tiling(struct hubp *hubp)
+{
+ struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+ REG_UPDATE(DCHUBP_REQ_SIZE_CONFIG, SWATH_HEIGHT, 0);
+ REG_UPDATE(DCSURF_TILING_CONFIG, SW_MODE, DC_SW_LINEAR);
+
+ REG_UPDATE_6(DCSURF_SURFACE_CONTROL,
+ PRIMARY_SURFACE_DCC_EN, 0,
+ PRIMARY_SURFACE_DCC_IND_BLK, 0,
+ PRIMARY_SURFACE_DCC_IND_BLK_C, 0,
+ SECONDARY_SURFACE_DCC_EN, 0,
+ SECONDARY_SURFACE_DCC_IND_BLK, 0,
+ SECONDARY_SURFACE_DCC_IND_BLK_C, 0);
+}
+
void hubp3_dcc_control(struct hubp *hubp, bool enable,
enum hubp_ind_block_size blk_size)
{
@@ -512,6 +528,7 @@ static struct hubp_funcs dcn30_hubp_funcs = {
.hubp_in_blank = hubp1_in_blank,
.hubp_soft_reset = hubp1_soft_reset,
.hubp_set_flip_int = hubp1_set_flip_int,
+ .hubp_clear_tiling = hubp3_clear_tiling,
};
bool hubp3_construct(
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.h
index b010531a7fe88..cfb01bf340a1a 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.h
@@ -297,6 +297,8 @@ void hubp3_read_state(struct hubp *hubp);
void hubp3_init(struct hubp *hubp);
+void hubp3_clear_tiling(struct hubp *hubp);
+
#endif /* __DC_HUBP_DCN30_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
index 16580d6242789..d0878fc0cc948 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
@@ -275,6 +275,7 @@ struct hubp_funcs {
enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cb_b,
enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cr_r);
int (*hubp_get_3dlut_fl_done)(struct hubp *hubp);
+ void (*hubp_clear_tiling)(struct hubp *hubp);
};
#endif
base-commit: a5c2320151ff7cdf9ec50630d638a417ff927e31
--
2.46.1
On Fri, Oct 4, 2024 at 5:09 AM Jocelyn Falempe <jfalempe@redhat.com> wrote: > > Add support for the drm_panic module, which displays a pretty user > friendly message on the screen when a Linux kernel panic occurs. > > It should work on all readeon using amdgpu_dm_plane.c, when the radeon > framebuffer is linear (like when in a VT). For tiled framebuffer, it > will only work on radeon with dcn30. It should be easy to add support > for dcn20 or dcn31, but I can't test it. > I've tested it on a Radeon W6400 pro. Looks good to me. @Wentland, Harry, @Siqueira, Rodrigo, etc, does this look ok to you guys? If so, can you pick it up and look at adding the callbacks for other DCN versions? Thanks, Alex > > Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com> > --- > .../amd/display/amdgpu_dm/amdgpu_dm_plane.c | 137 +++++++++++++++++- > .../amd/display/dc/hubp/dcn30/dcn30_hubp.c | 17 +++ > .../amd/display/dc/hubp/dcn30/dcn30_hubp.h | 2 + > drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h | 1 + > 4 files changed, 155 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c > index 25f63b2e7a8e2..a62b197ab6833 100644 > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c > @@ -26,7 +26,9 @@ > > #include <drm/drm_atomic_helper.h> > #include <drm/drm_blend.h> > +#include "drm/drm_framebuffer.h" > #include <drm/drm_gem_atomic_helper.h> > +#include <drm/drm_panic.h> > #include <drm/drm_plane_helper.h> > #include <drm/drm_gem_framebuffer_helper.h> > #include <drm/drm_fourcc.h> > @@ -36,6 +38,7 @@ > #include "amdgpu_display.h" > #include "amdgpu_dm_trace.h" > #include "amdgpu_dm_plane.h" > +#include "bif/bif_4_1_d.h" > #include "gc/gc_11_0_0_offset.h" > #include "gc/gc_11_0_0_sh_mask.h" > > @@ -1420,6 +1423,125 @@ static void amdgpu_dm_plane_atomic_async_update(struct drm_plane *plane, > amdgpu_dm_plane_handle_cursor_update(plane, old_state); > } > > +/* panic_bo is set in amdgpu_dm_plane_get_scanout_buffer() and only used in amdgpu_dm_set_pixel() > + * they are called from the panic handler, and no race condition can occurs. > + */ > +static struct amdgpu_bo *panic_abo; > + > +/* Use the indirect MMIO to write each pixel to the GPU VRAM, > + * This is a simplified version of amdgpu_device_mm_access() > + */ > +static void amdgpu_dm_set_pixel(struct drm_scanout_buffer *sb, > + unsigned int x, > + unsigned int y, > + u32 color) > +{ > + struct amdgpu_res_cursor cursor; > + unsigned long offset; > + struct amdgpu_bo *abo = panic_abo; > + struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev); > + uint32_t tmp; > + > + offset = x * 4 + y * sb->pitch[0]; > + amdgpu_res_first(abo->tbo.resource, offset, 4, &cursor); > + > + tmp = cursor.start >> 31; > + WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t) cursor.start) | 0x80000000); > + if (tmp != 0xffffffff) > + WREG32_NO_KIQ(mmMM_INDEX_HI, tmp); > + WREG32_NO_KIQ(mmMM_DATA, color); > +} > + > +static int amdgpu_dm_plane_disable_tiling(struct dc_plane_state *dc_plane_state) > +{ > + struct dc_state *dc_state; > + int i; > + > + if (!dc_plane_state) > + return -EINVAL; > + > + dc_state = dc_plane_state->ctx->dc->current_state; > + if (!dc_state) > + return -EINVAL; > + > + for (i = 0; i < dc_plane_state->ctx->dc->res_pool->pipe_count; i++) { > + struct pipe_ctx *pipe_ctx = &dc_state->res_ctx.pipe_ctx[i]; > + struct hubp *hubp; > + > + if (!pipe_ctx) > + continue; > + > + hubp = pipe_ctx->plane_res.hubp; > + if (!hubp) > + continue; > + > + if (!hubp->funcs->hubp_clear_tiling) > + return -EINVAL; > + > + hubp->funcs->hubp_clear_tiling(hubp); > + hubp->funcs->hubp_program_surface_flip_and_addr(hubp, > + &dc_plane_state->address, > + dc_plane_state->flip_immediate); > + } > + return 0; > +} > + > +static int amdgpu_dm_plane_get_scanout_buffer(struct drm_plane *plane, > + struct drm_scanout_buffer *sb) > +{ > + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane->state); > + struct amdgpu_bo *abo; > + struct drm_framebuffer *fb = plane->state->fb; > + > + if (!fb) > + return -EINVAL; > + > + DRM_DEBUG_KMS("Framebuffer %dx%d %p4cc\n", fb->width, fb->height, &fb->format->format); > + > + abo = gem_to_amdgpu_bo(fb->obj[0]); > + if (!abo) > + return -EINVAL; > + > + /* disable tiling */ > + if (fb->modifier && amdgpu_dm_plane_disable_tiling(dm_plane_state->dc_state)) > + return -EINVAL; > + > + sb->width = fb->width; > + sb->height = fb->height; > + /* Use the generic linear format, because we just disabled tiling */ > + sb->format = drm_format_info(fb->format->format); > + if (!sb->format) > + return -EINVAL; > + > + sb->pitch[0] = fb->pitches[0]; > + > + if (abo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) { > + if (abo->tbo.resource->mem_type != TTM_PL_VRAM) { > + DRM_WARN("amdgpu panic, framebuffer not in VRAM\n"); > + return -EINVAL; > + } > + /* Only handle 32bits format, to simplify mmio access */ > + if (fb->format->cpp[0] != 4) { > + DRM_WARN("amdgpu panic, pixel format is not 32bits\n"); > + return -EINVAL; > + } > + sb->set_pixel = amdgpu_dm_set_pixel; > + panic_abo = abo; > + return 0; > + } > + if (!abo->kmap.virtual && > + ttm_bo_kmap(&abo->tbo, 0, PFN_UP(abo->tbo.base.size), &abo->kmap)) { > + DRM_WARN("amdgpu bo map failed, panic won't be displayed\n"); > + return -ENOMEM; > + } > + if (abo->kmap.bo_kmap_type & TTM_BO_MAP_IOMEM_MASK) > + iosys_map_set_vaddr_iomem(&sb->map[0], abo->kmap.virtual); > + else > + iosys_map_set_vaddr(&sb->map[0], abo->kmap.virtual); > + > + return 0; > +} > + > static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { > .prepare_fb = amdgpu_dm_plane_helper_prepare_fb, > .cleanup_fb = amdgpu_dm_plane_helper_cleanup_fb, > @@ -1428,6 +1550,15 @@ static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { > .atomic_async_update = amdgpu_dm_plane_atomic_async_update > }; > > +static const struct drm_plane_helper_funcs dm_primary_plane_helper_funcs = { > + .prepare_fb = amdgpu_dm_plane_helper_prepare_fb, > + .cleanup_fb = amdgpu_dm_plane_helper_cleanup_fb, > + .atomic_check = amdgpu_dm_plane_atomic_check, > + .atomic_async_check = amdgpu_dm_plane_atomic_async_check, > + .atomic_async_update = amdgpu_dm_plane_atomic_async_update, > + .get_scanout_buffer = amdgpu_dm_plane_get_scanout_buffer, > +}; > + > static void amdgpu_dm_plane_drm_plane_reset(struct drm_plane *plane) > { > struct dm_plane_state *amdgpu_state = NULL; > @@ -1854,7 +1985,10 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, > plane->type != DRM_PLANE_TYPE_CURSOR) > drm_plane_enable_fb_damage_clips(plane); > > - drm_plane_helper_add(plane, &dm_plane_helper_funcs); > + if (plane->type == DRM_PLANE_TYPE_PRIMARY) > + drm_plane_helper_add(plane, &dm_primary_plane_helper_funcs); > + else > + drm_plane_helper_add(plane, &dm_plane_helper_funcs); > > #ifdef AMD_PRIVATE_COLOR > dm_atomic_plane_attach_color_mgmt_properties(dm, plane); > @@ -1876,4 +2010,3 @@ bool amdgpu_dm_plane_is_video_format(uint32_t format) > > return false; > } > - > diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c > index 60a64d2903527..3b16c3cda2c3e 100644 > --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c > +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c > @@ -334,6 +334,22 @@ void hubp3_program_tiling( > > } > > +void hubp3_clear_tiling(struct hubp *hubp) > +{ > + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); > + > + REG_UPDATE(DCHUBP_REQ_SIZE_CONFIG, SWATH_HEIGHT, 0); > + REG_UPDATE(DCSURF_TILING_CONFIG, SW_MODE, DC_SW_LINEAR); > + > + REG_UPDATE_6(DCSURF_SURFACE_CONTROL, > + PRIMARY_SURFACE_DCC_EN, 0, > + PRIMARY_SURFACE_DCC_IND_BLK, 0, > + PRIMARY_SURFACE_DCC_IND_BLK_C, 0, > + SECONDARY_SURFACE_DCC_EN, 0, > + SECONDARY_SURFACE_DCC_IND_BLK, 0, > + SECONDARY_SURFACE_DCC_IND_BLK_C, 0); > +} > + > void hubp3_dcc_control(struct hubp *hubp, bool enable, > enum hubp_ind_block_size blk_size) > { > @@ -512,6 +528,7 @@ static struct hubp_funcs dcn30_hubp_funcs = { > .hubp_in_blank = hubp1_in_blank, > .hubp_soft_reset = hubp1_soft_reset, > .hubp_set_flip_int = hubp1_set_flip_int, > + .hubp_clear_tiling = hubp3_clear_tiling, > }; > > bool hubp3_construct( > diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.h > index b010531a7fe88..cfb01bf340a1a 100644 > --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.h > +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.h > @@ -297,6 +297,8 @@ void hubp3_read_state(struct hubp *hubp); > > void hubp3_init(struct hubp *hubp); > > +void hubp3_clear_tiling(struct hubp *hubp); > + > #endif /* __DC_HUBP_DCN30_H__ */ > > > diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h > index 16580d6242789..d0878fc0cc948 100644 > --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h > +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h > @@ -275,6 +275,7 @@ struct hubp_funcs { > enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cb_b, > enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cr_r); > int (*hubp_get_3dlut_fl_done)(struct hubp *hubp); > + void (*hubp_clear_tiling)(struct hubp *hubp); > }; > > #endif > > base-commit: a5c2320151ff7cdf9ec50630d638a417ff927e31 > -- > 2.46.1 >
On 22/10/2024 22:10, Alex Deucher wrote: > On Fri, Oct 4, 2024 at 5:09 AM Jocelyn Falempe <jfalempe@redhat.com> wrote: >> >> Add support for the drm_panic module, which displays a pretty user >> friendly message on the screen when a Linux kernel panic occurs. >> >> It should work on all readeon using amdgpu_dm_plane.c, when the > > radeon > >> framebuffer is linear (like when in a VT). For tiled framebuffer, it >> will only work on radeon with dcn30. It should be easy to add support >> for dcn20 or dcn31, but I can't test it. >> I've tested it on a Radeon W6400 pro. > > Looks good to me. @Wentland, Harry, @Siqueira, Rodrigo, etc, does > this look ok to you guys? If so, can you pick it up and look at > adding the callbacks for other DCN versions? I've sent a v2 of this patch, and I'm preparing a v3, which adds dcn31, dnc32 and dnc35 support. I've tested it successfully on a 7900XTX and radeon RX 5700. One thing that doesn't work yet, is on a laptop's panel. Thomas Weißschuh tested it on a laptop with an integrated radeon 780M, and the screen is not updated. It has something to do with PSR, but I didn't find a way to workaround this. So basically calling hubp_program_surface_flip_and_addr() is not enough to get the new framebuffer content to the internal panel, but it works on an external display on his laptop. I tried to call dc_set_psr_allow_active(dc, false), but it has no effect. Anyway I will send the v3 tomorrow. Best regards, -- Jocelyn > > Thanks, > > Alex > >> >> Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com> >> --- >> .../amd/display/amdgpu_dm/amdgpu_dm_plane.c | 137 +++++++++++++++++- >> .../amd/display/dc/hubp/dcn30/dcn30_hubp.c | 17 +++ >> .../amd/display/dc/hubp/dcn30/dcn30_hubp.h | 2 + >> drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h | 1 + >> 4 files changed, 155 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c >> index 25f63b2e7a8e2..a62b197ab6833 100644 >> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c >> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c >> @@ -26,7 +26,9 @@ >> >> #include <drm/drm_atomic_helper.h> >> #include <drm/drm_blend.h> >> +#include "drm/drm_framebuffer.h" >> #include <drm/drm_gem_atomic_helper.h> >> +#include <drm/drm_panic.h> >> #include <drm/drm_plane_helper.h> >> #include <drm/drm_gem_framebuffer_helper.h> >> #include <drm/drm_fourcc.h> >> @@ -36,6 +38,7 @@ >> #include "amdgpu_display.h" >> #include "amdgpu_dm_trace.h" >> #include "amdgpu_dm_plane.h" >> +#include "bif/bif_4_1_d.h" >> #include "gc/gc_11_0_0_offset.h" >> #include "gc/gc_11_0_0_sh_mask.h" >> >> @@ -1420,6 +1423,125 @@ static void amdgpu_dm_plane_atomic_async_update(struct drm_plane *plane, >> amdgpu_dm_plane_handle_cursor_update(plane, old_state); >> } >> >> +/* panic_bo is set in amdgpu_dm_plane_get_scanout_buffer() and only used in amdgpu_dm_set_pixel() >> + * they are called from the panic handler, and no race condition can occurs. >> + */ >> +static struct amdgpu_bo *panic_abo; >> + >> +/* Use the indirect MMIO to write each pixel to the GPU VRAM, >> + * This is a simplified version of amdgpu_device_mm_access() >> + */ >> +static void amdgpu_dm_set_pixel(struct drm_scanout_buffer *sb, >> + unsigned int x, >> + unsigned int y, >> + u32 color) >> +{ >> + struct amdgpu_res_cursor cursor; >> + unsigned long offset; >> + struct amdgpu_bo *abo = panic_abo; >> + struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev); >> + uint32_t tmp; >> + >> + offset = x * 4 + y * sb->pitch[0]; >> + amdgpu_res_first(abo->tbo.resource, offset, 4, &cursor); >> + >> + tmp = cursor.start >> 31; >> + WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t) cursor.start) | 0x80000000); >> + if (tmp != 0xffffffff) >> + WREG32_NO_KIQ(mmMM_INDEX_HI, tmp); >> + WREG32_NO_KIQ(mmMM_DATA, color); >> +} >> + >> +static int amdgpu_dm_plane_disable_tiling(struct dc_plane_state *dc_plane_state) >> +{ >> + struct dc_state *dc_state; >> + int i; >> + >> + if (!dc_plane_state) >> + return -EINVAL; >> + >> + dc_state = dc_plane_state->ctx->dc->current_state; >> + if (!dc_state) >> + return -EINVAL; >> + >> + for (i = 0; i < dc_plane_state->ctx->dc->res_pool->pipe_count; i++) { >> + struct pipe_ctx *pipe_ctx = &dc_state->res_ctx.pipe_ctx[i]; >> + struct hubp *hubp; >> + >> + if (!pipe_ctx) >> + continue; >> + >> + hubp = pipe_ctx->plane_res.hubp; >> + if (!hubp) >> + continue; >> + >> + if (!hubp->funcs->hubp_clear_tiling) >> + return -EINVAL; >> + >> + hubp->funcs->hubp_clear_tiling(hubp); >> + hubp->funcs->hubp_program_surface_flip_and_addr(hubp, >> + &dc_plane_state->address, >> + dc_plane_state->flip_immediate); >> + } >> + return 0; >> +} >> + >> +static int amdgpu_dm_plane_get_scanout_buffer(struct drm_plane *plane, >> + struct drm_scanout_buffer *sb) >> +{ >> + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane->state); >> + struct amdgpu_bo *abo; >> + struct drm_framebuffer *fb = plane->state->fb; >> + >> + if (!fb) >> + return -EINVAL; >> + >> + DRM_DEBUG_KMS("Framebuffer %dx%d %p4cc\n", fb->width, fb->height, &fb->format->format); >> + >> + abo = gem_to_amdgpu_bo(fb->obj[0]); >> + if (!abo) >> + return -EINVAL; >> + >> + /* disable tiling */ >> + if (fb->modifier && amdgpu_dm_plane_disable_tiling(dm_plane_state->dc_state)) >> + return -EINVAL; >> + >> + sb->width = fb->width; >> + sb->height = fb->height; >> + /* Use the generic linear format, because we just disabled tiling */ >> + sb->format = drm_format_info(fb->format->format); >> + if (!sb->format) >> + return -EINVAL; >> + >> + sb->pitch[0] = fb->pitches[0]; >> + >> + if (abo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) { >> + if (abo->tbo.resource->mem_type != TTM_PL_VRAM) { >> + DRM_WARN("amdgpu panic, framebuffer not in VRAM\n"); >> + return -EINVAL; >> + } >> + /* Only handle 32bits format, to simplify mmio access */ >> + if (fb->format->cpp[0] != 4) { >> + DRM_WARN("amdgpu panic, pixel format is not 32bits\n"); >> + return -EINVAL; >> + } >> + sb->set_pixel = amdgpu_dm_set_pixel; >> + panic_abo = abo; >> + return 0; >> + } >> + if (!abo->kmap.virtual && >> + ttm_bo_kmap(&abo->tbo, 0, PFN_UP(abo->tbo.base.size), &abo->kmap)) { >> + DRM_WARN("amdgpu bo map failed, panic won't be displayed\n"); >> + return -ENOMEM; >> + } >> + if (abo->kmap.bo_kmap_type & TTM_BO_MAP_IOMEM_MASK) >> + iosys_map_set_vaddr_iomem(&sb->map[0], abo->kmap.virtual); >> + else >> + iosys_map_set_vaddr(&sb->map[0], abo->kmap.virtual); >> + >> + return 0; >> +} >> + >> static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { >> .prepare_fb = amdgpu_dm_plane_helper_prepare_fb, >> .cleanup_fb = amdgpu_dm_plane_helper_cleanup_fb, >> @@ -1428,6 +1550,15 @@ static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { >> .atomic_async_update = amdgpu_dm_plane_atomic_async_update >> }; >> >> +static const struct drm_plane_helper_funcs dm_primary_plane_helper_funcs = { >> + .prepare_fb = amdgpu_dm_plane_helper_prepare_fb, >> + .cleanup_fb = amdgpu_dm_plane_helper_cleanup_fb, >> + .atomic_check = amdgpu_dm_plane_atomic_check, >> + .atomic_async_check = amdgpu_dm_plane_atomic_async_check, >> + .atomic_async_update = amdgpu_dm_plane_atomic_async_update, >> + .get_scanout_buffer = amdgpu_dm_plane_get_scanout_buffer, >> +}; >> + >> static void amdgpu_dm_plane_drm_plane_reset(struct drm_plane *plane) >> { >> struct dm_plane_state *amdgpu_state = NULL; >> @@ -1854,7 +1985,10 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, >> plane->type != DRM_PLANE_TYPE_CURSOR) >> drm_plane_enable_fb_damage_clips(plane); >> >> - drm_plane_helper_add(plane, &dm_plane_helper_funcs); >> + if (plane->type == DRM_PLANE_TYPE_PRIMARY) >> + drm_plane_helper_add(plane, &dm_primary_plane_helper_funcs); >> + else >> + drm_plane_helper_add(plane, &dm_plane_helper_funcs); >> >> #ifdef AMD_PRIVATE_COLOR >> dm_atomic_plane_attach_color_mgmt_properties(dm, plane); >> @@ -1876,4 +2010,3 @@ bool amdgpu_dm_plane_is_video_format(uint32_t format) >> >> return false; >> } >> - >> diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c >> index 60a64d2903527..3b16c3cda2c3e 100644 >> --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c >> +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c >> @@ -334,6 +334,22 @@ void hubp3_program_tiling( >> >> } >> >> +void hubp3_clear_tiling(struct hubp *hubp) >> +{ >> + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); >> + >> + REG_UPDATE(DCHUBP_REQ_SIZE_CONFIG, SWATH_HEIGHT, 0); >> + REG_UPDATE(DCSURF_TILING_CONFIG, SW_MODE, DC_SW_LINEAR); >> + >> + REG_UPDATE_6(DCSURF_SURFACE_CONTROL, >> + PRIMARY_SURFACE_DCC_EN, 0, >> + PRIMARY_SURFACE_DCC_IND_BLK, 0, >> + PRIMARY_SURFACE_DCC_IND_BLK_C, 0, >> + SECONDARY_SURFACE_DCC_EN, 0, >> + SECONDARY_SURFACE_DCC_IND_BLK, 0, >> + SECONDARY_SURFACE_DCC_IND_BLK_C, 0); >> +} >> + >> void hubp3_dcc_control(struct hubp *hubp, bool enable, >> enum hubp_ind_block_size blk_size) >> { >> @@ -512,6 +528,7 @@ static struct hubp_funcs dcn30_hubp_funcs = { >> .hubp_in_blank = hubp1_in_blank, >> .hubp_soft_reset = hubp1_soft_reset, >> .hubp_set_flip_int = hubp1_set_flip_int, >> + .hubp_clear_tiling = hubp3_clear_tiling, >> }; >> >> bool hubp3_construct( >> diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.h >> index b010531a7fe88..cfb01bf340a1a 100644 >> --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.h >> +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.h >> @@ -297,6 +297,8 @@ void hubp3_read_state(struct hubp *hubp); >> >> void hubp3_init(struct hubp *hubp); >> >> +void hubp3_clear_tiling(struct hubp *hubp); >> + >> #endif /* __DC_HUBP_DCN30_H__ */ >> >> >> diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h >> index 16580d6242789..d0878fc0cc948 100644 >> --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h >> +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h >> @@ -275,6 +275,7 @@ struct hubp_funcs { >> enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cb_b, >> enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cr_r); >> int (*hubp_get_3dlut_fl_done)(struct hubp *hubp); >> + void (*hubp_clear_tiling)(struct hubp *hubp); >> }; >> >> #endif >> >> base-commit: a5c2320151ff7cdf9ec50630d638a417ff927e31 >> -- >> 2.46.1 >> >
© 2016 - 2024 Red Hat, Inc.