Skip to content

Commit

Permalink
drm/i915/uc: Unify firmware loading
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Michal Wajdeczko authored and Joonas Lahtinen committed Oct 16, 2017
1 parent f1e86ce commit 4502e9e
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 95 deletions.
52 changes: 5 additions & 47 deletions drivers/gpu/drm/i915/intel_guc_fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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;
}

Expand All @@ -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);
}
53 changes: 5 additions & 48 deletions drivers/gpu/drm/i915/intel_huc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
}

/**
Expand Down
79 changes: 79 additions & 0 deletions drivers/gpu/drm/i915/intel_uc_fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,85 @@ void intel_uc_fw_fetch(struct drm_i915_private *dev_priv,
release_firmware(fw); /* OK even if fw is NULL */
}

/**
* 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
*
Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/i915/intel_uc_fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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

0 comments on commit 4502e9e

Please sign in to comment.