21st century intel_gpu_top
Subsystems (3)
Tvrtko Ursulin
maintainercover 21st century intel_gpu_top
From: Tvrtko Ursulin <[email protected]>
A collection of patches which I have been sending before, sometimes together and sometimes separately, which enable intel_gpu_top to report queue depths (also translates as overall GPU load average) and per DRM client per engine busyness.
This enables a fancy intel_gpu_top which looks like this (a picture is worth a thousand words):
intel-gpu-top - load avg 3.30, 1.51, 0.08; 949/ 949 MHz; 0% RC6; 14.66 Watts; 3605 irqs/s
IMC reads: 4651 MiB/s
IMC writes: 25 MiB/s
ENGINE BUSY Q r R MI_SEMA MI_WAIT
Render/3D/0 61.51% |█████████████████████████████████████████████▌ | 3 0 1 0% 0%
Blitter/0 0.00% | | 0 0 0 0% 0%
Video/0 60.86% |█████████████████████████████████████████████ | 1 0 1 0% 0%
Video/1 59.04% |███████████████████████████████████████████▋ | 1 0 1 0% 0%
VideoEnhance/0 0.00% | | 0 0 0 0% 0%
PID NAME Render/3D/0 Blitter/0 Video/0 Video/1 VideoEnhance/0
23373 gem_wsim |█████▎ || ||████████▍ ||█████▎ || | 23374 gem_wsim |███▉ || ||██▏ ||███ || | 23375 gem_wsim |███ || ||█▍ ||███▌ || |
All of this work actually came to be via different feature requests not directly asking for this. Things like engine queue depth query and per context engine busyness ioctl. Those bits need userspace which is not there yet and so I have removed them from this posting to avoid confusion.
What remains is a set of patches which add some PMU counters and a completely new sysfs interface to enable intel_gpu_top to read the per client stats.
IGT counterpart will be sent separately.
Tvrtko Ursulin (13):
drm/i915/pmu: Fix enable count array size and bounds checking drm/i915: Keep a count of requests waiting for a slot on GPU drm/i915: Keep a count of requests submitted from userspace drm/i915/pmu: Add queued counter
drm/i915/pmu: Add runnable counter
drm/i915/pmu: Add running counter
drm/i915: Store engine backpointer in the intel_context drm/i915: Move intel_engine_context_in/out into intel_lrc.c drm/i915: Track per-context engine busyness drm/i915: Expose list of clients in sysfs
drm/i915: Update client name on context create drm/i915: Expose per-engine client busyness drm/i915: Add sysfs toggle to enable per-client engine stats
drivers/gpu/drm/i915/i915_drv.h | 39 +++++ drivers/gpu/drm/i915/i915_gem.c | 197 +++++++++++++++++++++++- drivers/gpu/drm/i915/i915_gem_context.c | 18 ++- drivers/gpu/drm/i915/i915_gem_context.h | 18 +++ drivers/gpu/drm/i915/i915_pmu.c | 103 +++++++++++-- drivers/gpu/drm/i915/i915_request.c | 10 ++ drivers/gpu/drm/i915/i915_sysfs.c | 81 ++++++++++ drivers/gpu/drm/i915/intel_engine_cs.c | 33 +++- drivers/gpu/drm/i915/intel_lrc.c | 109 ++++++++++++- drivers/gpu/drm/i915/intel_ringbuffer.h | 76 +++------ include/uapi/drm/i915_drm.h | 19 ++- 11 files changed, 614 insertions(+), 89 deletions(-)
Signature · 6 lines
2.17.1 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Tvrtko Ursulin
maintainerRFC 1/13 drm/i915/pmu: Fix enable count array size and bounds checking
From: Tvrtko Ursulin <[email protected]>
Enable count array is supposed to have one counter for each possible engine sampler. As such array sizing and bounds checking is not correct when more engine samplers are added.
At the same time tidy the assert for readability and robustness.
--- drivers/gpu/drm/i915/i915_pmu.c | 13 +++++++++---- drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-)
drivers/gpu/drm/i915/i915_pmu.c +9 -4
@@ -594,7 +594,8 @@ static void i915_pmu_enable(struct perf_event *event)* Update the bitmask of enabled events and increment * the event reference counter. */ -GEM_BUG_ON (bit >=I915_PMU_MASK_BITS ); +BUILD_BUG_ON (ARRAY_SIZE (i915->pmu.enable_count) !=I915_PMU_MASK_BITS ); +GEM_BUG_ON (bit >=ARRAY_SIZE (i915->pmu.enable_count));GEM_BUG_ON (i915->pmu.enable_count[bit] == ~0 ); i915->pmu.enable |=BIT_ULL (bit); i915->pmu.enable_count[bit]++;
@@ -618,7 +619,10 @@ static void i915_pmu_enable(struct perf_event *event)GEM_BUG_ON (!engine); engine->pmu.enable |=BIT (sample); -GEM_BUG_ON (sample >=I915_PMU_SAMPLE_BITS ); +BUILD_BUG_ON (ARRAY_SIZE (engine->pmu.enable_count) != + (1 <<I915_PMU_SAMPLE_BITS )); +GEM_BUG_ON (sample >=ARRAY_SIZE (engine->pmu.enable_count)); +GEM_BUG_ON (sample >=ARRAY_SIZE (engine->pmu.sample));GEM_BUG_ON (engine->pmu.enable_count[sample] == ~0 ); engine->pmu.enable_count[sample]++; }
@@ -650,7 +654,8 @@ static void i915_pmu_disable(struct perf_event *event)engine_event_class (event), engine_event_instance(event));GEM_BUG_ON (!engine); -GEM_BUG_ON (sample >=I915_PMU_SAMPLE_BITS ); +GEM_BUG_ON (sample >=ARRAY_SIZE (engine->pmu.enable_count)); +GEM_BUG_ON (sample >=ARRAY_SIZE (engine->pmu.sample));GEM_BUG_ON (engine->pmu.enable_count[sample] ==0 );/* * Decrement the reference count and clear the enabled
@@ -660,7 +665,7 @@ static void i915_pmu_disable(struct perf_event *event) engine->pmu.enable &= ~BIT (sample); } -GEM_BUG_ON (bit >=I915_PMU_MASK_BITS ); +GEM_BUG_ON (bit >=ARRAY_SIZE (i915->pmu.enable_count));GEM_BUG_ON (i915->pmu.enable_count[bit] ==0 );/* * Decrement the reference count and clear the enabled
drivers/gpu/drm/i915/intel_ringbuffer.h +1 -1
@@ -432,7 +432,7 @@ struct intel_engine_cs {* * Index number corresponds to the bit number from @enable. */ -unsigned int enable_count[I915_PMU_SAMPLE_BITS ]; +unsigned int enable_count[1 <<I915_PMU_SAMPLE_BITS ];/** * @sample: Counter values for sampling events. *
Signature · 6 lines
2.17.1 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Tvrtko Ursulin
maintainerRFC 2/13 drm/i915: Keep a count of requests waiting for a slot on GPU
In reply to Tvrtko UrsulinFrom: Tvrtko Ursulin <[email protected]>
Keep a per-engine number of runnable (waiting for GPU time) requests.
We choose to mange the runnable counter at the backend level instead of at the request submit_notify callback. The latter would be more consolidated and less code, but it would require making the counter either atomic_t or taking the engine->timeline->lock in submit_notify. So the choice is to do it at the backend level for the benefit of fewer atomic instructions.
v2:
* Move queued increment from insert_request to execlist_submit_request to avoid bumping when re-ordering for priority.
* Support the counter on the ringbuffer submission path as well, albeit just notionally. (Chris Wilson)
v3:
* Rebase.
v4:
* Rename and move the stats into a container structure. (Chris Wilson)
v5:
* Re-order fields in struct intel_engine_cs. (Chris Wilson)
v6-v8:
* Rebases.
v9:
* Fix accounting during wedging.
v10:
* Improved commit message. (Chris Wilson)
--- drivers/gpu/drm/i915/i915_gem.c | 1 + drivers/gpu/drm/i915/i915_request.c | 7 +++++++ drivers/gpu/drm/i915/intel_engine_cs.c | 5 +++-- drivers/gpu/drm/i915/intel_lrc.c | 1 + drivers/gpu/drm/i915/intel_ringbuffer.h | 9 +++++++++ 5 files changed, 21 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/i915_gem.c +1 -0
@@ -3309,6 +3309,7 @@ static void nop_complete_submit_request(struct i915_request *request)dma_fence_set_error (&request->fence, -EIO );spin_lock_irqsave (&request->engine->timeline.lock, flags); + request->engine->request_stats.runnable++;__i915_request_submit (request);intel_engine_init_global_seqno (request->engine, request->global_seqno);spin_unlock_irqrestore (&request->engine->timeline.lock, flags);
drivers/gpu/drm/i915/i915_request.c +7 -0
@@ -457,6 +457,9 @@ void __i915_request_submit(struct i915_request *request)/* Transfer from per-context onto the global per-engine timeline */ move_to_timeline (request, &engine->timeline); +GEM_BUG_ON (engine->request_stats.runnable ==0 ); + engine->request_stats.runnable--; +trace_i915_request_execute (request);wake_up_all (&request->execute);
@@ -470,6 +473,8 @@ void i915_request_submit(struct i915_request *request)/* Will be called from irq-context when using foreign fences. */ spin_lock_irqsave (&engine->timeline.lock, flags); + engine->request_stats.runnable++; +__i915_request_submit (request);spin_unlock_irqrestore (&engine->timeline.lock, flags);
@@ -507,6 +512,8 @@ void __i915_request_unsubmit(struct i915_request *request)/* Transfer back from the global per-engine timeline to per-context */ move_to_timeline (request, request->timeline); + engine->request_stats.runnable++; +/* * We don't need to wake_up any waiters on request->execute, they * will get woken by any other event or us re-adding this request
drivers/gpu/drm/i915/intel_engine_cs.c +3 -2
@@ -1460,11 +1460,12 @@ void intel_engine_dump(struct intel_engine_cs *engine,if (i915_terminally_wedged (&engine->i915->gpu_error))drm_printf (m,"*** WEDGED ***\n" ); -drm_printf (m,"\tcurrent seqno %x, last %x, hangcheck %x [%d ms]\n" , +drm_printf (m,"\tcurrent seqno %x, last %x, hangcheck %x [%d ms], runnable %u\n" ,intel_engine_get_seqno (engine),intel_engine_last_submit (engine), engine->hangcheck.seqno, -jiffies_to_msecs (jiffies - engine->hangcheck.action_timestamp)); +jiffies_to_msecs (jiffies - engine->hangcheck.action_timestamp), + engine->request_stats.runnable);drm_printf (m,"\tReset count: %d (global %d)\n" ,i915_reset_engine_count (error, engine),i915_reset_count (error));
drivers/gpu/drm/i915/intel_lrc.c +1 -0
@@ -1023,6 +1023,7 @@ static void queue_request(struct intel_engine_cs *engine, int prio) {list_add_tail (&node->link,i915_sched_lookup_priolist (engine, prio)); + engine->request_stats.runnable++; }static void __submit_queue_imm (struct intel_engine_cs *engine)
drivers/gpu/drm/i915/intel_ringbuffer.h +9 -0
@@ -380,6 +380,15 @@ struct intel_engine_cs {struct drm_i915_gem_object *default_state;void *pinned_default_state; +struct { +/** +* @runnable: Number of runnable requests sent to the backend. +* +* Count of requests waiting for the GPU to execute them. +*/ +unsigned int runnable; + } request_stats; +unsigned long irq_posted;#define ENGINE_IRQ_BREADCRUMB 0
Signature · 6 lines
2.17.1 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Tvrtko Ursulin
maintainerRFC 3/13 drm/i915: Keep a count of requests submitted from userspace
In reply to Tvrtko UrsulinFrom: Tvrtko Ursulin <[email protected]>
Keep a count of requests submitted from userspace and not yet runnable due unresolved dependencies.
v2: Rename and move under the container struct. (Chris Wilson)
v3: Rebase.
v4: Move decrement site to the backend to shrink the window of double-
accounting as much as possible. (Chris Wilson)
--- drivers/gpu/drm/i915/i915_request.c | 3 +++ drivers/gpu/drm/i915/intel_engine_cs.c | 3 ++- drivers/gpu/drm/i915/intel_lrc.c | 1 + drivers/gpu/drm/i915/intel_ringbuffer.h | 8 ++++++++ 4 files changed, 14 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_request.c +3 -0
@@ -474,6 +474,7 @@ void i915_request_submit(struct i915_request *request)spin_lock_irqsave (&engine->timeline.lock, flags); engine->request_stats.runnable++; +atomic_dec (&engine->request_stats.queued);__i915_request_submit (request);
@@ -1036,6 +1037,8 @@ void i915_request_add(struct i915_request *request) } request->emitted_jiffies = jiffies; +atomic_inc (&engine->request_stats.queued); +/* * Let the backend know a new request has arrived that may need * to adjust the existing execution schedule due to a high priority
drivers/gpu/drm/i915/intel_engine_cs.c +2 -1
@@ -1460,11 +1460,12 @@ void intel_engine_dump(struct intel_engine_cs *engine,if (i915_terminally_wedged (&engine->i915->gpu_error))drm_printf (m,"*** WEDGED ***\n" ); -drm_printf (m,"\tcurrent seqno %x, last %x, hangcheck %x [%d ms], runnable %u\n" , +drm_printf (m,"\tcurrent seqno %x, last %x, hangcheck %x [%d ms], queued %u, runnable %u\n" ,intel_engine_get_seqno (engine),intel_engine_last_submit (engine), engine->hangcheck.seqno,jiffies_to_msecs (jiffies - engine->hangcheck.action_timestamp), +atomic_read (&engine->request_stats.queued), engine->request_stats.runnable); drm_printf(m, "\tReset count: %d (global %d)\n", i915_reset_engine_count(error, engine),
drivers/gpu/drm/i915/intel_lrc.c +1 -0
@@ -1024,6 +1024,7 @@ static void queue_request(struct intel_engine_cs *engine, {list_add_tail (&node->link,i915_sched_lookup_priolist (engine, prio)); engine->request_stats.runnable++; +atomic_dec (&engine->request_stats.queued); }static void __submit_queue_imm (struct intel_engine_cs *engine)
drivers/gpu/drm/i915/intel_ringbuffer.h +8 -0
@@ -381,6 +381,14 @@ struct intel_engine_cs {void *pinned_default_state;struct { +/** +* @queued: Number of submitted requests with dependencies. +* +* Count of requests waiting for dependencies before they can be +* submitted to the backend. +*/ +atomic_t queued; +/** * @runnable: Number of runnable requests sent to the backend. *
Signature · 6 lines
2.17.1 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Tvrtko Ursulin
maintainerRFC 4/13 drm/i915/pmu: Add queued counter
In reply to Tvrtko UrsulinFrom: Tvrtko Ursulin <[email protected]>
We add a PMU counter to expose the number of requests which have been submitted from userspace but are not yet runnable due dependencies and unsignaled fences.
This is useful to analyze the overall load of the system.
v2:
* Rebase for name change and re-order.
* Drop floating point constant. (Chris Wilson)
v3:
* Change scale to 1024 for faster arithmetics. (Chris Wilson)
v4:
* Refactored for timer period accounting.
v5:
* Avoid 64-division. (Chris Wilson)
v6:
* Do fewer divisions by accumulating in qd.ns units. (Chris Wilson)
* Change counter scale to avoid multiplication in readout and increase counter headroom.
--- drivers/gpu/drm/i915/i915_pmu.c | 58 ++++++++++++++++++++----- drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +- include/uapi/drm/i915_drm.h | 9 +++- 3 files changed, 57 insertions(+), 12 deletions(-)
drivers/gpu/drm/i915/i915_pmu.c +48 -10
@@ -16,7 +16,8 @@#define ENGINE_SAMPLE_MASK \ (BIT(I915_SAMPLE_BUSY) | \ BIT(I915_SAMPLE_WAIT) | \ - BIT(I915_SAMPLE_SEMA)) + BIT(I915_SAMPLE_SEMA) | \ + BIT(I915_SAMPLE_QUEUED))#define ENGINE_SAMPLE_BITS (1 << I915_PMU_SAMPLE_BITS)
@@ -162,6 +163,12 @@ add_sample(struct i915_pmu_sample *sample, u32 val) sample->cur += val; } +static void +add_sample_mult (struct i915_pmu_sample *sample,u32 val,u32 mul) +{ + sample->cur +=mul_u32_u32 (val, mul); +} +static void engines_sample (struct drm_i915_private *dev_priv,unsigned int period_ns) {
@@ -205,6 +212,11 @@ engines_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)if (val &RING_WAIT_SEMAPHORE )add_sample (&engine->pmu.sample[I915_SAMPLE_SEMA ], period_ns); + +if (engine->pmu.enable &BIT (I915_SAMPLE_QUEUED )) +add_sample_mult (&engine->pmu.sample[I915_SAMPLE_QUEUED ], +atomic_read (&engine->request_stats.queued), + period_ns); }if (fw)
@@ -213,12 +225,6 @@ engines_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)intel_runtime_pm_put (dev_priv); } -static void -add_sample_mult (struct i915_pmu_sample *sample,u32 val,u32 mul) -{ - sample->cur +=mul_u32_u32 (val, mul); -} -static void frequency_sample (struct drm_i915_private *dev_priv,unsigned int period_ns) {
@@ -324,6 +330,7 @@ engine_event_status(struct intel_engine_cs *engine,switch (sample) {case I915_SAMPLE_BUSY :case I915_SAMPLE_WAIT : +case I915_SAMPLE_QUEUED :break ;case I915_SAMPLE_SEMA :if (INTEL_GEN (engine->i915) <6 )
@@ -541,6 +548,15 @@ static u64 __i915_pmu_event_read(struct perf_event *event) val =ktime_to_ns (intel_engine_get_busy_time (engine)); }else { val = engine->pmu.sample[sample].cur; + +if (sample ==I915_SAMPLE_QUEUED ) { +BUILD_BUG_ON (NSEC_PER_SEC % +I915_SAMPLE_QUEUED_DIVISOR ); +/* to qd */ + val =div_u64 (val, +NSEC_PER_SEC / +I915_SAMPLE_QUEUED_DIVISOR ); + } } }else {switch (event->attr.config) {
@@ -797,6 +813,16 @@ static const struct attribute_group *i915_pmu_attr_groups[] = { { \ .sample = (__sample), \ .name = (__name), \ + .suffix = "unit", \ + .value = "ns", \ +} + +#define __engine_event_scale (__sample, __name, __scale) \ +{ \ + .sample = (__sample), \ + .name = (__name), \ + .suffix = "scale", \ + .value = (__scale), \ } static struct i915_ext_attribute *
@@ -824,6 +850,9 @@ add_pmu_attr(struct perf_pmu_events_attr *attr, const char *name,return ++attr; } +/* No brackets or quotes below please. */ +#define I915_SAMPLE_QUEUED_SCALE 0.001 +static struct attribute **create_event_attributes (struct drm_i915_private *i915) {
@@ -840,10 +869,14 @@ create_event_attributes(struct drm_i915_private *i915)static const struct {enum drm_i915_pmu_engine_sample sample;char *name; +char *suffix; +char *value; } engine_events[] = {__engine_event (I915_SAMPLE_BUSY ,"busy" ),__engine_event (I915_SAMPLE_SEMA ,"sema" ),__engine_event (I915_SAMPLE_WAIT ,"wait" ), +__engine_event_scale (I915_SAMPLE_QUEUED ,"queued" , +__stringify (I915_SAMPLE_QUEUED_SCALE )), };unsigned int count =0 ;struct perf_pmu_events_attr *pmu_attr =NULL , *pmu_iter;
@@ -853,6 +886,9 @@ create_event_attributes(struct drm_i915_private *i915)enum intel_engine_id id;unsigned int i; +BUILD_BUG_ON (I915_SAMPLE_QUEUED_DIVISOR != + (1 /I915_SAMPLE_QUEUED_SCALE )); +/* Count how many counters we will be exposing. */ for (i =0 ; i <ARRAY_SIZE (events); i++) {if (!config_status (i915, events[i].config))
@@ -930,13 +966,15 @@ create_event_attributes(struct drm_i915_private *i915) engine->instance, engine_events[i].sample)); - str =kasprintf (GFP_KERNEL ,"%s-%s.unit" , - engine->name, engine_events[i].name); + str =kasprintf (GFP_KERNEL ,"%s-%s.%s" , + engine->name, engine_events[i].name, + engine_events[i].suffix);if (!str) goto err; *attr_iter++ = &pmu_iter->attr.attr; - pmu_iter =add_pmu_attr (pmu_iter, str,"ns" ); + pmu_iter =add_pmu_attr (pmu_iter, str, + engine_events[i].value); } }
drivers/gpu/drm/i915/intel_ringbuffer.h +1 -1
@@ -455,7 +455,7 @@ struct intel_engine_cs {* * Our internal timer stores the current counters in this field. */ -#define I915_ENGINE_SAMPLE_MAX (I915_SAMPLE_SEMA + 1) +#define I915_ENGINE_SAMPLE_MAX (I915_SAMPLE_QUEUED + 1)struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX ]; } pmu;
include/uapi/drm/i915_drm.h +8 -1
@@ -110,9 +110,13 @@ enum drm_i915_gem_engine_class {enum drm_i915_pmu_engine_sample {I915_SAMPLE_BUSY =0 ,I915_SAMPLE_WAIT =1 , -I915_SAMPLE_SEMA =2 +I915_SAMPLE_SEMA =2 , +I915_SAMPLE_QUEUED =3 }; +/* Divide counter value by divisor to get the real value. */ +#define I915_SAMPLE_QUEUED_DIVISOR (1000) +#define I915_PMU_SAMPLE_BITS (4)#define I915_PMU_SAMPLE_MASK (0xf)#define I915_PMU_SAMPLE_INSTANCE_BITS (8)
@@ -133,6 +137,9 @@ enum drm_i915_pmu_engine_sample {#define I915_PMU_ENGINE_SEMA (class, instance) \ __I915_PMU_ENGINE(class, instance, I915_SAMPLE_SEMA) +#define I915_PMU_ENGINE_QUEUED (class, instance) \ + __I915_PMU_ENGINE(class, instance, I915_SAMPLE_QUEUED) +#define __I915_PMU_OTHER (x) (__I915_PMU_ENGINE(0xff, 0xff, 0xf) + 1 + (x))#define I915_PMU_ACTUAL_FREQUENCY __I915_PMU_OTHER(0)
Signature · 6 lines
2.17.1 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Tvrtko Ursulin
maintainerRFC 5/13 drm/i915/pmu: Add runnable counter
In reply to Tvrtko UrsulinFrom: Tvrtko Ursulin <[email protected]>
We add a PMU counter to expose the number of requests with resolved dependencies waiting for a slot on the GPU to run.
This is useful to analyze the overall load of the system.
v2: Don't limit to gen8+.
v3:
* Rebase for dynamic sysfs.
* Drop currently executing requests.
v4:
* Sync with internal renaming.
* Drop floating point constant. (Chris Wilson)
v5:
* Change scale to 1024 for faster arithmetics. (Chris Wilson)
v6:
* Refactored for timer period accounting.
v7:
* Avoid 64-division. (Chris Wilson)
v8:
* Do fewer divisions by accumulating in qd.ns units. (Chris Wilson)
* Change counter scale to avoid multiplication in readout and increase counter headroom.
--- drivers/gpu/drm/i915/i915_pmu.c | 20 ++++++++++++++++++-- drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +- include/uapi/drm/i915_drm.h | 7 ++++++- 3 files changed, 25 insertions(+), 4 deletions(-)
drivers/gpu/drm/i915/i915_pmu.c +18 -2
@@ -17,7 +17,8 @@ (BIT (I915_SAMPLE_BUSY ) | \BIT (I915_SAMPLE_WAIT ) | \BIT (I915_SAMPLE_SEMA ) | \ - BIT(I915_SAMPLE_QUEUED)) +BIT (I915_SAMPLE_QUEUED ) | \ + BIT(I915_SAMPLE_RUNNABLE))#define ENGINE_SAMPLE_BITS (1 << I915_PMU_SAMPLE_BITS)
@@ -217,6 +218,11 @@ engines_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)add_sample_mult (&engine->pmu.sample[I915_SAMPLE_QUEUED ],atomic_read (&engine->request_stats.queued), period_ns); + +if (engine->pmu.enable &BIT (I915_SAMPLE_RUNNABLE )) +add_sample_mult (&engine->pmu.sample[I915_SAMPLE_RUNNABLE ], + engine->request_stats.runnable, + period_ns); }if (fw)
@@ -331,6 +337,7 @@ engine_event_status(struct intel_engine_cs *engine,case I915_SAMPLE_BUSY :case I915_SAMPLE_WAIT :case I915_SAMPLE_QUEUED : +case I915_SAMPLE_RUNNABLE :break ;case I915_SAMPLE_SEMA :if (INTEL_GEN (engine->i915) <6 )
@@ -549,9 +556,12 @@ static u64 __i915_pmu_event_read(struct perf_event *event) }else { val = engine->pmu.sample[sample].cur; -if (sample ==I915_SAMPLE_QUEUED ) { +if (sample ==I915_SAMPLE_QUEUED || + sample ==I915_SAMPLE_RUNNABLE ) {BUILD_BUG_ON (NSEC_PER_SEC %I915_SAMPLE_QUEUED_DIVISOR ); +BUILD_BUG_ON (I915_SAMPLE_QUEUED_DIVISOR != +I915_SAMPLE_RUNNABLE_DIVISOR );/* to qd */ val = div_u64(val, NSEC_PER_SEC /
@@ -852,6 +862,7 @@ add_pmu_attr(struct perf_pmu_events_attr *attr, const char *name,/* No brackets or quotes below please. */ #define I915_SAMPLE_QUEUED_SCALE 0.001 +#define I915_SAMPLE_RUNNABLE_SCALE 0.001static struct attribute **create_event_attributes (struct drm_i915_private *i915)
@@ -877,6 +888,8 @@ create_event_attributes(struct drm_i915_private *i915)__engine_event (I915_SAMPLE_WAIT ,"wait" ),__engine_event_scale (I915_SAMPLE_QUEUED ,"queued" ,__stringify (I915_SAMPLE_QUEUED_SCALE )), +__engine_event_scale (I915_SAMPLE_RUNNABLE ,"runnable" , + __stringify(I915_SAMPLE_RUNNABLE_SCALE)), };unsigned int count =0 ;struct perf_pmu_events_attr *pmu_attr =NULL , *pmu_iter;
@@ -889,6 +902,9 @@ create_event_attributes(struct drm_i915_private *i915)BUILD_BUG_ON (I915_SAMPLE_QUEUED_DIVISOR != (1 /I915_SAMPLE_QUEUED_SCALE )); +BUILD_BUG_ON (I915_SAMPLE_RUNNABLE_DIVISOR != + (1 /I915_SAMPLE_RUNNABLE_SCALE )); +/* Count how many counters we will be exposing. */ for (i =0 ; i <ARRAY_SIZE (events); i++) {if (!config_status (i915, events[i].config))
drivers/gpu/drm/i915/intel_ringbuffer.h +1 -1
@@ -455,7 +455,7 @@ struct intel_engine_cs {* * Our internal timer stores the current counters in this field. */ -#define I915_ENGINE_SAMPLE_MAX (I915_SAMPLE_QUEUED + 1) +#define I915_ENGINE_SAMPLE_MAX (I915_SAMPLE_RUNNABLE + 1)struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX ]; } pmu;
include/uapi/drm/i915_drm.h +6 -1
@@ -111,11 +111,13 @@ enum drm_i915_pmu_engine_sample {I915_SAMPLE_BUSY =0 ,I915_SAMPLE_WAIT =1 ,I915_SAMPLE_SEMA =2 , - I915_SAMPLE_QUEUED = 3 +I915_SAMPLE_QUEUED =3 , + I915_SAMPLE_RUNNABLE = 4, };/* Divide counter value by divisor to get the real value. */ #define I915_SAMPLE_QUEUED_DIVISOR (1000) +#define I915_SAMPLE_RUNNABLE_DIVISOR (1000)#define I915_PMU_SAMPLE_BITS (4)#define I915_PMU_SAMPLE_MASK (0xf)
@@ -140,6 +142,9 @@ enum drm_i915_pmu_engine_sample {#define I915_PMU_ENGINE_QUEUED (class, instance) \ __I915_PMU_ENGINE(class, instance, I915_SAMPLE_QUEUED) +#define I915_PMU_ENGINE_RUNNABLE (class, instance) \ + __I915_PMU_ENGINE(class, instance, I915_SAMPLE_RUNNABLE) +#define __I915_PMU_OTHER (x) (__I915_PMU_ENGINE(0xff, 0xff, 0xf) + 1 + (x))#define I915_PMU_ACTUAL_FREQUENCY __I915_PMU_OTHER(0)
Signature · 6 lines
2.17.1 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Tvrtko Ursulin
maintainerRFC 6/13 drm/i915/pmu: Add running counter
In reply to Tvrtko UrsulinFrom: Tvrtko Ursulin <[email protected]>
We add a PMU counter to expose the number of requests currently executing on the GPU.
This is useful to analyze the overall load of the system.
v2:
* Rebase.
* Drop floating point constant. (Chris Wilson)
v3:
* Change scale to 1024 for faster arithmetics. (Chris Wilson)
v4:
* Refactored for timer period accounting.
v5:
* Avoid 64-division. (Chris Wilson)
v6:
* Do fewer divisions by accumulating in qd.ns units. (Chris Wilson)
* Change counter scale to avoid multiplication in readout and increase counter headroom.
--- drivers/gpu/drm/i915/i915_pmu.c | 20 ++++++++++++++++++-- drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +- include/uapi/drm/i915_drm.h | 5 +++++ 3 files changed, 24 insertions(+), 3 deletions(-)
drivers/gpu/drm/i915/i915_pmu.c +18 -2
@@ -18,7 +18,8 @@BIT (I915_SAMPLE_WAIT ) | \BIT (I915_SAMPLE_SEMA ) | \BIT (I915_SAMPLE_QUEUED ) | \ - BIT(I915_SAMPLE_RUNNABLE)) +BIT (I915_SAMPLE_RUNNABLE ) | \ + BIT(I915_SAMPLE_RUNNING)) #define ENGINE_SAMPLE_BITS (1 << I915_PMU_SAMPLE_BITS)
@@ -223,6 +224,11 @@ engines_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)add_sample_mult (&engine->pmu.sample[I915_SAMPLE_RUNNABLE ], engine->request_stats.runnable, period_ns); + +if (engine->pmu.enable &BIT (I915_SAMPLE_RUNNING )) +add_sample_mult (&engine->pmu.sample[I915_SAMPLE_RUNNING ], + last_seqno - current_seqno, + period_ns); }if (fw)
@@ -338,6 +344,7 @@ engine_event_status(struct intel_engine_cs *engine,case I915_SAMPLE_WAIT :case I915_SAMPLE_QUEUED :case I915_SAMPLE_RUNNABLE : +case I915_SAMPLE_RUNNING :break ;case I915_SAMPLE_SEMA :if (INTEL_GEN (engine->i915) <6 )
@@ -557,11 +564,14 @@ static u64 __i915_pmu_event_read(struct perf_event *event) val = engine->pmu.sample[sample].cur;if (sample ==I915_SAMPLE_QUEUED || - sample ==I915_SAMPLE_RUNNABLE ) { + sample ==I915_SAMPLE_RUNNABLE || + sample ==I915_SAMPLE_RUNNING ) {BUILD_BUG_ON (NSEC_PER_SEC %I915_SAMPLE_QUEUED_DIVISOR );BUILD_BUG_ON (I915_SAMPLE_QUEUED_DIVISOR !=I915_SAMPLE_RUNNABLE_DIVISOR ); +BUILD_BUG_ON (I915_SAMPLE_QUEUED_DIVISOR != +I915_SAMPLE_RUNNING_DIVISOR );/* to qd */ val = div_u64(val, NSEC_PER_SEC /
@@ -863,6 +873,7 @@ add_pmu_attr(struct perf_pmu_events_attr *attr, const char *name,/* No brackets or quotes below please. */ #define I915_SAMPLE_QUEUED_SCALE 0.001#define I915_SAMPLE_RUNNABLE_SCALE 0.001 +#define I915_SAMPLE_RUNNING_SCALE 0.001static struct attribute **create_event_attributes (struct drm_i915_private *i915)
@@ -890,6 +901,8 @@ create_event_attributes(struct drm_i915_private *i915) __stringify(I915_SAMPLE_QUEUED_SCALE)),__engine_event_scale (I915_SAMPLE_RUNNABLE ,"runnable" ,__stringify (I915_SAMPLE_RUNNABLE_SCALE )), +__engine_event_scale (I915_SAMPLE_RUNNING ,"running" , + __stringify(I915_SAMPLE_RUNNING_SCALE)), };unsigned int count =0 ;struct perf_pmu_events_attr *pmu_attr =NULL , *pmu_iter;
@@ -905,6 +918,9 @@ create_event_attributes(struct drm_i915_private *i915)BUILD_BUG_ON (I915_SAMPLE_RUNNABLE_DIVISOR != (1 /I915_SAMPLE_RUNNABLE_SCALE )); +BUILD_BUG_ON (I915_SAMPLE_RUNNING_DIVISOR != + (1 /I915_SAMPLE_RUNNING_SCALE )); +/* Count how many counters we will be exposing. */ for (i =0 ; i <ARRAY_SIZE (events); i++) {if (!config_status (i915, events[i].config))
drivers/gpu/drm/i915/intel_ringbuffer.h +1 -1
@@ -455,7 +455,7 @@ struct intel_engine_cs {* * Our internal timer stores the current counters in this field. */ -#define I915_ENGINE_SAMPLE_MAX (I915_SAMPLE_RUNNABLE + 1) +#define I915_ENGINE_SAMPLE_MAX (I915_SAMPLE_RUNNING + 1)struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX ]; } pmu;
include/uapi/drm/i915_drm.h +5 -0
@@ -113,11 +113,13 @@ enum drm_i915_pmu_engine_sample {I915_SAMPLE_SEMA =2 ,I915_SAMPLE_QUEUED =3 ,I915_SAMPLE_RUNNABLE =4 , + I915_SAMPLE_RUNNING = 5, };/* Divide counter value by divisor to get the real value. */ #define I915_SAMPLE_QUEUED_DIVISOR (1000)#define I915_SAMPLE_RUNNABLE_DIVISOR (1000) +#define I915_SAMPLE_RUNNING_DIVISOR (1000)#define I915_PMU_SAMPLE_BITS (4)#define I915_PMU_SAMPLE_MASK (0xf)
@@ -145,6 +147,9 @@ enum drm_i915_pmu_engine_sample {#define I915_PMU_ENGINE_RUNNABLE (class, instance) \ __I915_PMU_ENGINE(class, instance, I915_SAMPLE_RUNNABLE) +#define I915_PMU_ENGINE_RUNNING (class, instance) \ + __I915_PMU_ENGINE(class, instance, I915_SAMPLE_RUNNING) +#define __I915_PMU_OTHER (x) (__I915_PMU_ENGINE(0xff, 0xff, 0xf) + 1 + (x))#define I915_PMU_ACTUAL_FREQUENCY __I915_PMU_OTHER(0)
Signature · 6 lines
2.17.1 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Tvrtko Ursulin
maintainerRFC 7/13 drm/i915: Store engine backpointer in the intel_context
In reply to Tvrtko UrsulinFrom: Tvrtko Ursulin <[email protected]>
It will become useful in a later patch.
--- drivers/gpu/drm/i915/i915_gem_context.c | 1 + drivers/gpu/drm/i915/i915_gem_context.h | 1 + 2 files changed, 2 insertions(+)
drivers/gpu/drm/i915/i915_gem_context.c +1 -0
@@ -343,6 +343,7 @@ __create_hw_context(struct drm_i915_private *dev_priv,struct intel_context *ce = &ctx->__engine[n]; ce->gem_context = ctx; + ce->engine = dev_priv->engine[n]; }INIT_RADIX_TREE (&ctx->handles_vma,GFP_KERNEL );
drivers/gpu/drm/i915/i915_gem_context.h +1 -0
@@ -163,6 +163,7 @@ struct i915_gem_context {/** engine: per-engine logical HW state */ struct intel_context {struct i915_gem_context *gem_context; +struct intel_engine_cs *engine;struct i915_vma *state;struct intel_ring *ring;u32 *lrc_reg_state;
Signature · 6 lines
2.17.1 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Tvrtko Ursulin
maintainerRFC 8/13 drm/i915: Move intel_engine_context_in/out into intel_lrc.c
In reply to Tvrtko UrsulinFrom: Tvrtko Ursulin <[email protected]>
Intel_lrc.c is the only caller and so to avoid some header file ordering issues in future patches move these two over there.
--- drivers/gpu/drm/i915/intel_lrc.c | 57 +++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 55 ------------------------ 2 files changed, 57 insertions(+), 55 deletions(-)
drivers/gpu/drm/i915/intel_lrc.c +57 -0
@@ -329,6 +329,63 @@ execlists_context_status_change(struct i915_request *rq, unsigned long status) status, rq); } +static inline void +intel_engine_context_in (struct intel_engine_cs *engine) +{ +unsigned long flags; + +if (READ_ONCE (engine->stats.enabled) ==0 ) +return ; + +write_seqlock_irqsave (&engine->stats.lock, flags); + +if (engine->stats.enabled >0 ) { +if (engine->stats.active++ ==0 ) + engine->stats.start =ktime_get (); +GEM_BUG_ON (engine->stats.active ==0 ); + } + +write_sequnlock_irqrestore (&engine->stats.lock, flags); +} + +static inline void +intel_engine_context_out (struct intel_engine_cs *engine) +{ +unsigned long flags; + +if (READ_ONCE (engine->stats.enabled) ==0 ) +return ; + +write_seqlock_irqsave (&engine->stats.lock, flags); + +if (engine->stats.enabled >0 ) { +ktime_t last; + +if (engine->stats.active && --engine->stats.active ==0 ) { +/* +* Decrement the active context count and in case GPU +* is now idle add up to the running total. +*/ + last =ktime_sub (ktime_get (), engine->stats.start); + + engine->stats.total =ktime_add (engine->stats.total, + last); + }else if (engine->stats.active ==0 ) { +/* +* After turning on engine stats, context out might be +* the first event in which case we account from the +* time stats gathering was turned on. +*/ + last =ktime_sub (ktime_get (), engine->stats.enabled_at); + + engine->stats.total =ktime_add (engine->stats.total, + last); + } + } + +write_sequnlock_irqrestore (&engine->stats.lock, flags); +} +inline void execlists_user_begin (struct intel_engine_execlists *execlists,const struct execlist_port *port)
drivers/gpu/drm/i915/intel_ringbuffer.h +0 -55
61 lines not on this page · raw message
Signature · 6 lines
2.17.1 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Tvrtko Ursulin
maintainerRFC 9/13 drm/i915: Track per-context engine busyness
In reply to Tvrtko UrsulinFrom: Tvrtko Ursulin <[email protected]>
Some customers want to know how much of the GPU time are their clients using in order to make dynamic load balancing decisions.
With the hooks already in place which track the overall engine busyness, we can extend that slightly to split that time between contexts.
v2: Fix accounting for tail updates.
v3: Rebase.
v4: Mark currently running contexts as active on stats enable.
v5: Include some headers to fix the build.
v6: Added fine grained lock.
v7: Convert to seqlock. (Chris Wilson)
v8: Rebase and tidy with helpers.
--- drivers/gpu/drm/i915/i915_gem_context.c | 1 + drivers/gpu/drm/i915/i915_gem_context.h | 17 +++++++ drivers/gpu/drm/i915/intel_engine_cs.c | 27 +++++++++++ drivers/gpu/drm/i915/intel_lrc.c | 62 +++++++++++++++++++++---- 4 files changed, 97 insertions(+), 10 deletions(-)
drivers/gpu/drm/i915/i915_gem_context.c +1 -0
@@ -344,6 +344,7 @@ __create_hw_context(struct drm_i915_private *dev_priv, ce->gem_context = ctx; ce->engine = dev_priv->engine[n]; +seqlock_init (&ce->stats.lock); }INIT_RADIX_TREE (&ctx->handles_vma,GFP_KERNEL );
drivers/gpu/drm/i915/i915_gem_context.h +17 -0
@@ -28,6 +28,7 @@#include <linux/bitops.h> #include <linux/list.h> #include <linux/radix-tree.h> +#include <linux/seqlock.h> #include "i915_gem.h" #include "i915_scheduler.h"
@@ -170,6 +171,13 @@ struct i915_gem_context {u64 lrc_desc;int pin_count; +struct intel_context_stats { +seqlock_t lock; +bool active; +ktime_t start; +ktime_t total; + } stats; +const struct intel_context_ops *ops; } __engine[I915_NUM_ENGINES ];
@@ -364,4 +372,13 @@ static inline void i915_gem_context_put(struct i915_gem_context *ctx) kref_put(&ctx->ref, i915_gem_context_release); } +static inline void +__intel_context_stats_start (struct intel_context_stats *stats,ktime_t now) +{ + stats->start = now; + stats->active = true; +} + +ktime_t intel_context_get_busy_time (struct intel_context *ce); +#endif /* !__I915_GEM_CONTEXT_H__ */
drivers/gpu/drm/i915/intel_engine_cs.c +27 -0
@@ -1632,6 +1632,14 @@ int intel_enable_engine_stats(struct intel_engine_cs *engine) engine->stats.enabled_at =ktime_get (); +/* Mark currently running context as active. */ +if (port_isset (port)) { +struct i915_request *rq =port_request (port); + +__intel_context_stats_start (&rq->hw_context->stats, + engine->stats.enabled_at); + } +/* XXX submission method oblivious? */ while (num_ports-- &&port_isset (port)) { engine->stats.active++;
@@ -1705,6 +1713,25 @@ void intel_disable_engine_stats(struct intel_engine_cs *engine)write_sequnlock_irqrestore (&engine->stats.lock, flags); } +ktime_t intel_context_get_busy_time (struct intel_context *ce) +{ +unsigned int seq; +ktime_t total; + +do { + seq =read_seqbegin (&ce->stats.lock); + + total = ce->stats.total; + +if (ce->stats.active) + total =ktime_add (total, +ktime_sub (ktime_get (), + ce->stats.start)); + }while (read_seqretry (&ce->stats.lock, seq)); + +return total; +} +#if IS_ENABLED (CONFIG_DRM_I915_SELFTEST )#include "selftests/mock_engine.c" #include "selftests/intel_engine_cs.c"
drivers/gpu/drm/i915/intel_lrc.c +52 -10
122 lines not on this page · raw message
Signature · 6 lines
2.17.1 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Tvrtko Ursulin
maintainerRFC 10/13 drm/i915: Expose list of clients in sysfs
In reply to Tvrtko UrsulinFrom: Tvrtko Ursulin <[email protected]>
Expose a list of clients with open file handles in sysfs.
This will be a basis for a top-like utility showing per-client and per- engine GPU load.
Currently we only expose each client's pid and name under opaque numbered directories in /sys/class/drm/card0/clients/.
For instance:
/sys/class/drm/card0/clients/3/name: Xorg/sys/class/drm/card0/clients/3/pid: 5664
v2:
Chris Wilson:
* Enclose new members into dedicated structs.
* Protect against failed sysfs registration.
v3:
* sysfs_attr_init.
--- drivers/gpu/drm/i915/i915_drv.h | 19 +++++ drivers/gpu/drm/i915/i915_gem.c | 121 ++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/i915_sysfs.c | 8 ++ 3 files changed, 140 insertions(+), 8 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +19 -0
@@ -367,6 +367,20 @@ struct drm_i915_file_private {/** ban_score: Accumulated score of all ctx bans and fast hangs. */ atomic_t ban_score;unsigned long hang_timestamp; + +struct i915_drm_client { +unsigned int id; + +pid_t pid; +char *name; + +struct kobject *root; + +struct { +struct device_attribute pid; +struct device_attribute name; + } attr; + } client; };/* Interface history:
@@ -2171,6 +2185,11 @@ struct drm_i915_private {struct i915_pmu pmu; +struct i915_drm_clients { +struct kobject *root; +atomic_t serial; + } clients; +/* * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place.
drivers/gpu/drm/i915/i915_gem.c +113 -8
152 lines not on this page · raw message
drivers/gpu/drm/i915/i915_sysfs.c +8 -0
@@ -581,6 +581,11 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv)struct device *kdev = dev_priv->drm.primary->kdev;int ret; + dev_priv->clients.root = +kobject_create_and_add ("clients" , &kdev->kobj); +if (!dev_priv->clients.root) +DRM_ERROR ("Per-client sysfs setup failed\n" ); +#ifdef CONFIG_PM if (HAS_RC6 (dev_priv)) { ret = sysfs_merge_group(&kdev->kobj,
@@ -641,4 +646,7 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv)sysfs_unmerge_group (&kdev->kobj, &rc6_attr_group);sysfs_unmerge_group (&kdev->kobj, &rc6p_attr_group);#endif + +if (dev_priv->clients.root) +kobject_put (dev_priv->clients.root); }
Signature · 6 lines
2.17.1 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Tvrtko Ursulin
maintainerRFC 11/13 drm/i915: Update client name on context create
In reply to Tvrtko UrsulinFrom: Tvrtko Ursulin <[email protected]>
Some clients have the DRM fd passed to them over a socket by the X server.
Grab the real client and pid when they create their first context and update the exposed data for more useful enumeration.
--- drivers/gpu/drm/i915/i915_drv.h | 8 ++++++++ drivers/gpu/drm/i915/i915_gem.c | 4 ++-- drivers/gpu/drm/i915/i915_gem_context.c | 16 +++++++++++++--- 3 files changed, 23 insertions(+), 5 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +8 -0
@@ -3273,6 +3273,14 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,void i915_gem_object_unpin_from_display_plane (struct i915_vma *vma);int i915_gem_object_attach_phys (struct drm_i915_gem_object *obj,int align); + +int +i915_gem_add_client (struct drm_i915_private *i915, +struct drm_i915_file_private *file_priv, +struct task_struct *task, +unsigned int serial); +void i915_gem_remove_client (struct drm_i915_file_private *file_priv); +int i915_gem_open (struct drm_i915_private *i915,struct drm_file *file);void i915_gem_release (struct drm_device *dev,struct drm_file *file);
drivers/gpu/drm/i915/i915_gem.c +2 -2
@@ -5908,7 +5908,7 @@ show_client_pid(struct device *kdev, struct device_attribute *attr, char *buf)return snprintf (buf,PAGE_SIZE ,"%u" , file_priv->client.pid); } -static int +int i915_gem_add_client(struct drm_i915_private *i915, struct drm_i915_file_private *file_priv, struct task_struct *task,
@@ -5968,7 +5968,7 @@ i915_gem_add_client(struct drm_i915_private *i915,return ret; } -static void i915_gem_remove_client (struct drm_i915_file_private *file_priv) +void i915_gem_remove_client (struct drm_i915_file_private *file_priv) {sysfs_remove_file (file_priv->client.root, (struct attribute *)&file_priv->client.attr.pid);
drivers/gpu/drm/i915/i915_gem_context.c +13 -3
@@ -779,9 +779,10 @@ static bool client_is_banned(struct drm_i915_file_private *file_priv)int i915_gem_context_create_ioctl (struct drm_device *dev,void *data,struct drm_file *file) { +struct drm_i915_file_private *file_priv = file->driver_priv; +pid_t pid =pid_nr (get_task_pid (current,PIDTYPE_PID ));struct drm_i915_private *dev_priv =to_i915 (dev);struct drm_i915_gem_context_create *args = data; -struct drm_i915_file_private *file_priv = file->driver_priv;struct i915_gem_context *ctx;int ret;
@@ -793,8 +794,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,if (client_is_banned (file_priv)) {DRM_DEBUG ("client %s[%d] banned from creating ctx\n" , - current->comm, -pid_nr (get_task_pid (current,PIDTYPE_PID ))); + current->comm, pid);return -EIO ; }
@@ -803,6 +803,16 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,if (ret)return ret; +if (file_priv->client.pid != pid) { +i915_gem_remove_client (file_priv); + ret =i915_gem_add_client (dev_priv, file_priv, current, + file_priv->client.id); +if (ret) { +mutex_unlock (&dev->struct_mutex); +return ret; + } + } + ctx =i915_gem_create_context (dev_priv, file_priv);mutex_unlock (&dev->struct_mutex);if (IS_ERR (ctx))
Signature · 6 lines
2.17.1 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Tvrtko Ursulin
maintainerRFC 12/13 drm/i915: Expose per-engine client busyness
In reply to Tvrtko UrsulinFrom: Tvrtko Ursulin <[email protected]>
Expose per-client and per-engine busyness under the previously added sysfs client root.
The new files are one per-engine instance and located under the 'busy' directory.
Each contains a monotonically increasing nano-second resolution times each client's jobs were executing on the GPU.
$ cat /sys/class/drm/card0/clients/5/busy/rcs0 32516602
This data can serve as an interface to implement a top like utility for GPU jobs. For instance I have prototyped a tool in IGT which produces periodic output like:
neverball[ 6011]: rcs0: 41.01% bcs0: 0.00% vcs0: 0.00% vecs0: 0.00%
Xorg[ 5664]: rcs0: 31.16% bcs0: 0.00% vcs0: 0.00% vecs0: 0.00%
xfwm4[ 5727]: rcs0: 0.00% bcs0: 0.00% vcs0: 0.00% vecs0: 0.00%This tools can also be extended to use the i915 PMU and show overall engine busyness, and engine loads using the queue depth metric.
v2: Use intel_context_engine_get_busy_time.
v3: New directory structure.
v4: Rebase.
v5: sysfs_attr_init.
--- drivers/gpu/drm/i915/i915_drv.h | 8 ++++ drivers/gpu/drm/i915/i915_gem.c | 81 +++++++++++++++++++++++++++++++-- 2 files changed, 86 insertions(+), 3 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +8 -0
@@ -330,6 +330,12 @@ struct drm_i915_private;struct i915_mm_struct ;struct i915_mmu_object ; +struct i915_engine_busy_attribute { +struct device_attribute attr; +struct drm_i915_file_private *file_priv; +struct intel_engine_cs *engine; +}; +struct drm_i915_file_private {struct drm_i915_private *dev_priv;struct drm_file *file;
@@ -375,10 +381,12 @@ struct drm_i915_file_private {char *name;struct kobject *root; +struct kobject *busy_root;struct {struct device_attribute pid;struct device_attribute name; +struct i915_engine_busy_attribute busy[I915_NUM_ENGINES ]; } attr; } client; };
drivers/gpu/drm/i915/i915_gem.c +78 -3
120 lines not on this page · raw message
Signature · 6 lines
2.17.1 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Tvrtko Ursulin
maintainerRFC 13/13 drm/i915: Add sysfs toggle to enable per-client engine stats
In reply to Tvrtko UrsulinFrom: Tvrtko Ursulin <[email protected]>
By default we are not collecting any per-engine and per-context statistcs.
Add a new sysfs toggle to enable this facility:
$ echo 1 >/sys/class/drm/card0/clients/enable_stats
v2: Rebase.
v3: sysfs_attr_init.
--- drivers/gpu/drm/i915/i915_drv.h | 4 ++ drivers/gpu/drm/i915/i915_sysfs.c | 73 +++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+)
drivers/gpu/drm/i915/i915_drv.h +4 -0
@@ -2196,6 +2196,10 @@ struct drm_i915_private {struct i915_drm_clients {struct kobject *root;atomic_t serial; +struct { +bool enabled; +struct device_attribute attr; + } stats; } clients;/*
drivers/gpu/drm/i915/i915_sysfs.c +73 -0
94 lines not on this page · raw message
Signature · 6 lines
2.17.1 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Quoting Tvrtko Ursulin (2018-10-03 13:03:53)
Quoted 5 lines
From: Tvrtko Ursulin <[email protected]>
A collection of patches which I have been sending before, sometimes together and sometimes separately, which enable
intel_gpu_topto report queue depths (also translates as overall GPU load average) and per DRM client per engine busyness.
Queued falls apart with v.engine and I don't have a good suggestion for a remedy. :(
-Chris
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Quoted 9 lines · Chris Wilson
Quoting Tvrtko Ursulin (2018-10-03 13:03:53)
Quoted 5 lines
From: Tvrtko Ursulin <[email protected]>
A collection of patches which I have been sending before, sometimes together and sometimes separately, which enable
intel_gpu_topto report queue depths (also translates as overall GPU load average) and per DRM client per engine busyness.Queued falls apart with v.engine and I don't have a good suggestion for a remedy. :(
Indeed, I forgot about it. I have now even found a few months old branch with queued and runnable removed already.
I think we also talked about the option of exposing aggregate engine class counters but that also has problems.
We could go global and not expose this per engine, but that wouldn't make <gen11 users happy.
Regards,
Tvrtko
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Patchwork
CI✗ Fi.CI.BAT: failure for 21st century intel_gpu_top
In reply to Tvrtko Ursulin== Series Details ==
== Series Details ==
Series: 21st century intel_gpu_top
URL : https://patchwork.freedesktop.org/series/50498/
State : failure
== Summary ==
Applying: drm/i915/pmu: Fix enable count array size and bounds checking
Applying: drm/i915: Keep a count of requests waiting for a slot on GPU
Applying: drm/i915: Keep a count of requests submitted from userspace
Applying: drm/i915/pmu: Add queued counter
Applying: drm/i915/pmu: Add runnable counter
Applying: drm/i915/pmu: Add running counter
Applying: drm/i915: Store engine backpointer in the intel_context Using index info to reconstruct a base tree...
M drivers/gpu/drm/i915/i915_gem_context.h
Falling back to patching base and 3-way merge...
Auto-merging drivers/gpu/drm/i915/i915_gem_context.h
CONFLICT (content): Merge conflict in drivers/gpu/drm/i915/i915_gem_context.h
error: Failed to merge in the changes.
Patch failed at 0007 drm/i915: Store engine backpointer in the intel_context Use 'git am --show-current-patch' to see the failed patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Quoted 31 lines · Tvrtko Ursulin
From: Tvrtko Ursulin <[email protected]>
A collection of patches which I have been sending before, sometimes together and sometimes separately, which enable
intel_gpu_topto report queue depths (also translates as overall GPU load average) and per DRM client per engine busyness.This enables a fancy
intel_gpu_topwhich looks like this (a picture is worth a thousand words):intel-gpu-top - load avg 3.30, 1.51, 0.08; 949/ 949 MHz; 0% RC6; 14.66 Watts; 3605 irqs/s
IMC reads: 4651 MiB/s
IMC writes: 25 MiB/sENGINE BUSY Q r R
MI_SEMAMI_WAIT
Render/3D/0 61.51% |█████████████████████████████████████████████▌ | 3 0 1 0% 0%
Blitter/0 0.00% | | 0 0 0 0% 0%
Video/0 60.86% |█████████████████████████████████████████████ | 1 0 1 0% 0%
Video/1 59.04% |███████████████████████████████████████████▋ | 1 0 1 0% 0%
VideoEnhance/0 0.00% | | 0 0 0 0% 0%PID NAME Render/3D/0 Blitter/0 Video/0 Video/1 VideoEnhance/0
23373 gem_wsim |█████▎ || ||████████▍ ||█████▎ || | 23374 gem_wsim |███▉ || ||██▏ ||███ || | 23375 gem_wsim |███ || ||█▍ ||███▌ || |All of this work actually came to be via different feature requests not directly asking for this. Things like engine queue depth query and per context engine busyness ioctl. Those bits need userspace which is not there yet and so I have removed them from this posting to avoid confusion.
Quoted 4 lines
What remains is a set of patches which add some PMU counters and a completely new sysfs interface to enable
intel_gpu_topto read the per client stats.IGT counterpart will be sent separately.
FWIW at least one more person thinks this would be a nice to have feature - https://twitter.com/IntelGraphics/status/1047991913972826112. But it sure feels weird to cross-link twitter to intel-gfx! Sign of times.. :)
Regards,
Tvrtko
Quoted 16 lines
Tvrtko Ursulin (13):
drm/i915/pmu: Fix enable count array size and bounds checking drm/i915: Keep a count of requests waiting for a slot on GPU drm/i915: Keep a count of requests submitted from userspace drm/i915/pmu: Add queued counter
drm/i915/pmu: Add runnable counter
drm/i915/pmu: Add running counter
drm/i915: Store engine backpointer in theintel_contextdrm/i915: Move intel_engine_context_in/out intointel_lrc.cdrm/i915: Track per-context engine busyness drm/i915: Expose list of clients in sysfs
drm/i915: Update client name on context create drm/i915: Expose per-engine client busyness drm/i915: Add sysfs toggle to enable per-client engine stats
Quoted 13 lines
drivers/gpu/drm/i915/i915_drv.h | 39 +++++ drivers/gpu/drm/i915/i915_gem.c | 197 +++++++++++++++++++++++- drivers/gpu/drm/i915/i915_gem_context.c | 18 ++- drivers/gpu/drm/i915/i915_gem_context.h | 18 +++ drivers/gpu/drm/i915/i915_pmu.c | 103 +++++++++++-- drivers/gpu/drm/i915/i915_request.c | 10 ++ drivers/gpu/drm/i915/i915_sysfs.c | 81 ++++++++++ drivers/gpu/drm/i915/intel_engine_cs.c | 33 +++- drivers/gpu/drm/i915/intel_lrc.c | 109 ++++++++++++- drivers/gpu/drm/i915/intel_ringbuffer.h | 76 +++------ include/uapi/drm/i915_drm.h | 19 ++- 11 files changed, 614 insertions(+), 89 deletions(-)
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx