Commit 3afef438 authored by Ville Syrjälä's avatar Ville Syrjälä
Browse files

drm/i915/frontbuffer: Split fb_tracking.lock into two



Our fb_tracking.lock is serving a double duty:
- protects fb_tracking.busy_bits
- provides the write-side protection for obj->frontbuffer

Split obj->frontbuffer role into a separate lock so that
we can clean up the current mess with the frontbuffer lifetime
management.

Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patch.msgid.link/20251016185408.22735-7-ville.syrjala@linux.intel.com


Reviewed-by: default avatarJani Nikula <jani.nikula@intel.com>
parent 65417489
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -142,6 +142,10 @@ struct intel_dpll_global {
};

struct intel_frontbuffer_tracking {
	/* protects obj->frontbuffer (write-side) */
	spinlock_t frontbuffer_lock;

	/* protects busy_bits */
	spinlock_t lock;

	/*
+1 −0
Original line number Diff line number Diff line
@@ -186,6 +186,7 @@ void intel_display_driver_early_probe(struct intel_display *display)
	if (!HAS_DISPLAY(display))
		return;

	spin_lock_init(&display->fb_tracking.frontbuffer_lock);
	spin_lock_init(&display->fb_tracking.lock);
	mutex_init(&display->backlight.lock);
	mutex_init(&display->audio.mutex);
+5 −5
Original line number Diff line number Diff line
@@ -210,7 +210,7 @@ static void frontbuffer_retire(struct i915_active *ref)
}

static void frontbuffer_release(struct kref *ref)
	__releases(&to_intel_display(front->obj->dev)->fb_tracking.lock)
	__releases(&to_intel_display(front->obj->dev)->fb_tracking.frontbuffer_lock)
{
	struct intel_frontbuffer *ret, *front =
		container_of(ref, typeof(*front), ref);
@@ -223,7 +223,7 @@ static void frontbuffer_release(struct kref *ref)

	ret = intel_bo_set_frontbuffer(obj, NULL);
	drm_WARN_ON(display->drm, ret);
	spin_unlock(&display->fb_tracking.lock);
	spin_unlock(&display->fb_tracking.frontbuffer_lock);

	i915_active_fini(&front->write);

@@ -256,9 +256,9 @@ intel_frontbuffer_get(struct drm_gem_object *obj)
			 I915_ACTIVE_RETIRE_SLEEPS);
	INIT_WORK(&front->flush_work, intel_frontbuffer_flush_work);

	spin_lock(&display->fb_tracking.lock);
	spin_lock(&display->fb_tracking.frontbuffer_lock);
	cur = intel_bo_set_frontbuffer(obj, front);
	spin_unlock(&display->fb_tracking.lock);
	spin_unlock(&display->fb_tracking.frontbuffer_lock);

	if (cur != front) {
		drm_gem_object_put(obj);
@@ -272,7 +272,7 @@ void intel_frontbuffer_put(struct intel_frontbuffer *front)
{
	kref_put_lock(&front->ref,
		      frontbuffer_release,
		      &to_intel_display(front->obj->dev)->fb_tracking.lock);
		      &to_intel_display(front->obj->dev)->fb_tracking.frontbuffer_lock);
}

/**
+1 −1
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ i915_gem_object_get_frontbuffer(const struct drm_i915_gem_object *obj)
 * Set object's frontbuffer pointer. If frontbuffer is already set for the
 * object keep it and return it's pointer to the caller. Please note that RCU
 * mechanism is used to handle e.g. ongoing removal of frontbuffer pointer. This
 * function is protected by i915->display->fb_tracking.lock
 * function is protected by i915->display->fb_tracking.frontbuffer_lock
 *
 * Return: pointer to frontbuffer which was set.
 */