1
0
Fork 0

drm/i915: Extract intel_frontbuffer active tracking

Move the active tracking for the frontbuffer operations out of the
i915_gem_object and into its own first class (refcounted) object. In the
process of detangling, we switch from low level request tracking to the
easier i915_active -- with the plan that this avoids any potential
atomic callbacks as the frontbuffer tracking wishes to sleep as it
flushes.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190816074635.26062-1-chris@chris-wilson.co.uk
alistair/sunxi64-5.4-dsi
Chris Wilson 2019-08-16 08:46:35 +01:00
parent e5dadff4b0
commit 8e7cb1799b
17 changed files with 306 additions and 260 deletions

View File

@ -91,9 +91,6 @@ Frontbuffer Tracking
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_frontbuffer.c .. kernel-doc:: drivers/gpu/drm/i915/display/intel_frontbuffer.c
:internal: :internal:
.. kernel-doc:: drivers/gpu/drm/i915/i915_gem.c
:functions: i915_gem_track_fb
Display FIFO Underrun Reporting Display FIFO Underrun Reporting
------------------------------- -------------------------------

View File

@ -3049,12 +3049,13 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
{ {
struct drm_device *dev = crtc->base.dev; struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_gem_object *obj = NULL;
struct drm_mode_fb_cmd2 mode_cmd = { 0 }; struct drm_mode_fb_cmd2 mode_cmd = { 0 };
struct drm_framebuffer *fb = &plane_config->fb->base; struct drm_framebuffer *fb = &plane_config->fb->base;
u32 base_aligned = round_down(plane_config->base, PAGE_SIZE); u32 base_aligned = round_down(plane_config->base, PAGE_SIZE);
u32 size_aligned = round_up(plane_config->base + plane_config->size, u32 size_aligned = round_up(plane_config->base + plane_config->size,
PAGE_SIZE); PAGE_SIZE);
struct drm_i915_gem_object *obj;
bool ret = false;
size_aligned -= base_aligned; size_aligned -= base_aligned;
@ -3096,7 +3097,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
break; break;
default: default:
MISSING_CASE(plane_config->tiling); MISSING_CASE(plane_config->tiling);
return false; goto out;
} }
mode_cmd.pixel_format = fb->format->format; mode_cmd.pixel_format = fb->format->format;
@ -3108,16 +3109,15 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
if (intel_framebuffer_init(to_intel_framebuffer(fb), obj, &mode_cmd)) { if (intel_framebuffer_init(to_intel_framebuffer(fb), obj, &mode_cmd)) {
DRM_DEBUG_KMS("intel fb init failed\n"); DRM_DEBUG_KMS("intel fb init failed\n");
goto out_unref_obj; goto out;
} }
DRM_DEBUG_KMS("initial plane fb obj %p\n", obj); DRM_DEBUG_KMS("initial plane fb obj %p\n", obj);
return true; ret = true;
out:
out_unref_obj:
i915_gem_object_put(obj); i915_gem_object_put(obj);
return false; return ret;
} }
static void static void
@ -3174,6 +3174,12 @@ static void intel_plane_disable_noatomic(struct intel_crtc *crtc,
intel_disable_plane(plane, crtc_state); intel_disable_plane(plane, crtc_state);
} }
static struct intel_frontbuffer *
to_intel_frontbuffer(struct drm_framebuffer *fb)
{
return fb ? to_intel_framebuffer(fb)->frontbuffer : NULL;
}
static void static void
intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
struct intel_initial_plane_config *plane_config) struct intel_initial_plane_config *plane_config)
@ -3181,7 +3187,6 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
struct drm_device *dev = intel_crtc->base.dev; struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_crtc *c; struct drm_crtc *c;
struct drm_i915_gem_object *obj;
struct drm_plane *primary = intel_crtc->base.primary; struct drm_plane *primary = intel_crtc->base.primary;
struct drm_plane_state *plane_state = primary->state; struct drm_plane_state *plane_state = primary->state;
struct intel_plane *intel_plane = to_intel_plane(primary); struct intel_plane *intel_plane = to_intel_plane(primary);
@ -3257,8 +3262,7 @@ valid_fb:
return; return;
} }
obj = intel_fb_obj(fb); intel_frontbuffer_flush(to_intel_frontbuffer(fb), ORIGIN_DIRTYFB);
intel_fb_obj_flush(obj, ORIGIN_DIRTYFB);
plane_state->src_x = 0; plane_state->src_x = 0;
plane_state->src_y = 0; plane_state->src_y = 0;
@ -3273,14 +3277,14 @@ valid_fb:
intel_state->base.src = drm_plane_state_src(plane_state); intel_state->base.src = drm_plane_state_src(plane_state);
intel_state->base.dst = drm_plane_state_dest(plane_state); intel_state->base.dst = drm_plane_state_dest(plane_state);
if (i915_gem_object_is_tiled(obj)) if (plane_config->tiling)
dev_priv->preserve_bios_swizzle = true; dev_priv->preserve_bios_swizzle = true;
plane_state->fb = fb; plane_state->fb = fb;
plane_state->crtc = &intel_crtc->base; plane_state->crtc = &intel_crtc->base;
atomic_or(to_intel_plane(primary)->frontbuffer_bit, atomic_or(to_intel_plane(primary)->frontbuffer_bit,
&obj->frontbuffer_bits); &to_intel_frontbuffer(fb)->bits);
} }
static int skl_max_plane_width(const struct drm_framebuffer *fb, static int skl_max_plane_width(const struct drm_framebuffer *fb,
@ -14132,9 +14136,9 @@ static void intel_atomic_track_fbs(struct intel_atomic_state *state)
for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state, for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
new_plane_state, i) new_plane_state, i)
i915_gem_track_fb(intel_fb_obj(old_plane_state->base.fb), intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->base.fb),
intel_fb_obj(new_plane_state->base.fb), to_intel_frontbuffer(new_plane_state->base.fb),
plane->frontbuffer_bit); plane->frontbuffer_bit);
} }
static int intel_atomic_commit(struct drm_device *dev, static int intel_atomic_commit(struct drm_device *dev,
@ -14418,7 +14422,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
return ret; return ret;
fb_obj_bump_render_priority(obj); fb_obj_bump_render_priority(obj);
intel_fb_obj_flush(obj, ORIGIN_DIRTYFB); intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_DIRTYFB);
if (!new_state->fence) { /* implicit fencing */ if (!new_state->fence) { /* implicit fencing */
struct dma_fence *fence; struct dma_fence *fence;
@ -14681,13 +14685,12 @@ intel_legacy_cursor_update(struct drm_plane *plane,
struct drm_modeset_acquire_ctx *ctx) struct drm_modeset_acquire_ctx *ctx)
{ {
struct drm_i915_private *dev_priv = to_i915(crtc->dev); struct drm_i915_private *dev_priv = to_i915(crtc->dev);
int ret;
struct drm_plane_state *old_plane_state, *new_plane_state; struct drm_plane_state *old_plane_state, *new_plane_state;
struct intel_plane *intel_plane = to_intel_plane(plane); struct intel_plane *intel_plane = to_intel_plane(plane);
struct drm_framebuffer *old_fb;
struct intel_crtc_state *crtc_state = struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->state); to_intel_crtc_state(crtc->state);
struct intel_crtc_state *new_crtc_state; struct intel_crtc_state *new_crtc_state;
int ret;
/* /*
* When crtc is inactive or there is a modeset pending, * When crtc is inactive or there is a modeset pending,
@ -14755,11 +14758,10 @@ intel_legacy_cursor_update(struct drm_plane *plane,
if (ret) if (ret)
goto out_unlock; goto out_unlock;
intel_fb_obj_flush(intel_fb_obj(fb), ORIGIN_FLIP); intel_frontbuffer_flush(to_intel_frontbuffer(fb), ORIGIN_FLIP);
intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->fb),
old_fb = old_plane_state->fb; to_intel_frontbuffer(fb),
i915_gem_track_fb(intel_fb_obj(old_fb), intel_fb_obj(fb), intel_plane->frontbuffer_bit);
intel_plane->frontbuffer_bit);
/* Swap plane state */ /* Swap plane state */
plane->state = new_plane_state; plane->state = new_plane_state;
@ -15540,15 +15542,9 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
{ {
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
drm_framebuffer_cleanup(fb); drm_framebuffer_cleanup(fb);
intel_frontbuffer_put(intel_fb->frontbuffer);
i915_gem_object_lock(obj);
WARN_ON(!obj->framebuffer_references--);
i915_gem_object_unlock(obj);
i915_gem_object_put(obj);
kfree(intel_fb); kfree(intel_fb);
} }
@ -15576,7 +15572,7 @@ static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb,
struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct drm_i915_gem_object *obj = intel_fb_obj(fb);
i915_gem_object_flush_if_display(obj); i915_gem_object_flush_if_display(obj);
intel_fb_obj_flush(obj, ORIGIN_DIRTYFB); intel_frontbuffer_flush(to_intel_frontbuffer(fb), ORIGIN_DIRTYFB);
return 0; return 0;
} }
@ -15598,8 +15594,11 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
int ret = -EINVAL; int ret = -EINVAL;
int i; int i;
intel_fb->frontbuffer = intel_frontbuffer_get(obj);
if (!intel_fb->frontbuffer)
return -ENOMEM;
i915_gem_object_lock(obj); i915_gem_object_lock(obj);
obj->framebuffer_references++;
tiling = i915_gem_object_get_tiling(obj); tiling = i915_gem_object_get_tiling(obj);
stride = i915_gem_object_get_stride(obj); stride = i915_gem_object_get_stride(obj);
i915_gem_object_unlock(obj); i915_gem_object_unlock(obj);
@ -15716,9 +15715,7 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
return 0; return 0;
err: err:
i915_gem_object_lock(obj); intel_frontbuffer_put(intel_fb->frontbuffer);
obj->framebuffer_references--;
i915_gem_object_unlock(obj);
return ret; return ret;
} }
@ -15736,8 +15733,7 @@ intel_user_framebuffer_create(struct drm_device *dev,
return ERR_PTR(-ENOENT); return ERR_PTR(-ENOENT);
fb = intel_framebuffer_create(obj, &mode_cmd); fb = intel_framebuffer_create(obj, &mode_cmd);
if (IS_ERR(fb)) i915_gem_object_put(obj);
i915_gem_object_put(obj);
return fb; return fb;
} }

