1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2020 Intel Corporation 4 */ 5 6 #include <linux/kernel.h> 7 #include <linux/slab.h> 8 #include <linux/types.h> 9 10 #include <uapi/drm/i915_drm.h> 11 12 #include <drm/drm_print.h> 13 14 #include "gem/i915_gem_context.h" 15 #include "i915_drm_client.h" 16 #include "i915_file_private.h" 17 #include "i915_gem.h" 18 #include "i915_utils.h" 19 20 struct i915_drm_client *i915_drm_client_alloc(void) 21 { 22 struct i915_drm_client *client; 23 24 client = kzalloc(sizeof(*client), GFP_KERNEL); 25 if (!client) 26 return NULL; 27 28 kref_init(&client->kref); 29 spin_lock_init(&client->ctx_lock); 30 INIT_LIST_HEAD(&client->ctx_list); 31 32 return client; 33 } 34 35 void __i915_drm_client_free(struct kref *kref) 36 { 37 struct i915_drm_client *client = 38 container_of(kref, typeof(*client), kref); 39 40 kfree(client); 41 } 42 43 #ifdef CONFIG_PROC_FS 44 static const char * const uabi_class_names[] = { 45 [I915_ENGINE_CLASS_RENDER] = "render", 46 [I915_ENGINE_CLASS_COPY] = "copy", 47 [I915_ENGINE_CLASS_VIDEO] = "video", 48 [I915_ENGINE_CLASS_VIDEO_ENHANCE] = "video-enhance", 49 [I915_ENGINE_CLASS_COMPUTE] = "compute", 50 }; 51 52 static u64 busy_add(struct i915_gem_context *ctx, unsigned int class) 53 { 54 struct i915_gem_engines_iter it; 55 struct intel_context *ce; 56 u64 total = 0; 57 58 for_each_gem_engine(ce, rcu_dereference(ctx->engines), it) { 59 if (ce->engine->uabi_class != class) 60 continue; 61 62 total += intel_context_get_total_runtime_ns(ce); 63 } 64 65 return total; 66 } 67 68 static void 69 show_client_class(struct drm_printer *p, 70 struct drm_i915_private *i915, 71 struct i915_drm_client *client, 72 unsigned int class) 73 { 74 const unsigned int capacity = i915->engine_uabi_class_count[class]; 75 u64 total = atomic64_read(&client->past_runtime[class]); 76 struct i915_gem_context *ctx; 77 78 rcu_read_lock(); 79 list_for_each_entry_rcu(ctx, &client->ctx_list, client_link) 80 total += busy_add(ctx, class); 81 rcu_read_unlock(); 82 83 if (capacity) 84 drm_printf(p, "drm-engine-%s:\t%llu ns\n", 85 uabi_class_names[class], total); 86 87 if (capacity > 1) 88 drm_printf(p, "drm-engine-capacity-%s:\t%u\n", 89 uabi_class_names[class], 90 capacity); 91 } 92 93 void i915_drm_client_fdinfo(struct drm_printer *p, struct drm_file *file) 94 { 95 struct drm_i915_file_private *file_priv = file->driver_priv; 96 struct drm_i915_private *i915 = file_priv->i915; 97 unsigned int i; 98 99 /* 100 * ****************************************************************** 101 * For text output format description please see drm-usage-stats.rst! 102 * ****************************************************************** 103 */ 104 105 if (GRAPHICS_VER(i915) < 8) 106 return; 107 108 for (i = 0; i < ARRAY_SIZE(uabi_class_names); i++) 109 show_client_class(p, i915, file_priv->client, i); 110 } 111 #endif 112