4
4
*/
5
5
6
6
#include <drm/drm_cache.h>
7
+ #include <drm/drm_panic.h>
7
8
#include <linux/vmalloc.h>
8
9
10
+ #include "display/intel_fb.h"
9
11
#include "display/intel_display_types.h"
10
12
#include "gt/intel_gt.h"
11
13
#include "gt/intel_tlb.h"
@@ -366,6 +368,67 @@ struct i915_framebuffer {
366
368
struct i915_panic_data panic ;
367
369
};
368
370
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
+
369
432
struct intel_framebuffer * i915_gem_object_alloc_framebuffer (void )
370
433
{
371
434
struct i915_framebuffer * i915_fb ;
@@ -376,6 +439,49 @@ struct intel_framebuffer *i915_gem_object_alloc_framebuffer(void)
376
439
return NULL ;
377
440
}
378
441
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
+
379
485
/* get, pin, and map the pages of the object into kernel space */
380
486
void * i915_gem_object_pin_map (struct drm_i915_gem_object * obj ,
381
487
enum i915_map_type type )
0 commit comments