drm/i915: properly init lockdep class
[sfrench/cifs-2.6.git] / drivers / gpu / drm / i915 / i915_gem_timeline.c
1 /*
2  * Copyright © 2016 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  */
24
25 #include "i915_drv.h"
26 #include "i915_syncmap.h"
27
28 static void __intel_timeline_init(struct intel_timeline *tl,
29                                   struct i915_gem_timeline *parent,
30                                   u64 context,
31                                   struct lock_class_key *lockclass,
32                                   const char *lockname)
33 {
34         tl->fence_context = context;
35         tl->common = parent;
36         spin_lock_init(&tl->lock);
37         lockdep_set_class_and_name(&tl->lock, lockclass, lockname);
38         init_request_active(&tl->last_request, NULL);
39         INIT_LIST_HEAD(&tl->requests);
40         i915_syncmap_init(&tl->sync);
41 }
42
43 static void __intel_timeline_fini(struct intel_timeline *tl)
44 {
45         GEM_BUG_ON(!list_empty(&tl->requests));
46
47         i915_syncmap_free(&tl->sync);
48 }
49
50 static int __i915_gem_timeline_init(struct drm_i915_private *i915,
51                                     struct i915_gem_timeline *timeline,
52                                     const char *name,
53                                     struct lock_class_key *lockclass,
54                                     const char *lockname)
55 {
56         unsigned int i;
57         u64 fences;
58
59         lockdep_assert_held(&i915->drm.struct_mutex);
60
61         /*
62          * Ideally we want a set of engines on a single leaf as we expect
63          * to mostly be tracking synchronisation between engines. It is not
64          * a huge issue if this is not the case, but we may want to mitigate
65          * any page crossing penalties if they become an issue.
66          */
67         BUILD_BUG_ON(KSYNCMAP < I915_NUM_ENGINES);
68
69         timeline->i915 = i915;
70         timeline->name = kstrdup(name ?: "[kernel]", GFP_KERNEL);
71         if (!timeline->name)
72                 return -ENOMEM;
73
74         list_add(&timeline->link, &i915->gt.timelines);
75
76         /* Called during early_init before we know how many engines there are */
77         fences = dma_fence_context_alloc(ARRAY_SIZE(timeline->engine));
78         for (i = 0; i < ARRAY_SIZE(timeline->engine); i++)
79                 __intel_timeline_init(&timeline->engine[i],
80                                       timeline, fences++,
81                                       lockclass, lockname);
82
83         return 0;
84 }
85
86 int i915_gem_timeline_init(struct drm_i915_private *i915,
87                            struct i915_gem_timeline *timeline,
88                            const char *name)
89 {
90         static struct lock_class_key class;
91
92         return __i915_gem_timeline_init(i915, timeline, name,
93                                         &class, "&timeline->lock");
94 }
95
96 int i915_gem_timeline_init__global(struct drm_i915_private *i915)
97 {
98         static struct lock_class_key class;
99
100         return __i915_gem_timeline_init(i915,
101                                         &i915->gt.global_timeline,
102                                         "[execution]",
103                                         &class, "&global_timeline->lock");
104 }
105
106 /**
107  * i915_gem_timelines_park - called when the driver idles
108  * @i915: the drm_i915_private device
109  *
110  * When the driver is completely idle, we know that all of our sync points
111  * have been signaled and our tracking is then entirely redundant. Any request
112  * to wait upon an older sync point will be completed instantly as we know
113  * the fence is signaled and therefore we will not even look them up in the
114  * sync point map.
115  */
116 void i915_gem_timelines_park(struct drm_i915_private *i915)
117 {
118         struct i915_gem_timeline *timeline;
119         int i;
120
121         lockdep_assert_held(&i915->drm.struct_mutex);
122
123         list_for_each_entry(timeline, &i915->gt.timelines, link) {
124                 for (i = 0; i < ARRAY_SIZE(timeline->engine); i++) {
125                         struct intel_timeline *tl = &timeline->engine[i];
126
127                         /*
128                          * All known fences are completed so we can scrap
129                          * the current sync point tracking and start afresh,
130                          * any attempt to wait upon a previous sync point
131                          * will be skipped as the fence was signaled.
132                          */
133                         i915_syncmap_free(&tl->sync);
134                 }
135         }
136 }
137
138 void i915_gem_timeline_fini(struct i915_gem_timeline *timeline)
139 {
140         int i;
141
142         lockdep_assert_held(&timeline->i915->drm.struct_mutex);
143
144         for (i = 0; i < ARRAY_SIZE(timeline->engine); i++)
145                 __intel_timeline_fini(&timeline->engine[i]);
146
147         list_del(&timeline->link);
148         kfree(timeline->name);
149 }
150
151 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
152 #include "selftests/mock_timeline.c"
153 #include "selftests/i915_gem_timeline.c"
154 #endif