|
@@ -14523,8 +14523,14 @@ intel_atomic_commit_ready(struct i915_sw_fence *fence,
|
|
|
break;
|
|
|
|
|
|
case FENCE_FREE:
|
|
|
- drm_atomic_state_put(&state->base);
|
|
|
- break;
|
|
|
+ {
|
|
|
+ struct intel_atomic_helper *helper =
|
|
|
+ &to_i915(state->base.dev)->atomic_helper;
|
|
|
+
|
|
|
+ if (llist_add(&state->freed, &helper->free_list))
|
|
|
+ schedule_work(&helper->free_work);
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return NOTIFY_DONE;
|
|
@@ -16403,6 +16409,18 @@ fail:
|
|
|
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);
|
|
@@ -16422,6 +16440,9 @@ 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_init_quirks(dev);
|
|
|
|
|
|
intel_init_pm(dev_priv);
|
|
@@ -17106,6 +17127,9 @@ void intel_modeset_cleanup(struct drm_device *dev)
|
|
|
{
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
|
|
|
+ flush_work(&dev_priv->atomic_helper.free_work);
|
|
|
+ WARN_ON(!llist_empty(&dev_priv->atomic_helper.free_list));
|
|
|
+
|
|
|
intel_disable_gt_powersave(dev_priv);
|
|
|
|
|
|
/*
|