Commit ba318c61 authored by Chris Wilson's avatar Chris Wilson

drm/i915: Drain the freed state from the tail of the next commit

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: eb955eee ("drm/i915: Move atomic state free from out of fence release")
Testcase: igt/kms_cursor/legacy/all-pipes-single-bo
Reported-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: default avatarChris 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.ukReviewed-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
parent 28b6def6
...@@ -14395,6 +14395,24 @@ static void skl_update_crtcs(struct drm_atomic_state *state, ...@@ -14395,6 +14395,24 @@ static void skl_update_crtcs(struct drm_atomic_state *state,
} while (progress); } 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) static void intel_atomic_commit_tail(struct drm_atomic_state *state)
{ {
struct drm_device *dev = state->dev; struct drm_device *dev = state->dev;
...@@ -14561,6 +14579,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -14561,6 +14579,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
* can happen also when the device is completely off. * can happen also when the device is completely off.
*/ */
intel_uncore_arm_unclaimed_mmio_detection(dev_priv); 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) static void intel_atomic_commit_work(struct work_struct *work)
...@@ -16615,18 +16635,6 @@ static void sanitize_watermarks(struct drm_device *dev) ...@@ -16615,18 +16635,6 @@ static void sanitize_watermarks(struct drm_device *dev)
drm_modeset_acquire_fini(&ctx); 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) int intel_modeset_init(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
...@@ -16647,7 +16655,7 @@ int intel_modeset_init(struct drm_device *dev) ...@@ -16647,7 +16655,7 @@ int intel_modeset_init(struct drm_device *dev)
dev->mode_config.funcs = &intel_mode_funcs; dev->mode_config.funcs = &intel_mode_funcs;
INIT_WORK(&dev_priv->atomic_helper.free_work, INIT_WORK(&dev_priv->atomic_helper.free_work,
intel_atomic_helper_free_state); intel_atomic_helper_free_state_worker);
intel_init_quirks(dev); intel_init_quirks(dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment