Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a20def95 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'topic/vma-fix-for-4.10-2017-02-02' of...

Merge tag 'topic/vma-fix-for-4.10-2017-02-02' of git://anongit.freedesktop.org/git/drm-intel into drm-fixes

here's Maarten's backport of the vma fixes for v4.10.

* tag 'topic/vma-fix-for-4.10-2017-02-02' of git://anongit.freedesktop.org/git/drm-intel:
  drm/i915: Track pinned vma in intel_plane_state
  drm/atomic: Unconditionally call prepare_fb.
parents 52b679f6 e8fe4f4b
Loading
Loading
Loading
Loading
+0 −9
Original line number Diff line number Diff line
@@ -1666,9 +1666,6 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,

		funcs = plane->helper_private;

		if (!drm_atomic_helper_framebuffer_changed(dev, state, plane_state->crtc))
			continue;

		if (funcs->prepare_fb) {
			ret = funcs->prepare_fb(plane, plane_state);
			if (ret)
@@ -1685,9 +1682,6 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
		if (j >= i)
			continue;

		if (!drm_atomic_helper_framebuffer_changed(dev, state, plane_state->crtc))
			continue;

		funcs = plane->helper_private;

		if (funcs->cleanup_fb)
@@ -1954,9 +1948,6 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
	for_each_plane_in_state(old_state, plane, plane_state, i) {
		const struct drm_plane_helper_funcs *funcs;

		if (!drm_atomic_helper_framebuffer_changed(dev, old_state, plane_state->crtc))
			continue;

		funcs = plane->helper_private;

		if (funcs->cleanup_fb)
+4 −12
Original line number Diff line number Diff line
@@ -1012,6 +1012,8 @@ struct intel_fbc {
	struct work_struct underrun_work;

	struct intel_fbc_state_cache {
		struct i915_vma *vma;

		struct {
			unsigned int mode_flags;
			uint32_t hsw_bdw_pixel_rate;
@@ -1025,15 +1027,14 @@ struct intel_fbc {
		} plane;

		struct {
			u64 ilk_ggtt_offset;
			uint32_t pixel_format;
			unsigned int stride;
			int fence_reg;
			unsigned int tiling_mode;
		} fb;
	} state_cache;

	struct intel_fbc_reg_params {
		struct i915_vma *vma;

		struct {
			enum pipe pipe;
			enum plane plane;
@@ -1041,10 +1042,8 @@ struct intel_fbc {
		} crtc;

		struct {
			u64 ggtt_offset;
			uint32_t pixel_format;
			unsigned int stride;
			int fence_reg;
		} fb;

		int cfb_size;
@@ -3168,13 +3167,6 @@ i915_gem_object_to_ggtt(struct drm_i915_gem_object *obj,
	return i915_gem_obj_to_vma(obj, &to_i915(obj->base.dev)->ggtt.base, view);
}

static inline unsigned long
i915_gem_object_ggtt_offset(struct drm_i915_gem_object *o,
			    const struct i915_ggtt_view *view)
{
	return i915_ggtt_offset(i915_gem_object_to_ggtt(o, view));
}

/* i915_gem_fence_reg.c */
int __must_check i915_vma_get_fence(struct i915_vma *vma);
int __must_check i915_vma_put_fence(struct i915_vma *vma);
+20 −0
Original line number Diff line number Diff line
@@ -85,6 +85,8 @@ intel_plane_duplicate_state(struct drm_plane *plane)

	__drm_atomic_helper_plane_duplicate_state(plane, state);

	intel_state->vma = NULL;

	return state;
}

@@ -100,6 +102,24 @@ void
intel_plane_destroy_state(struct drm_plane *plane,
			  struct drm_plane_state *state)
{
	struct i915_vma *vma;

	vma = fetch_and_zero(&to_intel_plane_state(state)->vma);

	/*
	 * FIXME: Normally intel_cleanup_plane_fb handles destruction of vma.
	 * We currently don't clear all planes during driver unload, so we have
	 * to be able to unpin vma here for now.
	 *
	 * Normally this can only happen during unload when kmscon is disabled
	 * and userspace doesn't attempt to set a framebuffer at all.
	 */
	if (vma) {
		mutex_lock(&plane->dev->struct_mutex);
		intel_unpin_fb_vma(vma);
		mutex_unlock(&plane->dev->struct_mutex);
	}

	drm_atomic_helper_plane_destroy_state(plane, state);
}

+42 −83
Original line number Diff line number Diff line
@@ -2235,27 +2235,22 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
			i915_vma_pin_fence(vma);
	}

	i915_vma_get(vma);
err:
	intel_runtime_pm_put(dev_priv);
	return vma;
}

void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
void intel_unpin_fb_vma(struct i915_vma *vma)
{
	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
	struct i915_ggtt_view view;
	struct i915_vma *vma;

	WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));

	intel_fill_fb_ggtt_view(&view, fb, rotation);
	vma = i915_gem_object_to_ggtt(obj, &view);
	lockdep_assert_held(&vma->vm->dev->struct_mutex);

	if (WARN_ON_ONCE(!vma))
		return;

	i915_vma_unpin_fence(vma);
	i915_gem_object_unpin_from_display_plane(vma);
	i915_vma_put(vma);
}

static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane,
@@ -2750,7 +2745,6 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
	struct drm_device *dev = intel_crtc->base.dev;
	struct drm_i915_private *dev_priv = to_i915(dev);
	struct drm_crtc *c;
	struct intel_crtc *i;
	struct drm_i915_gem_object *obj;
	struct drm_plane *primary = intel_crtc->base.primary;
	struct drm_plane_state *plane_state = primary->state;
@@ -2775,20 +2769,20 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
	 * an fb with another CRTC instead
	 */
	for_each_crtc(dev, c) {
		i = to_intel_crtc(c);
		struct intel_plane_state *state;

		if (c == &intel_crtc->base)
			continue;

		if (!i->active)
		if (!to_intel_crtc(c)->active)
			continue;

		fb = c->primary->fb;
		if (!fb)
		state = to_intel_plane_state(c->primary->state);
		if (!state->vma)
			continue;

		obj = intel_fb_obj(fb);
		if (i915_gem_object_ggtt_offset(obj, NULL) == plane_config->base) {
		if (intel_plane_ggtt_offset(state) == plane_config->base) {
			fb = c->primary->fb;
			drm_framebuffer_reference(fb);
			goto valid_fb;
		}
@@ -2809,6 +2803,19 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
	return;

valid_fb:
	mutex_lock(&dev->struct_mutex);
	intel_state->vma =
		intel_pin_and_fence_fb_obj(fb, primary->state->rotation);
	mutex_unlock(&dev->struct_mutex);
	if (IS_ERR(intel_state->vma)) {
		DRM_ERROR("failed to pin boot fb on pipe %d: %li\n",
			  intel_crtc->pipe, PTR_ERR(intel_state->vma));

		intel_state->vma = NULL;
		drm_framebuffer_unreference(fb);
		return;
	}

	plane_state->src_x = 0;
	plane_state->src_y = 0;
	plane_state->src_w = fb->width << 16;
@@ -3104,13 +3111,13 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
	if (INTEL_GEN(dev_priv) >= 4) {
		I915_WRITE(DSPSURF(plane),
			   intel_fb_gtt_offset(fb, rotation) +
			   intel_plane_ggtt_offset(plane_state) +
			   intel_crtc->dspaddr_offset);
		I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
		I915_WRITE(DSPLINOFF(plane), linear_offset);
	} else {
		I915_WRITE(DSPADDR(plane),
			   intel_fb_gtt_offset(fb, rotation) +
			   intel_plane_ggtt_offset(plane_state) +
			   intel_crtc->dspaddr_offset);
	}
	POSTING_READ(reg);
@@ -3207,7 +3214,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,

	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
	I915_WRITE(DSPSURF(plane),
		   intel_fb_gtt_offset(fb, rotation) +
		   intel_plane_ggtt_offset(plane_state) +
		   intel_crtc->dspaddr_offset);
	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
		I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
@@ -3230,23 +3237,6 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
	}
}

u32 intel_fb_gtt_offset(struct drm_framebuffer *fb,
			unsigned int rotation)
{
	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
	struct i915_ggtt_view view;
	struct i915_vma *vma;

	intel_fill_fb_ggtt_view(&view, fb, rotation);

	vma = i915_gem_object_to_ggtt(obj, &view);
	if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
		 view.type))
		return -1;

	return i915_ggtt_offset(vma);
}

static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
{
	struct drm_device *dev = intel_crtc->base.dev;
@@ -3441,7 +3431,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
	}

	I915_WRITE(PLANE_SURF(pipe, 0),
		   intel_fb_gtt_offset(fb, rotation) + surf_addr);
		   intel_plane_ggtt_offset(plane_state) + surf_addr);

	POSTING_READ(PLANE_SURF(pipe, 0));
}
@@ -11536,7 +11526,7 @@ static void intel_unpin_work_fn(struct work_struct *__work)
		flush_work(&work->mmio_work);

	mutex_lock(&dev->struct_mutex);
	intel_unpin_fb_obj(work->old_fb, primary->state->rotation);
	intel_unpin_fb_vma(work->old_vma);
	i915_gem_object_put(work->pending_flip_obj);
	mutex_unlock(&dev->struct_mutex);

@@ -12246,8 +12236,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
		goto cleanup_pending;
	}

	work->gtt_offset = intel_fb_gtt_offset(fb, primary->state->rotation);
	work->gtt_offset += intel_crtc->dspaddr_offset;
	work->old_vma = to_intel_plane_state(primary->state)->vma;
	to_intel_plane_state(primary->state)->vma = vma;

	work->gtt_offset = i915_ggtt_offset(vma) + intel_crtc->dspaddr_offset;
	work->rotation = crtc->primary->state->rotation;

	/*
@@ -12301,7 +12293,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
cleanup_request:
	i915_add_request_no_flush(request);
cleanup_unpin:
	intel_unpin_fb_obj(fb, crtc->primary->state->rotation);
	to_intel_plane_state(primary->state)->vma = work->old_vma;
	intel_unpin_fb_vma(vma);
cleanup_pending:
	atomic_dec(&intel_crtc->unpin_work_count);
unlock:
@@ -14794,6 +14787,8 @@ intel_prepare_plane_fb(struct drm_plane *plane,
			DRM_DEBUG_KMS("failed to pin object\n");
			return PTR_ERR(vma);
		}

		to_intel_plane_state(new_state)->vma = vma;
	}

	return 0;
@@ -14812,19 +14807,12 @@ void
intel_cleanup_plane_fb(struct drm_plane *plane,
		       struct drm_plane_state *old_state)
{
	struct drm_i915_private *dev_priv = to_i915(plane->dev);
	struct intel_plane_state *old_intel_state;
	struct drm_i915_gem_object *old_obj = intel_fb_obj(old_state->fb);
	struct drm_i915_gem_object *obj = intel_fb_obj(plane->state->fb);

	old_intel_state = to_intel_plane_state(old_state);

	if (!obj && !old_obj)
		return;
	struct i915_vma *vma;

	if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR ||
	    !INTEL_INFO(dev_priv)->cursor_needs_physical))
		intel_unpin_fb_obj(old_state->fb, old_state->rotation);
	/* Should only be called after a successful intel_prepare_plane_fb()! */
	vma = fetch_and_zero(&to_intel_plane_state(old_state)->vma);
	if (vma)
		intel_unpin_fb_vma(vma);
}

int
@@ -15166,7 +15154,7 @@ intel_update_cursor_plane(struct drm_plane *plane,
	if (!obj)
		addr = 0;
	else if (!INTEL_INFO(dev_priv)->cursor_needs_physical)
		addr = i915_gem_object_ggtt_offset(obj, NULL);
		addr = intel_plane_ggtt_offset(state);
	else
		addr = obj->phys_handle->busaddr;

@@ -17066,41 +17054,12 @@ void intel_display_resume(struct drm_device *dev)
void intel_modeset_gem_init(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = to_i915(dev);
	struct drm_crtc *c;
	struct drm_i915_gem_object *obj;

	intel_init_gt_powersave(dev_priv);

	intel_modeset_init_hw(dev);

	intel_setup_overlay(dev_priv);

	/*
	 * Make sure any fbs we allocated at startup are properly
	 * pinned & fenced.  When we do the allocation it's too early
	 * for this.
	 */
	for_each_crtc(dev, c) {
		struct i915_vma *vma;

		obj = intel_fb_obj(c->primary->fb);
		if (obj == NULL)
			continue;

		mutex_lock(&dev->struct_mutex);
		vma = intel_pin_and_fence_fb_obj(c->primary->fb,
						 c->primary->state->rotation);
		mutex_unlock(&dev->struct_mutex);
		if (IS_ERR(vma)) {
			DRM_ERROR("failed to pin boot fb on pipe %d\n",
				  to_intel_crtc(c)->pipe);
			drm_framebuffer_unreference(c->primary->fb);
			c->primary->fb = NULL;
			c->primary->crtc = c->primary->state->crtc = NULL;
			update_state_fb(c->primary);
			c->state->plane_mask &= ~(1 << drm_plane_index(c->primary));
		}
	}
}

int intel_connector_register(struct drm_connector *connector)
+7 −2
Original line number Diff line number Diff line
@@ -377,6 +377,7 @@ struct intel_atomic_state {
struct intel_plane_state {
	struct drm_plane_state base;
	struct drm_rect clip;
	struct i915_vma *vma;

	struct {
		u32 offset;
@@ -1046,6 +1047,7 @@ struct intel_flip_work {
	struct work_struct mmio_work;

	struct drm_crtc *crtc;
	struct i915_vma *old_vma;
	struct drm_framebuffer *old_fb;
	struct drm_i915_gem_object *pending_flip_obj;
	struct drm_pending_vblank_event *event;
@@ -1273,7 +1275,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
				    struct drm_modeset_acquire_ctx *ctx);
struct i915_vma *
intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation);
void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation);
void intel_unpin_fb_vma(struct i915_vma *vma);
struct drm_framebuffer *
__intel_framebuffer_create(struct drm_device *dev,
			   struct drm_mode_fb_cmd2 *mode_cmd,
@@ -1362,7 +1364,10 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);

u32 intel_fb_gtt_offset(struct drm_framebuffer *fb, unsigned int rotation);
static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
{
	return i915_ggtt_offset(state->vma);
}

u32 skl_plane_ctl_format(uint32_t pixel_format);
u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
Loading