Why sleep when you can busywait for an interrupt? Throw out the old irq
handlers, and use irq_poll instead.

References: https://bugs.freedesktop.org/show_bug.cgi?id=111880
Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuopp...@linux.intel.com>
---
 drivers/gpu/drm/i915/Kconfig                 |  1 +
 drivers/gpu/drm/i915/gt/intel_engine_types.h |  3 ++
 drivers/gpu/drm/i915/gt/intel_gt_irq.c       | 10 +++---
 drivers/gpu/drm/i915/gt/intel_lrc.c          | 34 ++++++++++++++++++++
 4 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index 0d21402945ab..bf2b27b6ebf2 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -13,6 +13,7 @@ config DRM_I915
        select DRM_PANEL
        select DRM_MIPI_DSI
        select RELAY
+       select IRQ_POLL
        select IRQ_WORK
        # i915 depends on ACPI_VIDEO when ACPI is enabled
        # but for select to work, need to select ACPI_VIDEO's dependencies, ick
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h 
b/drivers/gpu/drm/i915/gt/intel_engine_types.h
index 943f0663837e..53265add81ec 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h
@@ -8,6 +8,7 @@
 #define __INTEL_ENGINE_TYPES__
 
 #include <linux/hashtable.h>
+#include <linux/irq_poll.h>
 #include <linux/irq_work.h>
 #include <linux/kref.h>
 #include <linux/list.h>
@@ -330,6 +331,8 @@ struct intel_engine_cs {
        struct drm_i915_gem_object *default_state;
        void *pinned_default_state;
 
+       struct irq_poll irq_poll;
+
        struct {
                struct intel_ring *ring;
                struct intel_timeline *timeline;
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c 
b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
index 34a4fb624bf7..76ad58268f61 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
@@ -209,12 +209,14 @@ void gen11_gt_irq_reset(struct intel_gt *gt)
 
 void gen11_gt_irq_postinstall(struct intel_gt *gt)
 {
-       const u32 irqs = GT_RENDER_USER_INTERRUPT | GT_CONTEXT_SWITCH_INTERRUPT;
        struct intel_uncore *uncore = gt->uncore;
-       const u32 dmask = irqs << 16 | irqs;
-       const u32 smask = irqs << 16;
+       u32 irqs, dmask, smask;
 
-       BUILD_BUG_ON(irqs & 0xffff0000);
+       irqs = GT_RENDER_USER_INTERRUPT | GT_CONTEXT_SWITCH_INTERRUPT;
+       if (IS_TIGERLAKE(gt->i915))
+               irqs = 0; /* XXX lalalala */
+       smask = irqs << 16;
+       dmask = smask | irqs;
 
        /* Enable RCS, BCS, VCS and VECS class interrupts. */
        intel_uncore_write(uncore, GEN11_RENDER_COPY_INTR_ENABLE, dmask);
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c 
b/drivers/gpu/drm/i915/gt/intel_lrc.c
index 431d3b8c3371..08c144708af7 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -1944,6 +1944,8 @@ static void process_csb(struct intel_engine_cs *engine)
 
                        GEM_BUG_ON(execlists->active - execlists->inflight >
                                   execlists_num_ports(execlists));
+
+                       intel_engine_queue_breadcrumbs(engine);
                }
        } while (head != tail);
 
@@ -1987,6 +1989,27 @@ static void execlists_submission_tasklet(unsigned long 
data)
        }
 }
 
+static int iop_handler(struct irq_poll *iop, int budget)
+{
+       struct intel_engine_cs *engine =
+               container_of(iop, typeof(*engine), irq_poll);
+       struct intel_engine_execlists *execlists = &engine->execlists;
+       struct tasklet_struct *t = &execlists->tasklet;
+
+       if (execlists->csb_head == READ_ONCE(*execlists->csb_write))
+               return 0;
+
+       if (!tasklet_trylock(t))
+               return 0;
+
+       /* Must wait for any GPU reset in progress. */
+       if (__tasklet_is_enabled(t))
+               t->func(t->data);
+
+       tasklet_unlock(t);
+       return 0;
+}
+
 static void execlists_submission_timer(struct timer_list *timer)
 {
        struct intel_engine_cs *engine =
@@ -3414,9 +3437,16 @@ gen12_emit_fini_breadcrumb_rcs(struct i915_request 
*request, u32 *cs)
        return gen12_emit_fini_breadcrumb_footer(request, cs);
 }
 
+static void tgl_unpark(struct intel_engine_cs *engine)
+{
+       clear_bit(IRQ_POLL_F_DISABLE, &engine->irq_poll.state);
+       irq_poll_sched(&engine->irq_poll);
+}
+
 static void execlists_park(struct intel_engine_cs *engine)
 {
        del_timer(&engine->execlists.timer);
+       set_bit(IRQ_POLL_F_DISABLE, &engine->irq_poll.state);
 }
 
 void intel_execlists_set_default_submission(struct intel_engine_cs *engine)
@@ -3432,6 +3462,8 @@ void intel_execlists_set_default_submission(struct 
intel_engine_cs *engine)
 
        engine->park = execlists_park;
        engine->unpark = NULL;
+       if (IS_TIGERLAKE(engine->i915))
+               engine->unpark = tgl_unpark;
 
        engine->flags |= I915_ENGINE_SUPPORTS_STATS;
        if (!intel_vgpu_active(engine->i915)) {
@@ -3446,6 +3478,7 @@ void intel_execlists_set_default_submission(struct 
intel_engine_cs *engine)
 
 static void execlists_destroy(struct intel_engine_cs *engine)
 {
+       irq_poll_disable(&engine->irq_poll);
        intel_engine_cleanup_common(engine);
        lrc_destroy_wa_ctx(engine);
        kfree(engine);
@@ -3532,6 +3565,7 @@ static void rcs_submission_override(struct 
intel_engine_cs *engine)
 
 int intel_execlists_submission_setup(struct intel_engine_cs *engine)
 {
+       irq_poll_init(&engine->irq_poll, -1, iop_handler);
        tasklet_init(&engine->execlists.tasklet,
                     execlists_submission_tasklet, (unsigned long)engine);
        timer_setup(&engine->execlists.timer, execlists_submission_timer, 0);
-- 
2.23.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to