summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorMichal Wajdeczko <michal.wajdeczko@intel.com>2017-10-16 17:47:21 +0300
committerJoonas Lahtinen <joonas.lahtinen@linux.intel.com>2017-10-16 18:53:29 +0300
commit4502e9ec820d763750e54c11683d37b992358d6e (patch)
tree81858ff47f3bbaa2618d4f6a15772ba869b5ad4f /drivers/gpu
parentf1e86cecf1d1ae9b933d3f69cc24632556d5eb8c (diff)
downloadlinux-4502e9ec820d763750e54c11683d37b992358d6e.tar.xz
drm/i915/uc: Unify firmware loading
Firmware loading for GuC and HuC are similar. Move common code into generic function for maximum reuse. v2: change message levels (Chris) Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com> Cc: Anusha Srivatsa <anusha.srivatsa@intel.com> Cc: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20171016144724.17244-13-michal.wajdeczko@intel.com
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/intel_guc_fw.c52
-rw-r--r--drivers/gpu/drm/i915/intel_huc.c53
-rw-r--r--drivers/gpu/drm/i915/intel_uc_fw.c79
-rw-r--r--drivers/gpu/drm/i915/intel_uc_fw.h4
4 files changed, 93 insertions, 95 deletions
diff --git a/drivers/gpu/drm/i915/intel_guc_fw.c b/drivers/gpu/drm/i915/intel_guc_fw.c
index 4cb8c1cc6597..ef67a36354c5 100644
--- a/drivers/gpu/drm/i915/intel_guc_fw.c
+++ b/drivers/gpu/drm/i915/intel_guc_fw.c
@@ -188,24 +188,13 @@ static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv,
/*
* Load the GuC firmware blob into the MinuteIA.
*/
-static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
+static int guc_ucode_xfer(struct intel_uc_fw *guc_fw, struct i915_vma *vma)
{
- struct intel_uc_fw *guc_fw = &dev_priv->guc.fw;
- struct i915_vma *vma;
+ struct intel_guc *guc = container_of(guc_fw, struct intel_guc, fw);
+ struct drm_i915_private *dev_priv = guc_to_i915(guc);
int ret;
- ret = i915_gem_object_set_to_gtt_domain(guc_fw->obj, false);
- if (ret) {
- DRM_DEBUG_DRIVER("set-domain failed %d\n", ret);
- return ret;
- }
-
- vma = i915_gem_object_ggtt_pin(guc_fw->obj, NULL, 0, 0,
- PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
- if (IS_ERR(vma)) {
- DRM_DEBUG_DRIVER("pin failed %d\n", (int)PTR_ERR(vma));
- return PTR_ERR(vma);
- }
+ GEM_BUG_ON(guc_fw->type != INTEL_UC_FW_TYPE_GUC);
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
@@ -240,12 +229,6 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
- /*
- * We keep the object pages for reuse during resume. But we can unpin it
- * now that DMA has completed, so it doesn't continue to take up space.
- */
- i915_vma_unpin(vma);
-
return ret;
}
@@ -264,30 +247,5 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
*/
int intel_guc_fw_upload(struct intel_guc *guc)
{
- struct drm_i915_private *dev_priv = guc_to_i915(guc);
- const char *fw_path = guc->fw.path;
- int ret;
-
- DRM_DEBUG_DRIVER("GuC fw status: path %s, fetch %s, load %s\n",
- fw_path,
- intel_uc_fw_status_repr(guc->fw.fetch_status),
- intel_uc_fw_status_repr(guc->fw.load_status));
-
- if (guc->fw.fetch_status != INTEL_UC_FIRMWARE_SUCCESS)
- return -EIO;
-
- guc->fw.load_status = INTEL_UC_FIRMWARE_PENDING;
-
- DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
- intel_uc_fw_status_repr(guc->fw.fetch_status),
- intel_uc_fw_status_repr(guc->fw.load_status));
-
- ret = guc_ucode_xfer(dev_priv);
-
- if (ret)
- return -EAGAIN;
-
- guc->fw.load_status = INTEL_UC_FIRMWARE_SUCCESS;
-
- return 0;
+ return intel_uc_fw_upload(&guc->fw, guc_ucode_xfer);
}
diff --git a/drivers/gpu/drm/i915/intel_huc.c b/drivers/gpu/drm/i915/intel_huc.c
index 4b4cf56d29ad..8be3bfeb58dd 100644
--- a/drivers/gpu/drm/i915/intel_huc.c
+++ b/drivers/gpu/drm/i915/intel_huc.c
@@ -85,26 +85,15 @@ MODULE_FIRMWARE(I915_KBL_HUC_UCODE);
*
* Return: 0 on success, non-zero on failure
*/
-static int huc_ucode_xfer(struct drm_i915_private *dev_priv)
+static int huc_ucode_xfer(struct intel_uc_fw *huc_fw, struct i915_vma *vma)
{
- struct intel_uc_fw *huc_fw = &dev_priv->huc.fw;
- struct i915_vma *vma;
+ struct intel_huc *huc = container_of(huc_fw, struct intel_huc, fw);
+ struct drm_i915_private *dev_priv = huc_to_i915(huc);
unsigned long offset = 0;
u32 size;
int ret;
- ret = i915_gem_object_set_to_gtt_domain(huc_fw->obj, false);
- if (ret) {
- DRM_DEBUG_DRIVER("set-domain failed %d\n", ret);
- return ret;
- }
-
- vma = i915_gem_object_ggtt_pin(huc_fw->obj, NULL, 0, 0,
- PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
- if (IS_ERR(vma)) {
- DRM_DEBUG_DRIVER("pin failed %d\n", (int)PTR_ERR(vma));
- return PTR_ERR(vma);
- }
+ GEM_BUG_ON(huc_fw->type != INTEL_UC_FW_TYPE_HUC);
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
@@ -135,12 +124,6 @@ static int huc_ucode_xfer(struct drm_i915_private *dev_priv)
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
- /*
- * We keep the object pages for reuse during resume. But we can unpin it
- * now that DMA has completed, so it doesn't continue to take up space.
- */
- i915_vma_unpin(vma);
-
return ret;
}
@@ -194,33 +177,7 @@ void intel_huc_select_fw(struct intel_huc *huc)
*/
void intel_huc_init_hw(struct intel_huc *huc)
{
- struct drm_i915_private *dev_priv = huc_to_i915(huc);
- int err;
-
- DRM_DEBUG_DRIVER("%s fw status: fetch %s, load %s\n",
- huc->fw.path,
- intel_uc_fw_status_repr(huc->fw.fetch_status),
- intel_uc_fw_status_repr(huc->fw.load_status));
-
- if (huc->fw.fetch_status != INTEL_UC_FIRMWARE_SUCCESS)
- return;
-
- huc->fw.load_status = INTEL_UC_FIRMWARE_PENDING;
-
- err = huc_ucode_xfer(dev_priv);
-
- huc->fw.load_status = err ?
- INTEL_UC_FIRMWARE_FAIL : INTEL_UC_FIRMWARE_SUCCESS;
-
- DRM_DEBUG_DRIVER("%s fw status: fetch %s, load %s\n",
- huc->fw.path,
- intel_uc_fw_status_repr(huc->fw.fetch_status),
- intel_uc_fw_status_repr(huc->fw.load_status));
-
- if (huc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS)
- DRM_ERROR("Failed to complete HuC uCode load with ret %d\n", err);
-
- return;
+ intel_uc_fw_upload(&huc->fw, huc_ucode_xfer);
}
/**
diff --git a/drivers/gpu/drm/i915/intel_uc_fw.c b/drivers/gpu/drm/i915/intel_uc_fw.c
index 1bb031925239..7bb0109bfbbd 100644
--- a/drivers/gpu/drm/i915/intel_uc_fw.c
+++ b/drivers/gpu/drm/i915/intel_uc_fw.c
@@ -195,6 +195,85 @@ fail:
}
/**
+ * intel_uc_fw_upload - load uC firmware using custom loader
+ *
+ * @uc_fw: uC firmware
+ * @loader: custom uC firmware loader function
+ *
+ * Loads uC firmware using custom loader and updates internal flags.
+ */
+int intel_uc_fw_upload(struct intel_uc_fw *uc_fw,
+ int (*xfer)(struct intel_uc_fw *uc_fw,
+ struct i915_vma *vma))
+{
+ struct i915_vma *vma;
+ int err;
+
+ DRM_DEBUG_DRIVER("%s fw load %s\n",
+ intel_uc_fw_type_repr(uc_fw->type), uc_fw->path);
+
+ if (uc_fw->fetch_status != INTEL_UC_FIRMWARE_SUCCESS)
+ return -EIO;
+
+ uc_fw->load_status = INTEL_UC_FIRMWARE_PENDING;
+ DRM_DEBUG_DRIVER("%s fw load %s\n",
+ intel_uc_fw_type_repr(uc_fw->type),
+ intel_uc_fw_status_repr(uc_fw->load_status));
+
+ /* Pin object with firmware */
+ err = i915_gem_object_set_to_gtt_domain(uc_fw->obj, false);
+ if (err) {
+ DRM_DEBUG_DRIVER("%s fw set-domain err=%d\n",
+ intel_uc_fw_type_repr(uc_fw->type), err);
+ goto fail;
+ }
+
+ vma = i915_gem_object_ggtt_pin(uc_fw->obj, NULL, 0, 0,
+ PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
+ if (IS_ERR(vma)) {
+ err = PTR_ERR(vma);
+ DRM_DEBUG_DRIVER("%s fw ggtt-pin err=%d\n",
+ intel_uc_fw_type_repr(uc_fw->type), err);
+ goto fail;
+ }
+
+ /* Call custom loader */
+ err = xfer(uc_fw, vma);
+
+ /*
+ * We keep the object pages for reuse during resume. But we can unpin it
+ * now that DMA has completed, so it doesn't continue to take up space.
+ */
+ i915_vma_unpin(vma);
+
+ if (err)
+ goto fail;
+
+ uc_fw->load_status = INTEL_UC_FIRMWARE_SUCCESS;
+ DRM_DEBUG_DRIVER("%s fw load %s\n",
+ intel_uc_fw_type_repr(uc_fw->type),
+ intel_uc_fw_status_repr(uc_fw->load_status));
+
+ DRM_INFO("%s: Loaded firmware %s (version %u.%u)\n",
+ intel_uc_fw_type_repr(uc_fw->type),
+ uc_fw->path,
+ uc_fw->major_ver_found, uc_fw->minor_ver_found);
+
+ return 0;
+
+fail:
+ uc_fw->load_status = INTEL_UC_FIRMWARE_FAIL;
+ DRM_DEBUG_DRIVER("%s fw load %s\n",
+ intel_uc_fw_type_repr(uc_fw->type),
+ intel_uc_fw_status_repr(uc_fw->load_status));
+
+ DRM_WARN("%s: Failed to load firmware %s (error %d)\n",
+ intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err);
+
+ return err;
+}
+
+/**
* intel_uc_fw_fini - cleanup uC firmware
*
* @uc_fw: uC firmware
diff --git a/drivers/gpu/drm/i915/intel_uc_fw.h b/drivers/gpu/drm/i915/intel_uc_fw.h
index 849c3c0c007d..412fbdc4db93 100644
--- a/drivers/gpu/drm/i915/intel_uc_fw.h
+++ b/drivers/gpu/drm/i915/intel_uc_fw.h
@@ -26,6 +26,7 @@
#define _INTEL_UC_FW_H_
struct drm_i915_private;
+struct i915_vma;
/* Home of GuC, HuC and DMC firmwares */
#define INTEL_UC_FIRMWARE_URL "https://01.org/linuxgraphics/downloads/firmware"
@@ -110,6 +111,9 @@ void intel_uc_fw_init(struct intel_uc_fw *uc_fw, enum intel_uc_fw_type type)
void intel_uc_fw_fetch(struct drm_i915_private *dev_priv,
struct intel_uc_fw *uc_fw);
+int intel_uc_fw_upload(struct intel_uc_fw *uc_fw,
+ int (*xfer)(struct intel_uc_fw *uc_fw,
+ struct i915_vma *vma));
void intel_uc_fw_fini(struct intel_uc_fw *uc_fw);
#endif