drivers/gpu/drm/drm_gpusvm.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/drm_gpusvm.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/drm_gpusvm.c
Extension
.c
Size
54102 bytes
Lines
1806
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

*		if (IS_ERR(range)) {
 *			err = PTR_ERR(range);
 *			goto unlock;
 *		}
 *
 *		if (driver_migration_policy(range)) {
 *			err = drm_pagemap_populate_mm(driver_choose_drm_pagemap(),
 *						      gpuva_start, gpuva_end, gpusvm->mm,
 *						      ctx->timeslice_ms);
 *			if (err)	// CPU mappings may have changed
 *				goto retry;
 *		}
 *
 *		err = drm_gpusvm_range_get_pages(gpusvm, range, &ctx);
 *		if (err == -EOPNOTSUPP || err == -EFAULT || err == -EPERM) {	// CPU mappings changed
 *			if (err == -EOPNOTSUPP)
 *				drm_gpusvm_range_evict(gpusvm, range);
 *			goto retry;
 *		} else if (err) {
 *			goto unlock;
 *		}
 *
 *		err = driver_bind_range(gpusvm, range);
 *		if (err == -EAGAIN)	// CPU mappings changed
 *			goto retry
 *
 *	unlock:
 *		driver_svm_unlock();
 *		return err;
 *	}
 *
 * 2) Garbage Collector
 *
 * .. code-block:: c
 *
 *	void __driver_garbage_collector(struct drm_gpusvm *gpusvm,
 *					struct drm_gpusvm_range *range)
 *	{
 *		assert_driver_svm_locked(gpusvm);
 *
 *		// Partial unmap, migrate any remaining device memory pages back to RAM
 *		if (range->flags.partial_unmap)
 *			drm_gpusvm_range_evict(gpusvm, range);
 *
 *		driver_unbind_range(range);
 *		drm_gpusvm_range_remove(gpusvm, range);
 *	}
 *
 *	void driver_garbage_collector(struct drm_gpusvm *gpusvm)
 *	{
 *		assert_driver_svm_locked(gpusvm);
 *
 *		for_each_range_in_garbage_collector(gpusvm, range)
 *			__driver_garbage_collector(gpusvm, range);
 *	}
 *
 * 3) Notifier callback
 *
 * .. code-block:: c
 *
 *	void driver_invalidation(struct drm_gpusvm *gpusvm,
 *				 struct drm_gpusvm_notifier *notifier,
 *				 const struct mmu_notifier_range *mmu_range)
 *	{
 *		struct drm_gpusvm_ctx ctx = { .in_notifier = true, };
 *		struct drm_gpusvm_range *range = NULL;
 *
 *		driver_invalidate_device_pages(gpusvm, mmu_range->start, mmu_range->end);
 *
 *		drm_gpusvm_for_each_range(range, notifier, mmu_range->start,
 *					  mmu_range->end) {
 *			drm_gpusvm_range_unmap_pages(gpusvm, range, &ctx);
 *
 *			if (mmu_range->event != MMU_NOTIFY_UNMAP)
 *				continue;
 *
 *			drm_gpusvm_range_set_unmapped(range, mmu_range);
 *			driver_garbage_collector_add(gpusvm, range);
 *		}
 *	}
 */

/**
 * npages_in_range() - Calculate the number of pages in a given range
 * @start: The start address of the range
 * @end: The end address of the range
 *
 * This macro calculates the number of pages in a given memory range,
 * specified by the start and end addresses. It divides the difference
 * between the end and start addresses by the page size (PAGE_SIZE) to

Annotation

Implementation Notes