[Intel-gfx] [PATCH] TGL HAX drm/i915/tgl: Interrupts are overrated
Chris Wilson
chris at chris-wilson.co.uk
Fri Oct 4 07:03:30 UTC 2019
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 <chris at chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala at linux.intel.com>
---
drivers/gpu/drm/i915/Kconfig | 1 +
drivers/gpu/drm/i915/Kconfig.debug | 5 +++
drivers/gpu/drm/i915/gt/intel_engine_types.h | 3 ++
drivers/gpu/drm/i915/gt/intel_gt_irq.c | 13 +++++---
drivers/gpu/drm/i915/gt/intel_lrc.c | 34 ++++++++++++++++++++
drivers/gpu/drm/i915/i915_drv.h | 3 ++
drivers/gpu/drm/i915/i915_irq.c | 14 ++++++--
drivers/gpu/drm/i915/i915_pci.c | 1 -
8 files changed, 67 insertions(+), 7 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/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug
index 4a800faa275c..4d23a84ac2c4 100644
--- a/drivers/gpu/drm/i915/Kconfig.debug
+++ b/drivers/gpu/drm/i915/Kconfig.debug
@@ -44,6 +44,7 @@ config DRM_I915_DEBUG
select DRM_I915_SELFTEST
select DRM_I915_DEBUG_RUNTIME_PM
select DRM_I915_DEBUG_MMIO
+ select TIGERLAKE_DEBUG_IRQ
default n
help
Choose this option to turn on extra driver debugging that may affect
@@ -220,3 +221,7 @@ config DRM_I915_DEBUG_RUNTIME_PM
driver loading, suspend and resume operations.
If in doubt, say "N"
+
+config TIGERLAKE_DEBUG_IRQ
+ bool "[TGL] Reduce IRQ functionality for stability"
+ default n
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..7d4c2f18576e 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
@@ -45,6 +45,9 @@ gen11_gt_engine_identity(struct intel_gt *gt,
lockdep_assert_held(>->irq_lock);
+ if (WARN_ON(TIGERLAKE_NO_IRQ(gt->i915)))
+ return 0;
+
raw_reg_write(regs, GEN11_IIR_REG_SELECTOR(bank), BIT(bit));
/*
@@ -209,12 +212,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 (TIGERLAKE_NO_IRQ(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..900b473e280d 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 (TIGERLAKE_NO_IRQ(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);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 337d8306416a..c505d9e38e98 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2069,6 +2069,9 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#define IS_GEN9_LP(dev_priv) (IS_GEN(dev_priv, 9) && IS_LP(dev_priv))
#define IS_GEN9_BC(dev_priv) (IS_GEN(dev_priv, 9) && !IS_LP(dev_priv))
+#define TIGERLAKE_NO_IRQ(i915) \
+ IS_ENABLED(CONFIG_TIGERLAKE_DEBUG_IRQ) && IS_TIGERLAKE(i915)
+
#define HAS_ENGINE(dev_priv, id) (INTEL_INFO(dev_priv)->engine_mask & BIT(id))
#define ENGINE_INSTANCES_MASK(dev_priv, first, count) ({ \
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index bc83f094065a..05060f829981 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -360,6 +360,9 @@ void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv)
if (READ_ONCE(rps->interrupts_enabled))
return;
+ if (!dev_priv->pm_rps_events)
+ return;
+
spin_lock_irq(>->irq_lock);
WARN_ON_ONCE(rps->pm_iir);
@@ -376,7 +379,12 @@ void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv)
u32 gen6_sanitize_rps_pm_mask(const struct drm_i915_private *i915, u32 mask)
{
- return mask & ~i915->gt_pm.rps.pm_intrmsk_mbz;
+ const struct intel_rps *rps = &i915->gt_pm.rps;
+
+ if (!rps->interrupts_enabled)
+ return ~0u;
+
+ return mask & ~rps->pm_intrmsk_mbz;
}
void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv)
@@ -4314,7 +4322,9 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
dev_priv->gt.pm_guc_events = GUC_INTR_GUC2HOST << 16;
/* Let's track the enabled rps events */
- if (IS_VALLEYVIEW(dev_priv))
+ if (TIGERLAKE_NO_IRQ(dev_priv))
+ dev_priv->pm_rps_events = 0;
+ else if (IS_VALLEYVIEW(dev_priv))
/* WaGsvRC0ResidencyMethod:vlv */
dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED;
else
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index 1cbf3998b361..86be10cc6a70 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -806,7 +806,6 @@ static const struct intel_device_info intel_tigerlake_12_info = {
.display.has_modular_fia = 1,
.engine_mask =
BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2),
- .has_rps = false, /* XXX disabled for debugging */
};
#undef GEN
--
2.23.0
More information about the Intel-gfx
mailing list