View File

@ -84,6 +84,7 @@ enum intel_broadcast_rgb {
struct intel_framebuffer { struct intel_framebuffer {
struct drm_framebuffer base; struct drm_framebuffer base;
struct intel_frontbuffer *frontbuffer;
struct intel_rotation_info rot_info; struct intel_rotation_info rot_info;
/* for each plane in the normal GTT view */ /* for each plane in the normal GTT view */

View File

@ -47,13 +47,14 @@
#include "intel_fbdev.h" #include "intel_fbdev.h"
#include "intel_frontbuffer.h" #include "intel_frontbuffer.h"
static struct intel_frontbuffer *to_frontbuffer(struct intel_fbdev *ifbdev)
{
return ifbdev->fb->frontbuffer;
}
static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev) static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev)
{ {
struct drm_i915_gem_object *obj = intel_fb_obj(&ifbdev->fb->base); intel_frontbuffer_invalidate(to_frontbuffer(ifbdev), ORIGIN_CPU);
unsigned int origin =
ifbdev->vma_flags & PLANE_HAS_FENCE ? ORIGIN_GTT : ORIGIN_CPU;
intel_fb_obj_invalidate(obj, origin);
} }
static int intel_fbdev_set_par(struct fb_info *info) static int intel_fbdev_set_par(struct fb_info *info)
@ -120,7 +121,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_mode_fb_cmd2 mode_cmd = {}; struct drm_mode_fb_cmd2 mode_cmd = {};
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
int size, ret; int size;
/* we don't do packed 24bpp */ /* we don't do packed 24bpp */
if (sizes->surface_bpp == 24) if (sizes->surface_bpp == 24)
@ -147,24 +148,16 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
obj = i915_gem_object_create_shmem(dev_priv, size); obj = i915_gem_object_create_shmem(dev_priv, size);
if (IS_ERR(obj)) { if (IS_ERR(obj)) {
DRM_ERROR("failed to allocate framebuffer\n"); DRM_ERROR("failed to allocate framebuffer\n");
ret = PTR_ERR(obj); return PTR_ERR(obj);
goto err;
} }
fb = intel_framebuffer_create(obj, &mode_cmd); fb = intel_framebuffer_create(obj, &mode_cmd);
if (IS_ERR(fb)) { i915_gem_object_put(obj);
ret = PTR_ERR(fb); if (IS_ERR(fb))
goto err_obj; return PTR_ERR(fb);
}
ifbdev->fb = to_intel_framebuffer(fb); ifbdev->fb = to_intel_framebuffer(fb);
return 0; return 0;
err_obj:
i915_gem_object_put(obj);
err:
return ret;
} }
static int intelfb_create(struct drm_fb_helper *helper, static int intelfb_create(struct drm_fb_helper *helper,
@ -180,7 +173,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
const struct i915_ggtt_view view = { const struct i915_ggtt_view view = {
.type = I915_GGTT_VIEW_NORMAL, .type = I915_GGTT_VIEW_NORMAL,
}; };
struct drm_framebuffer *fb;
intel_wakeref_t wakeref; intel_wakeref_t wakeref;
struct fb_info *info; struct fb_info *info;
struct i915_vma *vma; struct i915_vma *vma;
@ -226,8 +218,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
goto out_unlock; goto out_unlock;
} }
fb = &ifbdev->fb->base; intel_frontbuffer_flush(to_frontbuffer(ifbdev), ORIGIN_DIRTYFB);
intel_fb_obj_flush(intel_fb_obj(fb), ORIGIN_DIRTYFB);
info = drm_fb_helper_alloc_fbi(helper); info = drm_fb_helper_alloc_fbi(helper);
if (IS_ERR(info)) { if (IS_ERR(info)) {
@ -236,7 +227,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
goto out_unpin; goto out_unpin;
} }
ifbdev->helper.fb = fb; ifbdev->helper.fb = &ifbdev->fb->base;
info->fbops = &intelfb_ops; info->fbops = &intelfb_ops;
@ -263,13 +254,14 @@ static int intelfb_create(struct drm_fb_helper *helper,
* If the object is stolen however, it will be full of whatever * If the object is stolen however, it will be full of whatever
* garbage was left in there. * garbage was left in there.
*/ */
if (intel_fb_obj(fb)->stolen && !prealloc) if (vma->obj->stolen && !prealloc)
memset_io(info->screen_base, 0, info->screen_size); memset_io(info->screen_base, 0, info->screen_size);
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x\n", DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x\n",
fb->width, fb->height, i915_ggtt_offset(vma)); ifbdev->fb->base.width, ifbdev->fb->base.height,
i915_ggtt_offset(vma));
ifbdev->vma = vma; ifbdev->vma = vma;
ifbdev->vma_flags = flags; ifbdev->vma_flags = flags;

View File

@ -30,11 +30,11 @@
* Many features require us to track changes to the currently active * Many features require us to track changes to the currently active
* frontbuffer, especially rendering targeted at the frontbuffer. * frontbuffer, especially rendering targeted at the frontbuffer.
* *
* To be able to do so GEM tracks frontbuffers using a bitmask for all possible * To be able to do so we track frontbuffers using a bitmask for all possible
* frontbuffer slots through i915_gem_track_fb(). The function in this file are * frontbuffer slots through intel_frontbuffer_track(). The functions in this
* then called when the contents of the frontbuffer are invalidated, when * file are then called when the contents of the frontbuffer are invalidated,
* frontbuffer rendering has stopped again to flush out all the changes and when * when frontbuffer rendering has stopped again to flush out all the changes
* the frontbuffer is exchanged with a flip. Subsystems interested in * and when the frontbuffer is exchanged with a flip. Subsystems interested in
* frontbuffer changes (e.g. PSR, FBC, DRRS) should directly put their callbacks * frontbuffer changes (e.g. PSR, FBC, DRRS) should directly put their callbacks
* into the relevant places and filter for the frontbuffer slots that they are * into the relevant places and filter for the frontbuffer slots that they are
* interested int. * interested int.
@ -63,28 +63,9 @@
#include "intel_frontbuffer.h" #include "intel_frontbuffer.h"
#include "intel_psr.h" #include "intel_psr.h"
void __intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
enum fb_op_origin origin,
unsigned int frontbuffer_bits)
{
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
if (origin == ORIGIN_CS) {
spin_lock(&dev_priv->fb_tracking.lock);
dev_priv->fb_tracking.busy_bits |= frontbuffer_bits;
dev_priv->fb_tracking.flip_bits &= ~frontbuffer_bits;
spin_unlock(&dev_priv->fb_tracking.lock);
}
might_sleep();
intel_psr_invalidate(dev_priv, frontbuffer_bits, origin);
intel_edp_drrs_invalidate(dev_priv, frontbuffer_bits);
intel_fbc_invalidate(dev_priv, frontbuffer_bits, origin);
}
/** /**
* intel_frontbuffer_flush - flush frontbuffer * frontbuffer_flush - flush frontbuffer
* @dev_priv: i915 device * @i915: i915 device
* @frontbuffer_bits: frontbuffer plane tracking bits * @frontbuffer_bits: frontbuffer plane tracking bits
* @origin: which operation caused the flush * @origin: which operation caused the flush
* *
@ -94,45 +75,27 @@ void __intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
* *
* Can be called without any locks held. * Can be called without any locks held.
*/ */
static void intel_frontbuffer_flush(struct drm_i915_private *dev_priv, static void frontbuffer_flush(struct drm_i915_private *i915,
unsigned frontbuffer_bits, unsigned int frontbuffer_bits,
enum fb_op_origin origin) enum fb_op_origin origin)
{ {
/* Delay flushing when rings are still busy.*/ /* Delay flushing when rings are still busy.*/
spin_lock(&dev_priv->fb_tracking.lock); spin_lock(&i915->fb_tracking.lock);
frontbuffer_bits &= ~dev_priv->fb_tracking.busy_bits; frontbuffer_bits &= ~i915->fb_tracking.busy_bits;
spin_unlock(&dev_priv->fb_tracking.lock); spin_unlock(&i915->fb_tracking.lock);
if (!frontbuffer_bits) if (!frontbuffer_bits)
return; return;
might_sleep(); might_sleep();
intel_edp_drrs_flush(dev_priv, frontbuffer_bits); intel_edp_drrs_flush(i915, frontbuffer_bits);
intel_psr_flush(dev_priv, frontbuffer_bits, origin); intel_psr_flush(i915, frontbuffer_bits, origin);
intel_fbc_flush(dev_priv, frontbuffer_bits, origin); intel_fbc_flush(i915, frontbuffer_bits, origin);
}
void __intel_fb_obj_flush(struct drm_i915_gem_object *obj,
enum fb_op_origin origin,
unsigned int frontbuffer_bits)
{
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
if (origin == ORIGIN_CS) {
spin_lock(&dev_priv->fb_tracking.lock);
/* Filter out new bits since rendering started. */
frontbuffer_bits &= dev_priv->fb_tracking.busy_bits;
dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits;
spin_unlock(&dev_priv->fb_tracking.lock);
}
if (frontbuffer_bits)
intel_frontbuffer_flush(dev_priv, frontbuffer_bits, origin);
} }
/** /**
* intel_frontbuffer_flip_prepare - prepare asynchronous frontbuffer flip * intel_frontbuffer_flip_prepare - prepare asynchronous frontbuffer flip
* @dev_priv: i915 device * @i915: i915 device
* @frontbuffer_bits: frontbuffer plane tracking bits * @frontbuffer_bits: frontbuffer plane tracking bits
* *
* This function gets called after scheduling a flip on @obj. The actual * This function gets called after scheduling a flip on @obj. The actual
@ -142,19 +105,19 @@ void __intel_fb_obj_flush(struct drm_i915_gem_object *obj,
* *
* Can be called without any locks held. * Can be called without any locks held.
*/ */
void intel_frontbuffer_flip_prepare(struct drm_i915_private *dev_priv, void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915,
unsigned frontbuffer_bits) unsigned frontbuffer_bits)
{ {
spin_lock(&dev_priv->fb_tracking.lock); spin_lock(&i915->fb_tracking.lock);
dev_priv->fb_tracking.flip_bits |= frontbuffer_bits; i915->fb_tracking.flip_bits |= frontbuffer_bits;
/* Remove stale busy bits due to the old buffer. */ /* Remove stale busy bits due to the old buffer. */
dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits; i915->fb_tracking.busy_bits &= ~frontbuffer_bits;
spin_unlock(&dev_priv->fb_tracking.lock); spin_unlock(&i915->fb_tracking.lock);
} }
/** /**
* intel_frontbuffer_flip_complete - complete asynchronous frontbuffer flip * intel_frontbuffer_flip_complete - complete asynchronous frontbuffer flip
* @dev_priv: i915 device * @i915: i915 device
* @frontbuffer_bits: frontbuffer plane tracking bits * @frontbuffer_bits: frontbuffer plane tracking bits
* *
* This function gets called after the flip has been latched and will complete * This function gets called after the flip has been latched and will complete
@ -162,23 +125,22 @@ void intel_frontbuffer_flip_prepare(struct drm_i915_private *dev_priv,
* *
* Can be called without any locks held. * Can be called without any locks held.
*/ */
void intel_frontbuffer_flip_complete(struct drm_i915_private *dev_priv, void intel_frontbuffer_flip_complete(struct drm_i915_private *i915,
unsigned frontbuffer_bits) unsigned frontbuffer_bits)
{ {
spin_lock(&dev_priv->fb_tracking.lock); spin_lock(&i915->fb_tracking.lock);
/* Mask any cancelled flips. */ /* Mask any cancelled flips. */
frontbuffer_bits &= dev_priv->fb_tracking.flip_bits; frontbuffer_bits &= i915->fb_tracking.flip_bits;
dev_priv->fb_tracking.flip_bits &= ~frontbuffer_bits; i915->fb_tracking.flip_bits &= ~frontbuffer_bits;
spin_unlock(&dev_priv->fb_tracking.lock); spin_unlock(&i915->fb_tracking.lock);
if (frontbuffer_bits) if (frontbuffer_bits)
intel_frontbuffer_flush(dev_priv, frontbuffer_flush(i915, frontbuffer_bits, ORIGIN_FLIP);
frontbuffer_bits, ORIGIN_FLIP);
} }
/** /**
* intel_frontbuffer_flip - synchronous frontbuffer flip * intel_frontbuffer_flip - synchronous frontbuffer flip
* @dev_priv: i915 device * @i915: i915 device
* @frontbuffer_bits: frontbuffer plane tracking bits * @frontbuffer_bits: frontbuffer plane tracking bits
* *
* This function gets called after scheduling a flip on @obj. This is for * This function gets called after scheduling a flip on @obj. This is for
@ -187,13 +149,160 @@ void intel_frontbuffer_flip_complete(struct drm_i915_private *dev_priv,
* *
* Can be called without any locks held. * Can be called without any locks held.
*/ */
void intel_frontbuffer_flip(struct drm_i915_private *dev_priv, void intel_frontbuffer_flip(struct drm_i915_private *i915,
unsigned frontbuffer_bits) unsigned frontbuffer_bits)
{ {
spin_lock(&dev_priv->fb_tracking.lock); spin_lock(&i915->fb_tracking.lock);
/* Remove stale busy bits due to the old buffer. */ /* Remove stale busy bits due to the old buffer. */
dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits; i915->fb_tracking.busy_bits &= ~frontbuffer_bits;
spin_unlock(&dev_priv->fb_tracking.lock); spin_unlock(&i915->fb_tracking.lock);
intel_frontbuffer_flush(dev_priv, frontbuffer_bits, ORIGIN_FLIP); frontbuffer_flush(i915, frontbuffer_bits, ORIGIN_FLIP);
}
void __intel_fb_invalidate(struct intel_frontbuffer *front,
enum fb_op_origin origin,
unsigned int frontbuffer_bits)
{
struct drm_i915_private *i915 = to_i915(front->obj->base.dev);
if (origin == ORIGIN_CS) {
spin_lock(&i915->fb_tracking.lock);
i915->fb_tracking.busy_bits |= frontbuffer_bits;
i915->fb_tracking.flip_bits &= ~frontbuffer_bits;
spin_unlock(&i915->fb_tracking.lock);
}
might_sleep();
intel_psr_invalidate(i915, frontbuffer_bits, origin);
intel_edp_drrs_invalidate(i915, frontbuffer_bits);
intel_fbc_invalidate(i915, frontbuffer_bits, origin);
}
void __intel_fb_flush(struct intel_frontbuffer *front,
enum fb_op_origin origin,
unsigned int frontbuffer_bits)
{
struct drm_i915_private *i915 = to_i915(front->obj->base.dev);
if (origin == ORIGIN_CS) {
spin_lock(&i915->fb_tracking.lock);
/* Filter out new bits since rendering started. */
frontbuffer_bits &= i915->fb_tracking.busy_bits;
i915->fb_tracking.busy_bits &= ~frontbuffer_bits;
spin_unlock(&i915->fb_tracking.lock);
}
if (frontbuffer_bits)
frontbuffer_flush(i915, frontbuffer_bits, origin);
}
static int frontbuffer_active(struct i915_active *ref)
{
struct intel_frontbuffer *front =
container_of(ref, typeof(*front), write);
kref_get(&front->ref);
return 0;
}
static void frontbuffer_retire(struct i915_active *ref)
{
struct intel_frontbuffer *front =
container_of(ref, typeof(*front), write);
intel_frontbuffer_flush(front, ORIGIN_CS);
intel_frontbuffer_put(front);
}
static void frontbuffer_release(struct kref *ref)
__releases(&to_i915(front->obj->base.dev)->fb_tracking.lock)
{
struct intel_frontbuffer *front =
container_of(ref, typeof(*front), ref);
front->obj->frontbuffer = NULL;
spin_unlock(&to_i915(front->obj->base.dev)->fb_tracking.lock);
i915_gem_object_put(front->obj);
kfree(front);
}
struct intel_frontbuffer *
intel_frontbuffer_get(struct drm_i915_gem_object *obj)
{
struct drm_i915_private *i915 = to_i915(obj->base.dev);
struct intel_frontbuffer *front;
spin_lock(&i915->fb_tracking.lock);
front = obj->frontbuffer;
if (front)
kref_get(&front->ref);
spin_unlock(&i915->fb_tracking.lock);
if (front)
return front;
front = kmalloc(sizeof(*front), GFP_KERNEL);
if (!front)
return NULL;
front->obj = obj;
kref_init(&front->ref);
atomic_set(&front->bits, 0);
i915_active_init(i915, &front->write,
frontbuffer_active, frontbuffer_retire);
spin_lock(&i915->fb_tracking.lock);
if (obj->frontbuffer) {
kfree(front);
front = obj->frontbuffer;
kref_get(&front->ref);
} else {
i915_gem_object_get(obj);
obj->frontbuffer = front;
}
spin_unlock(&i915->fb_tracking.lock);
return front;
}
void intel_frontbuffer_put(struct intel_frontbuffer *front)
{
kref_put_lock(&front->ref,
frontbuffer_release,
&to_i915(front->obj->base.dev)->fb_tracking.lock);
}
/**
* intel_frontbuffer_track - update frontbuffer tracking
* @old: current buffer for the frontbuffer slots
* @new: new buffer for the frontbuffer slots
* @frontbuffer_bits: bitmask of frontbuffer slots
*
* This updates the frontbuffer tracking bits @frontbuffer_bits by clearing them
* from @old and setting them in @new. Both @old and @new can be NULL.
*/
void intel_frontbuffer_track(struct intel_frontbuffer *old,
struct intel_frontbuffer *new,
unsigned int frontbuffer_bits)
{
/*
* Control of individual bits within the mask are guarded by
* the owning plane->mutex, i.e. we can never see concurrent
* manipulation of individual bits. But since the bitfield as a whole
* is updated using RMW, we need to use atomics in order to update
* the bits.
*/
BUILD_BUG_ON(INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES >
BITS_PER_TYPE(atomic_t));
if (old) {
WARN_ON(!(atomic_read(&old->bits) & frontbuffer_bits));
atomic_andnot(frontbuffer_bits, &old->bits);
}
if (new) {
WARN_ON(atomic_read(&new->bits) & frontbuffer_bits);
atomic_or(frontbuffer_bits, &new->bits);
}
} }

