[Intel-gfx] [PATCH 4/6] drm/i915: Allow mmio updates on all platforms.
Maarten Lankhorst
maarten.lankhorst at linux.intel.com
Thu Mar 24 08:35:04 UTC 2016
Op 23-03-16 om 16:07 schreef Ville Syrjälä:
> On Wed, Mar 23, 2016 at 02:24:30PM +0100, Maarten Lankhorst wrote:
>> Rename intel_unpin_work to intel_flip_work and use it for mmio flips
>> and unpinning. Use flip_queued_req to hold the wait request in the
>> mmio case and allow the vblank interrupt to complete mmio work to
>> have mmio flips run correctly on g4 and earlier.
> Before you actually go and trust drm_vblank_count() you should make it
> race free.
How about adding the below to the patch?
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index befac649aa96..05ec832e02de 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11224,12 +11224,11 @@ static void intel_mmio_flip_work_func(struct work_struct *w)
false, false,
MAX_SCHEDULE_TIMEOUT) < 0);
- intel_pipe_update_start(crtc);
+ intel_pipe_update_start(crtc, work);
primary->update_plane(&primary->base,
crtc->config,
to_intel_plane_state(primary->base.state));
- atomic_set(&work->pending, INTEL_FLIP_PENDING);
- intel_pipe_update_end(crtc);
+ intel_pipe_update_end(crtc, work);
}
static int intel_default_queue_flip(struct drm_device *dev,
@@ -13800,7 +13799,7 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc,
bool modeset = needs_modeset(crtc->state);
/* Perform vblank evasion around commit operation */
- intel_pipe_update_start(intel_crtc);
+ intel_pipe_update_start(intel_crtc, NULL);
if (modeset)
return;
@@ -13816,7 +13815,7 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc,
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- intel_pipe_update_end(intel_crtc);
+ intel_pipe_update_end(intel_crtc, NULL);
}
/**
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index cac368138764..86d486cfd778 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1604,8 +1604,8 @@ bool intel_sdvo_init(struct drm_device *dev,
int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-void intel_pipe_update_start(struct intel_crtc *crtc);
-void intel_pipe_update_end(struct intel_crtc *crtc);
+void intel_pipe_update_start(struct intel_crtc *crtc, struct intel_flip_work *work);
+void intel_pipe_update_end(struct intel_crtc *crtc, struct intel_flip_work *work);
/* intel_tv.c */
void intel_tv_init(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 8821533561b1..8da59a1eca56 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -78,7 +78,8 @@ static int usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
* avoid random delays. The value written to @start_vbl_count should be
* supplied to intel_pipe_update_end() for error checking.
*/
-void intel_pipe_update_start(struct intel_crtc *crtc)
+void intel_pipe_update_start(struct intel_crtc *crtc,
+ struct intel_flip_work *work)
{
struct drm_device *dev = crtc->base.dev;
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
@@ -142,6 +143,9 @@ void intel_pipe_update_start(struct intel_crtc *crtc)
crtc->debug.start_vbl_count =
dev->driver->get_vblank_counter(dev, pipe);
+ if (work)
+ work->flip_queued_vblank = crtc->debug.start_vbl_count;
+
trace_i915_pipe_update_vblank_evaded(crtc);
}
@@ -154,7 +158,7 @@ void intel_pipe_update_start(struct intel_crtc *crtc)
* re-enables interrupts and verifies the update was actually completed
* before a vblank using the value of @start_vbl_count.
*/
-void intel_pipe_update_end(struct intel_crtc *crtc)
+void intel_pipe_update_end(struct intel_crtc *crtc, struct intel_flip_work *work)
{
struct drm_device *dev = crtc->base.dev;
enum pipe pipe = crtc->pipe;
@@ -162,6 +166,12 @@ void intel_pipe_update_end(struct intel_crtc *crtc)
u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe);
ktime_t end_vbl_time = ktime_get();
+ if (work) {
+ work->flip_queued_vblank = end_vbl_count;
+ smp_mb__before_atomic();
+ atomic_set(&work->pending, INTEL_FLIP_PENDING);
+ }
+
trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
local_irq_enable();
More information about the Intel-gfx
mailing list