The panic handling is a bit special and isolated part of i915_gem_pages.c. Split it out to i915_gem_panic.[ch].
Cc: Jocelyn Falempe <[email protected]> Signed-off-by: Jani Nikula <[email protected]> --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/gem/i915_gem_object.h | 7 -- drivers/gpu/drm/i915/gem/i915_gem_pages.c | 128 ------------------- drivers/gpu/drm/i915/gem/i915_gem_panic.c | 135 +++++++++++++++++++++ drivers/gpu/drm/i915/gem/i915_gem_panic.h | 18 +++ drivers/gpu/drm/i915/i915_panic.c | 2 +- 6 files changed, 155 insertions(+), 136 deletions(-) create mode 100644 drivers/gpu/drm/i915/gem/i915_gem_panic.c create mode 100644 drivers/gpu/drm/i915/gem/i915_gem_panic.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 07802a7f4ce5..091b6647c383 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -167,6 +167,7 @@ gem-y += \ gem/i915_gem_object.o \ gem/i915_gem_object_frontbuffer.o \ gem/i915_gem_pages.o \ + gem/i915_gem_panic.o \ gem/i915_gem_phys.o \ gem/i915_gem_pm.o \ gem/i915_gem_region.o \ diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index 8878539c10ed..2c5d20e4dbaf 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -17,8 +17,6 @@ #include "i915_vma_types.h" enum intel_region_id; -struct drm_scanout_buffer; -struct intel_panic; #define obj_to_i915(obj__) to_i915((obj__)->base.dev) @@ -693,11 +691,6 @@ i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj); int i915_gem_object_truncate(struct drm_i915_gem_object *obj); -struct intel_panic *i915_gem_object_alloc_panic(void); -int i915_gem_object_panic_setup(struct intel_panic *panic, struct drm_scanout_buffer *sb, - struct drm_gem_object *_obj, bool panic_tiling); -void i915_gem_object_panic_finish(struct intel_panic *panic); - /** * i915_gem_object_pin_map - return a contiguous mapping of the entire object * @obj: the object to map into kernel address space diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c index df35bdb755e4..59e3d4de7d3c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c @@ -6,11 +6,8 @@ #include <linux/vmalloc.h> #include <drm/drm_cache.h> -#include <drm/drm_panic.h> #include <drm/drm_print.h> -#include "display/intel_fb.h" -#include "display/intel_display_types.h" #include "gt/intel_gt.h" #include "gt/intel_tlb.h" @@ -359,131 +356,6 @@ static void *i915_gem_object_map_pfn(struct drm_i915_gem_object *obj, return vaddr ?: ERR_PTR(-ENOMEM); } -struct intel_panic { - struct page **pages; - int page; - void *vaddr; -}; - -static void i915_panic_kunmap(struct intel_panic *panic) -{ - if (panic->vaddr) { - drm_clflush_virt_range(panic->vaddr, PAGE_SIZE); - kunmap_local(panic->vaddr); - panic->vaddr = NULL; - } -} - -static struct page **i915_gem_object_panic_pages(struct drm_i915_gem_object *obj) -{ - unsigned long n_pages = obj->base.size >> PAGE_SHIFT, i; - struct page *page; - struct page **pages; - struct sgt_iter iter; - - /* For a 3840x2160 32 bits Framebuffer, this should require ~64K */ - pages = kmalloc_objs(*pages, n_pages, GFP_ATOMIC); - if (!pages) - return NULL; - - i = 0; - for_each_sgt_page(page, iter, obj->mm.pages) - pages[i++] = page; - return pages; -} - -static void i915_gem_object_panic_map_set_pixel(struct drm_scanout_buffer *sb, unsigned int x, - unsigned int y, u32 color) -{ - struct intel_framebuffer *fb = (struct intel_framebuffer *)sb->private; - unsigned int offset = fb->panic_tiling(sb->width, x, y); - - iosys_map_wr(&sb->map[0], offset, u32, color); -} - -/* - * The scanout buffer pages are not mapped, so for each pixel, - * use kmap_local_page_try_from_panic() to map the page, and write the pixel. - * Try to keep the map from the previous pixel, to avoid too much map/unmap. - */ -static void i915_gem_object_panic_page_set_pixel(struct drm_scanout_buffer *sb, unsigned int x, - unsigned int y, u32 color) -{ - unsigned int new_page; - unsigned int offset; - struct intel_framebuffer *fb = (struct intel_framebuffer *)sb->private; - struct intel_panic *panic = fb->panic; - - if (fb->panic_tiling) - offset = fb->panic_tiling(sb->width, x, y); - else - offset = y * sb->pitch[0] + x * sb->format->cpp[0]; - - new_page = offset >> PAGE_SHIFT; - offset = offset % PAGE_SIZE; - if (new_page != panic->page) { - i915_panic_kunmap(panic); - panic->page = new_page; - panic->vaddr = - kmap_local_page_try_from_panic(panic->pages[panic->page]); - } - if (panic->vaddr) { - u32 *pix = panic->vaddr + offset; - *pix = color; - } -} - -struct intel_panic *i915_gem_object_alloc_panic(void) -{ - struct intel_panic *panic; - - panic = kzalloc_obj(*panic); - - return panic; -} - -/* - * Setup the gem framebuffer for drm_panic access. - * Use current vaddr if it exists, or setup a list of pages. - * pfn is not supported yet. - */ -int i915_gem_object_panic_setup(struct intel_panic *panic, struct drm_scanout_buffer *sb, - struct drm_gem_object *_obj, bool panic_tiling) -{ - enum i915_map_type has_type; - struct drm_i915_gem_object *obj = to_intel_bo(_obj); - void *ptr; - - ptr = page_unpack_bits(obj->mm.mapping, &has_type); - if (ptr) { - if (i915_gem_object_has_iomem(obj)) - iosys_map_set_vaddr_iomem(&sb->map[0], (void __iomem *)ptr); - else - iosys_map_set_vaddr(&sb->map[0], ptr); - - if (panic_tiling) - sb->set_pixel = i915_gem_object_panic_map_set_pixel; - return 0; - } - if (i915_gem_object_has_struct_page(obj)) { - panic->pages = i915_gem_object_panic_pages(obj); - if (!panic->pages) - return -ENOMEM; - panic->page = -1; - sb->set_pixel = i915_gem_object_panic_page_set_pixel; - return 0; - } - return -EOPNOTSUPP; -} - -void i915_gem_object_panic_finish(struct intel_panic *panic) -{ - i915_panic_kunmap(panic); - panic->page = -1; - kfree(panic->pages); - panic->pages = NULL; -} - /* get, pin, and map the pages of the object into kernel space */ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj, enum i915_map_type type) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_panic.c b/drivers/gpu/drm/i915/gem/i915_gem_panic.c new file mode 100644 index 000000000000..7407c5668c71 --- /dev/null +++ b/drivers/gpu/drm/i915/gem/i915_gem_panic.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: MIT +/* Copyright © 2026 Intel Corporation */ + +#include <drm/drm_cache.h> +#include <drm/drm_panic.h> + +#include "display/intel_fb.h" +#include "display/intel_display_types.h" +#include "i915_gem_object.h" +#include "i915_gem_panic.h" + +struct intel_panic { + struct page **pages; + int page; + void *vaddr; +}; + +static void i915_panic_kunmap(struct intel_panic *panic) +{ + if (panic->vaddr) { + drm_clflush_virt_range(panic->vaddr, PAGE_SIZE); + kunmap_local(panic->vaddr); + panic->vaddr = NULL; + } +} + +static struct page **i915_gem_object_panic_pages(struct drm_i915_gem_object *obj) +{ + unsigned long n_pages = obj->base.size >> PAGE_SHIFT, i; + struct page *page; + struct page **pages; + struct sgt_iter iter; + + /* For a 3840x2160 32 bits Framebuffer, this should require ~64K */ + pages = kmalloc_objs(*pages, n_pages, GFP_ATOMIC); + if (!pages) + return NULL; + + i = 0; + for_each_sgt_page(page, iter, obj->mm.pages) + pages[i++] = page; + return pages; +} + +static void i915_gem_object_panic_map_set_pixel(struct drm_scanout_buffer *sb, unsigned int x, + unsigned int y, u32 color) +{ + struct intel_framebuffer *fb = (struct intel_framebuffer *)sb->private; + unsigned int offset = fb->panic_tiling(sb->width, x, y); + + iosys_map_wr(&sb->map[0], offset, u32, color); +} + +/* + * The scanout buffer pages are not mapped, so for each pixel, + * use kmap_local_page_try_from_panic() to map the page, and write the pixel. + * Try to keep the map from the previous pixel, to avoid too much map/unmap. + */ +static void i915_gem_object_panic_page_set_pixel(struct drm_scanout_buffer *sb, unsigned int x, + unsigned int y, u32 color) +{ + unsigned int new_page; + unsigned int offset; + struct intel_framebuffer *fb = (struct intel_framebuffer *)sb->private; + struct intel_panic *panic = fb->panic; + + if (fb->panic_tiling) + offset = fb->panic_tiling(sb->width, x, y); + else + offset = y * sb->pitch[0] + x * sb->format->cpp[0]; + + new_page = offset >> PAGE_SHIFT; + offset = offset % PAGE_SIZE; + if (new_page != panic->page) { + i915_panic_kunmap(panic); + panic->page = new_page; + panic->vaddr = + kmap_local_page_try_from_panic(panic->pages[panic->page]); + } + if (panic->vaddr) { + u32 *pix = panic->vaddr + offset; + *pix = color; + } +} + +struct intel_panic *i915_gem_object_alloc_panic(void) +{ + struct intel_panic *panic; + + panic = kzalloc_obj(*panic); + + return panic; +} + +/* + * Setup the gem framebuffer for drm_panic access. + * Use current vaddr if it exists, or setup a list of pages. + * pfn is not supported yet. + */ +int i915_gem_object_panic_setup(struct intel_panic *panic, struct drm_scanout_buffer *sb, + struct drm_gem_object *_obj, bool panic_tiling) +{ + enum i915_map_type has_type; + struct drm_i915_gem_object *obj = to_intel_bo(_obj); + void *ptr; + + ptr = page_unpack_bits(obj->mm.mapping, &has_type); + if (ptr) { + if (i915_gem_object_has_iomem(obj)) + iosys_map_set_vaddr_iomem(&sb->map[0], (void __iomem *)ptr); + else + iosys_map_set_vaddr(&sb->map[0], ptr); + + if (panic_tiling) + sb->set_pixel = i915_gem_object_panic_map_set_pixel; + return 0; + } + if (i915_gem_object_has_struct_page(obj)) { + panic->pages = i915_gem_object_panic_pages(obj); + if (!panic->pages) + return -ENOMEM; + panic->page = -1; + sb->set_pixel = i915_gem_object_panic_page_set_pixel; + return 0; + } + return -EOPNOTSUPP; +} + +void i915_gem_object_panic_finish(struct intel_panic *panic) +{ + i915_panic_kunmap(panic); + panic->page = -1; + kfree(panic->pages); + panic->pages = NULL; +} diff --git a/drivers/gpu/drm/i915/gem/i915_gem_panic.h b/drivers/gpu/drm/i915/gem/i915_gem_panic.h new file mode 100644 index 000000000000..91ab6722d37c --- /dev/null +++ b/drivers/gpu/drm/i915/gem/i915_gem_panic.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2026 Intel Corporation */ + +#ifndef __I915_GEM_PANIC_H__ +#define __I915_GEM_PANIC_H__ + +#include <linux/types.h> + +struct drm_gem_object; +struct drm_scanout_buffer; +struct intel_panic; + +struct intel_panic *i915_gem_object_alloc_panic(void); +int i915_gem_object_panic_setup(struct intel_panic *panic, struct drm_scanout_buffer *sb, + struct drm_gem_object *_obj, bool panic_tiling); +void i915_gem_object_panic_finish(struct intel_panic *panic); + +#endif /* __I915_GEM_PANIC_H__ */ diff --git a/drivers/gpu/drm/i915/i915_panic.c b/drivers/gpu/drm/i915/i915_panic.c index 728be077e8e8..412db72797d8 100644 --- a/drivers/gpu/drm/i915/i915_panic.c +++ b/drivers/gpu/drm/i915/i915_panic.c @@ -6,7 +6,7 @@ #include "display/intel_display_types.h" #include "display/intel_fb.h" -#include "gem/i915_gem_object.h" +#include "gem/i915_gem_panic.h" #include "i915_panic.h" -- 2.47.3
