Commit 72b585da authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-xe-next-2026-03-25' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-next



Hi Dave and Sima,

Here goes our third, perhaps, final drm-xe-next PR towards 7.1.

In the big things we have:
- THP support in drm_pagemap
- xe_vm_get_property_ioctl

Thanks,
Matt

UAPI Changes:
- Implement xe_vm_get_property_ioctl (Jonathan)

Cross-subsystem Changes:
- Enable THP support in drm_pagemap (Francois, Brost)

Core Changes:
- Improve VF FLR synchronization for Xe VFIO (Piotr)

Driver Changes:
- Fix confusion with locals on context creation (Tomasz, Fixes)
- Add new SVM copy GT stats per size (Francois)
- always keep track of remap prev/next (Auld, Fixes)
- AuxCCS handling and render compression modifiers (Tvrtko)
- Implement recent spec updates to Wa_16025250150 (Roper)
- xe3p_lpg: L2 flush optimization (Tejas)
- vf: Improve getting clean NULL context (Wajdeczko)
- pf: Fix use-after-free in migration restore (Winiarski. Fixes)
- Fix format specifier for printing pointer differences (Nathan Chancellor, Fixes)
- Extend Wa_14026781792 for xe3lpg (Niton)
- xe3p_lpg: Add Wa_16029437861 (Varun)
- Fix spelling mistakes and comment style in ttm_resource.c (Varun)
- Merge drm/drm-next into drm-xe-next (Thomas)
- Fix missing runtime PM reference in ccs_mode_store (Sanjay, Fixes)
- Fix uninitialized new_ts when capturing context timestamp (Umesh)
- Allow reading after disabling OA stream (Ashutosh)
- Page Reclamation Fixes (Brian Nguyen, Fixes)
- Include running dword offset in default_lrc dumps (Roper)
- Assert/Deassert I2C IRQ (Raag)
- Fixup reset, wedge, unload corner cases (Zhanjun, Brost)
- Fail immediately on GuC load error (Daniele)
- Fix kernel-doc for DRM_XE_VM_BIND_FLAG_DECOMPRESS (Niton, Fixes)
- Drop redundant entries for Wa_16021867713 & Wa_14019449301 (Roper, Fixes)

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Matthew Brost <matthew.brost@intel.com>
Link: https://patch.msgid.link/acS5xmWC3ivPTmyV@gsse-cloud1.jf.intel.com
parents 3f420725 3d4939c0
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -1488,12 +1488,15 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
		order = drm_gpusvm_hmm_pfn_to_order(pfns[i], i, npages);
		if (is_device_private_page(page) ||
		    is_device_coherent_page(page)) {
			struct drm_pagemap_zdd *__zdd =
				drm_pagemap_page_zone_device_data(page);

			if (!ctx->allow_mixed &&
			    zdd != page->zone_device_data && i > 0) {
			    zdd != __zdd && i > 0) {
				err = -EOPNOTSUPP;
				goto err_unmap;
			}
			zdd = page->zone_device_data;
			zdd = __zdd;
			if (pagemap != page_pgmap(page)) {
				if (pagemap) {
					err = -EOPNOTSUPP;
+128 −29
Original line number Diff line number Diff line
@@ -154,15 +154,15 @@ static void drm_pagemap_zdd_put(struct drm_pagemap_zdd *zdd)
}

/**
 * drm_pagemap_migration_unlock_put_page() - Put a migration page
 * @page: Pointer to the page to put
 * drm_pagemap_migration_unlock_put_folio() - Put a migration folio
 * @folio: Pointer to the folio to put
 *
 * This function unlocks and puts a page.
 * This function unlocks and puts a folio.
 */
static void drm_pagemap_migration_unlock_put_page(struct page *page)
static void drm_pagemap_migration_unlock_put_folio(struct folio *folio)
{
	unlock_page(page);
	put_page(page);
	folio_unlock(folio);
	folio_put(folio);
}

/**
@@ -177,31 +177,42 @@ static void drm_pagemap_migration_unlock_put_pages(unsigned long npages,
{
	unsigned long i;

	for (i = 0; i < npages; ++i) {
	for (i = 0; i < npages;) {
		struct page *page;
		struct folio *folio;
		unsigned int order = 0;

		if (!migrate_pfn[i])
			continue;
			goto next;

		page = migrate_pfn_to_page(migrate_pfn[i]);
		drm_pagemap_migration_unlock_put_page(page);
		folio = page_folio(page);
		order = folio_order(folio);

		drm_pagemap_migration_unlock_put_folio(folio);
		migrate_pfn[i] = 0;

next:
		i += NR_PAGES(order);
	}
}

/**
 * drm_pagemap_get_devmem_page() - Get a reference to a device memory page
 * @page: Pointer to the page
 * @order: Order
 * @zdd: Pointer to the GPU SVM zone device data
 *
 * This function associates the given page with the specified GPU SVM zone
 * device data and initializes it for zone device usage.
 */
static void drm_pagemap_get_devmem_page(struct page *page,
					unsigned int order,
					struct drm_pagemap_zdd *zdd)
{
	page->zone_device_data = drm_pagemap_zdd_get(zdd);
	zone_device_page_init(page, page_pgmap(page), 0);
	zone_device_folio_init((struct folio *)page, zdd->dpagemap->pagemap,
			       order);
	folio_set_zone_device_data(page_folio(page), drm_pagemap_zdd_get(zdd));
}

/**
@@ -244,7 +255,7 @@ static int drm_pagemap_migrate_map_pages(struct device *dev,
		order = folio_order(folio);

		if (is_device_private_page(page)) {
			struct drm_pagemap_zdd *zdd = page->zone_device_data;
			struct drm_pagemap_zdd *zdd = drm_pagemap_page_zone_device_data(page);
			struct drm_pagemap *dpagemap = zdd->dpagemap;
			struct drm_pagemap_addr addr;

@@ -315,7 +326,7 @@ static void drm_pagemap_migrate_unmap_pages(struct device *dev,
			goto next;

		if (is_zone_device_page(page)) {
			struct drm_pagemap_zdd *zdd = page->zone_device_data;
			struct drm_pagemap_zdd *zdd = drm_pagemap_page_zone_device_data(page);
			struct drm_pagemap *dpagemap = zdd->dpagemap;

			dpagemap->ops->device_unmap(dpagemap, dev, &pagemap_addr[i]);
@@ -444,6 +455,41 @@ static int drm_pagemap_migrate_range(struct drm_pagemap_devmem *devmem,
	return ret;
}

/**
 * drm_pagemap_cpages() - Count collected pages
 * @migrate_pfn: Array of migrate_pfn entries to account
 * @npages: Number of entries in @migrate_pfn
 *
 * Compute the total number of minimum-sized pages represented by the
 * collected entries in @migrate_pfn. The total is derived from the
 * order encoded in each entry.
 *
 * Return: Total number of minimum-sized pages.
 */
static int drm_pagemap_cpages(unsigned long *migrate_pfn, unsigned long npages)
{
	unsigned long i, cpages = 0;

	for (i = 0; i < npages;) {
		struct page *page = migrate_pfn_to_page(migrate_pfn[i]);
		struct folio *folio;
		unsigned int order = 0;

		if (page) {
			folio = page_folio(page);
			order = folio_order(folio);
			cpages += NR_PAGES(order);
		} else if (migrate_pfn[i] & MIGRATE_PFN_COMPOUND) {
			order = HPAGE_PMD_ORDER;
			cpages += NR_PAGES(order);
		}

		i += NR_PAGES(order);
	}

	return cpages;
}

/**
 * drm_pagemap_migrate_to_devmem() - Migrate a struct mm_struct range to device memory
 * @devmem_allocation: The device memory allocation to migrate to.
@@ -481,7 +527,7 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
		.end		= end,
		.pgmap_owner	= pagemap->owner,
		.flags		= MIGRATE_VMA_SELECT_SYSTEM | MIGRATE_VMA_SELECT_DEVICE_COHERENT |
		MIGRATE_VMA_SELECT_DEVICE_PRIVATE,
		MIGRATE_VMA_SELECT_DEVICE_PRIVATE | MIGRATE_VMA_SELECT_COMPOUND,
	};
	unsigned long i, npages = npages_in_range(start, end);
	unsigned long own_pages = 0, migrated_pages = 0;
@@ -546,7 +592,8 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
		goto err_free;
	}

	if (migrate.cpages != npages) {
	if (migrate.cpages != npages &&
	    drm_pagemap_cpages(migrate.src, npages) != npages) {
		/*
		 * Some pages to migrate. But we want to migrate all or
		 * nothing. Raced or unknown device pages.
@@ -586,20 +633,23 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,

	own_pages = 0;

	for (i = 0; i < npages; ++i) {
	for (i = 0; i < npages;) {
		unsigned long j;
		struct page *page = pfn_to_page(migrate.dst[i]);
		struct page *src_page = migrate_pfn_to_page(migrate.src[i]);
		cur.start = i;
		unsigned int order = 0;

		cur.start = i;
		pages[i] = NULL;
		if (src_page && is_device_private_page(src_page)) {
			struct drm_pagemap_zdd *src_zdd = src_page->zone_device_data;
			struct drm_pagemap_zdd *src_zdd =
				drm_pagemap_page_zone_device_data(src_page);

			if (page_pgmap(src_page) == pagemap &&
			    !mdetails->can_migrate_same_pagemap) {
				migrate.dst[i] = 0;
				own_pages++;
				continue;
				goto next;
			}
			if (mdetails->source_peer_migrates) {
				cur.dpagemap = src_zdd->dpagemap;
@@ -615,7 +665,20 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
			pages[i] = page;
		}
		migrate.dst[i] = migrate_pfn(migrate.dst[i]);
		drm_pagemap_get_devmem_page(page, zdd);

		if (migrate.src[i] & MIGRATE_PFN_COMPOUND) {
			drm_WARN_ONCE(dpagemap->drm, src_page &&
				      folio_order(page_folio(src_page)) != HPAGE_PMD_ORDER,
				      "Unexpected folio order\n");

			order = HPAGE_PMD_ORDER;
			migrate.dst[i] |= MIGRATE_PFN_COMPOUND;

			for (j = 1; j < NR_PAGES(order) && i + j < npages; j++)
				migrate.dst[i + j] = 0;
		}

		drm_pagemap_get_devmem_page(page, order, zdd);

		/* If we switched the migrating drm_pagemap, migrate previous pages now */
		err = drm_pagemap_migrate_range(devmem_allocation, migrate.src, migrate.dst,
@@ -625,7 +688,11 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
			npages = i + 1;
			goto err_finalize;
		}

next:
		i += NR_PAGES(order);
	}

	cur.start = npages;
	cur.ops = NULL; /* Force migration */
	err = drm_pagemap_migrate_range(devmem_allocation, migrate.src, migrate.dst,
@@ -715,8 +782,8 @@ static int drm_pagemap_migrate_populate_ram_pfn(struct vm_area_struct *vas,
			goto next;

		if (fault_page) {
			if (src_page->zone_device_data !=
			    fault_page->zone_device_data)
			if (drm_pagemap_page_zone_device_data(src_page) !=
			    drm_pagemap_page_zone_device_data(fault_page))
				goto next;
		}

@@ -734,6 +801,8 @@ static int drm_pagemap_migrate_populate_ram_pfn(struct vm_area_struct *vas,
		page = folio_page(folio, 0);
		mpfn[i] = migrate_pfn(page_to_pfn(page));

		if (order)
			mpfn[i] |= MIGRATE_PFN_COMPOUND;
next:
		if (page)
			addr += page_size(page);
@@ -989,8 +1058,15 @@ int drm_pagemap_evict_to_ram(struct drm_pagemap_devmem *devmem_allocation)
	if (err)
		goto err_finalize;

	for (i = 0; i < npages; ++i)
	for (i = 0; i < npages;) {
		unsigned int order = 0;

		pages[i] = migrate_pfn_to_page(src[i]);
		if (pages[i])
			order = folio_order(page_folio(pages[i]));

		i += NR_PAGES(order);
	}

	err = ops->copy_to_ram(pages, pagemap_addr, npages, NULL);
	if (err)
@@ -1043,7 +1119,8 @@ static int __drm_pagemap_migrate_to_ram(struct vm_area_struct *vas,
		.vma		= vas,
		.pgmap_owner	= page_pgmap(page)->owner,
		.flags		= MIGRATE_VMA_SELECT_DEVICE_PRIVATE |
		MIGRATE_VMA_SELECT_DEVICE_COHERENT,
				  MIGRATE_VMA_SELECT_DEVICE_COHERENT |
				  MIGRATE_VMA_SELECT_COMPOUND,
		.fault_page	= page,
	};
	struct drm_pagemap_migrate_details mdetails = {};
@@ -1057,7 +1134,7 @@ static int __drm_pagemap_migrate_to_ram(struct vm_area_struct *vas,
	void *buf;
	int i, err = 0;

	zdd = page->zone_device_data;
	zdd = drm_pagemap_page_zone_device_data(page);
	if (time_before64(get_jiffies_64(), zdd->devmem_allocation->timeslice_expiration))
		return 0;

@@ -1109,8 +1186,15 @@ static int __drm_pagemap_migrate_to_ram(struct vm_area_struct *vas,
	if (err)
		goto err_finalize;

	for (i = 0; i < npages; ++i)
	for (i = 0; i < npages;) {
		unsigned int order = 0;

		pages[i] = migrate_pfn_to_page(migrate.src[i]);
		if (pages[i])
			order = folio_order(page_folio(pages[i]));

		i += NR_PAGES(order);
	}

	err = ops->copy_to_ram(pages, pagemap_addr, npages, NULL);
	if (err)
@@ -1140,7 +1224,9 @@ static int __drm_pagemap_migrate_to_ram(struct vm_area_struct *vas,
 */
static void drm_pagemap_folio_free(struct folio *folio)
{
	drm_pagemap_zdd_put(folio->page.zone_device_data);
	struct page *page = folio_page(folio, 0);

	drm_pagemap_zdd_put(drm_pagemap_page_zone_device_data(page));
}

/**
@@ -1156,7 +1242,7 @@ static void drm_pagemap_folio_free(struct folio *folio)
 */
static vm_fault_t drm_pagemap_migrate_to_ram(struct vm_fault *vmf)
{
	struct drm_pagemap_zdd *zdd = vmf->page->zone_device_data;
	struct drm_pagemap_zdd *zdd = drm_pagemap_page_zone_device_data(vmf->page);
	int err;

	err = __drm_pagemap_migrate_to_ram(vmf->vma,
@@ -1166,9 +1252,22 @@ static vm_fault_t drm_pagemap_migrate_to_ram(struct vm_fault *vmf)
	return err ? VM_FAULT_SIGBUS : 0;
}

static void drm_pagemap_folio_split(struct folio *orig_folio, struct folio *new_folio)
{
	struct drm_pagemap_zdd *zdd;

	if (!new_folio)
		return;

	new_folio->pgmap = orig_folio->pgmap;
	zdd = folio_zone_device_data(orig_folio);
	folio_set_zone_device_data(new_folio, drm_pagemap_zdd_get(zdd));
}

static const struct dev_pagemap_ops drm_pagemap_pagemap_ops = {
	.folio_free = drm_pagemap_folio_free,
	.migrate_to_ram = drm_pagemap_migrate_to_ram,
	.folio_split = drm_pagemap_folio_split,
};

/**
@@ -1222,7 +1321,7 @@ EXPORT_SYMBOL_GPL(drm_pagemap_devmem_init);
 */
struct drm_pagemap *drm_pagemap_page_to_dpagemap(struct page *page)
{
	struct drm_pagemap_zdd *zdd = page->zone_device_data;
	struct drm_pagemap_zdd *zdd = drm_pagemap_page_zone_device_data(page);

	return zdd->devmem_allocation->dpagemap;
}
+14 −14
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@ void ttm_resource_cursor_init(struct ttm_resource_cursor *cursor,
 * ttm_resource_cursor_fini() - Finalize the LRU list cursor usage
 * @cursor: The struct ttm_resource_cursor to finalize.
 *
 * The function pulls the LRU list cursor off any lists it was previusly
 * The function pulls the LRU list cursor off any lists it was previously
 * attached to. Needs to be called with the LRU lock held. The function
 * can be called multiple times after each other.
 */
@@ -317,10 +317,10 @@ void ttm_resource_move_to_lru_tail(struct ttm_resource *res)
}

/**
 * ttm_resource_init - resource object constructure
 * @bo: buffer object this resources is allocated for
 * ttm_resource_init - resource object constructor
 * @bo: buffer object this resource is allocated for
 * @place: placement of the resource
 * @res: the resource object to inistilize
 * @res: the resource object to initialize
 *
 * Initialize a new resource object. Counterpart of ttm_resource_fini().
 */
@@ -435,7 +435,7 @@ EXPORT_SYMBOL(ttm_resource_free);
 * @size: How many bytes the new allocation needs.
 *
 * Test if @res intersects with @place and @size. Used for testing if evictions
 * are valueable or not.
 * are valuable or not.
 *
 * Returns true if the res placement intersects with @place and @size.
 */
@@ -513,7 +513,7 @@ void ttm_resource_set_bo(struct ttm_resource *res,
 * @bdev: ttm device this manager belongs to
 * @size: size of managed resources in arbitrary units
 *
 * Initialise core parts of a manager object.
 * Initialize core parts of a manager object.
 */
void ttm_resource_manager_init(struct ttm_resource_manager *man,
			       struct ttm_device *bdev,
@@ -536,8 +536,8 @@ EXPORT_SYMBOL(ttm_resource_manager_init);
/*
 * ttm_resource_manager_evict_all
 *
 * @bdev - device to use
 * @man - manager to use
 * @bdev: device to use
 * @man: manager to use
 *
 * Evict all the objects out of a memory manager until it is empty.
 * Part of memory manager cleanup sequence.
@@ -882,7 +882,7 @@ ttm_kmap_iter_linear_io_init(struct ttm_kmap_iter_linear_io *iter_io,

/**
 * ttm_kmap_iter_linear_io_fini - Clean up an iterator for linear io memory
 * @iter_io: The iterator to initialize
 * @iter_io: The iterator to finalize
 * @bdev: The TTM device
 * @mem: The ttm resource representing the iomap.
 *
@@ -921,11 +921,11 @@ DEFINE_SHOW_ATTRIBUTE(ttm_resource_manager);
/**
 * ttm_resource_manager_create_debugfs - Create debugfs entry for specified
 * resource manager.
 * @man: The TTM resource manager for which the debugfs stats file be creates
 * @man: The TTM resource manager for which the debugfs stats file to be created
 * @parent: debugfs directory in which the file will reside
 * @name: The filename to create.
 *
 * This function setups up a debugfs file that can be used to look
 * This function sets up a debugfs file that can be used to look
 * at debug statistics of the specified ttm_resource_manager.
 */
void ttm_resource_manager_create_debugfs(struct ttm_resource_manager *man,
+8 −4
Original line number Diff line number Diff line
@@ -56,9 +56,11 @@ struct drm_gem_object *intel_fbdev_fb_bo_create(struct drm_device *drm, int size
	if (intel_fbdev_fb_prefer_stolen(drm, size)) {
		obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe),
						size,
						ttm_bo_type_kernel, XE_BO_FLAG_SCANOUT |
						ttm_bo_type_kernel,
						XE_BO_FLAG_FORCE_WC |
						XE_BO_FLAG_STOLEN |
						XE_BO_FLAG_GGTT, false);
						XE_BO_FLAG_GGTT,
						false);
		if (!IS_ERR(obj))
			drm_info(&xe->drm, "Allocated fbdev into stolen\n");
		else
@@ -69,9 +71,11 @@ struct drm_gem_object *intel_fbdev_fb_bo_create(struct drm_device *drm, int size

	if (IS_ERR(obj)) {
		obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe), size,
						ttm_bo_type_kernel, XE_BO_FLAG_SCANOUT |
						ttm_bo_type_kernel,
						XE_BO_FLAG_FORCE_WC |
						XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(xe)) |
						XE_BO_FLAG_GGTT, false);
						XE_BO_FLAG_GGTT,
						false);
	}

	if (IS_ERR(obj)) {
+8 −0
Original line number Diff line number Diff line
@@ -541,6 +541,13 @@ static const struct intel_display_irq_interface xe_display_irq_interface = {
	.synchronize = irq_synchronize,
};

static bool has_auxccs(struct drm_device *drm)
{
	struct xe_device *xe = to_xe_device(drm);

	return xe->info.platform == XE_ALDERLAKE_P;
}

static const struct intel_display_parent_interface parent = {
	.bo = &xe_display_bo_interface,
	.dsb = &xe_display_dsb_interface,
@@ -552,6 +559,7 @@ static const struct intel_display_parent_interface parent = {
	.pcode = &xe_display_pcode_interface,
	.rpm = &xe_display_rpm_interface,
	.stolen = &xe_display_stolen_interface,
	.has_auxccs = has_auxccs,
};

/**
Loading