drivers/gpu/drm/i915/gem/i915_gem_pages.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/i915/gem/i915_gem_pages.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/gem/i915_gem_pages.c
Extension
.c
Size
20875 bytes
Lines
806
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

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)

Annotation

Implementation Notes