gem/i915_gem_lmem.o \
gem/i915_gem_mman.o \
gem/i915_gem_object.o \
+ gem/i915_gem_object_frontbuffer.o \
gem/i915_gem_pages.o \
gem/i915_gem_phys.o \
gem/i915_gem_pm.o \
return i915_gem_object_read_from_page(to_intel_bo(obj), offset, dst, size);
}
-struct intel_frontbuffer *intel_bo_get_frontbuffer(struct drm_gem_object *obj)
+struct intel_frontbuffer *intel_bo_frontbuffer_get(struct drm_gem_object *_obj)
{
- return i915_gem_object_get_frontbuffer(to_intel_bo(obj));
+ struct drm_i915_gem_object *obj = to_intel_bo(_obj);
+ struct i915_frontbuffer *front;
+
+ front = i915_gem_object_frontbuffer_get(obj);
+ if (!front)
+ return NULL;
+
+ return &front->base;
+}
+
+void intel_bo_frontbuffer_ref(struct intel_frontbuffer *_front)
+{
+ struct i915_frontbuffer *front =
+ container_of(_front, typeof(*front), base);
+
+ i915_gem_object_frontbuffer_ref(front);
}
-struct intel_frontbuffer *intel_bo_set_frontbuffer(struct drm_gem_object *obj,
- struct intel_frontbuffer *front)
+void intel_bo_frontbuffer_put(struct intel_frontbuffer *_front)
{
- return i915_gem_object_set_frontbuffer(to_intel_bo(obj), front);
+ struct i915_frontbuffer *front =
+ container_of(_front, typeof(*front), base);
+
+ return i915_gem_object_frontbuffer_put(front);
}
-void intel_bo_frontbuffer_flush_for_display(struct intel_frontbuffer *front)
+void intel_bo_frontbuffer_flush_for_display(struct intel_frontbuffer *_front)
{
- i915_gem_object_flush_if_display(to_intel_bo(front->obj));
+ struct i915_frontbuffer *front =
+ container_of(_front, typeof(*front), base);
+
+ i915_gem_object_flush_if_display(front->obj);
}
void intel_bo_describe(struct seq_file *m, struct drm_gem_object *obj)
int intel_bo_fb_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
int intel_bo_read_from_page(struct drm_gem_object *obj, u64 offset, void *dst, int size);
-struct intel_frontbuffer *intel_bo_get_frontbuffer(struct drm_gem_object *obj);
-struct intel_frontbuffer *intel_bo_set_frontbuffer(struct drm_gem_object *obj,
- struct intel_frontbuffer *front);
+struct intel_frontbuffer *intel_bo_frontbuffer_get(struct drm_gem_object *obj);
+void intel_bo_frontbuffer_ref(struct intel_frontbuffer *front);
+void intel_bo_frontbuffer_put(struct intel_frontbuffer *front);
void intel_bo_frontbuffer_flush_for_display(struct intel_frontbuffer *front);
void intel_bo_describe(struct seq_file *m, struct drm_gem_object *obj);
};
struct intel_frontbuffer_tracking {
- /* protects obj->frontbuffer (write-side) */
- spinlock_t frontbuffer_lock;
-
/* protects busy_bits */
spinlock_t lock;
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);
#include <drm/drm_gem.h>
-#include "i915_active.h"
-#include "i915_vma.h"
#include "intel_bo.h"
#include "intel_display_trace.h"
#include "intel_display_types.h"
static void intel_frontbuffer_ref(struct intel_frontbuffer *front)
{
- kref_get(&front->ref);
+ intel_bo_frontbuffer_ref(front);
}
static void intel_frontbuffer_flush_work(struct work_struct *work)
intel_frontbuffer_put(front);
}
-static int frontbuffer_active(struct i915_active *ref)
+void intel_frontbuffer_init(struct intel_frontbuffer *front, struct drm_device *drm)
{
- struct intel_frontbuffer *front =
- container_of(ref, typeof(*front), write);
-
- kref_get(&front->ref);
- return 0;
+ front->display = to_intel_display(drm);
+ atomic_set(&front->bits, 0);
+ INIT_WORK(&front->flush_work, intel_frontbuffer_flush_work);
}
-static void frontbuffer_retire(struct i915_active *ref)
+void intel_frontbuffer_fini(struct intel_frontbuffer *front)
{
- struct intel_frontbuffer *front =
- container_of(ref, typeof(*front), write);
-
- intel_frontbuffer_flush(front, ORIGIN_CS);
- intel_frontbuffer_put(front);
+ drm_WARN_ON(front->display->drm, atomic_read(&front->bits));
}
-static void frontbuffer_release(struct kref *ref)
- __releases(&front->display->fb_tracking.frontbuffer_lock)
+struct intel_frontbuffer *intel_frontbuffer_get(struct drm_gem_object *obj)
{
- struct intel_frontbuffer *ret, *front =
- container_of(ref, typeof(*front), ref);
- struct intel_display *display = front->display;
- struct drm_gem_object *obj = front->obj;
-
- drm_WARN_ON(display->drm, atomic_read(&front->bits));
-
- i915_ggtt_clear_scanout(to_intel_bo(obj));
-
- ret = intel_bo_set_frontbuffer(obj, NULL);
- drm_WARN_ON(display->drm, ret);
- spin_unlock(&display->fb_tracking.frontbuffer_lock);
-
- i915_active_fini(&front->write);
-
- drm_gem_object_put(obj);
- kfree_rcu(front, rcu);
-}
-
-struct intel_frontbuffer *
-intel_frontbuffer_get(struct drm_gem_object *obj)
-{
- struct intel_display *display = to_intel_display(obj->dev);
- struct intel_frontbuffer *front, *cur;
-
- front = intel_bo_get_frontbuffer(obj);
- if (front)
- return front;
-
- front = kmalloc(sizeof(*front), GFP_KERNEL);
- if (!front)
- return NULL;
-
- drm_gem_object_get(obj);
-
- front->obj = obj;
- front->display = display;
- kref_init(&front->ref);
- atomic_set(&front->bits, 0);
- i915_active_init(&front->write,
- frontbuffer_active,
- frontbuffer_retire,
- I915_ACTIVE_RETIRE_SLEEPS);
- INIT_WORK(&front->flush_work, intel_frontbuffer_flush_work);
-
- spin_lock(&display->fb_tracking.frontbuffer_lock);
- cur = intel_bo_set_frontbuffer(obj, front);
- spin_unlock(&display->fb_tracking.frontbuffer_lock);
-
- if (cur != front) {
- drm_gem_object_put(obj);
- kfree(front);
- }
-
- return cur;
+ return intel_bo_frontbuffer_get(obj);
}
void intel_frontbuffer_put(struct intel_frontbuffer *front)
{
- kref_put_lock(&front->ref,
- frontbuffer_release,
- &front->display->fb_tracking.frontbuffer_lock);
+ intel_bo_frontbuffer_put(front);
}
/**
#include <linux/atomic.h>
#include <linux/bits.h>
-#include <linux/kref.h>
-
-#include "i915_active_types.h"
+#include <linux/workqueue_types.h>
+struct drm_device;
struct drm_gem_object;
struct intel_display;
};
struct intel_frontbuffer {
- struct kref ref;
struct intel_display *display;
atomic_t bits;
- struct i915_active write;
- struct drm_gem_object *obj;
- struct rcu_head rcu;
-
struct work_struct flush_work;
};
struct intel_frontbuffer *new,
unsigned int frontbuffer_bits);
+void intel_frontbuffer_init(struct intel_frontbuffer *front, struct drm_device *drm);
+void intel_frontbuffer_fini(struct intel_frontbuffer *front);
+
#endif /* __INTEL_FRONTBUFFER_H__ */
void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj,
enum fb_op_origin origin)
{
- struct intel_frontbuffer *front;
+ struct i915_frontbuffer *front;
front = i915_gem_object_get_frontbuffer(obj);
if (front) {
- intel_frontbuffer_flush(front, origin);
- intel_frontbuffer_put(front);
+ intel_frontbuffer_flush(&front->base, origin);
+ i915_gem_object_frontbuffer_put(front);
}
}
void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
enum fb_op_origin origin)
{
- struct intel_frontbuffer *front;
+ struct i915_frontbuffer *front;
front = i915_gem_object_get_frontbuffer(obj);
if (front) {
- intel_frontbuffer_invalidate(front, origin);
- intel_frontbuffer_put(front);
+ intel_frontbuffer_invalidate(&front->base, origin);
+ i915_gem_object_frontbuffer_put(front);
}
}
--- /dev/null
+// SPDX-License-Identifier: MIT
+/* Copyright © 2025 Intel Corporation */
+
+#include "i915_drv.h"
+#include "i915_gem_object_frontbuffer.h"
+
+static int frontbuffer_active(struct i915_active *ref)
+{
+ struct i915_frontbuffer *front =
+ container_of(ref, typeof(*front), write);
+
+ kref_get(&front->ref);
+ return 0;
+}
+
+static void frontbuffer_retire(struct i915_active *ref)
+{
+ struct i915_frontbuffer *front =
+ container_of(ref, typeof(*front), write);
+
+ intel_frontbuffer_flush(&front->base, ORIGIN_CS);
+ i915_gem_object_frontbuffer_put(front);
+}
+
+struct i915_frontbuffer *
+i915_gem_object_frontbuffer_get(struct drm_i915_gem_object *obj)
+{
+ struct drm_i915_private *i915 = to_i915(obj->base.dev);
+ struct i915_frontbuffer *front, *cur;
+
+ front = i915_gem_object_get_frontbuffer(obj);
+ if (front)
+ return front;
+
+ front = kmalloc(sizeof(*front), GFP_KERNEL);
+ if (!front)
+ return NULL;
+
+ intel_frontbuffer_init(&front->base, &i915->drm);
+
+ kref_init(&front->ref);
+ i915_gem_object_get(obj);
+ front->obj = obj;
+
+ i915_active_init(&front->write,
+ frontbuffer_active,
+ frontbuffer_retire,
+ I915_ACTIVE_RETIRE_SLEEPS);
+
+ spin_lock(&i915->frontbuffer_lock);
+ if (rcu_access_pointer(obj->frontbuffer)) {
+ cur = rcu_dereference_protected(obj->frontbuffer, true);
+ kref_get(&cur->ref);
+ } else {
+ cur = front;
+ rcu_assign_pointer(obj->frontbuffer, front);
+ }
+ spin_unlock(&i915->frontbuffer_lock);
+
+ if (cur != front) {
+ i915_gem_object_put(obj);
+ intel_frontbuffer_fini(&front->base);
+ kfree(front);
+ }
+
+ return cur;
+}
+
+void i915_gem_object_frontbuffer_ref(struct i915_frontbuffer *front)
+{
+ kref_get(&front->ref);
+}
+
+static void frontbuffer_release(struct kref *ref)
+ __releases(&i915->frontbuffer_lock)
+{
+ struct i915_frontbuffer *front =
+ container_of(ref, typeof(*front), ref);
+ struct drm_i915_gem_object *obj = front->obj;
+ struct drm_i915_private *i915 = to_i915(obj->base.dev);
+
+ i915_ggtt_clear_scanout(obj);
+
+ RCU_INIT_POINTER(obj->frontbuffer, NULL);
+
+ spin_unlock(&i915->frontbuffer_lock);
+
+ i915_active_fini(&front->write);
+
+ i915_gem_object_put(obj);
+
+ intel_frontbuffer_fini(&front->base);
+
+ kfree_rcu(front, rcu);
+}
+
+void i915_gem_object_frontbuffer_put(struct i915_frontbuffer *front)
+{
+ struct drm_i915_private *i915 = to_i915(front->obj->base.dev);
+
+ kref_put_lock(&front->ref, frontbuffer_release,
+ &i915->frontbuffer_lock);
+}
#include "display/intel_frontbuffer.h"
#include "i915_gem_object_types.h"
+struct i915_frontbuffer {
+ struct intel_frontbuffer base;
+ struct drm_i915_gem_object *obj;
+ struct i915_active write;
+ struct rcu_head rcu;
+ struct kref ref;
+};
+
void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj,
enum fb_op_origin origin);
void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
__i915_gem_object_invalidate_frontbuffer(obj, origin);
}
+struct i915_frontbuffer *i915_gem_object_frontbuffer_get(struct drm_i915_gem_object *obj);
+void i915_gem_object_frontbuffer_ref(struct i915_frontbuffer *front);
+void i915_gem_object_frontbuffer_put(struct i915_frontbuffer *front);
+
/**
* i915_gem_object_get_frontbuffer - Get the object's frontbuffer
* @obj: The object whose frontbuffer to get.
*
* Return: pointer to object's frontbuffer is such exists or NULL
*/
-static inline struct intel_frontbuffer *
+static inline struct i915_frontbuffer *
i915_gem_object_get_frontbuffer(const struct drm_i915_gem_object *obj)
{
- struct intel_frontbuffer *front;
+ struct i915_frontbuffer *front;
if (likely(!rcu_access_pointer(obj->frontbuffer)))
return NULL;
if (likely(front == rcu_access_pointer(obj->frontbuffer)))
break;
- intel_frontbuffer_put(front);
+ i915_gem_object_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.frontbuffer_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 {
- rcu_assign_pointer(obj->frontbuffer, front);
- }
-
- return cur;
-}
-
#endif
*/
u16 write_domain;
- struct intel_frontbuffer __rcu *frontbuffer;
+ struct i915_frontbuffer __rcu *frontbuffer;
/** Current tiling stride for the object, if it's tiled. */
unsigned int tiling_and_stride;
struct file *mmap_singleton;
} gem;
+ spinlock_t frontbuffer_lock; /* protects obj->frontbuffer (write-side) */
+
struct intel_pxp *pxp;
struct i915_pmu pmu;
{
i915_gem_init__mm(dev_priv);
i915_gem_init__contexts(dev_priv);
+
+ spin_lock_init(&dev_priv->frontbuffer_lock);
}
void i915_gem_cleanup_early(struct drm_i915_private *dev_priv)
}
if (flags & EXEC_OBJECT_WRITE) {
- struct intel_frontbuffer *front;
+ struct i915_frontbuffer *front;
front = i915_gem_object_get_frontbuffer(obj);
if (unlikely(front)) {
- if (intel_frontbuffer_invalidate(front, ORIGIN_CS))
+ if (intel_frontbuffer_invalidate(&front->base, ORIGIN_CS))
i915_active_add_request(&front->write, rq);
- intel_frontbuffer_put(front);
+ i915_gem_object_frontbuffer_put(front);
}
}
struct xe_ggtt_node *node;
};
-#define i915_ggtt_clear_scanout(bo) do { } while (0)
-
#define i915_vma_fence_id(vma) -1
static inline u32 i915_ggtt_offset(const struct i915_vma *vma)
#include "xe_bo.h"
#include "intel_bo.h"
+#include "intel_frontbuffer.h"
bool intel_bo_is_tiled(struct drm_gem_object *obj)
{
return xe_bo_read(bo, offset, dst, size);
}
-struct intel_frontbuffer *intel_bo_get_frontbuffer(struct drm_gem_object *obj)
+struct xe_frontbuffer {
+ struct intel_frontbuffer base;
+ struct drm_gem_object *obj;
+ struct kref ref;
+};
+
+struct intel_frontbuffer *intel_bo_frontbuffer_get(struct drm_gem_object *obj)
{
- return NULL;
+ struct xe_frontbuffer *front;
+
+ front = kmalloc(sizeof(*front), GFP_KERNEL);
+ if (!front)
+ return NULL;
+
+ intel_frontbuffer_init(&front->base, obj->dev);
+
+ kref_init(&front->ref);
+
+ drm_gem_object_get(obj);
+ front->obj = obj;
+
+ return &front->base;
}
-struct intel_frontbuffer *intel_bo_set_frontbuffer(struct drm_gem_object *obj,
- struct intel_frontbuffer *front)
+void intel_bo_frontbuffer_ref(struct intel_frontbuffer *_front)
{
- return front;
+ struct xe_frontbuffer *front =
+ container_of(_front, typeof(*front), base);
+
+ kref_get(&front->ref);
+}
+
+static void frontbuffer_release(struct kref *ref)
+{
+ struct xe_frontbuffer *front =
+ container_of(ref, typeof(*front), ref);
+
+ intel_frontbuffer_fini(&front->base);
+
+ drm_gem_object_put(front->obj);
+
+ kfree(front);
+}
+
+void intel_bo_frontbuffer_put(struct intel_frontbuffer *_front)
+{
+ struct xe_frontbuffer *front =
+ container_of(_front, typeof(*front), base);
+
+ kref_put(&front->ref, frontbuffer_release);
}
void intel_bo_frontbuffer_flush_for_display(struct intel_frontbuffer *front)