clear-pkgs-linux-iot-lts2018/0678-MUST_REBASE-IOTG-drm-i...

212 lines
6.6 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Badiuzzaman Iskhandar <badiuzzaman.azzarfan.bin.iskhandar@intel.com>
Date: Tue, 9 Oct 2018 15:51:18 +0800
Subject: [PATCH] MUST_REBASE [IOTG]: drm/i915: Allow late GuC/HuC loading
This patch allows for the GuC and HuC to be loaded until the first
device is open (instead of during the driver initialisation).
Delaying the fw load prevents a load failure when the partition that the
firmware is supposed to be on has not been mounted yet, as is the case
in Android.
During i915 init, if huc/guc enabled, the huc/guc fw sizes need to be known.
As we defer the fw fetch later, the fw sizes can't be determined.
ggtt_pin_bias relies on the fw size as well.
MUST_REBASE: The hw_late code is part of a solution for loading firmware
of a file system that has not been mounted yet. Only a problem
on Android. This patch is a rewrote from similar patch in 4.11
Change-Id: Ic4f414deed9961d73c25434b3d8698ae9fbb425c
Tracked-On:
Signed-off-by: Badiuzzaman Iskhandar <badiuzzaman.azzarfan.bin.iskhandar@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 3 ++
drivers/gpu/drm/i915/i915_gem.c | 48 ++++++++++++++++++++-----
drivers/gpu/drm/i915/i915_gem_context.c | 44 +++++++++++++++++++----
drivers/gpu/drm/i915/intel_wopcm.c | 7 ++++
4 files changed, 88 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 3cd14d171c61..972b25e62711 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2148,6 +2148,8 @@ struct drm_i915_private {
struct i915_pmu pmu;
+ bool contexts_ready; /* for deferred initialization */
+
/*
* NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
* will be rejected. Instead look for a better place.
@@ -3210,6 +3212,7 @@ void i915_gem_reset_engine(struct intel_engine_cs *engine,
void i915_gem_init_mmio(struct drm_i915_private *i915);
int __must_check i915_gem_init(struct drm_i915_private *dev_priv);
int __must_check i915_gem_init_hw(struct drm_i915_private *dev_priv);
+int __must_check i915_gem_init_hw_late(struct drm_i915_private *dev_priv);
void i915_gem_init_swizzling(struct drm_i915_private *dev_priv);
void i915_gem_fini(struct drm_i915_private *dev_priv);
void i915_gem_cleanup_engines(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 402db0dac1c4..e9aad26ee653 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -6198,6 +6198,28 @@ static int __i915_gem_restart_engines(void *data)
return 0;
}
+int i915_gem_init_hw_late(struct drm_i915_private *dev_priv)
+{
+ int ret;
+
+ /*
+ * Place for things that can be delayed until the first context
+ * is open. For example, fw loading in android.
+ */
+
+ /* fetch firmware */
+ intel_uc_init_misc(dev_priv);
+
+ /* Load fw. We can't enable contexts until all firmware is loaded */
+ ret = intel_uc_init_hw(dev_priv);
+ if (ret) {
+ DRM_ERROR("Late init: enabling uc failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
int i915_gem_init_hw(struct drm_i915_private *dev_priv)
{
int ret;
@@ -6256,11 +6278,17 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv)
goto out;
}
- /* We can't enable contexts until all firmware is loaded */
- ret = intel_uc_init_hw(dev_priv);
- if (ret) {
- DRM_ERROR("Enabling uc failed (%d)\n", ret);
- goto out;
+ /*
+ * Don't call i915_gem_init_hw_late() the very first time (during
+ * driver load); it will get called during first open instead.
+ * It should only be called on subsequent (re-initialization) passes.
+ */
+ if (dev_priv->contexts_ready) {
+ ret = i915_gem_init_hw_late(dev_priv);
+ if (ret)
+ goto out;
+ } else {
+ DRM_DEBUG_DRIVER("Deferring late initialization\n");
}
intel_mocs_init_l3cc_table(dev_priv);
@@ -6424,9 +6452,13 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
if (ret)
return ret;
- ret = intel_uc_init_misc(dev_priv);
- if (ret)
- return ret;
+ /*
+ * ANDROID: fetch fw during drm_open instead
+ * due to filesystem is not up yet during driver init
+ * ret = intel_uc_init_misc(dev_priv);
+ * if (ret)
+ * return ret;
+ */
ret = intel_wopcm_init(&dev_priv->wopcm);
if (ret)
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 74917976d99e..29cd2281414b 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -567,23 +567,55 @@ static int context_idr_cleanup(int id, void *p, void *data)
return 0;
}
+int i915_gem_context_first_open(struct drm_i915_private *dev_priv)
+{
+ int ret;
+
+ lockdep_assert_held(&dev_priv->drm.struct_mutex);
+
+ DRM_DEBUG_DRIVER("Late initialization starting\n");
+
+ intel_runtime_pm_get(dev_priv);
+ intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
+
+ ret = i915_gem_init_hw_late(dev_priv);
+ if (ret == 0)
+ dev_priv->contexts_ready = true;
+ else
+ DRM_ERROR("Late initialization failed: %d\n", ret);
+
+ intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
+ intel_runtime_pm_put(dev_priv);
+
+ return ret;
+}
+
int i915_gem_context_open(struct drm_i915_private *i915,
struct drm_file *file)
{
struct drm_i915_file_private *file_priv = file->driver_priv;
struct i915_gem_context *ctx;
+ int ret = 0;
idr_init(&file_priv->context_idr);
mutex_lock(&i915->drm.struct_mutex);
- ctx = i915_gem_create_context(i915, file_priv);
- mutex_unlock(&i915->drm.struct_mutex);
- if (IS_ERR(ctx)) {
- idr_destroy(&file_priv->context_idr);
- return PTR_ERR(ctx);
+
+ if (!(i915->contexts_ready))
+ ret = i915_gem_context_first_open(i915);
+
+ if (ret == 0) {
+ ctx = i915_gem_create_context(i915, file_priv);
+ if (IS_ERR(ctx))
+ ret = PTR_ERR(ctx);
+
+ GEM_BUG_ON(i915_gem_context_is_kernel(ctx));
}
- GEM_BUG_ON(i915_gem_context_is_kernel(ctx));
+ mutex_unlock(&i915->drm.struct_mutex);
+
+ if (ret)
+ idr_destroy(&file_priv->context_idr);
return 0;
}
diff --git a/drivers/gpu/drm/i915/intel_wopcm.c b/drivers/gpu/drm/i915/intel_wopcm.c
index 74bf76f3fddc..5ff877ed7b12 100644
--- a/drivers/gpu/drm/i915/intel_wopcm.c
+++ b/drivers/gpu/drm/i915/intel_wopcm.c
@@ -207,6 +207,13 @@ int intel_wopcm_init(struct intel_wopcm *wopcm)
wopcm->guc.base = guc_wopcm_base;
wopcm->guc.size = guc_wopcm_size;
+ /*
+ * In deferred fw loading, we defer the intel_guc_init which will
+ * initialize the guc.ggtt_pin_bias. As it relies on wopcm size,
+ * set the ggtt_pin_bias after wopcm initialization
+ */
+ i915->guc.ggtt_pin_bias = i915->wopcm.size - i915->wopcm.guc.base;
+
return 0;
}
--
https://clearlinux.org