Commit 7b574550 authored by Jouni Högander's avatar Jouni Högander
Browse files

drm/i915: Add getter/setter for i915_gem_object->frontbuffer

Rendering aborted due to complexity issues. If this is valid markdown, please feel free to open an issue and attach the original markdown to the issue.

parent 72e31c0a
Loading
Loading
Loading
Loading
+7 −13
Original line number Diff line number Diff line
@@ -237,7 +237,7 @@ static void frontbuffer_release(struct kref *ref)
	}
	spin_unlock(&obj->vma.lock);

	RCU_INIT_POINTER(obj->frontbuffer, NULL);
	i915_gem_object_set_frontbuffer(obj, NULL);
	spin_unlock(&intel_bo_to_i915(obj)->display.fb_tracking.lock);

	i915_active_fini(&front->write);
@@ -250,9 +250,9 @@ struct intel_frontbuffer *
intel_frontbuffer_get(struct drm_i915_gem_object *obj)
{
	struct drm_i915_private *i915 = intel_bo_to_i915(obj);
	struct intel_frontbuffer *front;
	struct intel_frontbuffer *front, *cur;

	front = __intel_frontbuffer_get(obj);
	front = i915_gem_object_get_frontbuffer(obj);
	if (front)
		return front;

@@ -269,17 +269,11 @@ intel_frontbuffer_get(struct drm_i915_gem_object *obj)
			 I915_ACTIVE_RETIRE_SLEEPS);

	spin_lock(&i915->display.fb_tracking.lock);
	if (rcu_access_pointer(obj->frontbuffer)) {
		kfree(front);
		front = rcu_dereference_protected(obj->frontbuffer, true);
		kref_get(&front->ref);
	} else {
		i915_gem_object_get(obj);
		rcu_assign_pointer(obj->frontbuffer, front);
	}
	cur = i915_gem_object_set_frontbuffer(obj, front);
	spin_unlock(&i915->display.fb_tracking.lock);

	return front;
	if (cur != front)
		kfree(front);
	return cur;
}

void intel_frontbuffer_put(struct intel_frontbuffer *front)
+0 −27
Original line number Diff line number Diff line
@@ -75,33 +75,6 @@ void intel_frontbuffer_flip(struct drm_i915_private *i915,

void intel_frontbuffer_put(struct intel_frontbuffer *front);

static inline struct intel_frontbuffer *
__intel_frontbuffer_get(const struct drm_i915_gem_object *obj)
{
	struct intel_frontbuffer *front;

	if (likely(!rcu_access_pointer(obj->frontbuffer)))
		return NULL;

	rcu_read_lock();
	do {
		front = rcu_dereference(obj->frontbuffer);
		if (!front)
			break;

		if (unlikely(!kref_get_unless_zero(&front->ref)))
			continue;

		if (likely(front == rcu_access_pointer(obj->frontbuffer)))
			break;

		intel_frontbuffer_put(front);
	} while (1);
	rcu_read_unlock();

	return front;
}

struct intel_frontbuffer *
intel_frontbuffer_get(struct drm_i915_gem_object *obj);

+2 −2
Original line number Diff line number Diff line
@@ -469,7 +469,7 @@ void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj,
{
	struct intel_frontbuffer *front;

	front = __intel_frontbuffer_get(obj);
	front = i915_gem_object_get_frontbuffer(obj);
	if (front) {
		intel_frontbuffer_flush(front, origin);
		intel_frontbuffer_put(front);
@@ -481,7 +481,7 @@ void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
{
	struct intel_frontbuffer *front;

	front = __intel_frontbuffer_get(obj);
	front = i915_gem_object_get_frontbuffer(obj);
	if (front) {
		intel_frontbuffer_invalidate(front, origin);
		intel_frontbuffer_put(front);
+67 −0
Original line number Diff line number Diff line
@@ -891,4 +891,71 @@ static inline int i915_gem_object_userptr_validate(struct drm_i915_gem_object *o

#endif

/**
 * i915_gem_object_get_frontbuffer - Get the object's frontbuffer
 * @obj: The object whose frontbuffer to get.
 *
 * Get pointer to object's frontbuffer if such exists. Please note that RCU
 * mechanism is used to handle e.g. ongoing removal of frontbuffer pointer.
 *
 * Return: pointer to object's frontbuffer is such exists or NULL
 */
static inline struct intel_frontbuffer *
i915_gem_object_get_frontbuffer(const struct drm_i915_gem_object *obj)
{
	struct intel_frontbuffer *front;

	if (likely(!rcu_access_pointer(obj->frontbuffer)))
		return NULL;

	rcu_read_lock();
	do {
		front = rcu_dereference(obj->frontbuffer);
		if (!front)
			break;

		if (unlikely(!kref_get_unless_zero(&front->ref)))
			continue;

		if (likely(front == rcu_access_pointer(obj->frontbuffer)))
			break;

		intel_frontbuffer_put(front);
	} while (1);
	rcu_read_unlock();

	return front;
}

/**
 * i915_gem_object_set_frontbuffer - Set the object's frontbuffer
 * @obj: The object whose frontbuffer to set.
 * @front: The frontbuffer to set
 *
 * 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
 *
 * Return: pointer to frontbuffer which was set.
 */
static inline struct intel_frontbuffer *
i915_gem_object_set_frontbuffer(struct drm_i915_gem_object *obj,
				struct intel_frontbuffer *front)
{
	struct intel_frontbuffer *cur = front;

	if (!front) {
		RCU_INIT_POINTER(obj->frontbuffer, NULL);
	} else if (rcu_access_pointer(obj->frontbuffer)) {
		cur = rcu_dereference_protected(obj->frontbuffer, true);
		kref_get(&cur->ref);
	} else {
		drm_gem_object_get(intel_bo_to_drm_bo(obj));
		rcu_assign_pointer(obj->frontbuffer, front);
	}

	return cur;
}

#endif
+1 −1
Original line number Diff line number Diff line
@@ -1908,7 +1908,7 @@ int _i915_vma_move_to_active(struct i915_vma *vma,
	if (flags & EXEC_OBJECT_WRITE) {
		struct intel_frontbuffer *front;

		front = __intel_frontbuffer_get(obj);
		front = i915_gem_object_get_frontbuffer(obj);
		if (unlikely(front)) {
			if (intel_frontbuffer_invalidate(front, ORIGIN_CS))
				i915_active_add_request(&front->write, rq);