@@ -1609,6 +1609,29 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
goto out_mtrrfree;
}
+ /*
+ * Creating our own private workqueue for handling the
+ * MMIO based flips. This is to avoid the block of the
+ * display thread (who issued the flip ioctl), due to the
+ * synchronization needed between the Rendering & flip stages.
+ * Now with MMIO based flips, the synchronization will require a
+ * wait in sw for the ongoing rendering operation, if any, to
+ * complete before issuing the flip. Because of this work queue,
+ * the wait on rendering would be done by the worker thread.
+ *
+ * Also since the flip work has to be processed at earliest,
+ * HIGHPRI flag is used here. We also use an ordered one, as
+ * we need serialized execution but anyways we support one
+ * outstanding flip call only, so probably doesn't really matter.
+ */
+ dev_priv->flipwq = alloc_ordered_workqueue("i915_flip", WQ_HIGHPRI);
+ if (dev_priv->flipwq == NULL) {
+ DRM_ERROR("Failed to create flip workqueue.\n");
+ ret = -ENOMEM;
+ destroy_workqueue(dev_priv->wq);
+ goto out_mtrrfree;
+ }
+
intel_irq_init(dev);
intel_uncore_sanitize(dev);
@@ -1685,6 +1708,7 @@ out_gem_unload:
intel_teardown_gmbus(dev);
intel_teardown_mchbar(dev);
+ destroy_workqueue(dev_priv->flipwq);
destroy_workqueue(dev_priv->wq);
out_mtrrfree:
arch_phys_wc_del(dev_priv->gtt.mtrr);
@@ -1792,6 +1816,7 @@ int i915_driver_unload(struct drm_device *dev)
intel_teardown_mchbar(dev);
destroy_workqueue(dev_priv->wq);
+ destroy_workqueue(dev_priv->flipwq);
pm_qos_remove_request(&dev_priv->pm_qos);
dev_priv->gtt.base.cleanup(&dev_priv->gtt.base);
@@ -1451,6 +1451,7 @@ typedef struct drm_i915_private {
* result in deadlocks.
*/
struct workqueue_struct *wq;
+ struct workqueue_struct *flipwq;
/* Display functions */
struct drm_i915_display_funcs display;