Commit 0faeb8cf authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-xe-next-2025-09-19' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-next



UAPI Changes:
 - Drop L3 bank mask reporting from the media GT on Xe3 and later. Only
   do that for the primary GT. No userspace needs or uses it for media
   and some platforms may report bogus values.
 - Add SLPC power_profile sysfs interface with support for base and
   power_saving modes (Vinay Belgaumkar, Rodrigo Vivi)
 - Add configfs attributes to add post/mid context-switch commands
   (Lucas De Marchi)

Cross-subsystem Changes:
 - Fix hmm_pfn_to_map_order() usage in gpusvm and refactor APIs to
   align with pieces previous handled by xe_hmm (Matthew Auld)

Core Changes:
 - Add MEI driver for Late Binding Firmware Update/Upload
   (Alexander Usyskin)

Driver Changes:
 - Fix GuC CT teardown wrt TLB invalidation (Satyanarayana)
 - Fix CCS save/restore on VF (Satyanarayana)
 - Increase default GuC crash buffer size (Zhanjun)
 - Allow to clear GT stats in debugfs to aid debugging (Matthew Brost)
 - Add more SVM GT stats to debugfs (Matthew Brost)
 - Fix error handling in VMA attr query (Himal)
 - Move sa_info in debugfs to be per tile (Michal Wajdeczko)
 - Limit number of retries upon receiving NO_RESPONSE_RETRY from GuC to
   avoid endless loop (Michal Wajdeczko)
 - Fix configfs handling for survivability_mode undoing user choice when
   unbinding the module (Michal Wajdeczko)
 - Refactor configfs attribute visibility to future-proof it and stop
   exposing survivability_mode if not applicable (Michal Wajdeczko)
 - Constify some functions (Harish Chegondi, Michal Wajdeczko)
 - Add/extend more HW workarounds for Xe2 and Xe3
   (Harish Chegondi, Tangudu Tilak Tirumalesh)
 - Replace xe_hmm with gpusvm (Matthew Auld)
 - Improve fake pci and WA kunit handling for testing new platforms
   (Michal Wajdeczko)
 - Reduce unnecessary PTE writes when migrating (Sanjay Yadav)
 - Cleanup GuC interface definitions and log message (John Harrison)
 - Small improvements around VF CCS (Michal Wajdeczko)
 - Enable bus mastering for the I2C controller (Raag Jadav)
 - Prefer devm_mutex of hand rolling it (Christophe JAILLET)
 - Drop sysfs and debugfs attributes not available for VF (Michal Wajdeczko)
 - GuC CT devm actions improvements (Michal Wajdeczko)
 - Recommend new GuC versions for PTL and BMG (Julia Filipchuk)
 - Improveme driver handling for exhaustive eviction using new
   xe_validation wrapper around drm_exec (Thomas Hellström)
 - Add and use printk wrappers for tile and device (Michal Wajdeczko)
 - Better document workaround handling in Xe (Lucas De Marchi)
 - Improvements on ARRAY_SIZE  and ERR_CAST usage (Lucas De Marchi,
   Fushuai Wang)
 - Align CSS firmware headers with the GuC APIs (John Harrison)
 - Test GuC to GuC (G2G) communication to aid debug in pre-production
   firmware (John Harrison)
 - Bail out driver probing if GuC fails to load (John Harrison)
 - Allow error injection in xe_pxp_exec_queue_add()
   (Daniele Ceraolo Spurio)
 - Minor refactors in xe_svm (Shuicheng Lin)
 - Fix madvise ioctl error handling (Shuicheng Lin)
 - Use attribute groups to simplify sysfs registration
   (Michal Wajdeczko)
 - Add Late Binding Firmware implementation in Xe to work together with
   the MEI component (Badal Nilawar, Daniele Ceraolo Spurio, Rodrigo
   Vivi)
 - Fix build with CONFIG_MODULES=n (Lucas De Marchi)

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Lucas De Marchi <lucas.demarchi@intel.com>
Link: https://lore.kernel.org/r/c2et6dnkst2apsgt46dklej4nprqdukjosb55grpaknf3pvcxy@t7gtn3hqtp6n
parents 748f41f3 d9b26233
Loading
Loading
Loading
Loading
+214 −83
Original line number Diff line number Diff line
@@ -373,6 +373,12 @@ static const struct mmu_interval_notifier_ops drm_gpusvm_notifier_ops = {
 *
 * This function initializes the GPU SVM.
 *
 * Note: If only using the simple drm_gpusvm_pages API (get/unmap/free),
 * then only @gpusvm, @name, and @drm are expected. However, the same base
 * @gpusvm can also be used with both modes together in which case the full
 * setup is needed, where the core drm_gpusvm_pages API will simply never use
 * the other fields.
 *
 * Return: 0 on success, a negative error code on failure.
 */
int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
@@ -383,8 +389,16 @@ int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
		    const struct drm_gpusvm_ops *ops,
		    const unsigned long *chunk_sizes, int num_chunks)
{
	if (mm) {
		if (!ops->invalidate || !num_chunks)
			return -EINVAL;
		mmgrab(mm);
	} else {
		/* No full SVM mode, only core drm_gpusvm_pages API. */
		if (ops || num_chunks || mm_range || notifier_size ||
		    device_private_page_owner)
			return -EINVAL;
	}

	gpusvm->name = name;
	gpusvm->drm = drm;
@@ -397,7 +411,6 @@ int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
	gpusvm->chunk_sizes = chunk_sizes;
	gpusvm->num_chunks = num_chunks;

	mmgrab(mm);
	gpusvm->root = RB_ROOT_CACHED;
	INIT_LIST_HEAD(&gpusvm->notifier_list);

@@ -489,6 +502,7 @@ void drm_gpusvm_fini(struct drm_gpusvm *gpusvm)
			drm_gpusvm_range_remove(gpusvm, range);
	}

	if (gpusvm->mm)
		mmdrop(gpusvm->mm);
	WARN_ON(!RB_EMPTY_ROOT(&gpusvm->root.rb_root));
}
@@ -629,12 +643,41 @@ drm_gpusvm_range_alloc(struct drm_gpusvm *gpusvm,
	range->itree.start = ALIGN_DOWN(fault_addr, chunk_size);
	range->itree.last = ALIGN(fault_addr + 1, chunk_size) - 1;
	INIT_LIST_HEAD(&range->entry);
	range->notifier_seq = LONG_MAX;
	range->flags.migrate_devmem = migrate_devmem ? 1 : 0;
	range->pages.notifier_seq = LONG_MAX;
	range->pages.flags.migrate_devmem = migrate_devmem ? 1 : 0;

	return range;
}

/**
 * drm_gpusvm_hmm_pfn_to_order() - Get the largest CPU mapping order.
 * @hmm_pfn: The current hmm_pfn.
 * @hmm_pfn_index: Index of the @hmm_pfn within the pfn array.
 * @npages: Number of pages within the pfn array i.e the hmm range size.
 *
 * To allow skipping PFNs with the same flags (like when they belong to
 * the same huge PTE) when looping over the pfn array, take a given a hmm_pfn,
 * and return the largest order that will fit inside the CPU PTE, but also
 * crucially accounting for the original hmm range boundaries.
 *
 * Return: The largest order that will safely fit within the size of the hmm_pfn
 * CPU PTE.
 */
static unsigned int drm_gpusvm_hmm_pfn_to_order(unsigned long hmm_pfn,
						unsigned long hmm_pfn_index,
						unsigned long npages)
{
	unsigned long size;

	size = 1UL << hmm_pfn_to_map_order(hmm_pfn);
	size -= (hmm_pfn & ~HMM_PFN_FLAGS) & (size - 1);
	hmm_pfn_index += size;
	if (hmm_pfn_index > npages)
		size -= (hmm_pfn_index - npages);

	return ilog2(size);
}

/**
 * drm_gpusvm_check_pages() - Check pages
 * @gpusvm: Pointer to the GPU SVM structure
@@ -693,7 +736,7 @@ static bool drm_gpusvm_check_pages(struct drm_gpusvm *gpusvm,
			err = -EFAULT;
			goto err_free;
		}
		i += 0x1 << hmm_pfn_to_map_order(pfns[i]);
		i += 0x1 << drm_gpusvm_hmm_pfn_to_order(pfns[i], i, npages);
	}

err_free:
@@ -951,31 +994,31 @@ drm_gpusvm_range_find_or_insert(struct drm_gpusvm *gpusvm,
EXPORT_SYMBOL_GPL(drm_gpusvm_range_find_or_insert);

/**
 * __drm_gpusvm_range_unmap_pages() - Unmap pages associated with a GPU SVM range (internal)
 * __drm_gpusvm_unmap_pages() - Unmap pages associated with GPU SVM pages (internal)
 * @gpusvm: Pointer to the GPU SVM structure
 * @range: Pointer to the GPU SVM range structure
 * @svm_pages: Pointer to the GPU SVM pages structure
 * @npages: Number of pages to unmap
 *
 * This function unmap pages associated with a GPU SVM range. Assumes and
 * This function unmap pages associated with a GPU SVM pages struct. Assumes and
 * asserts correct locking is in place when called.
 */