View File

@ -24,7 +24,10 @@
#ifndef __INTEL_FRONTBUFFER_H__ #ifndef __INTEL_FRONTBUFFER_H__
#define __INTEL_FRONTBUFFER_H__ #define __INTEL_FRONTBUFFER_H__
#include "gem/i915_gem_object.h" #include <linux/atomic.h>
#include <linux/kref.h>
#include "i915_active.h"
struct drm_i915_private; struct drm_i915_private;
struct drm_i915_gem_object; struct drm_i915_gem_object;
@ -37,23 +40,30 @@ enum fb_op_origin {
ORIGIN_DIRTYFB, ORIGIN_DIRTYFB,
}; };
void intel_frontbuffer_flip_prepare(struct drm_i915_private *dev_priv, struct intel_frontbuffer {
struct kref ref;
atomic_t bits;
struct i915_active write;
struct drm_i915_gem_object *obj;
};
void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915,
unsigned frontbuffer_bits); unsigned frontbuffer_bits);
void intel_frontbuffer_flip_complete(struct drm_i915_private *dev_priv, void intel_frontbuffer_flip_complete(struct drm_i915_private *i915,
unsigned frontbuffer_bits); unsigned frontbuffer_bits);
void intel_frontbuffer_flip(struct drm_i915_private *dev_priv, void intel_frontbuffer_flip(struct drm_i915_private *i915,
unsigned frontbuffer_bits); unsigned frontbuffer_bits);
void __intel_fb_obj_invalidate(struct drm_i915_gem_object *obj, struct intel_frontbuffer *
enum fb_op_origin origin, intel_frontbuffer_get(struct drm_i915_gem_object *obj);
unsigned int frontbuffer_bits);
void __intel_fb_obj_flush(struct drm_i915_gem_object *obj, void __intel_fb_invalidate(struct intel_frontbuffer *front,
enum fb_op_origin origin, enum fb_op_origin origin,
unsigned int frontbuffer_bits); unsigned int frontbuffer_bits);
/** /**
* intel_fb_obj_invalidate - invalidate frontbuffer object * intel_frontbuffer_invalidate - invalidate frontbuffer object
* @obj: GEM object to invalidate * @front: GEM object to invalidate
* @origin: which operation caused the invalidation * @origin: which operation caused the invalidation
* *
* This function gets called every time rendering on the given object starts and * This function gets called every time rendering on the given object starts and
@ -62,37 +72,53 @@ void __intel_fb_obj_flush(struct drm_i915_gem_object *obj,
* until the rendering completes or a flip on this frontbuffer plane is * until the rendering completes or a flip on this frontbuffer plane is
* scheduled. * scheduled.
*/ */
static inline bool intel_fb_obj_invalidate(struct drm_i915_gem_object *obj, static inline bool intel_frontbuffer_invalidate(struct intel_frontbuffer *front,
enum fb_op_origin origin) enum fb_op_origin origin)
{ {
unsigned int frontbuffer_bits; unsigned int frontbuffer_bits;
frontbuffer_bits = atomic_read(&obj->frontbuffer_bits); if (!front)
return false;
frontbuffer_bits = atomic_read(&front->bits);
if (!frontbuffer_bits) if (!frontbuffer_bits)
return false; return false;
__intel_fb_obj_invalidate(obj, origin, frontbuffer_bits); __intel_fb_invalidate(front, origin, frontbuffer_bits);
return true; return true;
} }
void __intel_fb_flush(struct intel_frontbuffer *front,
enum fb_op_origin origin,
unsigned int frontbuffer_bits);
/** /**
* intel_fb_obj_flush - flush frontbuffer object * intel_frontbuffer_flush - flush frontbuffer object
* @obj: GEM object to flush * @front: GEM object to flush
* @origin: which operation caused the flush * @origin: which operation caused the flush
* *
* This function gets called every time rendering on the given object has * This function gets called every time rendering on the given object has
* completed and frontbuffer caching can be started again. * completed and frontbuffer caching can be started again.
*/ */
static inline void intel_fb_obj_flush(struct drm_i915_gem_object *obj, static inline void intel_frontbuffer_flush(struct intel_frontbuffer *front,
enum fb_op_origin origin) enum fb_op_origin origin)
{ {
unsigned int frontbuffer_bits; unsigned int frontbuffer_bits;
frontbuffer_bits = atomic_read(&obj->frontbuffer_bits); if (!front)
return;
frontbuffer_bits = atomic_read(&front->bits);
if (!frontbuffer_bits) if (!frontbuffer_bits)
return; return;
__intel_fb_obj_flush(obj, origin, frontbuffer_bits); __intel_fb_flush(front, origin, frontbuffer_bits);
} }
void intel_frontbuffer_track(struct intel_frontbuffer *old,
struct intel_frontbuffer *new,
unsigned int frontbuffer_bits);
void intel_frontbuffer_put(struct intel_frontbuffer *front);
#endif /* __INTEL_FRONTBUFFER_H__ */ #endif /* __INTEL_FRONTBUFFER_H__ */

