Commit | Line | Data |
---|---|---|
2017263e BG |
1 | /* |
2 | * Copyright © 2008 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 | * Authors: | |
24 | * Eric Anholt <eric@anholt.net> | |
25 | * Keith Packard <keithp@keithp.com> | |
26 | * | |
27 | */ | |
28 | ||
d92a8cfc | 29 | #include <linux/sched/mm.h> |
98afa316 | 30 | #include <linux/sort.h> |
01fabda8 | 31 | #include <linux/string_helpers.h> |
98afa316 | 32 | |
7fa043ea | 33 | #include <linux/debugfs.h> |
fcd70cd3 | 34 | #include <drm/drm_debugfs.h> |
379bc100 | 35 | |
10be98a7 | 36 | #include "gem/i915_gem_context.h" |
d0c56031 | 37 | #include "gt/intel_gt.h" |
16e87459 | 38 | #include "gt/intel_gt_buffer_pool.h" |
9c878557 | 39 | #include "gt/intel_gt_clock_utils.h" |
82a149a6 | 40 | #include "gt/intel_gt_debugfs.h" |
c7302f20 | 41 | #include "gt/intel_gt_pm.h" |
d0c56031 | 42 | #include "gt/intel_gt_pm_debugfs.h" |
0d6419e9 | 43 | #include "gt/intel_gt_regs.h" |
66101975 | 44 | #include "gt/intel_gt_requests.h" |
c1132367 | 45 | #include "gt/intel_rc6.h" |
d0c56031 | 46 | #include "gt/intel_reset.h" |
3e7abf81 | 47 | #include "gt/intel_rps.h" |
a00eda7d | 48 | #include "gt/intel_sseu_debugfs.h" |
112ed2d3 | 49 | |
2126d3e9 | 50 | #include "i915_debugfs.h" |
c43c5a88 | 51 | #include "i915_debugfs_params.h" |
a7f46d5b | 52 | #include "i915_driver.h" |
4fca5198 | 53 | #include "i915_gpu_error.h" |
440e2b3d | 54 | #include "i915_irq.h" |
476f62b8 | 55 | #include "i915_reg.h" |
da7ac715 | 56 | #include "i915_scheduler.h" |
e30e6c7b | 57 | #include "intel_mchbar_regs.h" |
9f58892e | 58 | |
36cdd013 DW |
59 | static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node) |
60 | { | |
61 | return to_i915(node->minor->dev); | |
62 | } | |
63 | ||
70d39fe4 CW |
64 | static int i915_capabilities(struct seq_file *m, void *data) |
65 | { | |
72404978 | 66 | struct drm_i915_private *i915 = node_to_i915(m->private); |
a8c9b849 | 67 | struct drm_printer p = drm_seq_file_printer(m); |
70d39fe4 | 68 | |
c7d3c844 | 69 | intel_device_info_print(INTEL_INFO(i915), RUNTIME_INFO(i915), &p); |
cca08469 | 70 | i915_print_iommu_status(i915, &p); |
2cbc876d | 71 | intel_gt_info_print(&to_gt(i915)->info, &p); |
72404978 | 72 | intel_driver_caps_print(&i915->caps, &p); |
70d39fe4 | 73 | |
8a25c4be | 74 | i915_params_dump(&i915->params, &p); |
418e3cd8 | 75 | |
70d39fe4 CW |
76 | return 0; |
77 | } | |
2017263e | 78 | |
a7363de7 | 79 | static char get_tiling_flag(struct drm_i915_gem_object *obj) |
a6172a80 | 80 | { |
3e510a8e | 81 | switch (i915_gem_object_get_tiling(obj)) { |
0206e353 | 82 | default: |
be12a86b TU |
83 | case I915_TILING_NONE: return ' '; |
84 | case I915_TILING_X: return 'X'; | |
85 | case I915_TILING_Y: return 'Y'; | |
0206e353 | 86 | } |
a6172a80 CW |
87 | } |
88 | ||
a7363de7 | 89 | static char get_global_flag(struct drm_i915_gem_object *obj) |
be12a86b | 90 | { |
b7d151ba | 91 | return READ_ONCE(obj->userfault_count) ? 'g' : ' '; |
be12a86b TU |
92 | } |
93 | ||
a7363de7 | 94 | static char get_pin_mapped_flag(struct drm_i915_gem_object *obj) |
1d693bcc | 95 | { |
a4f5ea64 | 96 | return obj->mm.mapping ? 'M' : ' '; |
1d693bcc BW |
97 | } |
98 | ||
7393b7ee MA |
99 | static const char * |
100 | stringify_page_sizes(unsigned int page_sizes, char *buf, size_t len) | |
101 | { | |
102 | size_t x = 0; | |
103 | ||
104 | switch (page_sizes) { | |
105 | case 0: | |
106 | return ""; | |
107 | case I915_GTT_PAGE_SIZE_4K: | |
108 | return "4K"; | |
109 | case I915_GTT_PAGE_SIZE_64K: | |
110 | return "64K"; | |
111 | case I915_GTT_PAGE_SIZE_2M: | |
112 | return "2M"; | |
113 | default: | |
114 | if (!buf) | |
115 | return "M"; | |
116 | ||
117 | if (page_sizes & I915_GTT_PAGE_SIZE_2M) | |
118 | x += snprintf(buf + x, len - x, "2M, "); | |
119 | if (page_sizes & I915_GTT_PAGE_SIZE_64K) | |
120 | x += snprintf(buf + x, len - x, "64K, "); | |
121 | if (page_sizes & I915_GTT_PAGE_SIZE_4K) | |
122 | x += snprintf(buf + x, len - x, "4K, "); | |
123 | buf[x-2] = '\0'; | |
124 | ||
125 | return buf; | |
126 | } | |
127 | } | |
128 | ||
0f926e5c ID |
129 | static const char *stringify_vma_type(const struct i915_vma *vma) |
130 | { | |
131 | if (i915_vma_is_ggtt(vma)) | |
132 | return "ggtt"; | |
133 | ||
134 | if (i915_vma_is_dpt(vma)) | |
135 | return "dpt"; | |
136 | ||
137 | return "ppgtt"; | |
138 | } | |
139 | ||
9275277d | 140 | static const char *i915_cache_level_str(struct drm_i915_gem_object *obj) |
74fc5954 | 141 | { |
9275277d FY |
142 | struct drm_i915_private *i915 = obj_to_i915(obj); |
143 | ||
84bf82f4 | 144 | if (IS_GFX_GT_IP_RANGE(to_gt(i915), IP_VER(12, 70), IP_VER(12, 74))) { |
9275277d FY |
145 | switch (obj->pat_index) { |
146 | case 0: return " WB"; | |
147 | case 1: return " WT"; | |
148 | case 2: return " UC"; | |
149 | case 3: return " WB (1-Way Coh)"; | |
150 | case 4: return " WB (2-Way Coh)"; | |
151 | default: return " not defined"; | |
152 | } | |
9275277d FY |
153 | } else if (GRAPHICS_VER(i915) >= 12) { |
154 | switch (obj->pat_index) { | |
155 | case 0: return " WB"; | |
156 | case 1: return " WC"; | |
157 | case 2: return " WT"; | |
158 | case 3: return " UC"; | |
159 | default: return " not defined"; | |
160 | } | |
161 | } else { | |
162 | switch (obj->pat_index) { | |
163 | case 0: return " UC"; | |
164 | case 1: return HAS_LLC(i915) ? | |
165 | " LLC" : " snooped"; | |
166 | case 2: return " L3+LLC"; | |
167 | case 3: return " WT"; | |
168 | default: return " not defined"; | |
169 | } | |
74fc5954 JN |
170 | } |
171 | } | |
172 | ||
926b005c JN |
173 | void |
174 | i915_debugfs_describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) | |
37811fcc | 175 | { |
1d693bcc | 176 | struct i915_vma *vma; |
d7f46fc4 BW |
177 | int pin_count = 0; |
178 | ||
5a90606d | 179 | seq_printf(m, "%pK: %c%c%c %8zdKiB %02x %02x %s%s%s", |
37811fcc | 180 | &obj->base, |
37811fcc | 181 | get_tiling_flag(obj), |
1d693bcc | 182 | get_global_flag(obj), |
be12a86b | 183 | get_pin_mapped_flag(obj), |
a05a5862 | 184 | obj->base.size / 1024, |
c0a51fd0 CK |
185 | obj->read_domains, |
186 | obj->write_domain, | |
9275277d | 187 | i915_cache_level_str(obj), |
a4f5ea64 CW |
188 | obj->mm.dirty ? " dirty" : "", |
189 | obj->mm.madv == I915_MADV_DONTNEED ? " purgeable" : ""); | |
37811fcc CW |
190 | if (obj->base.name) |
191 | seq_printf(m, " (name: %d)", obj->base.name); | |
0cf289bd CW |
192 | |
193 | spin_lock(&obj->vma.lock); | |
528cbd17 | 194 | list_for_each_entry(vma, &obj->vma.list, obj_link) { |
15717de2 CW |
195 | if (!drm_mm_node_allocated(&vma->node)) |
196 | continue; | |
197 | ||
0cf289bd CW |
198 | spin_unlock(&obj->vma.lock); |
199 | ||
200 | if (i915_vma_is_pinned(vma)) | |
201 | pin_count++; | |
202 | ||
0f926e5c ID |
203 | seq_printf(m, " (%s offset: %08llx, size: %08llx, pages: %s", |
204 | stringify_vma_type(vma), | |
8e4ee5e8 | 205 | i915_vma_offset(vma), i915_vma_size(vma), |
39a2bd34 TH |
206 | stringify_page_sizes(vma->resource->page_sizes_gtt, |
207 | NULL, 0)); | |
0f926e5c | 208 | if (i915_vma_is_ggtt(vma) || i915_vma_is_dpt(vma)) { |
3bb6a442 NV |
209 | switch (vma->gtt_view.type) { |
210 | case I915_GTT_VIEW_NORMAL: | |
21976853 CW |
211 | seq_puts(m, ", normal"); |
212 | break; | |
213 | ||
3bb6a442 | 214 | case I915_GTT_VIEW_PARTIAL: |
21976853 | 215 | seq_printf(m, ", partial [%08llx+%x]", |
3bb6a442 NV |
216 | vma->gtt_view.partial.offset << PAGE_SHIFT, |
217 | vma->gtt_view.partial.size << PAGE_SHIFT); | |
21976853 CW |
218 | break; |
219 | ||
3bb6a442 | 220 | case I915_GTT_VIEW_ROTATED: |
a4606d45 | 221 | seq_printf(m, ", rotated [(%ux%u, src_stride=%u, dst_stride=%u, offset=%u), (%ux%u, src_stride=%u, dst_stride=%u, offset=%u)]", |
3bb6a442 NV |
222 | vma->gtt_view.rotated.plane[0].width, |
223 | vma->gtt_view.rotated.plane[0].height, | |
224 | vma->gtt_view.rotated.plane[0].src_stride, | |
225 | vma->gtt_view.rotated.plane[0].dst_stride, | |
226 | vma->gtt_view.rotated.plane[0].offset, | |
227 | vma->gtt_view.rotated.plane[1].width, | |
228 | vma->gtt_view.rotated.plane[1].height, | |
229 | vma->gtt_view.rotated.plane[1].src_stride, | |
230 | vma->gtt_view.rotated.plane[1].dst_stride, | |
231 | vma->gtt_view.rotated.plane[1].offset); | |
21976853 CW |
232 | break; |
233 | ||
3bb6a442 | 234 | case I915_GTT_VIEW_REMAPPED: |
a4606d45 | 235 | seq_printf(m, ", remapped [(%ux%u, src_stride=%u, dst_stride=%u, offset=%u), (%ux%u, src_stride=%u, dst_stride=%u, offset=%u)]", |
3bb6a442 NV |
236 | vma->gtt_view.remapped.plane[0].width, |
237 | vma->gtt_view.remapped.plane[0].height, | |
238 | vma->gtt_view.remapped.plane[0].src_stride, | |
239 | vma->gtt_view.remapped.plane[0].dst_stride, | |
240 | vma->gtt_view.remapped.plane[0].offset, | |
241 | vma->gtt_view.remapped.plane[1].width, | |
242 | vma->gtt_view.remapped.plane[1].height, | |
243 | vma->gtt_view.remapped.plane[1].src_stride, | |
244 | vma->gtt_view.remapped.plane[1].dst_stride, | |
245 | vma->gtt_view.remapped.plane[1].offset); | |
1a74fc0b VS |
246 | break; |
247 | ||
21976853 | 248 | default: |
3bb6a442 | 249 | MISSING_CASE(vma->gtt_view.type); |
21976853 CW |
250 | break; |
251 | } | |
252 | } | |
49ef5294 | 253 | if (vma->fence) |
3d6792cf | 254 | seq_printf(m, " , fence: %d", vma->fence->id); |
596c5923 | 255 | seq_puts(m, ")"); |
0cf289bd CW |
256 | |
257 | spin_lock(&obj->vma.lock); | |
1d693bcc | 258 | } |
0cf289bd CW |
259 | spin_unlock(&obj->vma.lock); |
260 | ||
261 | seq_printf(m, " (pinned x %d)", pin_count); | |
41a9c75d | 262 | if (i915_gem_object_is_stolen(obj)) |
440fd528 | 263 | seq_printf(m, " (stolen: %08llx)", obj->stolen->start); |
5a90606d CW |
264 | if (i915_gem_object_is_framebuffer(obj)) |
265 | seq_printf(m, " (fb)"); | |
37811fcc CW |
266 | } |
267 | ||
36cdd013 | 268 | static int i915_gem_object_info(struct seq_file *m, void *data) |
73aa808f | 269 | { |
ecab9be1 | 270 | struct drm_i915_private *i915 = node_to_i915(m->private); |
8c3363c6 | 271 | struct drm_printer p = drm_seq_file_printer(m); |
38f1cb68 LF |
272 | struct intel_memory_region *mr; |
273 | enum intel_region_id id; | |
73aa808f | 274 | |
1aff1903 | 275 | seq_printf(m, "%u shrinkable [%u free] objects, %llu bytes\n", |
ecab9be1 | 276 | i915->mm.shrink_count, |
1aff1903 | 277 | atomic_read(&i915->mm.free_count), |
ecab9be1 | 278 | i915->mm.shrink_memory); |
38f1cb68 | 279 | for_each_memory_region(mr, i915, id) |
8c3363c6 | 280 | intel_memory_region_debug(mr, &p); |
73aa808f CW |
281 | |
282 | return 0; | |
283 | } | |
284 | ||
adb4bd12 | 285 | static int i915_frequency_info(struct seq_file *m, void *unused) |
f97108d1 | 286 | { |
d0c56031 | 287 | struct drm_i915_private *i915 = node_to_i915(m->private); |
2cbc876d | 288 | struct intel_gt *gt = to_gt(i915); |
d0c56031 | 289 | struct drm_printer p = drm_seq_file_printer(m); |
f97108d1 | 290 | |
d0c56031 | 291 | intel_gt_pm_frequency_dump(gt, &p); |
1170f28c | 292 | |
bd0cef2a | 293 | return 0; |
f97108d1 JB |
294 | } |
295 | ||
ea16a3cd DV |
296 | static const char *swizzle_string(unsigned swizzle) |
297 | { | |
aee56cff | 298 | switch (swizzle) { |
ea16a3cd DV |
299 | case I915_BIT_6_SWIZZLE_NONE: |
300 | return "none"; | |
301 | case I915_BIT_6_SWIZZLE_9: | |
302 | return "bit9"; | |
303 | case I915_BIT_6_SWIZZLE_9_10: | |
304 | return "bit9/bit10"; | |
305 | case I915_BIT_6_SWIZZLE_9_11: | |
306 | return "bit9/bit11"; | |
307 | case I915_BIT_6_SWIZZLE_9_10_11: | |
308 | return "bit9/bit10/bit11"; | |
309 | case I915_BIT_6_SWIZZLE_9_17: | |
310 | return "bit9/bit17"; | |
311 | case I915_BIT_6_SWIZZLE_9_10_17: | |
312 | return "bit9/bit10/bit17"; | |
313 | case I915_BIT_6_SWIZZLE_UNKNOWN: | |
8a168ca7 | 314 | return "unknown"; |
ea16a3cd DV |
315 | } |
316 | ||
317 | return "bug"; | |
318 | } | |
319 | ||
320 | static int i915_swizzle_info(struct seq_file *m, void *data) | |
321 | { | |
36cdd013 | 322 | struct drm_i915_private *dev_priv = node_to_i915(m->private); |
4f5fd91f | 323 | struct intel_uncore *uncore = &dev_priv->uncore; |
a037121c | 324 | intel_wakeref_t wakeref; |
22bcfc6a | 325 | |
ea16a3cd | 326 | seq_printf(m, "bit6 swizzle for X-tiling = %s\n", |
204129a2 | 327 | swizzle_string(to_gt(dev_priv)->ggtt->bit_6_swizzle_x)); |
ea16a3cd | 328 | seq_printf(m, "bit6 swizzle for Y-tiling = %s\n", |
204129a2 | 329 | swizzle_string(to_gt(dev_priv)->ggtt->bit_6_swizzle_y)); |
ea16a3cd | 330 | |
95086cb9 | 331 | if (dev_priv->gem_quirks & GEM_QUIRK_PIN_SWIZZLED_PAGES) |
1fe541cc LDM |
332 | seq_puts(m, "L-shaped memory detected\n"); |
333 | ||
334 | /* On BDW+, swizzling is not used. See detect_bit_6_swizzle() */ | |
651e7d48 | 335 | if (GRAPHICS_VER(dev_priv) >= 8 || IS_VALLEYVIEW(dev_priv)) |
1fe541cc LDM |
336 | return 0; |
337 | ||
338 | wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); | |
339 | ||
651e7d48 | 340 | if (IS_GRAPHICS_VER(dev_priv, 3, 4)) { |
ea16a3cd | 341 | seq_printf(m, "DDC = 0x%08x\n", |
4f5fd91f | 342 | intel_uncore_read(uncore, DCC)); |
656bfa3a | 343 | seq_printf(m, "DDC2 = 0x%08x\n", |
4f5fd91f | 344 | intel_uncore_read(uncore, DCC2)); |
ea16a3cd | 345 | seq_printf(m, "C0DRB3 = 0x%04x\n", |
924ad0e8 | 346 | intel_uncore_read16(uncore, C0DRB3_BW)); |
ea16a3cd | 347 | seq_printf(m, "C1DRB3 = 0x%04x\n", |
924ad0e8 | 348 | intel_uncore_read16(uncore, C1DRB3_BW)); |
d70cc074 | 349 | } else if (GRAPHICS_VER(dev_priv) >= 6) { |
3fa7d235 | 350 | seq_printf(m, "MAD_DIMM_C0 = 0x%08x\n", |
4f5fd91f | 351 | intel_uncore_read(uncore, MAD_DIMM_C0)); |
3fa7d235 | 352 | seq_printf(m, "MAD_DIMM_C1 = 0x%08x\n", |
4f5fd91f | 353 | intel_uncore_read(uncore, MAD_DIMM_C1)); |
3fa7d235 | 354 | seq_printf(m, "MAD_DIMM_C2 = 0x%08x\n", |
4f5fd91f | 355 | intel_uncore_read(uncore, MAD_DIMM_C2)); |
3fa7d235 | 356 | seq_printf(m, "TILECTL = 0x%08x\n", |
4f5fd91f | 357 | intel_uncore_read(uncore, TILECTL)); |
651e7d48 | 358 | if (GRAPHICS_VER(dev_priv) >= 8) |
9d3203e1 | 359 | seq_printf(m, "GAMTARBMODE = 0x%08x\n", |
4f5fd91f | 360 | intel_uncore_read(uncore, GAMTARBMODE)); |
9d3203e1 BW |
361 | else |
362 | seq_printf(m, "ARB_MODE = 0x%08x\n", | |
4f5fd91f | 363 | intel_uncore_read(uncore, ARB_MODE)); |
3fa7d235 | 364 | seq_printf(m, "DISP_ARB_CTL = 0x%08x\n", |
4f5fd91f | 365 | intel_uncore_read(uncore, DISP_ARB_CTL)); |
ea16a3cd | 366 | } |
656bfa3a | 367 | |
d858d569 | 368 | intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref); |
ea16a3cd DV |
369 | |
370 | return 0; | |
371 | } | |
372 | ||
1854d5ca CW |
373 | static int i915_rps_boost_info(struct seq_file *m, void *data) |
374 | { | |
36cdd013 | 375 | struct drm_i915_private *dev_priv = node_to_i915(m->private); |
2cbc876d | 376 | struct intel_rps *rps = &to_gt(dev_priv)->rps; |
c0a6aa7e | 377 | |
01fabda8 LDM |
378 | seq_printf(m, "RPS enabled? %s\n", |
379 | str_yes_no(intel_rps_is_enabled(rps))); | |
380 | seq_printf(m, "RPS active? %s\n", | |
381 | str_yes_no(intel_rps_is_active(rps))); | |
382 | seq_printf(m, "GPU busy? %s\n", str_yes_no(to_gt(dev_priv)->awake)); | |
7b92c1bd | 383 | seq_printf(m, "Boosts outstanding? %d\n", |
562d9bae | 384 | atomic_read(&rps->num_waiters)); |
60548c55 | 385 | seq_printf(m, "Interactive? %d\n", READ_ONCE(rps->power.interactive)); |
c0a6aa7e | 386 | seq_printf(m, "Frequency requested %d, actual %d\n", |
3e7abf81 | 387 | intel_gpu_freq(rps, rps->cur_freq), |
e03512ed | 388 | intel_rps_read_actual_frequency(rps)); |
7466c291 | 389 | seq_printf(m, " min hard:%d, soft:%d; max soft:%d, hard:%d\n", |
3e7abf81 AS |
390 | intel_gpu_freq(rps, rps->min_freq), |
391 | intel_gpu_freq(rps, rps->min_freq_softlimit), | |
392 | intel_gpu_freq(rps, rps->max_freq_softlimit), | |
393 | intel_gpu_freq(rps, rps->max_freq)); | |
7466c291 | 394 | seq_printf(m, " idle:%d, efficient:%d, boost:%d\n", |
3e7abf81 AS |
395 | intel_gpu_freq(rps, rps->idle_freq), |
396 | intel_gpu_freq(rps, rps->efficient_freq), | |
397 | intel_gpu_freq(rps, rps->boost_freq)); | |
1d2ac403 | 398 | |
4e5c8a99 | 399 | seq_printf(m, "Wait boosts: %d\n", READ_ONCE(rps->boosts)); |
1854d5ca | 400 | |
63573eb7 BW |
401 | return 0; |
402 | } | |
403 | ||
6455c870 | 404 | static int i915_runtime_pm_status(struct seq_file *m, void *unused) |
371db66a | 405 | { |
36cdd013 | 406 | struct drm_i915_private *dev_priv = node_to_i915(m->private); |
8ff5446a | 407 | struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); |
371db66a | 408 | |
a156e64d CW |
409 | if (!HAS_RUNTIME_PM(dev_priv)) |
410 | seq_puts(m, "Runtime power management not supported\n"); | |
371db66a | 411 | |
01fabda8 | 412 | seq_printf(m, "GPU idle: %s\n", str_yes_no(!to_gt(dev_priv)->awake)); |
371db66a | 413 | seq_printf(m, "IRQs disabled: %s\n", |
01fabda8 | 414 | str_yes_no(!intel_irqs_enabled(dev_priv))); |
0d804184 | 415 | #ifdef CONFIG_PM |
a6aaec8b | 416 | seq_printf(m, "Usage count: %d\n", |
36cdd013 | 417 | atomic_read(&dev_priv->drm.dev->power.usage_count)); |
0d804184 CW |
418 | #else |
419 | seq_printf(m, "Device Power Management (CONFIG_PM) disabled\n"); | |
420 | #endif | |
a156e64d | 421 | seq_printf(m, "PCI device power state: %s [%d]\n", |
52a05c30 DW |
422 | pci_power_name(pdev->current_state), |
423 | pdev->current_state); | |
371db66a | 424 | |
bd780f37 CW |
425 | if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)) { |
426 | struct drm_printer p = drm_seq_file_printer(m); | |
427 | ||
69c66355 | 428 | print_intel_runtime_pm_wakeref(&dev_priv->runtime_pm, &p); |
bd780f37 CW |
429 | } |
430 | ||
ec013e7f JB |
431 | return 0; |
432 | } | |
433 | ||
926b005c | 434 | static int i915_engine_info(struct seq_file *m, void *unused) |
1da51581 | 435 | { |
0986317a | 436 | struct drm_i915_private *i915 = node_to_i915(m->private); |
926b005c JN |
437 | struct intel_engine_cs *engine; |
438 | intel_wakeref_t wakeref; | |
439 | struct drm_printer p; | |
1da51581 | 440 | |
0986317a | 441 | wakeref = intel_runtime_pm_get(&i915->runtime_pm); |
1da51581 | 442 | |
8c3b1ba0 | 443 | seq_printf(m, "GT awake? %s [%d], %llums\n", |
01fabda8 | 444 | str_yes_no(to_gt(i915)->awake), |
2cbc876d MW |
445 | atomic_read(&to_gt(i915)->wakeref.count), |
446 | ktime_to_ms(intel_gt_get_awake_time(to_gt(i915)))); | |
f170523a | 447 | seq_printf(m, "CS timestamp frequency: %u Hz, %d ns\n", |
2cbc876d MW |
448 | to_gt(i915)->clock_frequency, |
449 | to_gt(i915)->clock_period_ns); | |
1da51581 | 450 | |
926b005c | 451 | p = drm_seq_file_printer(m); |
0986317a | 452 | for_each_uabi_engine(engine, i915) |
926b005c | 453 | intel_engine_dump(engine, &p, "%s\n", engine->name); |
1da51581 | 454 | |
2cbc876d | 455 | intel_gt_show_timelines(to_gt(i915), &p, i915_request_show_with_schedule); |
0986317a CW |
456 | |
457 | intel_runtime_pm_put(&i915->runtime_pm, wakeref); | |
1da51581 ID |
458 | |
459 | return 0; | |
460 | } | |
461 | ||
926b005c | 462 | static int i915_wa_registers(struct seq_file *m, void *unused) |
53f5e3ca | 463 | { |
926b005c JN |
464 | struct drm_i915_private *i915 = node_to_i915(m->private); |
465 | struct intel_engine_cs *engine; | |
cb634d3c | 466 | |
926b005c JN |
467 | for_each_uabi_engine(engine, i915) { |
468 | const struct i915_wa_list *wal = &engine->ctx_wa_list; | |
469 | const struct i915_wa *wa; | |
470 | unsigned int count; | |
ca851c22 | 471 | |
926b005c JN |
472 | count = wal->count; |
473 | if (!count) | |
474 | continue; | |
97e94b22 | 475 | |
926b005c JN |
476 | seq_printf(m, "%s: Workarounds applied: %u\n", |
477 | engine->name, count); | |
369a1342 | 478 | |
926b005c JN |
479 | for (wa = wal->list; count--; wa++) |
480 | seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X\n", | |
481 | i915_mmio_reg_offset(wa->reg), | |
482 | wa->set, wa->clr); | |
97e94b22 | 483 | |
926b005c JN |
484 | seq_printf(m, "\n"); |
485 | } | |
369a1342 | 486 | |
926b005c | 487 | return 0; |
369a1342 VS |
488 | } |
489 | ||
82a149a6 | 490 | static int i915_wedged_get(void *data, u64 *val) |
f3cd474b | 491 | { |
cb823ed9 | 492 | struct drm_i915_private *i915 = data; |
80ac788a AS |
493 | struct intel_gt *gt; |
494 | unsigned int i; | |
f3cd474b | 495 | |
80ac788a AS |
496 | *val = 0; |
497 | ||
498 | for_each_gt(gt, i915, i) { | |
499 | int ret; | |
500 | ||
501 | ret = intel_gt_debugfs_reset_show(gt, val); | |
502 | if (ret) | |
503 | return ret; | |
504 | ||
505 | /* at least one tile should be wedged */ | |
506 | if (*val) | |
507 | break; | |
508 | } | |
509 | ||
510 | return 0; | |
f3cd474b CW |
511 | } |
512 | ||
82a149a6 | 513 | static int i915_wedged_set(void *data, u64 val) |
f3cd474b | 514 | { |
598b6b5a | 515 | struct drm_i915_private *i915 = data; |
80ac788a AS |
516 | struct intel_gt *gt; |
517 | unsigned int i; | |
518 | ||
519 | for_each_gt(gt, i915, i) | |
520 | intel_gt_debugfs_reset_store(gt, val); | |
d46c0517 | 521 | |
7d14db8b | 522 | return 0; |
f3cd474b CW |
523 | } |
524 | ||
647416f9 KC |
525 | DEFINE_SIMPLE_ATTRIBUTE(i915_wedged_fops, |
526 | i915_wedged_get, i915_wedged_set, | |
3a3b4f98 | 527 | "%llu\n"); |
f3cd474b | 528 | |
daed3e44 LL |
529 | static int |
530 | i915_perf_noa_delay_set(void *data, u64 val) | |
531 | { | |
532 | struct drm_i915_private *i915 = data; | |
daed3e44 LL |
533 | |
534 | /* | |
535 | * This would lead to infinite waits as we're doing timestamp | |
536 | * difference on the CS with only 32bits. | |
537 | */ | |
2cbc876d | 538 | if (intel_gt_ns_to_clock_interval(to_gt(i915), val) > U32_MAX) |
daed3e44 LL |
539 | return -EINVAL; |
540 | ||
541 | atomic64_set(&i915->perf.noa_programming_delay, val); | |
542 | return 0; | |
543 | } | |
544 | ||
545 | static int | |
546 | i915_perf_noa_delay_get(void *data, u64 *val) | |
547 | { | |
548 | struct drm_i915_private *i915 = data; | |
549 | ||
550 | *val = atomic64_read(&i915->perf.noa_programming_delay); | |
551 | return 0; | |
552 | } | |
553 | ||
554 | DEFINE_SIMPLE_ATTRIBUTE(i915_perf_noa_delay_fops, | |
555 | i915_perf_noa_delay_get, | |
556 | i915_perf_noa_delay_set, | |
557 | "%llu\n"); | |
558 | ||
b4a0b32d CW |
559 | #define DROP_UNBOUND BIT(0) |
560 | #define DROP_BOUND BIT(1) | |
561 | #define DROP_RETIRE BIT(2) | |
562 | #define DROP_ACTIVE BIT(3) | |
563 | #define DROP_FREED BIT(4) | |
564 | #define DROP_SHRINK_ALL BIT(5) | |
565 | #define DROP_IDLE BIT(6) | |
6b048706 CW |
566 | #define DROP_RESET_ACTIVE BIT(7) |
567 | #define DROP_RESET_SEQNO BIT(8) | |
54895010 | 568 | #define DROP_RCU BIT(9) |
fbbd37b3 CW |
569 | #define DROP_ALL (DROP_UNBOUND | \ |
570 | DROP_BOUND | \ | |
571 | DROP_RETIRE | \ | |
572 | DROP_ACTIVE | \ | |
8eadc19b | 573 | DROP_FREED | \ |
b4a0b32d | 574 | DROP_SHRINK_ALL |\ |
6b048706 CW |
575 | DROP_IDLE | \ |
576 | DROP_RESET_ACTIVE | \ | |
54895010 CW |
577 | DROP_RESET_SEQNO | \ |
578 | DROP_RCU) | |
647416f9 KC |
579 | static int |
580 | i915_drop_caches_get(void *data, u64 *val) | |
dd624afd | 581 | { |
647416f9 | 582 | *val = DROP_ALL; |
dd624afd | 583 | |
647416f9 | 584 | return 0; |
dd624afd | 585 | } |
6c13c825 | 586 | |
647416f9 | 587 | static int |
8726a2a4 | 588 | gt_drop_caches(struct intel_gt *gt, u64 val) |
dd624afd | 589 | { |
7e805762 | 590 | int ret; |
dd624afd | 591 | |
ad4062da | 592 | if (val & DROP_RESET_ACTIVE && |
fdbc5aeb | 593 | wait_for(intel_engines_are_idle(gt), 200)) |
66101975 | 594 | intel_gt_set_wedged(gt); |
6b048706 | 595 | |
7e805762 | 596 | if (val & DROP_RETIRE) |
66101975 | 597 | intel_gt_retire_requests(gt); |
6cffeb83 | 598 | |
7e805762 | 599 | if (val & (DROP_IDLE | DROP_ACTIVE)) { |
66101975 | 600 | ret = intel_gt_wait_for_idle(gt, MAX_SCHEDULE_TIMEOUT); |
dd624afd | 601 | if (ret) |
6cffeb83 | 602 | return ret; |
7e805762 | 603 | } |
dd624afd | 604 | |
7e805762 | 605 | if (val & DROP_IDLE) { |
66101975 | 606 | ret = intel_gt_pm_wait_for_idle(gt); |
7e805762 CW |
607 | if (ret) |
608 | return ret; | |
6b048706 CW |
609 | } |
610 | ||
66101975 CW |
611 | if (val & DROP_RESET_ACTIVE && intel_gt_terminally_wedged(gt)) |
612 | intel_gt_handle_error(gt, ALL_ENGINES, 0, NULL); | |
dd624afd | 613 | |
16e87459 CW |
614 | if (val & DROP_FREED) |
615 | intel_gt_flush_buffer_pool(gt); | |
616 | ||
8726a2a4 TU |
617 | return 0; |
618 | } | |
619 | ||
620 | static int | |
621 | i915_drop_caches_set(void *data, u64 val) | |
622 | { | |
623 | struct drm_i915_private *i915 = data; | |
c795d2f4 | 624 | struct intel_gt *gt; |
1b9e8b1f | 625 | unsigned int flags; |
c795d2f4 | 626 | unsigned int i; |
8726a2a4 TU |
627 | int ret; |
628 | ||
a10234fd TU |
629 | drm_dbg(&i915->drm, "Dropping caches: 0x%08llx [0x%08llx]\n", |
630 | val, val & DROP_ALL); | |
8726a2a4 | 631 | |
c795d2f4 TU |
632 | for_each_gt(gt, i915, i) { |
633 | ret = gt_drop_caches(gt, val); | |
634 | if (ret) | |
635 | return ret; | |
636 | } | |
8726a2a4 | 637 | |
d92a8cfc | 638 | fs_reclaim_acquire(GFP_KERNEL); |
1b9e8b1f | 639 | flags = memalloc_noreclaim_save(); |
21ab4e74 | 640 | if (val & DROP_BOUND) |
cf41a8f1 | 641 | i915_gem_shrink(NULL, i915, LONG_MAX, NULL, I915_SHRINK_BOUND); |
4ad72b7f | 642 | |
21ab4e74 | 643 | if (val & DROP_UNBOUND) |
cf41a8f1 | 644 | i915_gem_shrink(NULL, i915, LONG_MAX, NULL, I915_SHRINK_UNBOUND); |
dd624afd | 645 | |
8eadc19b | 646 | if (val & DROP_SHRINK_ALL) |
6b048706 | 647 | i915_gem_shrink_all(i915); |
1b9e8b1f | 648 | memalloc_noreclaim_restore(flags); |
d92a8cfc | 649 | fs_reclaim_release(GFP_KERNEL); |
8eadc19b | 650 | |
54895010 CW |
651 | if (val & DROP_RCU) |
652 | rcu_barrier(); | |
653 | ||
c9c70471 | 654 | if (val & DROP_FREED) |
6b048706 | 655 | i915_gem_drain_freed_objects(i915); |
fbbd37b3 | 656 | |
6cffeb83 | 657 | return 0; |
dd624afd CW |
658 | } |
659 | ||
647416f9 KC |
660 | DEFINE_SIMPLE_ATTRIBUTE(i915_drop_caches_fops, |
661 | i915_drop_caches_get, i915_drop_caches_set, | |
662 | "0x%08llx\n"); | |
dd624afd | 663 | |
3873218f JM |
664 | static int i915_sseu_status(struct seq_file *m, void *unused) |
665 | { | |
5df79ff1 | 666 | struct drm_i915_private *i915 = node_to_i915(m->private); |
2cbc876d | 667 | struct intel_gt *gt = to_gt(i915); |
3873218f | 668 | |
a00eda7d | 669 | return intel_sseu_status(m, gt); |
3873218f JM |
670 | } |
671 | ||
6d794d42 BW |
672 | static int i915_forcewake_open(struct inode *inode, struct file *file) |
673 | { | |
d7a133d8 | 674 | struct drm_i915_private *i915 = inode->i_private; |
80ac788a AS |
675 | struct intel_gt *gt; |
676 | unsigned int i; | |
677 | ||
678 | for_each_gt(gt, i915, i) | |
679 | intel_gt_pm_debugfs_forcewake_user_open(gt); | |
6d794d42 | 680 | |
7d14db8b | 681 | return 0; |
6d794d42 BW |
682 | } |
683 | ||
c43b5634 | 684 | static int i915_forcewake_release(struct inode *inode, struct file *file) |
6d794d42 | 685 | { |
d7a133d8 | 686 | struct drm_i915_private *i915 = inode->i_private; |
80ac788a AS |
687 | struct intel_gt *gt; |
688 | unsigned int i; | |
689 | ||
690 | for_each_gt(gt, i915, i) | |
691 | intel_gt_pm_debugfs_forcewake_user_release(gt); | |
6d794d42 | 692 | |
7d14db8b | 693 | return 0; |
6d794d42 BW |
694 | } |
695 | ||
696 | static const struct file_operations i915_forcewake_fops = { | |
697 | .owner = THIS_MODULE, | |
698 | .open = i915_forcewake_open, | |
699 | .release = i915_forcewake_release, | |
700 | }; | |
701 | ||
06c5bf8c | 702 | static const struct drm_info_list i915_debugfs_list[] = { |
311bd68e | 703 | {"i915_capabilities", i915_capabilities, 0}, |
73aa808f | 704 | {"i915_gem_objects", i915_gem_object_info, 0}, |
adb4bd12 | 705 | {"i915_frequency_info", i915_frequency_info, 0}, |
ea16a3cd | 706 | {"i915_swizzle_info", i915_swizzle_info, 0}, |
6455c870 | 707 | {"i915_runtime_pm_status", i915_runtime_pm_status, 0}, |
1b36595f | 708 | {"i915_engine_info", i915_engine_info, 0}, |
1ed1ef9d | 709 | {"i915_wa_registers", i915_wa_registers, 0}, |
3873218f | 710 | {"i915_sseu_status", i915_sseu_status, 0}, |
1854d5ca | 711 | {"i915_rps_boost_info", i915_rps_boost_info, 0}, |
2017263e | 712 | }; |
2017263e | 713 | |
06c5bf8c | 714 | static const struct i915_debugfs_files { |
34b9674c DV |
715 | const char *name; |
716 | const struct file_operations *fops; | |
717 | } i915_debugfs_files[] = { | |
daed3e44 | 718 | {"i915_perf_noa_delay", &i915_perf_noa_delay_fops}, |
34b9674c | 719 | {"i915_wedged", &i915_wedged_fops}, |
34b9674c | 720 | {"i915_gem_drop_caches", &i915_drop_caches_fops}, |
34b9674c DV |
721 | }; |
722 | ||
f06b2052 | 723 | void i915_debugfs_register(struct drm_i915_private *dev_priv) |
2017263e | 724 | { |
91c8a326 | 725 | struct drm_minor *minor = dev_priv->drm.primary; |
6cc42152 | 726 | int i; |
f3cd474b | 727 | |
c43c5a88 JN |
728 | i915_debugfs_params(dev_priv); |
729 | ||
0780f3b6 GKH |
730 | debugfs_create_file("i915_forcewake_user", S_IRUSR, minor->debugfs_root, |
731 | to_i915(minor->dev), &i915_forcewake_fops); | |
34b9674c | 732 | for (i = 0; i < ARRAY_SIZE(i915_debugfs_files); i++) { |
0780f3b6 GKH |
733 | debugfs_create_file(i915_debugfs_files[i].name, |
734 | S_IRUGO | S_IWUSR, | |
735 | minor->debugfs_root, | |
736 | to_i915(minor->dev), | |
737 | i915_debugfs_files[i].fops); | |
34b9674c | 738 | } |
40633219 | 739 | |
f06b2052 | 740 | drm_debugfs_create_files(i915_debugfs_list, |
fdbc5aeb | 741 | ARRAY_SIZE(i915_debugfs_list), |
f06b2052 | 742 | minor->debugfs_root, minor); |
4fca5198 JN |
743 | |
744 | i915_gpu_error_debugfs_register(dev_priv); | |
2017263e | 745 | } |