Commit 48a8dd17 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'drm-fixes-2019-12-28' of git://anongit.freedesktop.org/drm/drm

Pull drm fixes from Dave Airlie:
 "Post-xmas food coma recovery fixes. Only three fixes for i915 since I
  expect most people are holidaying.

  i915:
   - power management rc6 fix
   - framebuffer tracking fix
   - display power management ratelimit fix"

* tag 'drm-fixes-2019-12-28' of git://anongit.freedesktop.org/drm/drm:
  drm/i915: Hold reference to intel_frontbuffer as we track activity
  drm/i915/gt: Ratelimit display power w/a
  drm/i915/pmu: Ensure monotonic rc6
parents f4b39746 e31d941c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -15112,7 +15112,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
		return ret;

	fb_obj_bump_render_priority(obj);
	intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_DIRTYFB);
	i915_gem_object_flush_frontbuffer(obj, ORIGIN_DIRTYFB);

	if (!new_plane_state->base.fence) { /* implicit fencing */
		struct dma_fence *fence;
+6 −10
Original line number Diff line number Diff line
@@ -229,11 +229,11 @@ static void frontbuffer_release(struct kref *ref)
		vma->display_alignment = I915_GTT_MIN_ALIGNMENT;
	spin_unlock(&obj->vma.lock);

	obj->frontbuffer = NULL;
	RCU_INIT_POINTER(obj->frontbuffer, NULL);
	spin_unlock(&to_i915(obj->base.dev)->fb_tracking.lock);

	i915_gem_object_put(obj);
	kfree(front);
	kfree_rcu(front, rcu);
}

struct intel_frontbuffer *
@@ -242,11 +242,7 @@ 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);
	front = __intel_frontbuffer_get(obj);
	if (front)
		return front;

@@ -262,13 +258,13 @@ intel_frontbuffer_get(struct drm_i915_gem_object *obj)
			 i915_active_may_sleep(frontbuffer_retire));

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

+31 −3
Original line number Diff line number Diff line
@@ -27,10 +27,10 @@
#include <linux/atomic.h>
#include <linux/kref.h>

#include "gem/i915_gem_object_types.h"
#include "i915_active.h"

struct drm_i915_private;
struct drm_i915_gem_object;

enum fb_op_origin {
	ORIGIN_GTT,
@@ -45,6 +45,7 @@ struct intel_frontbuffer {
	atomic_t bits;
	struct i915_active write;
	struct drm_i915_gem_object *obj;
	struct rcu_head rcu;
};

void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915,
@@ -54,6 +55,35 @@ void intel_frontbuffer_flip_complete(struct drm_i915_private *i915,
void intel_frontbuffer_flip(struct drm_i915_private *i915,
			    unsigned frontbuffer_bits);

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);

@@ -119,6 +149,4 @@ 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__ */
+13 −4
Original line number Diff line number Diff line
@@ -279,12 +279,21 @@ static void intel_overlay_flip_prepare(struct intel_overlay *overlay,
				       struct i915_vma *vma)
{
	enum pipe pipe = overlay->crtc->pipe;
	struct intel_frontbuffer *from = NULL, *to = NULL;

	WARN_ON(overlay->old_vma);

	intel_frontbuffer_track(overlay->vma ? overlay->vma->obj->frontbuffer : NULL,
				vma ? vma->obj->frontbuffer : NULL,
				INTEL_FRONTBUFFER_OVERLAY(pipe));
	if (overlay->vma)
		from = intel_frontbuffer_get(overlay->vma->obj);
	if (vma)
		to = intel_frontbuffer_get(vma->obj);

	intel_frontbuffer_track(from, to, INTEL_FRONTBUFFER_OVERLAY(pipe));

	if (to)
		intel_frontbuffer_put(to);
	if (from)
		intel_frontbuffer_put(from);

	intel_frontbuffer_flip_prepare(overlay->i915,
				       INTEL_FRONTBUFFER_OVERLAY(pipe));
@@ -766,7 +775,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
		ret = PTR_ERR(vma);
		goto out_pin_section;
	}
	intel_frontbuffer_flush(new_bo->frontbuffer, ORIGIN_DIRTYFB);
	i915_gem_object_flush_frontbuffer(new_bo, ORIGIN_DIRTYFB);

	if (!overlay->active) {
		u32 oconfig;
+2 −1
Original line number Diff line number Diff line
@@ -20,7 +20,8 @@ static void __do_clflush(struct drm_i915_gem_object *obj)
{
	GEM_BUG_ON(!i915_gem_object_has_pages(obj));
	drm_clflush_sg(obj->mm.pages);
	intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);

	i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
}

static int clflush_work(struct dma_fence_work *base)
Loading