View File

@ -281,9 +281,9 @@ static void intel_overlay_flip_prepare(struct intel_overlay *overlay,
WARN_ON(overlay->old_vma); WARN_ON(overlay->old_vma);
i915_gem_track_fb(overlay->vma ? overlay->vma->obj : NULL, intel_frontbuffer_track(overlay->vma ? overlay->vma->obj->frontbuffer : NULL,
vma ? vma->obj : NULL, vma ? vma->obj->frontbuffer : NULL,
INTEL_FRONTBUFFER_OVERLAY(pipe)); INTEL_FRONTBUFFER_OVERLAY(pipe));
intel_frontbuffer_flip_prepare(overlay->i915, intel_frontbuffer_flip_prepare(overlay->i915,
INTEL_FRONTBUFFER_OVERLAY(pipe)); INTEL_FRONTBUFFER_OVERLAY(pipe));
@ -768,7 +768,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
ret = PTR_ERR(vma); ret = PTR_ERR(vma);
goto out_pin_section; goto out_pin_section;
} }
intel_fb_obj_flush(new_bo, ORIGIN_DIRTYFB); intel_frontbuffer_flush(new_bo->frontbuffer, ORIGIN_DIRTYFB);
ret = i915_vma_put_fence(vma); ret = i915_vma_put_fence(vma);
if (ret) if (ret)

