From 1bb4308e7130428917bfa54c556daa98f7aa1ac9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 7 Mar 2016 12:05:57 +0000 Subject: [PATCH] drm/i915/csr: Allow matching unknown HW steppings with generic firmware If the firmware is generic and has a run-anywhere mode, enable it rather than completely failing on unknown HW revisions. Signed-off-by: Chris Wilson Cc: Damien Lespiau Cc: Imre Deak Cc: Sunil Kamath Cc: Daniel Vetter Cc: Animesh Manna Cc: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/1457352357-8433-1-git-send-email-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_csr.c | 46 +++++++++++++------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index d417d9ab49b5..3f57cb94d9ad 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -188,28 +188,31 @@ static const struct stepping_info bxt_stepping_info[] = { {'B', '0'}, {'B', '1'}, {'B', '2'} }; -static const struct stepping_info *intel_get_stepping_info(struct drm_device *dev) +static const struct stepping_info no_stepping_info = { '*', '*' }; + +static const struct stepping_info * +intel_get_stepping_info(struct drm_i915_private *dev_priv) { const struct stepping_info *si; unsigned int size; - if (IS_KABYLAKE(dev)) { + if (IS_KABYLAKE(dev_priv)) { size = ARRAY_SIZE(kbl_stepping_info); si = kbl_stepping_info; - } else if (IS_SKYLAKE(dev)) { + } else if (IS_SKYLAKE(dev_priv)) { size = ARRAY_SIZE(skl_stepping_info); si = skl_stepping_info; - } else if (IS_BROXTON(dev)) { + } else if (IS_BROXTON(dev_priv)) { size = ARRAY_SIZE(bxt_stepping_info); si = bxt_stepping_info; } else { - return NULL; + size = 0; } - if (INTEL_REVID(dev) < size) - return si + INTEL_REVID(dev); + if (INTEL_REVID(dev_priv) < size) + return si + INTEL_REVID(dev_priv); - return NULL; + return &no_stepping_info; } static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv) @@ -270,13 +273,11 @@ void intel_csr_load_program(struct drm_i915_private *dev_priv) static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, const struct firmware *fw) { - struct drm_device *dev = dev_priv->dev; struct intel_css_header *css_header; struct intel_package_header *package_header; struct intel_dmc_header *dmc_header; struct intel_csr *csr = &dev_priv->csr; - const struct stepping_info *stepping_info = intel_get_stepping_info(dev); - char stepping, substepping; + const struct stepping_info *si = intel_get_stepping_info(dev_priv); uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes; uint32_t i; uint32_t *dmc_payload; @@ -284,14 +285,6 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, if (!fw) return NULL; - if (!stepping_info) { - DRM_ERROR("Unknown stepping info, firmware loading failed\n"); - return NULL; - } - - stepping = stepping_info->stepping; - substepping = stepping_info->substepping; - /* Extract CSS Header information*/ css_header = (struct intel_css_header *)fw->data; if (sizeof(struct intel_css_header) != @@ -303,7 +296,7 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, csr->version = css_header->version; - if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) && + if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && csr->version < SKL_CSR_VERSION_REQUIRED) { DRM_INFO("Refusing to load old Skylake DMC firmware v%u.%u," " please upgrade to v%u.%u or later" @@ -331,11 +324,11 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, /* Search for dmc_offset to find firware binary. */ for (i = 0; i < package_header->num_entries; i++) { if (package_header->fw_info[i].substepping == '*' && - stepping == package_header->fw_info[i].stepping) { + si->stepping == package_header->fw_info[i].stepping) { dmc_offset = package_header->fw_info[i].offset; break; - } else if (stepping == package_header->fw_info[i].stepping && - substepping == package_header->fw_info[i].substepping) { + } else if (si->stepping == package_header->fw_info[i].stepping && + si->substepping == package_header->fw_info[i].substepping) { dmc_offset = package_header->fw_info[i].offset; break; } else if (package_header->fw_info[i].stepping == '*' && @@ -343,7 +336,8 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, dmc_offset = package_header->fw_info[i].offset; } if (dmc_offset == CSR_DEFAULT_FW_OFFSET) { - DRM_ERROR("Firmware not supported for %c stepping\n", stepping); + DRM_ERROR("Firmware not supported for %c stepping\n", + si->stepping); return NULL; } readcount += dmc_offset; @@ -389,9 +383,7 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, return NULL; } - memcpy(dmc_payload, &fw->data[readcount], nbytes); - - return dmc_payload; + return memcpy(dmc_payload, &fw->data[readcount], nbytes); } static void csr_load_work_fn(struct work_struct *work)