diff options
-rw-r--r-- | drivers/gpu/drm/i915/Makefile | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_context.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_guc.c | 66 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_guc.h | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_guc_reg.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_huc.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_uc.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_uc_fw.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_uc_fw.h | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_wopcm.c | 182 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_wopcm.h | 30 |
14 files changed, 321 insertions, 41 deletions
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index fcb8a7b27ae2..552e43e9663f 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -79,7 +79,8 @@ i915-y += i915_cmd_parser.o \ intel_lrc.o \ intel_mocs.o \ intel_ringbuffer.o \ - intel_uncore.o + intel_uncore.o \ + intel_wopcm.o # general-purpose microcontroller (GuC) support i915-y += intel_uc.o \ diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 0126b222ab7f..f03555efc520 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -919,6 +919,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, mutex_init(&dev_priv->wm.wm_mutex); mutex_init(&dev_priv->pps_mutex); + intel_wopcm_init_early(&dev_priv->wopcm); intel_uc_init_early(dev_priv); i915_memcpy_init_early(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 74b0e9d8ff62..e27ba8fb64e6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -64,6 +64,7 @@ #include "intel_opregion.h" #include "intel_ringbuffer.h" #include "intel_uncore.h" +#include "intel_wopcm.h" #include "intel_uc.h" #include "i915_gem.h" @@ -1589,6 +1590,8 @@ struct drm_i915_private { struct intel_gvt *gvt; + struct intel_wopcm wopcm; + struct intel_huc huc; struct intel_guc guc; @@ -2121,6 +2124,11 @@ static inline struct drm_i915_private *kdev_to_i915(struct device *kdev) return to_i915(dev_get_drvdata(kdev)); } +static inline struct drm_i915_private *wopcm_to_i915(struct intel_wopcm *wopcm) +{ + return container_of(wopcm, struct drm_i915_private, wopcm); +} + static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) { return container_of(guc, struct drm_i915_private, guc); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d0624c57d9a6..51faa6506739 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5294,6 +5294,10 @@ int i915_gem_init(struct drm_i915_private *dev_priv) if (ret) return ret; + ret = intel_wopcm_init(&dev_priv->wopcm); + if (ret) + return ret; + ret = intel_uc_init_misc(dev_priv); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index f2cbea7cf940..5cfac0255758 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -318,12 +318,13 @@ __create_hw_context(struct drm_i915_private *dev_priv, ctx->desc_template = default_desc_template(dev_priv, dev_priv->mm.aliasing_ppgtt); - /* GuC requires the ring to be placed above GUC_WOPCM_TOP. If GuC is not + /* + * GuC requires the ring to be placed in Non-WOPCM memory. If GuC is not * present or not in use we still need a small bias as ring wraparound * at offset 0 sometimes hangs. No idea why. */ if (USES_GUC(dev_priv)) - ctx->ggtt_offset_bias = GUC_WOPCM_TOP; + ctx->ggtt_offset_bias = dev_priv->guc.ggtt_pin_bias; else ctx->ggtt_offset_bias = I915_GTT_PAGE_SIZE; diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c index 78463842ea7b..3eb516e7c225 100644 --- a/drivers/gpu/drm/i915/intel_guc.c +++ b/drivers/gpu/drm/i915/intel_guc.c @@ -493,6 +493,57 @@ int intel_guc_resume(struct intel_guc *guc) } /** + * DOC: GuC Address Space + * + * The layout of GuC address space is shown as below: + * + * +==============> +====================+ <== GUC_GGTT_TOP + * ^ | | + * | | | + * | | DRAM | + * | | Memory | + * | | | + * GuC | | + * Address +========> +====================+ <== WOPCM Top + * Space ^ | HW contexts RSVD | + * | | | WOPCM | + * | | +==> +--------------------+ <== GuC WOPCM Top + * | GuC ^ | | + * | GGTT | | | + * | Pin GuC | GuC | + * | Bias WOPCM | WOPCM | + * | | Size | | + * | | | | | + * v v v | | + * +=====+=====+==> +====================+ <== GuC WOPCM Base + * | Non-GuC WOPCM | + * | (HuC/Reserved) | + * +====================+ <== WOPCM Base + * + * The lower part [0, GuC ggtt_pin_bias) is mapped to WOPCM which consists of + * GuC WOPCM and WOPCM reserved for other usage (e.g.RC6 context). The value of + * the GuC ggtt_pin_bias is determined by the actually GuC WOPCM size which is + * set in GUC_WOPCM_SIZE register. + */ + +/** + * intel_guc_init_ggtt_pin_bias() - Initialize the GuC ggtt_pin_bias value. + * @guc: intel_guc structure. + * + * This function will calculate and initialize the ggtt_pin_bias value based on + * overall WOPCM size and GuC WOPCM size. + */ +void intel_guc_init_ggtt_pin_bias(struct intel_guc *guc) +{ + struct drm_i915_private *i915 = guc_to_i915(guc); + + GEM_BUG_ON(!i915->wopcm.size); + GEM_BUG_ON(i915->wopcm.size < i915->wopcm.guc.base); + + guc->ggtt_pin_bias = i915->wopcm.size - i915->wopcm.guc.base; +} + +/** * intel_guc_allocate_vma() - Allocate a GGTT VMA for GuC usage * @guc: the guc * @size: size of area to allocate (both virtual space and memory) @@ -500,7 +551,7 @@ int intel_guc_resume(struct intel_guc *guc) * This is a wrapper to create an object for use with the GuC. In order to * use it inside the GuC, an object needs to be pinned lifetime, so we allocate * both some backing storage and a range inside the Global GTT. We must pin - * it in the GGTT somewhere other than than [0, GUC_WOPCM_TOP) because that + * it in the GGTT somewhere other than than [0, GUC ggtt_pin_bias) because that * range is reserved inside GuC. * * Return: A i915_vma if successful, otherwise an ERR_PTR. @@ -521,7 +572,7 @@ struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size) goto err; ret = i915_vma_pin(vma, 0, PAGE_SIZE, - PIN_GLOBAL | PIN_OFFSET_BIAS | GUC_WOPCM_TOP); + PIN_GLOBAL | PIN_OFFSET_BIAS | guc->ggtt_pin_bias); if (ret) { vma = ERR_PTR(ret); goto err; @@ -533,14 +584,3 @@ err: i915_gem_object_put(obj); return vma; } - -u32 intel_guc_wopcm_size(struct drm_i915_private *dev_priv) -{ - u32 wopcm_size = GUC_WOPCM_TOP; - - /* On BXT, the top of WOPCM is reserved for RC6 context */ - if (IS_GEN9_LP(dev_priv)) - wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED; - - return wopcm_size; -} diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index a1be04eaafda..cdb649a9a4cf 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -49,6 +49,9 @@ struct intel_guc { struct intel_guc_log log; struct intel_guc_ct ct; + /* Offset where Non-WOPCM memory starts. */ + u32 ggtt_pin_bias; + /* Log snapshot if GuC errors during load */ struct drm_i915_gem_object *load_err_log; @@ -108,19 +111,20 @@ static inline void intel_guc_notify(struct intel_guc *guc) * @guc: intel_guc structure. * @vma: i915 graphics virtual memory area. * - * GuC does not allow any gfx GGTT address that falls into range [0, WOPCM_TOP), - * which is reserved for Boot ROM, SRAM and WOPCM. Currently this top address is - * 512K. In order to exclude 0-512K address space from GGTT, all gfx objects - * used by GuC is pinned with PIN_OFFSET_BIAS along with size of WOPCM. + * GuC does not allow any gfx GGTT address that falls into range + * [0, GuC ggtt_pin_bias), which is reserved for Boot ROM, SRAM and WOPCM. + * Currently, in order to exclude [0, GuC ggtt_pin_bias) address space from + * GGTT, all gfx objects used by GuC are allocated with intel_guc_allocate_vma() + * and pinned with PIN_OFFSET_BIAS along with the value of GuC ggtt_pin_bias. * - * Return: GGTT offset that meets the GuC gfx address requirement. + * Return: GGTT offset of the @vma. */ static inline u32 intel_guc_ggtt_offset(struct intel_guc *guc, struct i915_vma *vma) { u32 offset = i915_ggtt_offset(vma); - GEM_BUG_ON(offset < GUC_WOPCM_TOP); + GEM_BUG_ON(offset < guc->ggtt_pin_bias); GEM_BUG_ON(range_overflows_t(u64, offset, vma->size, GUC_GGTT_TOP)); return offset; @@ -129,6 +133,7 @@ static inline u32 intel_guc_ggtt_offset(struct intel_guc *guc, void intel_guc_init_early(struct intel_guc *guc); void intel_guc_init_send_regs(struct intel_guc *guc); void intel_guc_init_params(struct intel_guc *guc); +void intel_guc_init_ggtt_pin_bias(struct intel_guc *guc); int intel_guc_init_wq(struct intel_guc *guc); void intel_guc_fini_wq(struct intel_guc *guc); int intel_guc_init(struct intel_guc *guc); @@ -141,7 +146,6 @@ int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset); int intel_guc_suspend(struct intel_guc *guc); int intel_guc_resume(struct intel_guc *guc); struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size); -u32 intel_guc_wopcm_size(struct drm_i915_private *dev_priv); static inline int intel_guc_sanitize(struct intel_guc *guc) { diff --git a/drivers/gpu/drm/i915/intel_guc_reg.h b/drivers/gpu/drm/i915/intel_guc_reg.h index 711e9e974b7c..01963d085ed6 100644 --- a/drivers/gpu/drm/i915/intel_guc_reg.h +++ b/drivers/gpu/drm/i915/intel_guc_reg.h @@ -68,17 +68,15 @@ #define DMA_GUC_WOPCM_OFFSET _MMIO(0xc340) #define HUC_LOADING_AGENT_VCR (0<<1) #define HUC_LOADING_AGENT_GUC (1<<1) -#define GUC_WOPCM_OFFSET_VALUE 0x80000 /* 512KB */ +#define GUC_WOPCM_OFFSET_SHIFT 14 #define GUC_MAX_IDLE_COUNT _MMIO(0xC3E4) #define HUC_STATUS2 _MMIO(0xD3B0) #define HUC_FW_VERIFIED (1<<7) -/* Defines WOPCM space available to GuC firmware */ #define GUC_WOPCM_SIZE _MMIO(0xc050) -/* GuC addresses below GUC_WOPCM_TOP don't map through the GTT */ -#define GUC_WOPCM_TOP (0x80 << 12) /* 512KB */ -#define BXT_GUC_WOPCM_RC6_RESERVED (0x10 << 12) /* 64KB */ +#define GUC_WOPCM_SIZE_SHIFT 12 +#define GUC_WOPCM_SIZE_MASK (0xfffff << GUC_WOPCM_SIZE_SHIFT) #define GEN8_GT_PM_CONFIG _MMIO(0x138140) #define GEN9LP_GT_PM_CONFIG _MMIO(0x138140) diff --git a/drivers/gpu/drm/i915/intel_huc.c b/drivers/gpu/drm/i915/intel_huc.c index 858c9543630d..1d6c47b17935 100644 --- a/drivers/gpu/drm/i915/intel_huc.c +++ b/drivers/gpu/drm/i915/intel_huc.c @@ -55,7 +55,7 @@ int intel_huc_auth(struct intel_huc *huc) return -ENOEXEC; vma = i915_gem_object_ggtt_pin(huc->fw.obj, NULL, 0, 0, - PIN_OFFSET_BIAS | GUC_WOPCM_TOP); + PIN_OFFSET_BIAS | guc->ggtt_pin_bias); if (IS_ERR(vma)) { ret = PTR_ERR(vma); DRM_ERROR("HuC: Failed to pin huc fw object %d\n", ret); diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c index 9d5ffd74c16a..ed5a6fcc8557 100644 --- a/drivers/gpu/drm/i915/intel_uc.c +++ b/drivers/gpu/drm/i915/intel_uc.c @@ -272,6 +272,8 @@ int intel_uc_init_misc(struct drm_i915_private *dev_priv) if (!USES_GUC(dev_priv)) return 0; + intel_guc_init_ggtt_pin_bias(guc); + ret = intel_guc_init_wq(guc); if (ret) return ret; @@ -366,9 +368,9 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) gen9_reset_guc_interrupts(dev_priv); /* init WOPCM */ - I915_WRITE(GUC_WOPCM_SIZE, intel_guc_wopcm_size(dev_priv)); + I915_WRITE(GUC_WOPCM_SIZE, dev_priv->wopcm.guc.size); I915_WRITE(DMA_GUC_WOPCM_OFFSET, - GUC_WOPCM_OFFSET_VALUE | HUC_LOADING_AGENT_GUC); + dev_priv->wopcm.guc.base | HUC_LOADING_AGENT_GUC); /* WaEnableuKernelHeaderValidFix:skl */ /* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */ diff --git a/drivers/gpu/drm/i915/intel_uc_fw.c b/drivers/gpu/drm/i915/intel_uc_fw.c index 3ec0ce505b76..30c73243f54d 100644 --- a/drivers/gpu/drm/i915/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/intel_uc_fw.c @@ -95,15 +95,6 @@ void intel_uc_fw_fetch(struct drm_i915_private *dev_priv, uc_fw->ucode_offset = uc_fw->header_offset + uc_fw->header_size; uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32); - /* Header and uCode will be loaded to WOPCM */ - size = uc_fw->header_size + uc_fw->ucode_size; - if (size > intel_guc_wopcm_size(dev_priv)) { - DRM_WARN("%s: Firmware is too large to fit in WOPCM\n", - intel_uc_fw_type_repr(uc_fw->type)); - err = -E2BIG; - goto fail; - } - /* now RSA */ if (css->key_size_dw != UOS_RSA_SCRATCH_COUNT) { DRM_WARN("%s: Mismatched firmware RSA key size (%u)\n", @@ -208,6 +199,7 @@ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, int (*xfer)(struct intel_uc_fw *uc_fw, struct i915_vma *vma)) { + struct drm_i915_private *i915 = to_i915(uc_fw->obj->base.dev); struct i915_vma *vma; int err; @@ -231,7 +223,8 @@ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, } vma = i915_gem_object_ggtt_pin(uc_fw->obj, NULL, 0, 0, - PIN_OFFSET_BIAS | GUC_WOPCM_TOP); + PIN_OFFSET_BIAS | + i915->guc.ggtt_pin_bias); if (IS_ERR(vma)) { err = PTR_ERR(vma); DRM_DEBUG_DRIVER("%s fw ggtt-pin err=%d\n", diff --git a/drivers/gpu/drm/i915/intel_uc_fw.h b/drivers/gpu/drm/i915/intel_uc_fw.h index 2601521a4006..dc33b12394de 100644 --- a/drivers/gpu/drm/i915/intel_uc_fw.h +++ b/drivers/gpu/drm/i915/intel_uc_fw.h @@ -121,6 +121,22 @@ static inline void intel_uc_fw_sanitize(struct intel_uc_fw *uc_fw) uc_fw->load_status = INTEL_UC_FIRMWARE_PENDING; } +/** + * intel_uc_fw_get_upload_size() - Get size of firmware needed to be uploaded. + * @uc_fw: uC firmware. + * + * Get the size of the firmware and header that will be uploaded to WOPCM. + * + * Return: Upload firmware size, or zero on firmware fetch failure. + */ +static inline u32 intel_uc_fw_get_upload_size(struct intel_uc_fw *uc_fw) +{ + if (uc_fw->fetch_status != INTEL_UC_FIRMWARE_SUCCESS) + return 0; + + return uc_fw->header_size + uc_fw->ucode_size; +} + 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, diff --git a/drivers/gpu/drm/i915/intel_wopcm.c b/drivers/gpu/drm/i915/intel_wopcm.c new file mode 100644 index 000000000000..7b150d580d4a --- /dev/null +++ b/drivers/gpu/drm/i915/intel_wopcm.c @@ -0,0 +1,182 @@ +/* + * SPDX-License-Identifier: MIT + * + * Copyright © 2017-2018 Intel Corporation + */ + +#include "intel_wopcm.h" +#include "i915_drv.h" + +/** + * DOC: WOPCM Layout + * + * The layout of the WOPCM will be fixed after writing to GuC WOPCM size and + * offset registers whose are calculated are determined by size of HuC/GuC + * firmware size and set of hw requirements/restrictions as shown below: + * + * +=========> +====================+ <== WOPCM Top + * ^ | HW contexts RSVD | + * | +===> +====================+ <== GuC WOPCM Top + * | ^ | | + * | | | | + * | | | | + * | GuC | | + * | WOPCM | | + * | Size +--------------------+ + * WOPCM | | GuC FW RSVD | + * | | +--------------------+ + * | | | GuC Stack RSVD | + * | | +------------------- + + * | v | GuC WOPCM RSVD | + * | +===> +====================+ <== GuC WOPCM base + * | | WOPCM RSVD | + * | +------------------- + <== HuC Firmware Top + * v | HuC FW | + * +=========> +====================+ <== WOPCM Base + * + * GuC accessible WOPCM starts at GuC WOPCM base and ends at GuC WOPCM top. + * The top part of the WOPCM is reserved for hardware contexts (e.g. RC6 + * context). + */ + +/* Default WOPCM size 1MB. */ +#define GEN9_WOPCM_SIZE (1024 * 1024) +/* 16KB WOPCM (RSVD WOPCM) is reserved from HuC firmware top. */ +#define WOPCM_RESERVED_SIZE (16 * 1024) + +/* 16KB reserved at the beginning of GuC WOPCM. */ +#define GUC_WOPCM_RESERVED (16 * 1024) +/* 8KB from GUC_WOPCM_RESERVED is reserved for GuC stack. */ +#define GUC_WOPCM_STACK_RESERVED (8 * 1024) + +/* GuC WOPCM Offset value needs to be aligned to 16KB. */ +#define GUC_WOPCM_OFFSET_ALIGNMENT (1UL << GUC_WOPCM_OFFSET_SHIFT) + +/* 24KB at the end of WOPCM is reserved for RC6 CTX on BXT. */ +#define BXT_WOPCM_RC6_CTX_RESERVED (24 * 1024) + +/* 128KB from GUC_WOPCM_RESERVED is reserved for FW on Gen9. */ +#define GEN9_GUC_FW_RESERVED (128 * 1024) +#define GEN9_GUC_WOPCM_OFFSET (GUC_WOPCM_RESERVED + GEN9_GUC_FW_RESERVED) + +/** + * intel_wopcm_init_early() - Early initialization of the WOPCM. + * @wopcm: pointer to intel_wopcm. + * + * Setup the size of WOPCM which will be used by later on WOPCM partitioning. + */ +void intel_wopcm_init_early(struct intel_wopcm *wopcm) +{ + wopcm->size = GEN9_WOPCM_SIZE; + + DRM_DEBUG_DRIVER("WOPCM size: %uKiB\n", wopcm->size / 1024); +} + +static inline u32 context_reserved_size(struct drm_i915_private *i915) +{ + if (IS_GEN9_LP(i915)) + return BXT_WOPCM_RC6_CTX_RESERVED; + else + return 0; +} + +static inline int gen9_check_dword_gap(u32 guc_wopcm_base, u32 guc_wopcm_size) +{ + u32 offset; + + /* + * GuC WOPCM size shall be at least a dword larger than the offset from + * WOPCM base (GuC WOPCM offset from WOPCM base + GEN9_GUC_WOPCM_OFFSET) + * due to hardware limitation on Gen9. + */ + offset = guc_wopcm_base + GEN9_GUC_WOPCM_OFFSET; + if (offset > guc_wopcm_size || + (guc_wopcm_size - offset) < sizeof(u32)) { + DRM_ERROR("GuC WOPCM size %uKiB is too small. %uKiB needed.\n", + guc_wopcm_size / 1024, + (u32)(offset + sizeof(u32)) / 1024); + return -E2BIG; + } + + return 0; +} + +static inline int check_hw_restriction(struct drm_i915_private *i915, + u32 guc_wopcm_base, u32 guc_wopcm_size) +{ + int err = 0; + + if (IS_GEN9(i915)) + err = gen9_check_dword_gap(guc_wopcm_base, guc_wopcm_size); + + return err; +} + +/** + * intel_wopcm_init() - Initialize the WOPCM structure. + * @wopcm: pointer to intel_wopcm. + * + * This function will partition WOPCM space based on GuC and HuC firmware sizes + * and will allocate max remaining for use by GuC. This function will also + * enforce platform dependent hardware restrictions on GuC WOPCM offset and + * size. It will fail the WOPCM init if any of these checks were failed, so that + * the following GuC firmware uploading would be aborted. + * + * Return: 0 on success, non-zero error code on failure. + */ +int intel_wopcm_init(struct intel_wopcm *wopcm) +{ + struct drm_i915_private *i915 = wopcm_to_i915(wopcm); + u32 guc_fw_size = intel_uc_fw_get_upload_size(&i915->guc.fw); + u32 huc_fw_size = intel_uc_fw_get_upload_size(&i915->huc.fw); + u32 ctx_rsvd = context_reserved_size(i915); + u32 guc_wopcm_base; + u32 guc_wopcm_size; + u32 guc_wopcm_rsvd; + int err; + + GEM_BUG_ON(!wopcm->size); + + if (guc_fw_size >= wopcm->size) { + DRM_ERROR("GuC FW (%uKiB) is too big to fit in WOPCM.", + guc_fw_size / 1024); + return -E2BIG; + } + + if (huc_fw_size >= wopcm->size) { + DRM_ERROR("HuC FW (%uKiB) is too big to fit in WOPCM.", + huc_fw_size / 1024); + return -E2BIG; + } + + guc_wopcm_base = ALIGN(huc_fw_size + WOPCM_RESERVED_SIZE, + GUC_WOPCM_OFFSET_ALIGNMENT); + if ((guc_wopcm_base + ctx_rsvd) >= wopcm->size) { + DRM_ERROR("GuC WOPCM base (%uKiB) is too big.\n", + guc_wopcm_base / 1024); + return -E2BIG; + } + + guc_wopcm_size = wopcm->size - guc_wopcm_base - ctx_rsvd; + guc_wopcm_size &= GUC_WOPCM_SIZE_MASK; + + DRM_DEBUG_DRIVER("Calculated GuC WOPCM Region: [%uKiB, %uKiB)\n", + guc_wopcm_base / 1024, guc_wopcm_size / 1024); + + guc_wopcm_rsvd = GUC_WOPCM_RESERVED + GUC_WOPCM_STACK_RESERVED; + if ((guc_fw_size + guc_wopcm_rsvd) > guc_wopcm_size) { + DRM_ERROR("Need %uKiB WOPCM for GuC, %uKiB available.\n", + (guc_fw_size + guc_wopcm_rsvd) / 1024, + guc_wopcm_size / 1024); + return -E2BIG; + } + + err = check_hw_restriction(i915, guc_wopcm_base, guc_wopcm_size); + if (err) + return err; + + wopcm->guc.base = guc_wopcm_base; + wopcm->guc.size = guc_wopcm_size; + + return 0; +} diff --git a/drivers/gpu/drm/i915/intel_wopcm.h b/drivers/gpu/drm/i915/intel_wopcm.h new file mode 100644 index 000000000000..93c402ca7489 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_wopcm.h @@ -0,0 +1,30 @@ +/* + * SPDX-License-Identifier: MIT + * + * Copyright © 2017-2018 Intel Corporation + */ + +#ifndef _INTEL_WOPCM_H_ +#define _INTEL_WOPCM_H_ + +#include <linux/types.h> + +/** + * struct intel_wopcm - Overall WOPCM info and WOPCM regions. + * @size: Size of overall WOPCM. + * @guc: GuC WOPCM Region info. + * @guc.base: GuC WOPCM base which is offset from WOPCM base. + * @guc.size: Size of the GuC WOPCM region. + */ +struct intel_wopcm { + u32 size; + struct { + u32 base; + u32 size; + } guc; +}; + +void intel_wopcm_init_early(struct intel_wopcm *wopcm); +int intel_wopcm_init(struct intel_wopcm *wopcm); + +#endif |