static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
					   struct drm_gpusvm_range *range,
static void __drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
				     struct drm_gpusvm_pages *svm_pages,
				     unsigned long npages)
{
	unsigned long i, j;
	struct drm_pagemap *dpagemap = range->dpagemap;
	struct drm_pagemap *dpagemap = svm_pages->dpagemap;
	struct device *dev = gpusvm->drm->dev;
	unsigned long i, j;

	lockdep_assert_held(&gpusvm->notifier_lock);

	if (range->flags.has_dma_mapping) {
		struct drm_gpusvm_range_flags flags = {
			.__flags = range->flags.__flags,
	if (svm_pages->flags.has_dma_mapping) {
		struct drm_gpusvm_pages_flags flags = {
			.__flags = svm_pages->flags.__flags,
		};

		for (i = 0, j = 0; i < npages; j++) {
			struct drm_pagemap_addr *addr = &range->dma_addr[j];
			struct drm_pagemap_addr *addr = &svm_pages->dma_addr[j];

			if (addr->proto == DRM_INTERCONNECT_SYSTEM)
				dma_unmap_page(dev,
@@ -991,29 +1034,50 @@ static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
		/* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */
		flags.has_devmem_pages = false;
		flags.has_dma_mapping = false;
		WRITE_ONCE(range->flags.__flags, flags.__flags);
		WRITE_ONCE(svm_pages->flags.__flags, flags.__flags);

		range->dpagemap = NULL;
		svm_pages->dpagemap = NULL;
	}
}

/**
 * drm_gpusvm_range_free_pages() - Free pages associated with a GPU SVM range
 * __drm_gpusvm_free_pages() - Free dma array associated with GPU SVM pages
 * @gpusvm: Pointer to the GPU SVM structure
 * @range: Pointer to the GPU SVM range structure
 * @svm_pages: Pointer to the GPU SVM pages structure
 *
 * This function frees the dma address array associated with a GPU SVM range.
 */
static void drm_gpusvm_range_free_pages(struct drm_gpusvm *gpusvm,
					struct drm_gpusvm_range *range)
static void __drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
				    struct drm_gpusvm_pages *svm_pages)
{
	lockdep_assert_held(&gpusvm->notifier_lock);

	if (range->dma_addr) {
		kvfree(range->dma_addr);
		range->dma_addr = NULL;
	if (svm_pages->dma_addr) {
		kvfree(svm_pages->dma_addr);
		svm_pages->dma_addr = NULL;
	}
}

/**
 * drm_gpusvm_free_pages() - Free dma-mapping associated with GPU SVM pages
 * struct
 * @gpusvm: Pointer to the GPU SVM structure
 * @svm_pages: Pointer to the GPU SVM pages structure
 * @npages: Number of mapped pages
 *
 * This function unmaps and frees the dma address array associated with a GPU
 * SVM pages struct.
 */
void drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
			   struct drm_gpusvm_pages *svm_pages,
			   unsigned long npages)
{
	drm_gpusvm_notifier_lock(gpusvm);
	__drm_gpusvm_unmap_pages(gpusvm, svm_pages, npages);
	__drm_gpusvm_free_pages(gpusvm, svm_pages);
	drm_gpusvm_notifier_unlock(gpusvm);
}
EXPORT_SYMBOL_GPL(drm_gpusvm_free_pages);

/**
 * drm_gpusvm_range_remove() - Remove GPU SVM range
@@ -1040,8 +1104,8 @@ void drm_gpusvm_range_remove(struct drm_gpusvm *gpusvm,
		return;

	drm_gpusvm_notifier_lock(gpusvm);
	__drm_gpusvm_range_unmap_pages(gpusvm, range, npages);
	drm_gpusvm_range_free_pages(gpusvm, range);
	__drm_gpusvm_unmap_pages(gpusvm, &range->pages, npages);
	__drm_gpusvm_free_pages(gpusvm, &range->pages);
	__drm_gpusvm_range_remove(notifier, range);
	drm_gpusvm_notifier_unlock(gpusvm);

@@ -1106,6 +1170,28 @@ void drm_gpusvm_range_put(struct drm_gpusvm_range *range)
}
EXPORT_SYMBOL_GPL(drm_gpusvm_range_put);

/**
 * drm_gpusvm_pages_valid() - GPU SVM range pages valid
 * @gpusvm: Pointer to the GPU SVM structure
 * @svm_pages: Pointer to the GPU SVM pages structure
 *
 * This function determines if a GPU SVM range pages are valid. Expected be
 * called holding gpusvm->notifier_lock and as the last step before committing a
 * GPU binding. This is akin to a notifier seqno check in the HMM documentation
 * but due to wider notifiers (i.e., notifiers which span multiple ranges) this
 * function is required for finer grained checking (i.e., per range) if pages
 * are valid.
 *
 * Return: True if GPU SVM range has valid pages, False otherwise
 */
static bool drm_gpusvm_pages_valid(struct drm_gpusvm *gpusvm,
				   struct drm_gpusvm_pages *svm_pages)
{
	lockdep_assert_held(&gpusvm->notifier_lock);

	return svm_pages->flags.has_devmem_pages || svm_pages->flags.has_dma_mapping;
}

/**
 * drm_gpusvm_range_pages_valid() - GPU SVM range pages valid
 * @gpusvm: Pointer to the GPU SVM structure
@@ -1123,9 +1209,7 @@ EXPORT_SYMBOL_GPL(drm_gpusvm_range_put);
bool drm_gpusvm_range_pages_valid(struct drm_gpusvm *gpusvm,
				  struct drm_gpusvm_range *range)
{
	lockdep_assert_held(&gpusvm->notifier_lock);

	return range->flags.has_devmem_pages || range->flags.has_dma_mapping;
	return drm_gpusvm_pages_valid(gpusvm, &range->pages);
}
EXPORT_SYMBOL_GPL(drm_gpusvm_range_pages_valid);

@@ -1139,66 +1223,71 @@ EXPORT_SYMBOL_GPL(drm_gpusvm_range_pages_valid);
 *
 * Return: True if GPU SVM range has valid pages, False otherwise
 */
static bool
drm_gpusvm_range_pages_valid_unlocked(struct drm_gpusvm *gpusvm,
				      struct drm_gpusvm_range *range)
static bool drm_gpusvm_pages_valid_unlocked(struct drm_gpusvm *gpusvm,
					    struct drm_gpusvm_pages *svm_pages)
{
	bool pages_valid;

	if (!range->dma_addr)
	if (!svm_pages->dma_addr)
		return false;

	drm_gpusvm_notifier_lock(gpusvm);
	pages_valid = drm_gpusvm_range_pages_valid(gpusvm, range);
	pages_valid = drm_gpusvm_pages_valid(gpusvm, svm_pages);
	if (!pages_valid)
		drm_gpusvm_range_free_pages(gpusvm, range);
		__drm_gpusvm_free_pages(gpusvm, svm_pages);
	drm_gpusvm_notifier_unlock(gpusvm);

	return pages_valid;
}

/**
 * drm_gpusvm_range_get_pages() - Get pages for a GPU SVM range
 * drm_gpusvm_get_pages() - Get pages and populate GPU SVM pages struct
 * @gpusvm: Pointer to the GPU SVM structure
 * @range: Pointer to the GPU SVM range structure
 * @svm_pages: The SVM pages to populate. This will contain the dma-addresses
 * @mm: The mm corresponding to the CPU range
 * @notifier: The corresponding notifier for the given CPU range
 * @pages_start: Start CPU address for the pages
 * @pages_end: End CPU address for the pages (exclusive)
 * @ctx: GPU SVM context
 *
 * This function gets pages for a GPU SVM range and ensures they are mapped for
 * DMA access.
 * This function gets and maps pages for CPU range and ensures they are
 * mapped for DMA access.
 *
 * Return: 0 on success, negative error code on failure.
 */
int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
			       struct drm_gpusvm_range *range,
int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
			 struct drm_gpusvm_pages *svm_pages,
			 struct mm_struct *mm,
			 struct mmu_interval_notifier *notifier,
			 unsigned long pages_start, unsigned long pages_end,
			 const struct drm_gpusvm_ctx *ctx)
{
	struct mmu_interval_notifier *notifier = &range->notifier->notifier;
	struct hmm_range hmm_range = {
		.default_flags = HMM_PFN_REQ_FAULT | (ctx->read_only ? 0 :
			HMM_PFN_REQ_WRITE),
		.notifier = notifier,
		.start = drm_gpusvm_range_start(range),
		.end = drm_gpusvm_range_end(range),
		.start = pages_start,
		.end = pages_end,
		.dev_private_owner = gpusvm->device_private_page_owner,
	};
	struct mm_struct *mm = gpusvm->mm;
	void *zdd;
	unsigned long timeout =
		jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
	unsigned long i, j;
	unsigned long npages = npages_in_range(drm_gpusvm_range_start(range),
					       drm_gpusvm_range_end(range));
	unsigned long npages = npages_in_range(pages_start, pages_end);
	unsigned long num_dma_mapped;
	unsigned int order = 0;
	unsigned long *pfns;
	int err = 0;
	struct dev_pagemap *pagemap;
	struct drm_pagemap *dpagemap;
	struct drm_gpusvm_range_flags flags;
	struct drm_gpusvm_pages_flags flags;
	enum dma_data_direction dma_dir = ctx->read_only ? DMA_TO_DEVICE :
							   DMA_BIDIRECTIONAL;

retry:
	hmm_range.notifier_seq = mmu_interval_read_begin(notifier);
	if (drm_gpusvm_range_pages_valid_unlocked(gpusvm, range))
	if (drm_gpusvm_pages_valid_unlocked(gpusvm, svm_pages))
		goto set_seqno;

	pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
@@ -1238,7 +1327,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
	 */
	drm_gpusvm_notifier_lock(gpusvm);

	flags.__flags = range->flags.__flags;
	flags.__flags = svm_pages->flags.__flags;
	if (flags.unmapped) {
		drm_gpusvm_notifier_unlock(gpusvm);
		err = -EFAULT;
@@ -1251,13 +1340,12 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
		goto retry;
	}

	if (!range->dma_addr) {
	if (!svm_pages->dma_addr) {
		/* Unlock and restart mapping to allocate memory. */
		drm_gpusvm_notifier_unlock(gpusvm);
		range->dma_addr = kvmalloc_array(npages,
						 sizeof(*range->dma_addr),
						 GFP_KERNEL);
		if (!range->dma_addr) {
		svm_pages->dma_addr =
			kvmalloc_array(npages, sizeof(*svm_pages->dma_addr), GFP_KERNEL);
		if (!svm_pages->dma_addr) {
			err = -ENOMEM;
			goto err_free;
		}
@@ -1270,7 +1358,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
	for (i = 0, j = 0; i < npages; ++j) {
		struct page *page = hmm_pfn_to_page(pfns[i]);

		order = hmm_pfn_to_map_order(pfns[i]);
		order = drm_gpusvm_hmm_pfn_to_order(pfns[i], i, npages);
		if (is_device_private_page(page) ||
		    is_device_coherent_page(page)) {
			if (zdd != page->zone_device_data && i > 0) {
@@ -1296,13 +1384,13 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
					goto err_unmap;
				}
			}
			range->dma_addr[j] =
			svm_pages->dma_addr[j] =
				dpagemap->ops->device_map(dpagemap,
							  gpusvm->drm->dev,
							  page, order,
							  DMA_BIDIRECTIONAL);
							  dma_dir);
			if (dma_mapping_error(gpusvm->drm->dev,
					      range->dma_addr[j].addr)) {
					      svm_pages->dma_addr[j].addr)) {
				err = -EFAULT;
				goto err_unmap;
			}
@@ -1322,15 +1410,15 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
			addr = dma_map_page(gpusvm->drm->dev,
					    page, 0,
					    PAGE_SIZE << order,
					    DMA_BIDIRECTIONAL);
					    dma_dir);
			if (dma_mapping_error(gpusvm->drm->dev, addr)) {
				err = -EFAULT;
				goto err_unmap;
			}

			range->dma_addr[j] = drm_pagemap_addr_encode
			svm_pages->dma_addr[j] = drm_pagemap_addr_encode
				(addr, DRM_INTERCONNECT_SYSTEM, order,
				 DMA_BIDIRECTIONAL);
				 dma_dir);
		}
		i += 1 << order;
		num_dma_mapped = i;
@@ -1339,21 +1427,21 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,

	if (pagemap) {
		flags.has_devmem_pages = true;
		range->dpagemap = dpagemap;
		svm_pages->dpagemap = dpagemap;
	}

	/* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */
	WRITE_ONCE(range->flags.__flags, flags.__flags);
	WRITE_ONCE(svm_pages->flags.__flags, flags.__flags);

	drm_gpusvm_notifier_unlock(gpusvm);
	kvfree(pfns);
set_seqno:
	range->notifier_seq = hmm_range.notifier_seq;
	svm_pages->notifier_seq = hmm_range.notifier_seq;

	return 0;

err_unmap:
	__drm_gpusvm_range_unmap_pages(gpusvm, range, num_dma_mapped);
	__drm_gpusvm_unmap_pages(gpusvm, svm_pages, num_dma_mapped);
	drm_gpusvm_notifier_unlock(gpusvm);
err_free:
	kvfree(pfns);
@@ -1361,11 +1449,62 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
		goto retry;
	return err;
}
EXPORT_SYMBOL_GPL(drm_gpusvm_get_pages);

/**
 * drm_gpusvm_range_get_pages() - Get pages for a GPU SVM range
 * @gpusvm: Pointer to the GPU SVM structure
 * @range: Pointer to the GPU SVM range structure
 * @ctx: GPU SVM context
 *
 * This function gets pages for a GPU SVM range and ensures they are mapped for
 * DMA access.
 *
 * Return: 0 on success, negative error code on failure.
 */
int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
			       struct drm_gpusvm_range *range,
			       const struct drm_gpusvm_ctx *ctx)
{
	return drm_gpusvm_get_pages(gpusvm, &range->pages, gpusvm->mm,
				    &range->notifier->notifier,
				    drm_gpusvm_range_start(range),
				    drm_gpusvm_range_end(range), ctx);
}
EXPORT_SYMBOL_GPL(drm_gpusvm_range_get_pages);

