Skip to content

Commit

Permalink
drm/i915: Drain the freed state from the tail of the next commit
Browse files Browse the repository at this point in the history
If we have any residual freed atomic state from earlier commits, flush
the freed list after performing the current modeset. This prevents the
freed list from ever-growing if userspace manages to starve the kernel
threads (i.e. we are never able to run our free state worker and
eventually the system may even oom).

Fixes: eb955ee ("drm/i915: Move atomic state free from out of fence release")
Testcase: igt/kms_cursor/legacy/all-pipes-single-bo
Reported-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20170202204741.18231-1-chris@chris-wilson.co.uk
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
  • Loading branch information
Chris Wilson committed Feb 6, 2017
1 parent 28b6def commit ba318c6
Showing 1 changed file with 21 additions and 13 deletions.
34 changes: 21 additions & 13 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -14395,6 +14395,24 @@ static void skl_update_crtcs(struct drm_atomic_state *state,
} while (progress);
}

static void intel_atomic_helper_free_state(struct drm_i915_private *dev_priv)
{
struct intel_atomic_state *state, *next;
struct llist_node *freed;

freed = llist_del_all(&dev_priv->atomic_helper.free_list);
llist_for_each_entry_safe(state, next, freed, freed)
drm_atomic_state_put(&state->base);
}

static void intel_atomic_helper_free_state_worker(struct work_struct *work)
{
struct drm_i915_private *dev_priv =
container_of(work, typeof(*dev_priv), atomic_helper.free_work);

intel_atomic_helper_free_state(dev_priv);
}

static void intel_atomic_commit_tail(struct drm_atomic_state *state)
{
struct drm_device *dev = state->dev;
Expand Down Expand Up @@ -14561,6 +14579,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
* can happen also when the device is completely off.
*/
intel_uncore_arm_unclaimed_mmio_detection(dev_priv);

intel_atomic_helper_free_state(dev_priv);
}

static void intel_atomic_commit_work(struct work_struct *work)
Expand Down Expand Up @@ -16615,18 +16635,6 @@ static void sanitize_watermarks(struct drm_device *dev)
drm_modeset_acquire_fini(&ctx);
}

static void intel_atomic_helper_free_state(struct work_struct *work)
{
struct drm_i915_private *dev_priv =
container_of(work, typeof(*dev_priv), atomic_helper.free_work);
struct intel_atomic_state *state, *next;
struct llist_node *freed;

freed = llist_del_all(&dev_priv->atomic_helper.free_list);
llist_for_each_entry_safe(state, next, freed, freed)
drm_atomic_state_put(&state->base);
}

int intel_modeset_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
Expand All @@ -16647,7 +16655,7 @@ int intel_modeset_init(struct drm_device *dev)
dev->mode_config.funcs = &intel_mode_funcs;

INIT_WORK(&dev_priv->atomic_helper.free_work,
intel_atomic_helper_free_state);
intel_atomic_helper_free_state_worker);

intel_init_quirks(dev);

Expand Down

0 comments on commit ba318c6

Please sign in to comment.