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 <[email protected]>
---
 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
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to