/**
 * drm_gpusvm_unmap_pages() - Unmap GPU svm pages
 * @gpusvm: Pointer to the GPU SVM structure
 * @svm_pages: Pointer to the GPU SVM pages structure
 * @npages: Number of pages in @svm_pages.
 * @ctx: GPU SVM context
 *
 * This function unmaps pages associated with a GPU SVM pages struct. If
 * @in_notifier is set, it is assumed that gpusvm->notifier_lock is held in
 * write mode; if it is clear, it acquires gpusvm->notifier_lock in read mode.
 * Must be called in the invalidate() callback of the corresponding notifier for
 * IOMMU security model.
 */
void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
			    struct drm_gpusvm_pages *svm_pages,
			    unsigned long npages,
			    const struct drm_gpusvm_ctx *ctx)
{
	if (ctx->in_notifier)
		lockdep_assert_held_write(&gpusvm->notifier_lock);
	else
		drm_gpusvm_notifier_lock(gpusvm);

	__drm_gpusvm_unmap_pages(gpusvm, svm_pages, npages);

	if (!ctx->in_notifier)
		drm_gpusvm_notifier_unlock(gpusvm);
}
EXPORT_SYMBOL_GPL(drm_gpusvm_unmap_pages);

/**
 * drm_gpusvm_range_unmap_pages() - Unmap pages associated with a GPU SVM range
 * drm_gpusvm_range_evict() - Evict GPU SVM range
 * @gpusvm: Pointer to the GPU SVM structure
 * @range: Pointer to the GPU SVM range structure
 * @ctx: GPU SVM context
@@ -1383,15 +1522,7 @@ void drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
	unsigned long npages = npages_in_range(drm_gpusvm_range_start(range),
					       drm_gpusvm_range_end(range));

	if (ctx->in_notifier)
		lockdep_assert_held_write(&gpusvm->notifier_lock);
	else
		drm_gpusvm_notifier_lock(gpusvm);

	__drm_gpusvm_range_unmap_pages(gpusvm, range, npages);

	if (!ctx->in_notifier)
		drm_gpusvm_notifier_unlock(gpusvm);
	return drm_gpusvm_unmap_pages(gpusvm, &range->pages, npages, ctx);
}
EXPORT_SYMBOL_GPL(drm_gpusvm_range_unmap_pages);

@@ -1489,10 +1620,10 @@ void drm_gpusvm_range_set_unmapped(struct drm_gpusvm_range *range,
{
	lockdep_assert_held_write(&range->gpusvm->notifier_lock);

	range->flags.unmapped = true;
	range->pages.flags.unmapped = true;
	if (drm_gpusvm_range_start(range) < mmu_range->start ||
	    drm_gpusvm_range_end(range) > mmu_range->end)
		range->flags.partial_unmap = true;
		range->pages.flags.partial_unmap = true;
}
EXPORT_SYMBOL_GPL(drm_gpusvm_range_set_unmapped);

+1 −1
Original line number Diff line number Diff line
@@ -40,12 +40,12 @@ config DRM_XE
	select DRM_TTM
	select DRM_TTM_HELPER
	select DRM_EXEC
	select DRM_GPUSVM if !UML && DEVICE_PRIVATE
	select DRM_GPUVM
	select DRM_SCHED
	select MMU_NOTIFIER
	select WANT_DEV_COREDUMP
	select AUXILIARY_BUS
	select HMM_MIRROR
	select REGMAP if I2C
	help
	  Driver for Intel Xe2 series GPUs and later. Experimental support
+1 −0
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ config DRM_XE_DEBUG_GUC

config DRM_XE_USERPTR_INVAL_INJECT
       bool "Inject userptr invalidation -EINVAL errors"
       depends on DRM_GPUSVM
       default n
       help
         Choose this option when debugging error paths that
+4 −1
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ xe-y += xe_bb.o \
	xe_hw_error.o \
	xe_hw_fence.o \
	xe_irq.o \
	xe_late_bind_fw.o \
	xe_lrc.o \
	xe_migrate.o \
	xe_mmio.o \
@@ -130,6 +131,7 @@ xe-y += xe_bb.o \
	xe_tuning.o \
	xe_uc.o \
	xe_uc_fw.o \
	xe_validation.o \
	xe_vm.o \
	xe_vm_madvise.o \
	xe_vram.o \
@@ -140,8 +142,8 @@ xe-y += xe_bb.o \
	xe_wopcm.o

xe-$(CONFIG_I2C)	+= xe_i2c.o
xe-$(CONFIG_HMM_MIRROR) += xe_hmm.o
xe-$(CONFIG_DRM_XE_GPUSVM) += xe_svm.o
xe-$(CONFIG_DRM_GPUSVM) += xe_userptr.o

# graphics hardware monitoring (HWMON) support
xe-$(CONFIG_HWMON) += xe_hwmon.o
@@ -326,6 +328,7 @@ ifeq ($(CONFIG_DEBUG_FS),y)
		xe_gt_stats.o \
		xe_guc_debugfs.o \
		xe_huc_debugfs.o \
		xe_tile_debugfs.o \
		xe_uc_debugfs.o

	xe-$(CONFIG_PCI_IOV) += xe_gt_sriov_pf_debugfs.o
+3 −0
Original line number Diff line number Diff line
@@ -117,6 +117,7 @@ enum xe_guc_action {
	XE_GUC_ACTION_ENTER_S_STATE = 0x501,
	XE_GUC_ACTION_EXIT_S_STATE = 0x502,
	XE_GUC_ACTION_GLOBAL_SCHED_POLICY_CHANGE = 0x506,
	XE_GUC_ACTION_UPDATE_SCHEDULING_POLICIES_KLV = 0x509,
	XE_GUC_ACTION_SCHED_CONTEXT = 0x1000,
	XE_GUC_ACTION_SCHED_CONTEXT_MODE_SET = 0x1001,
	XE_GUC_ACTION_SCHED_CONTEXT_MODE_DONE = 0x1002,
@@ -154,6 +155,8 @@ enum xe_guc_action {
	XE_GUC_ACTION_NOTIFY_FLUSH_LOG_BUFFER_TO_FILE = 0x8003,
	XE_GUC_ACTION_NOTIFY_CRASH_DUMP_POSTED = 0x8004,
	XE_GUC_ACTION_NOTIFY_EXCEPTION = 0x8005,
	XE_GUC_ACTION_TEST_G2G_SEND = 0xF001,
	XE_GUC_ACTION_TEST_G2G_RECV = 0xF002,
	XE_GUC_ACTION_LIMIT
};

Loading