drm/i915/pmu: Initialise the spinlock before registering
authorChris Wilson <chris@chris-wilson.co.uk>
Fri, 25 Oct 2019 16:54:42 +0000 (17:54 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Fri, 25 Oct 2019 21:56:14 +0000 (22:56 +0100)
As the GT may be running in parallel with the module initialisation
code, we may enter i915_pmu_gt_parked() as we are executing
i915_pmu_register(). We have to init the spinlock before we mark
pmu.event_init so that it is available for use by i915_pmu_gt_parked()
(which may run as soon as event_init is set).

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112127
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191025165442.23356-1-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/i915_pmu.c

index 8591291..b5b67c0 100644 (file)
@@ -1101,20 +1101,6 @@ void i915_pmu_register(struct drm_i915_private *i915)
                return;
        }
 
-       i915_pmu_events_attr_group.attrs = create_event_attributes(pmu);
-       if (!i915_pmu_events_attr_group.attrs)
-               goto err;
-
-       pmu->base.attr_groups   = i915_pmu_attr_groups;
-       pmu->base.task_ctx_nr   = perf_invalid_context;
-       pmu->base.event_init    = i915_pmu_event_init;
-       pmu->base.add           = i915_pmu_event_add;
-       pmu->base.del           = i915_pmu_event_del;
-       pmu->base.start         = i915_pmu_event_start;
-       pmu->base.stop          = i915_pmu_event_stop;
-       pmu->base.read          = i915_pmu_event_read;
-       pmu->base.event_idx     = i915_pmu_event_event_idx;
-
        spin_lock_init(&pmu->lock);
        hrtimer_init(&pmu->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        pmu->timer.function = i915_sample;
@@ -1128,9 +1114,23 @@ void i915_pmu_register(struct drm_i915_private *i915)
        if (!pmu->name)
                goto err;
 
+       i915_pmu_events_attr_group.attrs = create_event_attributes(pmu);
+       if (!i915_pmu_events_attr_group.attrs)
+               goto err_name;
+
+       pmu->base.attr_groups   = i915_pmu_attr_groups;
+       pmu->base.task_ctx_nr   = perf_invalid_context;
+       pmu->base.event_init    = i915_pmu_event_init;
+       pmu->base.add           = i915_pmu_event_add;
+       pmu->base.del           = i915_pmu_event_del;
+       pmu->base.start         = i915_pmu_event_start;
+       pmu->base.stop          = i915_pmu_event_stop;
+       pmu->base.read          = i915_pmu_event_read;
+       pmu->base.event_idx     = i915_pmu_event_event_idx;
+
        ret = perf_pmu_register(&pmu->base, pmu->name, -1);
        if (ret)
-               goto err_name;
+               goto err_attr;
 
        ret = i915_pmu_register_cpuhp_state(pmu);
        if (ret)
@@ -1140,13 +1140,14 @@ void i915_pmu_register(struct drm_i915_private *i915)
 
 err_unreg:
        perf_pmu_unregister(&pmu->base);
+err_attr:
+       pmu->base.event_init = NULL;
+       free_event_attributes(pmu);
 err_name:
        if (!is_igp(i915))
                kfree(pmu->name);
 err:
-       pmu->base.event_init = NULL;
-       free_event_attributes(pmu);
-       DRM_NOTE("Failed to register PMU! (err=%d)\n", ret);
+       dev_notice(i915->drm.dev, "Failed to register PMU!\n");
 }
 
 void i915_pmu_unregister(struct drm_i915_private *i915)