View File

@ -49,7 +49,7 @@ static void __i915_do_clflush(struct drm_i915_gem_object *obj)
{ {
GEM_BUG_ON(!i915_gem_object_has_pages(obj)); GEM_BUG_ON(!i915_gem_object_has_pages(obj));
drm_clflush_sg(obj->mm.pages); drm_clflush_sg(obj->mm.pages);
intel_fb_obj_flush(obj, ORIGIN_CPU); intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
} }
static void i915_clflush_work(struct work_struct *work) static void i915_clflush_work(struct work_struct *work)

View File

@ -551,13 +551,6 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
return 0; return 0;
} }
static inline enum fb_op_origin
fb_write_origin(struct drm_i915_gem_object *obj, unsigned int domain)
{
return (domain == I915_GEM_DOMAIN_GTT ?
obj->frontbuffer_ggtt_origin : ORIGIN_CPU);
}
/** /**
* Called when user space prepares to use an object with the CPU, either * Called when user space prepares to use an object with the CPU, either
* through the mmap ioctl's mapping or a GTT mapping. * through the mmap ioctl's mapping or a GTT mapping.
@ -661,9 +654,8 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
i915_gem_object_unlock(obj); i915_gem_object_unlock(obj);
if (write_domain != 0) if (write_domain)
intel_fb_obj_invalidate(obj, intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
fb_write_origin(obj, write_domain));
out_unpin: out_unpin:
i915_gem_object_unpin_pages(obj); i915_gem_object_unpin_pages(obj);
@ -783,7 +775,7 @@ int i915_gem_object_prepare_write(struct drm_i915_gem_object *obj,
} }
out: out:
intel_fb_obj_invalidate(obj, ORIGIN_CPU); intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
obj->mm.dirty = true; obj->mm.dirty = true;
/* return with the pages pinned */ /* return with the pages pinned */
return 0; return 0;

