Skip to content

Commit

Permalink
Merge tag 'drm-fixes-2019-12-28' of git://anongit.freedesktop.org/drm…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
torvalds committed Dec 27, 2019
2 parents f4b3974 + e31d941 commit 48a8dd1
Show file tree
Hide file tree
Showing 14 changed files with 139 additions and 86 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/display/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
16 changes: 6 additions & 10 deletions drivers/gpu/drm/i915/display/intel_frontbuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 *
Expand All @@ -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;

Expand All @@ -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);

Expand Down
34 changes: 31 additions & 3 deletions drivers/gpu/drm/i915/display/intel_frontbuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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);

Expand Down Expand Up @@ -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__ */
17 changes: 13 additions & 4 deletions drivers/gpu/drm/i915/display/intel_overlay.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/i915/gem/i915_gem_clflush.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/i915/gem/i915_gem_domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
i915_gem_object_unlock(obj);

if (write_domain)
intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);

out_unpin:
i915_gem_object_unpin_pages(obj);
Expand Down Expand Up @@ -784,7 +784,7 @@ int i915_gem_object_prepare_write(struct drm_i915_gem_object *obj,
}

out:
intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
obj->mm.dirty = true;
/* return with the pages pinned */
return 0;
Expand Down
26 changes: 25 additions & 1 deletion drivers/gpu/drm/i915/gem/i915_gem_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ i915_gem_object_flush_write_domain(struct drm_i915_gem_object *obj,
for_each_ggtt_vma(vma, obj)
intel_gt_flush_ggtt_writes(vma->vm->gt);

intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);

for_each_ggtt_vma(vma, obj) {
if (vma->iomap)
Expand Down Expand Up @@ -308,6 +308,30 @@ i915_gem_object_flush_write_domain(struct drm_i915_gem_object *obj,
obj->write_domain = 0;
}

void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj,
enum fb_op_origin origin)
{
struct intel_frontbuffer *front;

front = __intel_frontbuffer_get(obj);
if (front) {
intel_frontbuffer_flush(front, origin);
intel_frontbuffer_put(front);
}
}

void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
enum fb_op_origin origin)
{
struct intel_frontbuffer *front;

front = __intel_frontbuffer_get(obj);
if (front) {
intel_frontbuffer_invalidate(front, origin);
intel_frontbuffer_put(front);
}
}

void i915_gem_init__objects(struct drm_i915_private *i915)
{
INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
Expand Down
23 changes: 22 additions & 1 deletion drivers/gpu/drm/i915/gem/i915_gem_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@

#include <drm/i915_drm.h>

#include "display/intel_frontbuffer.h"
#include "i915_gem_object_types.h"

#include "i915_gem_gtt.h"

void i915_gem_init__objects(struct drm_i915_private *i915);
Expand Down Expand Up @@ -463,4 +463,25 @@ int i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
unsigned int flags,
const struct i915_sched_attr *attr);

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,
enum fb_op_origin origin);

static inline void
i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj,
enum fb_op_origin origin)
{
if (unlikely(rcu_access_pointer(obj->frontbuffer)))
__i915_gem_object_flush_frontbuffer(obj, origin);
}

static inline void
i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
enum fb_op_origin origin)
{
if (unlikely(rcu_access_pointer(obj->frontbuffer)))
__i915_gem_object_invalidate_frontbuffer(obj, origin);
}

#endif
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/gem/i915_gem_object_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ struct drm_i915_gem_object {
*/
u16 write_domain;

struct intel_frontbuffer *frontbuffer;
struct intel_frontbuffer __rcu *frontbuffer;

/** Current tiling stride for the object, if it's tiled. */
unsigned int tiling_and_stride;
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/i915/gt/intel_gt_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ static int __gt_park(struct intel_wakeref *wf)
intel_uncore_forcewake_put(&i915->uncore, FORCEWAKE_ALL);
}

/* Defer dropping the display power well for 100ms, it's slow! */
GEM_BUG_ON(!wakeref);
intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ, wakeref);
intel_display_power_put_async(i915, POWER_DOMAIN_GT_IRQ, wakeref);

i915_globals_park();

Expand Down
10 changes: 5 additions & 5 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,15 +161,15 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
* We manually control the domain here and pretend that it
* remains coherent i.e. in the GTT domain, like shmem_pwrite.
*/
intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);

if (copy_from_user(vaddr, user_data, args->size))
return -EFAULT;

drm_clflush_virt_range(vaddr, args->size);
intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);

intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
return 0;
}

Expand Down Expand Up @@ -589,7 +589,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
goto out_unpin;
}

intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);

user_data = u64_to_user_ptr(args->data_ptr);
offset = args->offset;
Expand Down Expand Up @@ -631,7 +631,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
user_data += page_length;
offset += page_length;
}
intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);

i915_gem_object_unlock_fence(obj, fence);
out_unpin:
Expand Down Expand Up @@ -721,7 +721,7 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
offset = 0;
}

intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
i915_gem_object_unlock_fence(obj, fence);

return ret;
Expand Down
Loading

0 comments on commit 48a8dd1

Please sign in to comment.