[PATCH] drm/amdgpu: Add dcn30 drm_panic support
Jocelyn Falempe
jfalempe at redhat.com
Tue Oct 22 23:09:56 UTC 2024
On 22/10/2024 22:10, Alex Deucher wrote:
> On Fri, Oct 4, 2024 at 5:09 AM Jocelyn Falempe <jfalempe at 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 at 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
>>
>
More information about the amd-gfx
mailing list