View File

@ -101,9 +101,6 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
up_write(&mm->mmap_sem); up_write(&mm->mmap_sem);
if (IS_ERR_VALUE(addr)) if (IS_ERR_VALUE(addr))
goto err; goto err;
/* This may race, but that's ok, it only gets set */
WRITE_ONCE(obj->frontbuffer_ggtt_origin, ORIGIN_CPU);
} }
i915_gem_object_put(obj); i915_gem_object_put(obj);
@ -283,7 +280,6 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
* Userspace is now writing through an untracked VMA, abandon * Userspace is now writing through an untracked VMA, abandon
* all hope that the hardware is able to track future writes. * all hope that the hardware is able to track future writes.
*/ */
obj->frontbuffer_ggtt_origin = ORIGIN_CPU;
vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, flags); vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, flags);
if (IS_ERR(vma) && !view.type) { if (IS_ERR(vma) && !view.type) {

View File

@ -46,16 +46,6 @@ void i915_gem_object_free(struct drm_i915_gem_object *obj)
return kmem_cache_free(global.slab_objects, obj); return kmem_cache_free(global.slab_objects, obj);
} }
static void
frontbuffer_retire(struct i915_active_request *active,
struct i915_request *request)
{
struct drm_i915_gem_object *obj =
container_of(active, typeof(*obj), frontbuffer_write);
intel_fb_obj_flush(obj, ORIGIN_CS);
}
void i915_gem_object_init(struct drm_i915_gem_object *obj, void i915_gem_object_init(struct drm_i915_gem_object *obj,
const struct drm_i915_gem_object_ops *ops) const struct drm_i915_gem_object_ops *ops)
{ {
@ -72,10 +62,6 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
obj->ops = ops; obj->ops = ops;
obj->frontbuffer_ggtt_origin = ORIGIN_GTT;
i915_active_request_init(&obj->frontbuffer_write,
NULL, frontbuffer_retire);
obj->mm.madv = I915_MADV_WILLNEED; obj->mm.madv = I915_MADV_WILLNEED;
INIT_RADIX_TREE(&obj->mm.get_page.radix, GFP_KERNEL | __GFP_NOWARN); INIT_RADIX_TREE(&obj->mm.get_page.radix, GFP_KERNEL | __GFP_NOWARN);
mutex_init(&obj->mm.get_page.lock); mutex_init(&obj->mm.get_page.lock);
@ -187,7 +173,6 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
GEM_BUG_ON(atomic_read(&obj->bind_count)); GEM_BUG_ON(atomic_read(&obj->bind_count));
GEM_BUG_ON(obj->userfault_count); GEM_BUG_ON(obj->userfault_count);
GEM_BUG_ON(atomic_read(&obj->frontbuffer_bits));
GEM_BUG_ON(!list_empty(&obj->lut_list)); GEM_BUG_ON(!list_empty(&obj->lut_list));
atomic_set(&obj->mm.pages_pin_count, 0); atomic_set(&obj->mm.pages_pin_count, 0);
@ -230,6 +215,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
struct drm_i915_private *i915 = to_i915(obj->base.dev); struct drm_i915_private *i915 = to_i915(obj->base.dev);
GEM_BUG_ON(i915_gem_object_is_framebuffer(obj));
/* /*
* Before we free the object, make sure any pure RCU-only * Before we free the object, make sure any pure RCU-only
* read-side critical sections are complete, e.g. * read-side critical sections are complete, e.g.
@ -261,13 +248,6 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
queue_work(i915->wq, &i915->mm.free_work); queue_work(i915->wq, &i915->mm.free_work);
} }
static inline enum fb_op_origin
fb_write_origin(struct drm_i915_gem_object *obj, unsigned int domain)
{
return (domain == I915_GEM_DOMAIN_GTT ?
obj->frontbuffer_ggtt_origin : ORIGIN_CPU);
}
static bool gpu_write_needs_clflush(struct drm_i915_gem_object *obj) static bool gpu_write_needs_clflush(struct drm_i915_gem_object *obj)
{ {
return !(obj->cache_level == I915_CACHE_NONE || return !(obj->cache_level == I915_CACHE_NONE ||
@ -290,8 +270,7 @@ i915_gem_object_flush_write_domain(struct drm_i915_gem_object *obj,
for_each_ggtt_vma(vma, obj) for_each_ggtt_vma(vma, obj)
intel_gt_flush_ggtt_writes(vma->vm->gt); intel_gt_flush_ggtt_writes(vma->vm->gt);
intel_fb_obj_flush(obj, intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
fb_write_origin(obj, I915_GEM_DOMAIN_GTT));
for_each_ggtt_vma(vma, obj) { for_each_ggtt_vma(vma, obj) {
if (vma->iomap) if (vma->iomap)

View File

@ -161,7 +161,7 @@ i915_gem_object_needs_async_cancel(const struct drm_i915_gem_object *obj)
static inline bool static inline bool
i915_gem_object_is_framebuffer(const struct drm_i915_gem_object *obj) i915_gem_object_is_framebuffer(const struct drm_i915_gem_object *obj)
{ {
return READ_ONCE(obj->framebuffer_references); return READ_ONCE(obj->frontbuffer);
} }
static inline unsigned int static inline unsigned int

View File

@ -13,6 +13,7 @@
#include "i915_selftest.h" #include "i915_selftest.h"
struct drm_i915_gem_object; struct drm_i915_gem_object;
struct intel_fronbuffer;
/* /*
* struct i915_lut_handle tracks the fast lookups from handle to vma used * struct i915_lut_handle tracks the fast lookups from handle to vma used
@ -141,9 +142,7 @@ struct drm_i915_gem_object {
*/ */
u16 write_domain; u16 write_domain;
atomic_t frontbuffer_bits; struct intel_frontbuffer *frontbuffer;
unsigned int frontbuffer_ggtt_origin; /* write once */
struct i915_active_request frontbuffer_write;
/** Current tiling stride for the object, if it's tiled. */ /** Current tiling stride for the object, if it's tiled. */
unsigned int tiling_and_stride; unsigned int tiling_and_stride;
@ -224,9 +223,6 @@ struct drm_i915_gem_object {
bool quirked:1; bool quirked:1;
} mm; } mm;
/** References from framebuffers, locks out tiling changes. */
unsigned int framebuffer_references;
/** Record of address bit 17 of each page at last unbind. */ /** Record of address bit 17 of each page at last unbind. */
unsigned long *bit_17; unsigned long *bit_17;

View File

@ -138,7 +138,6 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
struct drm_i915_private *dev_priv = to_i915(obj->base.dev); struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
struct intel_engine_cs *engine; struct intel_engine_cs *engine;
struct i915_vma *vma; struct i915_vma *vma;
unsigned int frontbuffer_bits;
int pin_count = 0; int pin_count = 0;
seq_printf(m, "%pK: %c%c%c%c %8zdKiB %02x %02x %s%s%s", seq_printf(m, "%pK: %c%c%c%c %8zdKiB %02x %02x %s%s%s",
@ -228,10 +227,6 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
engine = i915_gem_object_last_write_engine(obj); engine = i915_gem_object_last_write_engine(obj);
if (engine) if (engine)
seq_printf(m, " (%s)", engine->name); seq_printf(m, " (%s)", engine->name);
frontbuffer_bits = atomic_read(&obj->frontbuffer_bits);
if (frontbuffer_bits)
seq_printf(m, " (frontbuffer: 0x%03x)", frontbuffer_bits);
} }
struct file_stats { struct file_stats {

View File

@ -2355,10 +2355,6 @@ int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev,
u32 handle, u64 *offset); u32 handle, u64 *offset);
int i915_gem_mmap_gtt_version(void); int i915_gem_mmap_gtt_version(void);
void i915_gem_track_fb(struct drm_i915_gem_object *old,
struct drm_i915_gem_object *new,
unsigned frontbuffer_bits);
int __must_check i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno); int __must_check i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno);
static inline u32 i915_reset_count(struct i915_gpu_error *error) static inline u32 i915_reset_count(struct i915_gpu_error *error)

