44 */
55
66#include <drm/drm_cache.h>
7+ #include <drm/drm_panic.h>
78#include <linux/vmalloc.h>
89
10+ #include "display/intel_fb.h"
911#include "display/intel_display_types.h"
1012#include "gt/intel_gt.h"
1113#include "gt/intel_tlb.h"
@@ -366,6 +368,67 @@ struct i915_framebuffer {
366368 struct i915_panic_data panic ;
367369};
368370
371+ static inline struct i915_panic_data * to_i915_panic_data (struct intel_framebuffer * fb )
372+ {
373+ return & container_of_const (fb , struct i915_framebuffer , base )-> panic ;
374+ }
375+
376+ static void i915_panic_kunmap (struct i915_panic_data * panic )
377+ {
378+ if (panic -> vaddr ) {
379+ drm_clflush_virt_range (panic -> vaddr , PAGE_SIZE );
380+ kunmap_local (panic -> vaddr );
381+ panic -> vaddr = NULL ;
382+ }
383+ }
384+
385+ static struct page * * i915_gem_object_panic_pages (struct drm_i915_gem_object * obj )
386+ {
387+ unsigned long n_pages = obj -> base .size >> PAGE_SHIFT , i ;
388+ struct page * page ;
389+ struct page * * pages ;
390+ struct sgt_iter iter ;
391+
392+ /* For a 3840x2160 32 bits Framebuffer, this should require ~64K */
393+ pages = kmalloc_array (n_pages , sizeof (* pages ), GFP_ATOMIC );
394+ if (!pages )
395+ return NULL ;
396+
397+ i = 0 ;
398+ for_each_sgt_page (page , iter , obj -> mm .pages )
399+ pages [i ++ ] = page ;
400+ return pages ;
401+ }
402+
403+ /*
404+ * The scanout buffer pages are not mapped, so for each pixel,
405+ * use kmap_local_page_try_from_panic() to map the page, and write the pixel.
406+ * Try to keep the map from the previous pixel, to avoid too much map/unmap.
407+ */
408+ static void i915_gem_object_panic_page_set_pixel (struct drm_scanout_buffer * sb , unsigned int x ,
409+ unsigned int y , u32 color )
410+ {
411+ unsigned int new_page ;
412+ unsigned int offset ;
413+ struct intel_framebuffer * fb = (struct intel_framebuffer * )sb -> private ;
414+ struct i915_panic_data * panic = to_i915_panic_data (fb );
415+
416+ offset = y * sb -> pitch [0 ] + x * sb -> format -> cpp [0 ];
417+
418+ new_page = offset >> PAGE_SHIFT ;
419+ offset = offset % PAGE_SIZE ;
420+ if (new_page != panic -> page ) {
421+ i915_panic_kunmap (panic );
422+ panic -> page = new_page ;
423+ panic -> vaddr =
424+ kmap_local_page_try_from_panic (panic -> pages [panic -> page ]);
425+ }
426+ if (panic -> vaddr ) {
427+ u32 * pix = panic -> vaddr + offset ;
428+ * pix = color ;
429+ }
430+ }
431+
369432struct intel_framebuffer * i915_gem_object_alloc_framebuffer (void )
370433{
371434 struct i915_framebuffer * i915_fb ;
@@ -376,6 +439,49 @@ struct intel_framebuffer *i915_gem_object_alloc_framebuffer(void)
376439 return NULL ;
377440}
378441
442+ /*
443+ * Setup the gem framebuffer for drm_panic access.
444+ * Use current vaddr if it exists, or setup a list of pages.
445+ * pfn is not supported yet.
446+ */
447+ int i915_gem_object_panic_setup (struct drm_scanout_buffer * sb )
448+ {
449+ enum i915_map_type has_type ;
450+ struct intel_framebuffer * fb = (struct intel_framebuffer * )sb -> private ;
451+ struct i915_panic_data * panic = to_i915_panic_data (fb );
452+ struct drm_i915_gem_object * obj = to_intel_bo (intel_fb_bo (& fb -> base ));
453+ void * ptr ;
454+
455+ ptr = page_unpack_bits (obj -> mm .mapping , & has_type );
456+ if (ptr ) {
457+ if (i915_gem_object_has_iomem (obj ))
458+ iosys_map_set_vaddr_iomem (& sb -> map [0 ], (void __iomem * )ptr );
459+ else
460+ iosys_map_set_vaddr (& sb -> map [0 ], ptr );
461+
462+ return 0 ;
463+ }
464+ if (i915_gem_object_has_struct_page (obj )) {
465+ panic -> pages = i915_gem_object_panic_pages (obj );
466+ if (!panic -> pages )
467+ return - ENOMEM ;
468+ panic -> page = -1 ;
469+ sb -> set_pixel = i915_gem_object_panic_page_set_pixel ;
470+ return 0 ;
471+ }
472+ return - EOPNOTSUPP ;
473+ }
474+
475+ void i915_gem_object_panic_finish (struct intel_framebuffer * fb )
476+ {
477+ struct i915_panic_data * panic = to_i915_panic_data (fb );
478+
479+ i915_panic_kunmap (panic );
480+ panic -> page = -1 ;
481+ kfree (panic -> pages );
482+ panic -> pages = NULL ;
483+ }
484+
379485/* get, pin, and map the pages of the object into kernel space */
380486void * i915_gem_object_pin_map (struct drm_i915_gem_object * obj ,
381487 enum i915_map_type type )
0 commit comments