drivers/gpu/drm/i915/i915_fb_pin.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/i915_fb_pin.c
Extension
.c
Size
8178 bytes
Lines
312
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

if (HAS_LMEM(i915)) {
			unsigned int flags = obj->flags;

			/*
			 * For this type of buffer we need to able to read from the CPU
			 * the clear color value found in the buffer, hence we need to
			 * ensure it is always in the mappable part of lmem, if this is
			 * a small-bar device.
			 */
			if (pin_params->needs_cpu_lmem_access)
				flags &= ~I915_BO_ALLOC_GPU_ONLY;
			ret = __i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM_0,
							flags);
			if (ret)
				continue;
		}

		ret = i915_gem_object_set_cache_level(obj, I915_CACHE_NONE);
		if (ret)
			continue;

		vma = i915_vma_instance(obj, vm, pin_params->view);
		if (IS_ERR(vma)) {
			ret = PTR_ERR(vma);
			continue;
		}

		if (i915_vma_misplaced(vma, 0, pin_params->alignment, 0)) {
			ret = i915_vma_unbind(vma);
			if (ret)
				continue;
		}

		ret = i915_vma_pin_ww(vma, &ww, 0, pin_params->alignment,
				      PIN_GLOBAL);
		if (ret)
			continue;
	}
	if (ret) {
		vma = ERR_PTR(ret);
		goto err;
	}

	vma->display_alignment = max(vma->display_alignment,
				     pin_params->alignment);

	i915_gem_object_flush_if_display(obj);

	i915_vma_get(vma);

	/*
	 * The DPT object contains only one vma, and there is no VT-d
	 * guard, so the VMA's offset within the DPT is always 0.
	 */
	drm_WARN_ON(&i915->drm, i915_dpt_offset(vma));
err:
	atomic_dec(&i915->pending_fb_pin);

	return vma;
}

static struct i915_vma *
intel_fb_pin_to_ggtt(struct drm_gem_object *_obj,
		     const struct intel_fb_pin_params *pin_params,
		     int *out_fence_id)
{
	struct drm_i915_private *i915 = to_i915(_obj->dev);
	struct drm_i915_gem_object *obj = to_intel_bo(_obj);
	intel_wakeref_t wakeref;
	struct i915_gem_ww_ctx ww;
	struct i915_vma *vma;
	unsigned int pinctl;
	int ret;

	if (drm_WARN_ON(&i915->drm, !i915_gem_object_is_framebuffer(obj)))
		return ERR_PTR(-EINVAL);

	if (drm_WARN_ON(&i915->drm, pin_params->alignment &&
			!is_power_of_2(pin_params->alignment)))
		return ERR_PTR(-EINVAL);

	/*
	 * Global gtt pte registers are special registers which actually forward
	 * writes to a chunk of system memory. Which means that there is no risk
	 * that the register values disappear as soon as we call
	 * intel_runtime_pm_put(), so it is correct to wrap only the
	 * pin/unpin/fence and not more.
	 */
	wakeref = intel_runtime_pm_get(&i915->runtime_pm);

Annotation

Implementation Notes