In an upcoming patch we will introduce a display uncore with no forcewake domains, so let's avoid wasting memory and be ready to allocate only what we need. Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@xxxxxxxxx> --- drivers/gpu/drm/i915/intel_uncore.c | 141 +++++++++++++++++----------- drivers/gpu/drm/i915/intel_uncore.h | 13 +-- 2 files changed, 92 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index ef7eed9237a0..30650e6e2f54 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -344,7 +344,7 @@ intel_uncore_fw_release_timer(struct hrtimer *timer) { struct intel_uncore_forcewake_domain *domain = container_of(timer, struct intel_uncore_forcewake_domain, timer); - struct intel_uncore *uncore = forcewake_domain_to_uncore(domain); + struct intel_uncore *uncore = domain->uncore; unsigned long irqflags; assert_rpm_device_not_suspended(uncore->rpm); @@ -1283,23 +1283,24 @@ do { \ (uncore)->funcs.read_fw_domains = x##_reg_read_fw_domains; \ } while (0) -static void fw_domain_init(struct intel_uncore *uncore, +static int fw_domain_init(struct intel_uncore *uncore, enum forcewake_domain_id domain_id, i915_reg_t reg_set, i915_reg_t reg_ack) { struct intel_uncore_forcewake_domain *d; - if (WARN_ON(domain_id >= FW_DOMAIN_ID_COUNT)) - return; - - d = &uncore->fw_domain[domain_id]; + GEM_BUG_ON(domain_id >= FW_DOMAIN_ID_COUNT); + GEM_BUG_ON(uncore->fw_domain[domain_id]); - WARN_ON(d->wake_count); + d = kzalloc(sizeof(*d), GFP_KERNEL); + if (!d) + return -ENOMEM; WARN_ON(!i915_mmio_reg_valid(reg_set)); WARN_ON(!i915_mmio_reg_valid(reg_ack)); + d->uncore = uncore; d->wake_count = 0; d->reg_set = uncore->regs + i915_mmio_reg_offset(reg_set); d->reg_ack = uncore->regs + i915_mmio_reg_offset(reg_ack); @@ -1325,6 +1326,10 @@ static void fw_domain_init(struct intel_uncore *uncore, uncore->fw_domains |= BIT(domain_id); fw_domain_reset(d); + + uncore->fw_domain[domain_id] = d; + + return 0; } static void fw_domain_fini(struct intel_uncore *uncore, @@ -1332,78 +1337,93 @@ static void fw_domain_fini(struct intel_uncore *uncore, { struct intel_uncore_forcewake_domain *d; - if (WARN_ON(domain_id >= FW_DOMAIN_ID_COUNT)) - return; + GEM_BUG_ON(domain_id >= FW_DOMAIN_ID_COUNT); - d = &uncore->fw_domain[domain_id]; + d = fetch_and_zero(&uncore->fw_domain[domain_id]); + uncore->fw_domains &= ~BIT(domain_id); - WARN_ON(d->wake_count); - WARN_ON(hrtimer_cancel(&d->timer)); - memset(d, 0, sizeof(*d)); + if (d) { + WARN_ON(d->wake_count); + WARN_ON(hrtimer_cancel(&d->timer)); + kfree(d); + } +} - uncore->fw_domains &= ~BIT(domain_id); +static void intel_uncore_fw_domains_fini(struct intel_uncore *uncore) +{ + struct intel_uncore_forcewake_domain *d; + int tmp; + + for_each_fw_domain(d, uncore, tmp) + fw_domain_fini(uncore, d->id); } -static void intel_uncore_fw_domains_init(struct intel_uncore *uncore) +static int intel_uncore_fw_domains_init(struct intel_uncore *uncore) { struct drm_i915_private *i915 = uncore_to_i915(uncore); + int ret; + +#define __fw_domain_init(id, set, ack) \ + ret = fw_domain_init(uncore, id, set, ack); \ + if (ret) \ + goto out_clean; if (!intel_uncore_has_forcewake(uncore)) - return; + return 0; if (INTEL_GEN(i915) >= 11) { int i; - uncore->funcs.force_wake_get = - fw_domains_get_with_fallback; + uncore->funcs.force_wake_get = fw_domains_get_with_fallback; uncore->funcs.force_wake_put = fw_domains_put; - fw_domain_init(uncore, FW_DOMAIN_ID_RENDER, - FORCEWAKE_RENDER_GEN9, - FORCEWAKE_ACK_RENDER_GEN9); - fw_domain_init(uncore, FW_DOMAIN_ID_BLITTER, - FORCEWAKE_BLITTER_GEN9, - FORCEWAKE_ACK_BLITTER_GEN9); + __fw_domain_init(FW_DOMAIN_ID_RENDER, + FORCEWAKE_RENDER_GEN9, + FORCEWAKE_ACK_RENDER_GEN9); + __fw_domain_init(FW_DOMAIN_ID_BLITTER, + FORCEWAKE_BLITTER_GEN9, + FORCEWAKE_ACK_BLITTER_GEN9); + for (i = 0; i < I915_MAX_VCS; i++) { if (!HAS_ENGINE(i915, _VCS(i))) continue; - fw_domain_init(uncore, FW_DOMAIN_ID_MEDIA_VDBOX0 + i, - FORCEWAKE_MEDIA_VDBOX_GEN11(i), - FORCEWAKE_ACK_MEDIA_VDBOX_GEN11(i)); + __fw_domain_init(FW_DOMAIN_ID_MEDIA_VDBOX0 + i, + FORCEWAKE_MEDIA_VDBOX_GEN11(i), + FORCEWAKE_ACK_MEDIA_VDBOX_GEN11(i)); } for (i = 0; i < I915_MAX_VECS; i++) { if (!HAS_ENGINE(i915, _VECS(i))) continue; - fw_domain_init(uncore, FW_DOMAIN_ID_MEDIA_VEBOX0 + i, - FORCEWAKE_MEDIA_VEBOX_GEN11(i), - FORCEWAKE_ACK_MEDIA_VEBOX_GEN11(i)); + __fw_domain_init(FW_DOMAIN_ID_MEDIA_VEBOX0 + i, + FORCEWAKE_MEDIA_VEBOX_GEN11(i), + FORCEWAKE_ACK_MEDIA_VEBOX_GEN11(i)); } } else if (IS_GEN_RANGE(i915, 9, 10)) { - uncore->funcs.force_wake_get = - fw_domains_get_with_fallback; + uncore->funcs.force_wake_get = fw_domains_get_with_fallback; uncore->funcs.force_wake_put = fw_domains_put; - fw_domain_init(uncore, FW_DOMAIN_ID_RENDER, - FORCEWAKE_RENDER_GEN9, - FORCEWAKE_ACK_RENDER_GEN9); - fw_domain_init(uncore, FW_DOMAIN_ID_BLITTER, - FORCEWAKE_BLITTER_GEN9, - FORCEWAKE_ACK_BLITTER_GEN9); - fw_domain_init(uncore, FW_DOMAIN_ID_MEDIA, - FORCEWAKE_MEDIA_GEN9, FORCEWAKE_ACK_MEDIA_GEN9); + __fw_domain_init(FW_DOMAIN_ID_RENDER, + FORCEWAKE_RENDER_GEN9, + FORCEWAKE_ACK_RENDER_GEN9); + __fw_domain_init(FW_DOMAIN_ID_BLITTER, + FORCEWAKE_BLITTER_GEN9, + FORCEWAKE_ACK_BLITTER_GEN9); + __fw_domain_init(FW_DOMAIN_ID_MEDIA, + FORCEWAKE_MEDIA_GEN9, + FORCEWAKE_ACK_MEDIA_GEN9); } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { uncore->funcs.force_wake_get = fw_domains_get; uncore->funcs.force_wake_put = fw_domains_put; - fw_domain_init(uncore, FW_DOMAIN_ID_RENDER, - FORCEWAKE_VLV, FORCEWAKE_ACK_VLV); - fw_domain_init(uncore, FW_DOMAIN_ID_MEDIA, - FORCEWAKE_MEDIA_VLV, FORCEWAKE_ACK_MEDIA_VLV); + __fw_domain_init(FW_DOMAIN_ID_RENDER, + FORCEWAKE_VLV, FORCEWAKE_ACK_VLV); + __fw_domain_init(FW_DOMAIN_ID_MEDIA, + FORCEWAKE_MEDIA_VLV, FORCEWAKE_ACK_MEDIA_VLV); } else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) { uncore->funcs.force_wake_get = fw_domains_get_with_thread_status; uncore->funcs.force_wake_put = fw_domains_put; - fw_domain_init(uncore, FW_DOMAIN_ID_RENDER, - FORCEWAKE_MT, FORCEWAKE_ACK_HSW); + __fw_domain_init(FW_DOMAIN_ID_RENDER, + FORCEWAKE_MT, FORCEWAKE_ACK_HSW); } else if (IS_IVYBRIDGE(i915)) { u32 ecobus; @@ -1430,8 +1450,8 @@ static void intel_uncore_fw_domains_init(struct intel_uncore *uncore) __raw_uncore_write32(uncore, FORCEWAKE, 0); __raw_posting_read(uncore, ECOBUS); - fw_domain_init(uncore, FW_DOMAIN_ID_RENDER, - FORCEWAKE_MT, FORCEWAKE_MT_ACK); + __fw_domain_init(FW_DOMAIN_ID_RENDER, + FORCEWAKE_MT, FORCEWAKE_MT_ACK); spin_lock_irq(&uncore->lock); fw_domains_get_with_thread_status(uncore, FORCEWAKE_RENDER); @@ -1442,19 +1462,28 @@ static void intel_uncore_fw_domains_init(struct intel_uncore *uncore) if (!(ecobus & FORCEWAKE_MT_ENABLE)) { DRM_INFO("No MT forcewake available on Ivybridge, this can result in issues\n"); DRM_INFO("when using vblank-synced partial screen updates.\n"); - fw_domain_init(uncore, FW_DOMAIN_ID_RENDER, - FORCEWAKE, FORCEWAKE_ACK); + __fw_domain_init(FW_DOMAIN_ID_RENDER, + FORCEWAKE, FORCEWAKE_ACK); } } else if (IS_GEN(i915, 6)) { uncore->funcs.force_wake_get = fw_domains_get_with_thread_status; uncore->funcs.force_wake_put = fw_domains_put; - fw_domain_init(uncore, FW_DOMAIN_ID_RENDER, - FORCEWAKE, FORCEWAKE_ACK); + __fw_domain_init(FW_DOMAIN_ID_RENDER, + FORCEWAKE, FORCEWAKE_ACK); } +#undef __fw_domain_init + /* All future platforms are expected to require complex power gating */ WARN_ON(uncore->fw_domains == 0); + + return 0; + +out_clean: + intel_uncore_fw_domains_fini(uncore); + return ret; + } #define ASSIGN_FW_DOMAINS_TABLE(uncore, d) \ @@ -1554,7 +1583,12 @@ int intel_uncore_init_mmio(struct intel_uncore *uncore) if (INTEL_GEN(i915) > 5 && !intel_vgpu_active(i915)) uncore->flags |= UNCORE_HAS_FORCEWAKE; - intel_uncore_fw_domains_init(uncore); + ret = intel_uncore_fw_domains_init(uncore); + if (ret) { + uncore_mmio_cleanup(uncore); + return ret; + } + __intel_uncore_early_sanitize(uncore, 0); uncore->unclaimed_mmio_check = 1; @@ -1662,6 +1696,7 @@ void intel_uncore_fini_mmio(struct intel_uncore *uncore) iosf_mbi_unregister_pmic_bus_access_notifier_unlocked( &uncore->pmic_bus_access_nb); intel_uncore_forcewake_reset(uncore); + intel_uncore_fw_domains_fini(uncore); iosf_mbi_punit_release(); uncore_mmio_cleanup(uncore); } diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h index bf06b6b16892..2bb80962e7c5 100644 --- a/drivers/gpu/drm/i915/intel_uncore.h +++ b/drivers/gpu/drm/i915/intel_uncore.h @@ -125,6 +125,7 @@ struct intel_uncore { enum forcewake_domains fw_domains_saved; /* user domains saved for S3 */ struct intel_uncore_forcewake_domain { + struct intel_uncore *uncore; enum forcewake_domain_id id; enum forcewake_domains mask; unsigned int wake_count; @@ -132,7 +133,7 @@ struct intel_uncore { struct hrtimer timer; u32 __iomem *reg_set; u32 __iomem *reg_ack; - } fw_domain[FW_DOMAIN_ID_COUNT]; + } *fw_domain[FW_DOMAIN_ID_COUNT]; struct { unsigned int count; @@ -146,18 +147,12 @@ struct intel_uncore { /* Iterate over initialised fw domains */ #define for_each_fw_domain_masked(domain__, mask__, uncore__, tmp__) \ - for (tmp__ = (mask__); \ - tmp__ ? (domain__ = &(uncore__)->fw_domain[__mask_next_bit(tmp__)]), 1 : 0;) + for (tmp__ = (mask__); tmp__ ;) \ + for_each_if(domain__ = (uncore__)->fw_domain[__mask_next_bit(tmp__)]) #define for_each_fw_domain(domain__, uncore__, tmp__) \ for_each_fw_domain_masked(domain__, (uncore__)->fw_domains, uncore__, tmp__) -static inline struct intel_uncore * -forcewake_domain_to_uncore(const struct intel_uncore_forcewake_domain *d) -{ - return container_of(d, struct intel_uncore, fw_domain[d->id]); -} - static inline bool intel_uncore_has_forcewake(const struct intel_uncore *uncore) { -- 2.20.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx