| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- // SPDX-License-Identifier: GPL-2.0 or MIT
- /*
- * Copyright (c) 2025 Red Hat.
- * Author: Jocelyn Falempe <jfalempe@redhat.com>
- *
- * KUNIT tests for drm panic
- */
- #include <drm/drm_fourcc.h>
- #include <drm/drm_panic.h>
- #include <kunit/test.h>
- #include <linux/units.h>
- #include <linux/vmalloc.h>
- /* Check the framebuffer color only if the panic colors are the default */
- #if (CONFIG_DRM_PANIC_BACKGROUND_COLOR == 0 && \
- CONFIG_DRM_PANIC_FOREGROUND_COLOR == 0xffffff)
- static void drm_panic_check_color_byte(struct kunit *test, u8 b)
- {
- KUNIT_EXPECT_TRUE(test, (b == 0 || b == 0xff));
- }
- #else
- static void drm_panic_check_color_byte(struct kunit *test, u8 b) {}
- #endif
- struct drm_test_mode {
- const int width;
- const int height;
- const u32 format;
- void (*draw_screen)(struct drm_scanout_buffer *sb);
- const char *fname;
- };
- /*
- * Run all tests for the 3 panic screens: user, kmsg and qr_code
- */
- #define DRM_TEST_MODE_LIST(func) \
- DRM_PANIC_TEST_MODE(1024, 768, DRM_FORMAT_XRGB8888, func) \
- DRM_PANIC_TEST_MODE(300, 200, DRM_FORMAT_XRGB8888, func) \
- DRM_PANIC_TEST_MODE(1920, 1080, DRM_FORMAT_XRGB8888, func) \
- DRM_PANIC_TEST_MODE(1024, 768, DRM_FORMAT_RGB565, func) \
- DRM_PANIC_TEST_MODE(1024, 768, DRM_FORMAT_RGB888, func) \
- #define DRM_PANIC_TEST_MODE(w, h, f, name) { \
- .width = w, \
- .height = h, \
- .format = f, \
- .draw_screen = draw_panic_screen_##name, \
- .fname = #name, \
- }, \
- static const struct drm_test_mode drm_test_modes_cases[] = {
- DRM_TEST_MODE_LIST(user)
- DRM_TEST_MODE_LIST(kmsg)
- #if IS_ENABLED(CONFIG_DRM_PANIC_SCREEN_QR_CODE)
- DRM_TEST_MODE_LIST(qr_code)
- #endif
- };
- #undef DRM_PANIC_TEST_MODE
- static int drm_test_panic_init(struct kunit *test)
- {
- struct drm_scanout_buffer *priv;
- priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
- KUNIT_ASSERT_NOT_NULL(test, priv);
- test->priv = priv;
- drm_panic_set_description("Kunit testing");
- return 0;
- }
- /*
- * Test drawing the panic screen, using a memory mapped framebuffer
- * Set the whole buffer to 0xa5, and then check that all pixels have been
- * written.
- */
- static void drm_test_panic_screen_user_map(struct kunit *test)
- {
- struct drm_scanout_buffer *sb = test->priv;
- const struct drm_test_mode *params = test->param_value;
- char *fb;
- int fb_size;
- int i;
- sb->format = drm_format_info(params->format);
- fb_size = params->width * params->height * sb->format->cpp[0];
- fb = vmalloc(fb_size);
- KUNIT_ASSERT_NOT_NULL(test, fb);
- memset(fb, 0xa5, fb_size);
- iosys_map_set_vaddr(&sb->map[0], fb);
- sb->width = params->width;
- sb->height = params->height;
- sb->pitch[0] = params->width * sb->format->cpp[0];
- params->draw_screen(sb);
- for (i = 0; i < fb_size; i++)
- drm_panic_check_color_byte(test, fb[i]);
- vfree(fb);
- }
- /*
- * Test drawing the panic screen, using a list of pages framebuffer
- * Set the whole buffer to 0xa5, and then check that all pixels have been
- * written.
- */
- static void drm_test_panic_screen_user_page(struct kunit *test)
- {
- struct drm_scanout_buffer *sb = test->priv;
- const struct drm_test_mode *params = test->param_value;
- int fb_size, p, i, npages;
- struct page **pages;
- u8 *vaddr;
- sb->format = drm_format_info(params->format);
- fb_size = params->width * params->height * sb->format->cpp[0];
- npages = DIV_ROUND_UP(fb_size, PAGE_SIZE);
- pages = kmalloc_objs(struct page *, npages);
- KUNIT_ASSERT_NOT_NULL(test, pages);
- for (p = 0; p < npages; p++) {
- pages[p] = alloc_page(GFP_KERNEL);
- if (!pages[p]) {
- npages = p - 1;
- KUNIT_FAIL(test, "Can't allocate page\n");
- goto free_pages;
- }
- vaddr = kmap_local_page(pages[p]);
- memset(vaddr, 0xa5, PAGE_SIZE);
- kunmap_local(vaddr);
- }
- sb->pages = pages;
- sb->width = params->width;
- sb->height = params->height;
- sb->pitch[0] = params->width * sb->format->cpp[0];
- params->draw_screen(sb);
- for (p = 0; p < npages; p++) {
- int bytes_in_page = (p == npages - 1) ? fb_size - p * PAGE_SIZE : PAGE_SIZE;
- vaddr = kmap_local_page(pages[p]);
- for (i = 0; i < bytes_in_page; i++)
- drm_panic_check_color_byte(test, vaddr[i]);
- kunmap_local(vaddr);
- }
- free_pages:
- for (p = 0; p < npages; p++)
- __free_page(pages[p]);
- kfree(pages);
- }
- static void drm_test_panic_set_pixel(struct drm_scanout_buffer *sb,
- unsigned int x,
- unsigned int y,
- u32 color)
- {
- struct kunit *test = (struct kunit *)sb->private;
- KUNIT_ASSERT_TRUE(test, x < sb->width && y < sb->height);
- }
- /*
- * Test drawing the panic screen, using the set_pixel callback
- * Check that all calls to set_pixel() are within the framebuffer
- */
- static void drm_test_panic_screen_user_set_pixel(struct kunit *test)
- {
- struct drm_scanout_buffer *sb = test->priv;
- const struct drm_test_mode *params = test->param_value;
- sb->format = drm_format_info(params->format);
- sb->set_pixel = drm_test_panic_set_pixel;
- sb->width = params->width;
- sb->height = params->height;
- sb->private = test;
- params->draw_screen(sb);
- }
- static void drm_test_panic_desc(const struct drm_test_mode *t, char *desc)
- {
- sprintf(desc, "Panic screen %s, mode: %d x %d \t%p4cc",
- t->fname, t->width, t->height, &t->format);
- }
- KUNIT_ARRAY_PARAM(drm_test_panic_screen_user_map, drm_test_modes_cases, drm_test_panic_desc);
- KUNIT_ARRAY_PARAM(drm_test_panic_screen_user_page, drm_test_modes_cases, drm_test_panic_desc);
- KUNIT_ARRAY_PARAM(drm_test_panic_screen_user_set_pixel, drm_test_modes_cases, drm_test_panic_desc);
- static struct kunit_case drm_panic_screen_user_test[] = {
- KUNIT_CASE_PARAM(drm_test_panic_screen_user_map,
- drm_test_panic_screen_user_map_gen_params),
- KUNIT_CASE_PARAM(drm_test_panic_screen_user_page,
- drm_test_panic_screen_user_page_gen_params),
- KUNIT_CASE_PARAM(drm_test_panic_screen_user_set_pixel,
- drm_test_panic_screen_user_set_pixel_gen_params),
- { }
- };
- static struct kunit_suite drm_panic_suite = {
- .name = "drm_panic",
- .init = drm_test_panic_init,
- .test_cases = drm_panic_screen_user_test,
- };
- kunit_test_suite(drm_panic_suite);
|