View File

@ -139,17 +139,19 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
void *vaddr = obj->phys_handle->vaddr + args->offset; void *vaddr = obj->phys_handle->vaddr + args->offset;
char __user *user_data = u64_to_user_ptr(args->data_ptr); char __user *user_data = u64_to_user_ptr(args->data_ptr);
/* We manually control the domain here and pretend that it /*
* We manually control the domain here and pretend that it
* remains coherent i.e. in the GTT domain, like shmem_pwrite. * remains coherent i.e. in the GTT domain, like shmem_pwrite.
*/ */
intel_fb_obj_invalidate(obj, ORIGIN_CPU); intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
if (copy_from_user(vaddr, user_data, args->size)) if (copy_from_user(vaddr, user_data, args->size))
return -EFAULT; return -EFAULT;
drm_clflush_virt_range(vaddr, args->size); drm_clflush_virt_range(vaddr, args->size);
intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt); intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);
intel_fb_obj_flush(obj, ORIGIN_CPU); intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
return 0; return 0;
} }
@ -594,7 +596,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
goto out_unpin; goto out_unpin;
} }
intel_fb_obj_invalidate(obj, ORIGIN_CPU); intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
user_data = u64_to_user_ptr(args->data_ptr); user_data = u64_to_user_ptr(args->data_ptr);
offset = args->offset; offset = args->offset;
@ -636,7 +638,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
user_data += page_length; user_data += page_length;
offset += page_length; offset += page_length;
} }
intel_fb_obj_flush(obj, ORIGIN_CPU); intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
i915_gem_object_unlock_fence(obj, fence); i915_gem_object_unlock_fence(obj, fence);
out_unpin: out_unpin:
@ -729,7 +731,7 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
offset = 0; offset = 0;
} }
intel_fb_obj_flush(obj, ORIGIN_CPU); intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
i915_gem_object_unlock_fence(obj, fence); i915_gem_object_unlock_fence(obj, fence);
return ret; return ret;
@ -1763,39 +1765,6 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file)
return ret; return ret;
} }
/**
* i915_gem_track_fb - update frontbuffer tracking
* @old: current GEM buffer for the frontbuffer slots
* @new: new GEM buffer for the frontbuffer slots
* @frontbuffer_bits: bitmask of frontbuffer slots
*
* This updates the frontbuffer tracking bits @frontbuffer_bits by clearing them
* from @old and setting them in @new. Both @old and @new can be NULL.
*/
void i915_gem_track_fb(struct drm_i915_gem_object *old,
struct drm_i915_gem_object *new,
unsigned frontbuffer_bits)
{
/* Control of individual bits within the mask are guarded by
* the owning plane->mutex, i.e. we can never see concurrent
* manipulation of individual bits. But since the bitfield as a whole
* is updated using RMW, we need to use atomics in order to update
* the bits.
*/
BUILD_BUG_ON(INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES >
BITS_PER_TYPE(atomic_t));
if (old) {
WARN_ON(!(atomic_read(&old->frontbuffer_bits) & frontbuffer_bits));
atomic_andnot(frontbuffer_bits, &old->frontbuffer_bits);
}
if (new) {
WARN_ON(atomic_read(&new->frontbuffer_bits) & frontbuffer_bits);
atomic_or(frontbuffer_bits, &new->frontbuffer_bits);
}
}
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftests/mock_gem_device.c" #include "selftests/mock_gem_device.c"
#include "selftests/i915_gem.c" #include "selftests/i915_gem.c"

View File

@ -908,8 +908,10 @@ int i915_vma_move_to_active(struct i915_vma *vma,
return err; return err;
if (flags & EXEC_OBJECT_WRITE) { if (flags & EXEC_OBJECT_WRITE) {
if (intel_fb_obj_invalidate(obj, ORIGIN_CS)) if (intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CS))
__i915_active_request_set(&obj->frontbuffer_write, rq); i915_active_ref(&obj->frontbuffer->write,
rq->fence.context,
rq);
reservation_object_add_excl_fence(vma->resv, &rq->fence); reservation_object_add_excl_fence(vma->resv, &rq->fence);
obj->write_domain = I915_GEM_DOMAIN_RENDER; obj->write_domain = I915_GEM_DOMAIN_RENDER;