Skip to contentSkip to conversation

i915 PMU and engine busy stats

PATCH Superseded Tvrtko Ursulin 5 participants 26 messages Sep 29, 2017 – Oct 6, 2017

Subsystems (3)
lore
Share & tools
lore

Tvrtko Ursulin

author maintainer
#0 lore raw

v6 cover i915 PMU and engine busy stats

From: Tvrtko Ursulin <[email protected]>

Review feedback so far, plus re-organisation of the series to drop potentially not so interesting metrics into separate patches, at the end of the series.

Patche 1 is a small refactor to make the following work easier.

Patch 2 is the main bit.

Patch 3 is a small optimisation on top, to only run the sampling timer when it is required. (Depending on GPU awake status and active PMU counters.)

Patches 4-7 add software engine busyness tracking, which is then used from the PMU in patch 7. This allows more efficient and more accurate engine busyness metric.

Patches 8-10 add the RC6 and interrupt count metric.

Tvrtko Ursulin (10):
drm/i915: Extract intel_get_cagf
drm/i915/pmu: Expose a PMU interface for perf queries drm/i915/pmu: Suspend sampling when GPU is idle drm/i915: Wrap context schedule notification drm/i915: Engine busy time tracking drm/i915/pmu: Wire up engine busy stats to PMU drm/i915: Gate engine stats collection with a static key drm/i915/pmu: Add interrupt count metric drm/i915: Convert intel_rc6_residency_us to ns drm/i915/pmu: Add RC6 residency metrics

 drivers/gpu/drm/i915/Makefile           |   1 +
 drivers/gpu/drm/i915/i915_debugfs.c     |   9 +-
 drivers/gpu/drm/i915/i915_drv.c         |  15 +-
 drivers/gpu/drm/i915/i915_drv.h         |  33 +-
 drivers/gpu/drm/i915/i915_gem.c         |   1 +
 drivers/gpu/drm/i915/i915_gem_request.c |   1 +
 drivers/gpu/drm/i915/i915_pmu.c         | 862 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_pmu.h         | 100 ++++
 drivers/gpu/drm/i915/i915_reg.h         |   3 +
 drivers/gpu/drm/i915/i915_sysfs.c       |  20 +-
 drivers/gpu/drm/i915/intel_engine_cs.c  | 136 +++++
 drivers/gpu/drm/i915/intel_lrc.c        |  19 +-
 drivers/gpu/drm/i915/intel_pm.c         |  41 +-
 drivers/gpu/drm/i915/intel_ringbuffer.h | 148 ++++++
 include/uapi/drm/i915_drm.h             |  54 ++
 15 files changed, 1407 insertions(+), 36 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/i915_pmu.c
 create mode 100644 drivers/gpu/drm/i915/i915_pmu.h
Signature · 6 lines
2.9.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author maintainer
#1 lore raw

PATCH v6 1/10 drm/i915: Extract intel_get_cagf

From: Tvrtko Ursulin <[email protected]>

Code to be shared between debugfs and the PMU implementation.

v2: Checkpatch cleanup.
v3: Also consolidate i915_sysfs.c/gt_act_freq_mhz_show.
v4: Rebase.

---
 drivers/gpu/drm/i915/i915_debugfs.c |  9 ++-------
 drivers/gpu/drm/i915/i915_drv.h     |  2 ++
 drivers/gpu/drm/i915/i915_sysfs.c   | 11 +++--------
 drivers/gpu/drm/i915/intel_pm.c     | 14 ++++++++++++++
 4 files changed, 21 insertions(+), 15 deletions(-)
drivers/gpu/drm/i915/i915_debugfs.c +2 -7
index b4a6ac60e7c6..1d047a624ffa 100644
@@ -1113,13 +1113,8 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
 		rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI) & GEN6_CURIAVG_MASK;
 		rpcurdown = I915_READ(GEN6_RP_CUR_DOWN) & GEN6_CURBSYTAVG_MASK;
 		rpprevdown = I915_READ(GEN6_RP_PREV_DOWN) & GEN6_CURBSYTAVG_MASK;
-		if (INTEL_GEN(dev_priv) >= 9)
-			cagf = (rpstat & GEN9_CAGF_MASK) >> GEN9_CAGF_SHIFT;
-		else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
-			cagf = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT;
-		else
-			cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT;
-		cagf = intel_gpu_freq(dev_priv, cagf);
+		cagf = intel_gpu_freq(dev_priv,
+				      intel_get_cagf(dev_priv, rpstat));
 
 		intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
 
drivers/gpu/drm/i915/i915_drv.h +2 -0
index 7ca11318ac69..5c91ad6263a0 100644
@@ -4142,6 +4142,8 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val);
 u64 intel_rc6_residency_us(struct drm_i915_private *dev_priv,
 			   const i915_reg_t reg);
 
+u32 intel_get_cagf(struct drm_i915_private *dev_priv, u32 rpstat1);
+
 #define I915_READ8(reg)		dev_priv->uncore.funcs.mmio_readb(dev_priv, (reg), true)
 #define I915_WRITE8(reg, val)	dev_priv->uncore.funcs.mmio_writeb(dev_priv, (reg), (val), true)
 
drivers/gpu/drm/i915/i915_sysfs.c +3 -8
index d61c8727f756..3bcf1c8c0dd9 100644
@@ -252,14 +252,9 @@ static ssize_t gt_act_freq_mhz_show(struct device *kdev,
 		freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
 		ret = intel_gpu_freq(dev_priv, (freq >> 8) & 0xff);
 	} else {
-		u32 rpstat = I915_READ(GEN6_RPSTAT1);
-		if (INTEL_GEN(dev_priv) >= 9)
-			ret = (rpstat & GEN9_CAGF_MASK) >> GEN9_CAGF_SHIFT;
-		else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
-			ret = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT;
-		else
-			ret = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT;
-		ret = intel_gpu_freq(dev_priv, ret);
+		ret = intel_gpu_freq(dev_priv,
+				     intel_get_cagf(dev_priv,
+						    I915_READ(GEN6_RPSTAT1)));
 	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
drivers/gpu/drm/i915/intel_pm.c +14 -0
index c66af09e27a7..c682ae4c98e9 100644
@@ -9374,3 +9374,17 @@ u64 intel_rc6_residency_us(struct drm_i915_private *dev_priv,
 	intel_runtime_pm_put(dev_priv);
 	return DIV_ROUND_UP_ULL(time_hw * units, div);
 }
+
+u32 intel_get_cagf(struct drm_i915_private *dev_priv, u32 rpstat)
+{
+	u32 cagf;
+
+	if (INTEL_GEN(dev_priv) >= 9)
+		cagf = (rpstat & GEN9_CAGF_MASK) >> GEN9_CAGF_SHIFT;
+	else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
+		cagf = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT;
+	else
+		cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT;
+
+	return  cagf;
+}
Signature · 6 lines
2.9.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author maintainer
#2 lore raw

PATCH v6 2/10 drm/i915/pmu: Expose a PMU interface for perf queries

In reply to Tvrtko Ursulin

From: Tvrtko Ursulin <[email protected]>

From: Chris Wilson <[email protected]>
From: Tvrtko Ursulin <[email protected]>
From: Dmitry Rogozhkin <[email protected]>

The first goal is to be able to measure GPU (and invidual ring) busyness without having to poll registers from userspace. (Which not only incurs holding the forcewake lock indefinitely, perturbing the system, but also runs the risk of hanging the machine.) As an alternative we can use the perf event counter interface to sample the ring registers periodically and send those results to userspace.

Functionality we are exporting to userspace is via the existing perf PMU API and can be exercised via the existing tools. For example:

perf stat -a -e i915/rcs0-busy/ -I 1000

Will print the render engine busynnes once per second. All the performance counters can be enumerated (perf list) and have their unit of measure correctly reported in sysfs.

v1-v2 (Chris Wilson):

v2: Use a common timer for the ring sampling.

v3: (Tvrtko Ursulin)
* Decouple uAPI from i915 engine ids.
* Complete uAPI defines.
* Refactor some code to helpers for clarity.
* Skip sampling disabled engines.
* Expose counters in sysfs.
* Pass in fake regs to avoid null ptr deref in perf core.
* Convert to class/instance uAPI.
* Use shared driver code for rc6 residency, power and frequency.

v4: (Dmitry Rogozhkin)
* Register PMU with .task_ctx_nr=perf_invalid_context
* Expose cpumask for the PMU with the single CPU in the mask
* Properly support pmu->stop(): it should call pmu->read()
* Properly support pmu->del(): it should call stop(event, PERF_EF_UPDATE)
* Introduce refcounting of event subscriptions.
* Make pmu.busy_stats a refcounter to avoid busy stats going away with some deleted event.
* Expose cpumask for i915 PMU to avoid multiple events creation of the same type followed by counter aggregation by perf-stat.
* Track CPUs getting online/offline to migrate perf context. If (likely) cpumask will initially set CPU0, CONFIG_BOOTPARAM_HOTPLUG_CPU0 will be needed to see effect of CPU status tracking.
* End result is that only global events are supported and perf stat works correctly.
* Deny perf driver level sampling - it is prohibited for uncore PMU.

v5: (Tvrtko Ursulin)

* Don't hardcode number of engine samplers.
* Rewrite event ref-counting for correctness and simplicity.
* Store initial counter value when starting already enabled events to correctly report values to all listeners.
* Fix RC6 residency readout.
* Comments, GPL header.

v6:
* Add missing entry to v4 changelog.
* Fix accounting in CPU hotplug case by copying the approach from arch/x86/events/intel/cstate.c. (Dmitry Rogozhkin)

v7:
* Log failure message only on failure.
* Remove CPU hotplug notification state on unregister.

v8:
* Fix error unwind on failed registration.
* Checkpatch cleanup.

v9:
* Drop the energy metric, it is available via intel_rapl_perf. (Ville Syrjälä)
* Use HAS_RC6(p). (Chris Wilson)
* Handle unsupported non-engine events. (Dmitry Rogozhkin)
* Rebase for intel_rc6_residency_ns needing caller managed runtime pm.
* Drop HAS_RC6 checks from the read callback since creating those events will be rejected at init time already.
* Add counter units to sysfs so perf stat output is nicer.
* Cleanup the attribute tables for brevity and readability.

v10:
* Fixed queued accounting.

v11:
* Move intel_engine_lookup_user to intel_engine_cs.c
* Commit update. (Joonas Lahtinen)

v12:
* More accurate sampling. (Chris Wilson)
* Store and report frequency in MHz for better usability from perf stat.
* Removed metrics: queued, interrupts, rc6 counters.
* Sample engine busyness based on seqno difference only for less MMIO (and forcewake) on all platforms. (Chris Wilson)

Cc Tvrtko Ursulin <[email protected]>
Cc Chris Wilson <[email protected]>
Cc Dmitry Rogozhkin <[email protected]>
Cc Peter Zijlstra <[email protected]>
---
 drivers/gpu/drm/i915/Makefile           |   1 +
 drivers/gpu/drm/i915/i915_drv.c         |   2 +
 drivers/gpu/drm/i915/i915_drv.h         |  14 +
 drivers/gpu/drm/i915/i915_pmu.c         | 658 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_pmu.h         |  96 +++++
 drivers/gpu/drm/i915/i915_reg.h         |   3 +
 drivers/gpu/drm/i915/intel_engine_cs.c  |  35 ++
 drivers/gpu/drm/i915/intel_ringbuffer.h |  26 ++
 include/uapi/drm/i915_drm.h             |  48 +++
 9 files changed, 883 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/i915_pmu.c
 create mode 100644 drivers/gpu/drm/i915/i915_pmu.h
drivers/gpu/drm/i915/Makefile +1 -0
index 5182e3d5557d..5c6013961b3b 100644
@@ -26,6 +26,7 @@ i915-y := i915_drv.o \
 
 i915-$(CONFIG_COMPAT)   += i915_ioc32.o
 i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o intel_pipe_crc.o
+i915-$(CONFIG_PERF_EVENTS) += i915_pmu.o
 
 # GEM code
 i915-y += i915_cmd_parser.o \
drivers/gpu/drm/i915/i915_drv.c +2 -0
index 59ac9199b35d..187c0fad1b79 100644
@@ -1204,6 +1204,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
 	struct drm_device *dev = &dev_priv->drm;
 
 	i915_gem_shrinker_init(dev_priv);
+	i915_pmu_register(dev_priv);
 
 	/*
 	 * Notify a valid surface after modesetting,
@@ -1258,6 +1259,7 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
 	intel_opregion_unregister(dev_priv);
 
 	i915_perf_unregister(dev_priv);
+	i915_pmu_unregister(dev_priv);
 
 	i915_teardown_sysfs(dev_priv);
 	i915_guc_log_unregister(dev_priv);
drivers/gpu/drm/i915/i915_drv.h +14 -0
index 5c91ad6263a0..1f3fa46e10d3 100644
@@ -40,6 +40,7 @@
 #include <linux/hash.h>
 #include <linux/intel-iommu.h>
 #include <linux/kref.h>
+#include <linux/perf_event.h>
 #include <linux/pm_qos.h>
 #include <linux/reservation.h>
 #include <linux/shmem_fs.h>
@@ -2253,6 +2254,8 @@ struct drm_i915_private {
 	struct pci_dev *bridge_dev;
 	struct i915_gem_context *kernel_context;
 	struct intel_engine_cs *engine[I915_NUM_ENGINES];
+	struct intel_engine_cs *engine_class[MAX_ENGINE_CLASS + 1]
+					    [MAX_ENGINE_INSTANCE + 1];
 	struct i915_vma *semaphore;
 
 	struct drm_dma_handle *status_page_dmah;
@@ -2715,6 +2718,8 @@ struct drm_i915_private {
 		int	irq;
 	} lpe_audio;
 
+	struct i915_pmu pmu;
+
 	/*
 	 * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
 	 * will be rejected. Instead look for a better place.
@@ -3943,6 +3948,15 @@ extern void i915_perf_fini(struct drm_i915_private *dev_priv);
 extern void i915_perf_register(struct drm_i915_private *dev_priv);
 extern void i915_perf_unregister(struct drm_i915_private *dev_priv);
 
+/* i915_pmu.c */
+#ifdef CONFIG_PERF_EVENTS
+void i915_pmu_register(struct drm_i915_private *i915);
+void i915_pmu_unregister(struct drm_i915_private *i915);
+#else
+static inline void i915_pmu_register(struct drm_i915_private *i915) {}
+static inline void i915_pmu_unregister(struct drm_i915_private *i915) {}
+#endif
+
 /* i915_suspend.c */
 extern int i915_save_state(struct drm_i915_private *dev_priv);
 extern int i915_restore_state(struct drm_i915_private *dev_priv);
drivers/gpu/drm/i915/i915_pmu.c new file +658 -0

658 lines not on this page · raw message

drivers/gpu/drm/i915/i915_pmu.h new file +96 -0

96 lines not on this page · raw message

drivers/gpu/drm/i915/i915_reg.h +3 -0
index ee0d4f14ac98..74af7a633fcb 100644
@@ -186,6 +186,9 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
 #define VIDEO_ENHANCEMENT_CLASS	2
 #define COPY_ENGINE_CLASS	3
 #define OTHER_CLASS		4
+#define MAX_ENGINE_CLASS	4
+
+#define MAX_ENGINE_INSTANCE    1
 
 /* PCI config space */
 
drivers/gpu/drm/i915/intel_engine_cs.c +35 -0
index a28e2a864cf1..35c117c3fa0d 100644
@@ -200,6 +200,15 @@ intel_engine_setup(struct drm_i915_private *dev_priv,
 	GEM_BUG_ON(info->class >= ARRAY_SIZE(intel_engine_classes));
 	class_info = &intel_engine_classes[info->class];
 
+	if (GEM_WARN_ON(info->class > MAX_ENGINE_CLASS))
+		return -EINVAL;
+
+	if (GEM_WARN_ON(info->instance > MAX_ENGINE_INSTANCE))
+		return -EINVAL;
+
+	if (GEM_WARN_ON(dev_priv->engine_class[info->class][info->instance]))
+		return -EINVAL;
+
 	GEM_BUG_ON(dev_priv->engine[id]);
 	engine = kzalloc(sizeof(*engine), GFP_KERNEL);
 	if (!engine)
@@ -227,6 +236,7 @@ intel_engine_setup(struct drm_i915_private *dev_priv,
 
 	ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier);
 
+	dev_priv->engine_class[info->class][info->instance] = engine;
 	dev_priv->engine[id] = engine;
 	return 0;
 }
@@ -1578,6 +1588,31 @@ bool intel_engine_can_store_dword(struct intel_engine_cs *engine)
 	}
 }
 
+static u8 user_class_map[I915_ENGINE_CLASS_MAX] = {
+	[I915_ENGINE_CLASS_OTHER] = OTHER_CLASS,
+	[I915_ENGINE_CLASS_RENDER] = RENDER_CLASS,
+	[I915_ENGINE_CLASS_COPY] = COPY_ENGINE_CLASS,
+	[I915_ENGINE_CLASS_VIDEO] = VIDEO_DECODE_CLASS,
+	[I915_ENGINE_CLASS_VIDEO_ENHANCE] = VIDEO_ENHANCEMENT_CLASS,
+};
+
+struct intel_engine_cs *
+intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance)
+{
+	if (class >= ARRAY_SIZE(user_class_map))
+		return NULL;
+
+	class = user_class_map[class];
+
+	if (WARN_ON_ONCE(class > MAX_ENGINE_CLASS))
+		return NULL;
+
+	if (instance > MAX_ENGINE_INSTANCE)
+		return NULL;
+
+	return i915->engine_class[class][instance];
+}
+
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftests/mock_engine.c"
 #endif
drivers/gpu/drm/i915/intel_ringbuffer.h +26 -0
index 56d7ae9f298b..7e07ec1bfed1 100644
@@ -5,6 +5,7 @@
 #include "i915_gem_batch_pool.h"
 #include "i915_gem_request.h"
 #include "i915_gem_timeline.h"
+#include "i915_pmu.h"
 #include "i915_selftest.h"
 
 #define I915_CMD_HASH_ORDER 9
@@ -330,6 +331,28 @@ struct intel_engine_cs {
 		I915_SELFTEST_DECLARE(bool mock : 1);
 	} breadcrumbs;
 
+	struct {
+		/**
+		 * @enable: Bitmask of enable sample events on this engine.
+		 *
+		 * Bits correspond to sample event types, for instance
+		 * I915_SAMPLE_QUEUED is bit 0 etc.
+		 */
+		u32 enable;
+		/**
+		 * @enable_count: Reference count for the enabled samplers.
+		 *
+		 * Index number corresponds to the bit number from @enable.
+		 */
+		unsigned int enable_count[I915_PMU_SAMPLE_BITS];
+		/**
+		 * @sample: Counter values for sampling events.
+		 *
+		 * Our internal timer stores the current counters in this field.
+		 */
+		struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX];
+	} pmu;
+
 	/*
 	 * A pool of objects to use as shadow copies of client batch buffers
 	 * when the command parser is enabled. Prevents the client from
@@ -834,4 +857,7 @@ void intel_engines_reset_default_submission(struct drm_i915_private *i915);
 
 bool intel_engine_can_store_dword(struct intel_engine_cs *engine);
 
+struct intel_engine_cs *
+intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance);
+
 #endif /* _INTEL_RINGBUFFER_H_ */
include/uapi/drm/i915_drm.h +48 -0

54 lines not on this page · raw message

Signature · 6 lines
2.9.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Reviewed-by on v6 2/10
#3 lore raw

Re: [PATCH 02/10] drm/i915/pmu: Expose a PMU interface for perf queries

Quoting Tvrtko Ursulin (2017-09-29 13:34:52)

Quoted 110 lines

From: Tvrtko Ursulin <[email protected]>

From: Chris Wilson <[email protected]>
From: Tvrtko Ursulin <[email protected]>
From: Dmitry Rogozhkin <[email protected]>

The first goal is to be able to measure GPU (and invidual ring) busyness without having to poll registers from userspace. (Which not only incurs holding the forcewake lock indefinitely, perturbing the system, but also runs the risk of hanging the machine.) As an alternative we can use the perf event counter interface to sample the ring registers periodically and send those results to userspace.

Functionality we are exporting to userspace is via the existing perf PMU API and can be exercised via the existing tools. For example:

perf stat -a -e i915/rcs0-busy/ -I 1000

Will print the render engine busynnes once per second. All the performance counters can be enumerated (perf list) and have their unit of measure correctly reported in sysfs.

v1-v2 (Chris Wilson):

v2: Use a common timer for the ring sampling.

v3: (Tvrtko Ursulin)
* Decouple uAPI from i915 engine ids.
* Complete uAPI defines.
* Refactor some code to helpers for clarity.
* Skip sampling disabled engines.
* Expose counters in sysfs.
* Pass in fake regs to avoid null ptr deref in perf core.
* Convert to class/instance uAPI.
* Use shared driver code for rc6 residency, power and frequency.

v4: (Dmitry Rogozhkin)
* Register PMU with .task_ctx_nr=perf_invalid_context
* Expose cpumask for the PMU with the single CPU in the mask
* Properly support pmu->stop(): it should call pmu->read()
* Properly support pmu->del(): it should call stop(event, PERF_EF_UPDATE)
* Introduce refcounting of event subscriptions.
* Make pmu.busy_stats a refcounter to avoid busy stats going away with some deleted event.
* Expose cpumask for i915 PMU to avoid multiple events creation of the same type followed by counter aggregation by perf-stat.
* Track CPUs getting online/offline to migrate perf context. If (likely) cpumask will initially set CPU0, CONFIG_BOOTPARAM_HOTPLUG_CPU0 will be needed to see effect of CPU status tracking.
* End result is that only global events are supported and perf stat works correctly.
* Deny perf driver level sampling - it is prohibited for uncore PMU.

v5: (Tvrtko Ursulin)

* Don't hardcode number of engine samplers.
* Rewrite event ref-counting for correctness and simplicity.
* Store initial counter value when starting already enabled events to correctly report values to all listeners.
* Fix RC6 residency readout.
* Comments, GPL header.

v6:
* Add missing entry to v4 changelog.
* Fix accounting in CPU hotplug case by copying the approach from arch/x86/events/intel/cstate.c. (Dmitry Rogozhkin)

v7:
* Log failure message only on failure.
* Remove CPU hotplug notification state on unregister.

v8:
* Fix error unwind on failed registration.
* Checkpatch cleanup.

v9:
* Drop the energy metric, it is available via intel_rapl_perf. (Ville Syrjälä)
* Use HAS_RC6(p). (Chris Wilson)
* Handle unsupported non-engine events. (Dmitry Rogozhkin)
* Rebase for intel_rc6_residency_ns needing caller managed runtime pm.
* Drop HAS_RC6 checks from the read callback since creating those events will be rejected at init time already.
* Add counter units to sysfs so perf stat output is nicer.
* Cleanup the attribute tables for brevity and readability.

v10:
* Fixed queued accounting.

v11:
* Move intel_engine_lookup_user to intel_engine_cs.c
* Commit update. (Joonas Lahtinen)

v12:
* More accurate sampling. (Chris Wilson)
* Store and report frequency in MHz for better usability from perf stat.
* Removed metrics: queued, interrupts, rc6 counters.
* Sample engine busyness based on seqno difference only for less MMIO (and forcewake) on all platforms. (Chris Wilson)

Cc Tvrtko Ursulin <[email protected]>
Cc Chris Wilson <[email protected]>
Cc Dmitry Rogozhkin <[email protected]>
Cc Peter Zijlstra <[email protected]>

---

drivers/gpu/drm/i915/i915_pmu.c line 105

Quoted 5 lines
drivers/gpu/drm/i915/i915_pmu.c new file +5 -0
+static void
+update_sample(struct i915_pmu_sample *sample, u32 unit, u32 val)
+{
+       /*
+        * Since we are doing stohastical sampling for these counter,

stochastic

drivers/gpu/drm/i915/i915_pmu.c line 108

Quoted 3 lines
drivers/gpu/drm/i915/i915_pmu.c new file +3 -0
+        * average the delta with the previous value for better accuracy.
+        */
+       sample->cur += div_u64((u64)(sample->prev + val) * unit, 2);

div_u64(mul_32_32(sample->prev + val, unit), 2)

Quoted 17 lines
drivers/gpu/drm/i915/i915_pmu.c new file +17 -0
+       sample->prev = val;
+}
+
+static void engines_sample(struct drm_i915_private *dev_priv)
+{
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+       bool fw = false;
+
+       if ((dev_priv->pmu.enable & ENGINE_SAMPLE_MASK) == 0)
+               return;
+
+       if (!dev_priv->gt.awake)
+               return;
+
+       if (!intel_runtime_pm_get_if_in_use(dev_priv))
+               return;

drivers/gpu/drm/i915/i915_pmu.c line 135

Quoted 10 lines
drivers/gpu/drm/i915/i915_pmu.c new file +10 -0
+
+       for_each_engine(engine, dev_priv, id) {
+               u32 current_seqno = intel_engine_get_seqno(engine);
+               u32 last_seqno = intel_engine_last_submit(engine);
+               u32 val;
+
+               val = !i915_seqno_passed(current_seqno, last_seqno);
+
+               update_sample(&engine->pmu.sample[I915_SAMPLE_BUSY], PERIOD,
+                             val);

Personally I think

	update_sample(&engine->pmu.sample[I915_SAMPLE_BUSY],
		      PERIOD, val);

carries better visual weighting.

Quoted 11 lines
drivers/gpu/drm/i915/i915_pmu.c new file +11 -0
+
+               if (val && (engine->pmu.enable &
+                   (BIT(I915_SAMPLE_WAIT) | BIT(I915_SAMPLE_SEMA)))) {
+                       fw = grab_forcewake(dev_priv, fw);
+
+                       val = I915_READ_FW(RING_CTL(engine->mmio_base));
+               } else {
+                       val = 0;
+               }
+
+               update_sample(&engine->pmu.sample[I915_SAMPLE_WAIT], PERIOD,

drivers/gpu/drm/i915/i915_pmu.c line 156

Quoted 10 lines
drivers/gpu/drm/i915/i915_pmu.c new file +10 -0
+                             !!(val & RING_WAIT));
+
+               update_sample(&engine->pmu.sample[I915_SAMPLE_SEMA], PERIOD,
+                             !!(val & RING_WAIT_SEMAPHORE));
+       }
+
+       if (fw)
+               intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
+
+       intel_runtime_pm_put(dev_priv);

Ok.

Quoted 15 lines
drivers/gpu/drm/i915/i915_pmu.c new file +15 -0
+}
+
+static void frequency_sample(struct drm_i915_private *dev_priv)
+{
+       if (dev_priv->pmu.enable &
+           config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY)) {
+               u32 val;
+
+               val = dev_priv->rps.cur_freq;
+               if (dev_priv->gt.awake &&
+                   intel_runtime_pm_get_if_in_use(dev_priv)) {
+                       val = intel_get_cagf(dev_priv,
+                                            I915_READ_NOTRACE(GEN6_RPSTAT1));
+                       intel_runtime_pm_put(dev_priv);
+               }

drivers/gpu/drm/i915/i915_pmu.c line 181

Quoted 10 lines
drivers/gpu/drm/i915/i915_pmu.c new file +10 -0
+
+               update_sample(&dev_priv->pmu.sample[__I915_SAMPLE_FREQ_ACT], 1,
+                             intel_gpu_freq(dev_priv, val));
+       }
+
+       if (dev_priv->pmu.enable &
+           config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY)) {
+               update_sample(&dev_priv->pmu.sample[__I915_SAMPLE_FREQ_REQ], 1,
+                             intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq));
+       }

Ok.

Quoted 1 line

+}

Looks good as the introductory set of counters. I trust the improvements to the perf_event integration are good (as you can tell from the earlier patch, I have no idea what I'm doing there ;)

-Chris

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

author maintainer
#4 lore raw

PATCH v13 2/10 drm/i915/pmu: Expose a PMU interface for perf queries

From: Tvrtko Ursulin <[email protected]>

From: Chris Wilson <[email protected]>
From: Tvrtko Ursulin <[email protected]>
From: Dmitry Rogozhkin <[email protected]>

The first goal is to be able to measure GPU (and invidual ring) busyness without having to poll registers from userspace. (Which not only incurs holding the forcewake lock indefinitely, perturbing the system, but also runs the risk of hanging the machine.) As an alternative we can use the perf event counter interface to sample the ring registers periodically and send those results to userspace.

Functionality we are exporting to userspace is via the existing perf PMU API and can be exercised via the existing tools. For example:

perf stat -a -e i915/rcs0-busy/ -I 1000

Will print the render engine busynnes once per second. All the performance counters can be enumerated (perf list) and have their unit of measure correctly reported in sysfs.

v1-v2 (Chris Wilson):

v2: Use a common timer for the ring sampling.

v3: (Tvrtko Ursulin)
* Decouple uAPI from i915 engine ids.
* Complete uAPI defines.
* Refactor some code to helpers for clarity.
* Skip sampling disabled engines.
* Expose counters in sysfs.
* Pass in fake regs to avoid null ptr deref in perf core.
* Convert to class/instance uAPI.
* Use shared driver code for rc6 residency, power and frequency.

v4: (Dmitry Rogozhkin)
* Register PMU with .task_ctx_nr=perf_invalid_context
* Expose cpumask for the PMU with the single CPU in the mask
* Properly support pmu->stop(): it should call pmu->read()
* Properly support pmu->del(): it should call stop(event, PERF_EF_UPDATE)
* Introduce refcounting of event subscriptions.
* Make pmu.busy_stats a refcounter to avoid busy stats going away with some deleted event.
* Expose cpumask for i915 PMU to avoid multiple events creation of the same type followed by counter aggregation by perf-stat.
* Track CPUs getting online/offline to migrate perf context. If (likely) cpumask will initially set CPU0, CONFIG_BOOTPARAM_HOTPLUG_CPU0 will be needed to see effect of CPU status tracking.
* End result is that only global events are supported and perf stat works correctly.
* Deny perf driver level sampling - it is prohibited for uncore PMU.

v5: (Tvrtko Ursulin)

* Don't hardcode number of engine samplers.
* Rewrite event ref-counting for correctness and simplicity.
* Store initial counter value when starting already enabled events to correctly report values to all listeners.
* Fix RC6 residency readout.
* Comments, GPL header.

v6:
* Add missing entry to v4 changelog.
* Fix accounting in CPU hotplug case by copying the approach from arch/x86/events/intel/cstate.c. (Dmitry Rogozhkin)

v7:
* Log failure message only on failure.
* Remove CPU hotplug notification state on unregister.

v8:
* Fix error unwind on failed registration.
* Checkpatch cleanup.

v9:
* Drop the energy metric, it is available via intel_rapl_perf. (Ville Syrjälä)
* Use HAS_RC6(p). (Chris Wilson)
* Handle unsupported non-engine events. (Dmitry Rogozhkin)
* Rebase for intel_rc6_residency_ns needing caller managed runtime pm.
* Drop HAS_RC6 checks from the read callback since creating those events will be rejected at init time already.
* Add counter units to sysfs so perf stat output is nicer.
* Cleanup the attribute tables for brevity and readability.

v10:
* Fixed queued accounting.

v11:
* Move intel_engine_lookup_user to intel_engine_cs.c
* Commit update. (Joonas Lahtinen)

v12:
* More accurate sampling. (Chris Wilson)
* Store and report frequency in MHz for better usability from perf stat.
* Removed metrics: queued, interrupts, rc6 counters.
* Sample engine busyness based on seqno difference only for less MMIO (and forcewake) on all platforms. (Chris Wilson)

v13:
* Comment spelling, use mul_u32_u32 to work around potential GCC issue and somne code alignment changes. (Chris Wilson)

---
 drivers/gpu/drm/i915/Makefile           |   1 +
 drivers/gpu/drm/i915/i915_drv.c         |   2 +
 drivers/gpu/drm/i915/i915_drv.h         |  14 +
 drivers/gpu/drm/i915/i915_pmu.c         | 658 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_pmu.h         |  96 +++++
 drivers/gpu/drm/i915/i915_reg.h         |   3 +
 drivers/gpu/drm/i915/intel_engine_cs.c  |  35 ++
 drivers/gpu/drm/i915/intel_ringbuffer.h |  26 ++
 include/uapi/drm/i915_drm.h             |  48 +++
 9 files changed, 883 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/i915_pmu.c
 create mode 100644 drivers/gpu/drm/i915/i915_pmu.h
drivers/gpu/drm/i915/Makefile +1 -0
index 4850f260aead..d70d9b2602bc 100644
@@ -26,6 +26,7 @@ i915-y := i915_drv.o \
 
 i915-$(CONFIG_COMPAT)   += i915_ioc32.o
 i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o intel_pipe_crc.o
+i915-$(CONFIG_PERF_EVENTS) += i915_pmu.o
 
 # GEM code
 i915-y += i915_cmd_parser.o \
drivers/gpu/drm/i915/i915_drv.c +2 -0
index 66fc156b294a..d373a840566a 100644
@@ -1215,6 +1215,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
 	struct drm_device *dev = &dev_priv->drm;
 
 	i915_gem_shrinker_init(dev_priv);
+	i915_pmu_register(dev_priv);
 
 	/*
 	 * Notify a valid surface after modesetting,
@@ -1269,6 +1270,7 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
 	intel_opregion_unregister(dev_priv);
 
 	i915_perf_unregister(dev_priv);
+	i915_pmu_unregister(dev_priv);
 
 	i915_teardown_sysfs(dev_priv);
 	i915_guc_log_unregister(dev_priv);
drivers/gpu/drm/i915/i915_drv.h +14 -0
index c778f00d223a..339f5a88adc4 100644
@@ -40,6 +40,7 @@
 #include <linux/hash.h>
 #include <linux/intel-iommu.h>
 #include <linux/kref.h>
+#include <linux/perf_event.h>
 #include <linux/pm_qos.h>
 #include <linux/reservation.h>
 #include <linux/shmem_fs.h>
@@ -2259,6 +2260,8 @@ struct drm_i915_private {
 	struct i915_gem_context *kernel_context;
 	/* Context only to be used for injecting preemption commands */
 	struct i915_gem_context *preempt_context;
+	struct intel_engine_cs *engine_class[MAX_ENGINE_CLASS + 1]
+					    [MAX_ENGINE_INSTANCE + 1];
 	struct i915_vma *semaphore;
 
 	struct drm_dma_handle *status_page_dmah;
@@ -2721,6 +2724,8 @@ struct drm_i915_private {
 		int	irq;
 	} lpe_audio;
 
+	struct i915_pmu pmu;
+
 	/*
 	 * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
 	 * will be rejected. Instead look for a better place.
@@ -3949,6 +3954,15 @@ extern void i915_perf_fini(struct drm_i915_private *dev_priv);
 extern void i915_perf_register(struct drm_i915_private *dev_priv);
 extern void i915_perf_unregister(struct drm_i915_private *dev_priv);
 
+/* i915_pmu.c */
+#ifdef CONFIG_PERF_EVENTS
+void i915_pmu_register(struct drm_i915_private *i915);
+void i915_pmu_unregister(struct drm_i915_private *i915);
+#else
+static inline void i915_pmu_register(struct drm_i915_private *i915) {}
+static inline void i915_pmu_unregister(struct drm_i915_private *i915) {}
+#endif
+
 /* i915_suspend.c */
 extern int i915_save_state(struct drm_i915_private *dev_priv);
 extern int i915_restore_state(struct drm_i915_private *dev_priv);
drivers/gpu/drm/i915/i915_pmu.c new file +658 -0

658 lines not on this page · raw message

drivers/gpu/drm/i915/i915_pmu.h new file +96 -0

96 lines not on this page · raw message

drivers/gpu/drm/i915/i915_reg.h +3 -0
index e7dba5539b11..436cff9202f6 100644
@@ -186,6 +186,9 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
 #define VIDEO_ENHANCEMENT_CLASS	2
 #define COPY_ENGINE_CLASS	3
 #define OTHER_CLASS		4
+#define MAX_ENGINE_CLASS	4
+
+#define MAX_ENGINE_INSTANCE    1
 
 /* PCI config space */
 
drivers/gpu/drm/i915/intel_engine_cs.c +35 -0
index 8b8053d8e24b..867036cc8207 100644
@@ -200,6 +200,15 @@ intel_engine_setup(struct drm_i915_private *dev_priv,
 	GEM_BUG_ON(info->class >= ARRAY_SIZE(intel_engine_classes));
 	class_info = &intel_engine_classes[info->class];
 
+	if (GEM_WARN_ON(info->class > MAX_ENGINE_CLASS))
+		return -EINVAL;
+
+	if (GEM_WARN_ON(info->instance > MAX_ENGINE_INSTANCE))
+		return -EINVAL;
+
+	if (GEM_WARN_ON(dev_priv->engine_class[info->class][info->instance]))
+		return -EINVAL;
+
 	GEM_BUG_ON(dev_priv->engine[id]);
 	engine = kzalloc(sizeof(*engine), GFP_KERNEL);
 	if (!engine)
@@ -227,6 +236,7 @@ intel_engine_setup(struct drm_i915_private *dev_priv,
 
 	ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier);
 
+	dev_priv->engine_class[info->class][info->instance] = engine;
 	dev_priv->engine[id] = engine;
 	return 0;
 }
@@ -1616,6 +1626,31 @@ bool intel_engine_can_store_dword(struct intel_engine_cs *engine)
 	}
 }
 
+static u8 user_class_map[I915_ENGINE_CLASS_MAX] = {
+	[I915_ENGINE_CLASS_OTHER] = OTHER_CLASS,
+	[I915_ENGINE_CLASS_RENDER] = RENDER_CLASS,
+	[I915_ENGINE_CLASS_COPY] = COPY_ENGINE_CLASS,
+	[I915_ENGINE_CLASS_VIDEO] = VIDEO_DECODE_CLASS,
+	[I915_ENGINE_CLASS_VIDEO_ENHANCE] = VIDEO_ENHANCEMENT_CLASS,
+};
+
+struct intel_engine_cs *
+intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance)
+{
+	if (class >= ARRAY_SIZE(user_class_map))
+		return NULL;
+
+	class = user_class_map[class];
+
+	if (WARN_ON_ONCE(class > MAX_ENGINE_CLASS))
+		return NULL;
+
+	if (instance > MAX_ENGINE_INSTANCE)
+		return NULL;
+
+	return i915->engine_class[class][instance];
+}
+
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftests/mock_engine.c"
 #endif
drivers/gpu/drm/i915/intel_ringbuffer.h +26 -0
index 0fedda17488c..b84fc610a6c1 100644
@@ -5,6 +5,7 @@
 #include "i915_gem_batch_pool.h"
 #include "i915_gem_request.h"
 #include "i915_gem_timeline.h"
+#include "i915_pmu.h"
 #include "i915_selftest.h"
 
 #define I915_CMD_HASH_ORDER 9
@@ -335,6 +336,28 @@ struct intel_engine_cs {
 		I915_SELFTEST_DECLARE(bool mock : 1);
 	} breadcrumbs;
 
+	struct {
+		/**
+		 * @enable: Bitmask of enable sample events on this engine.
+		 *
+		 * Bits correspond to sample event types, for instance
+		 * I915_SAMPLE_QUEUED is bit 0 etc.
+		 */
+		u32 enable;
+		/**
+		 * @enable_count: Reference count for the enabled samplers.
+		 *
+		 * Index number corresponds to the bit number from @enable.
+		 */
+		unsigned int enable_count[I915_PMU_SAMPLE_BITS];
+		/**
+		 * @sample: Counter values for sampling events.
+		 *
+		 * Our internal timer stores the current counters in this field.
+		 */
+		struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX];
+	} pmu;
+
 	/*
 	 * A pool of objects to use as shadow copies of client batch buffers
 	 * when the command parser is enabled. Prevents the client from
@@ -839,4 +862,7 @@ void intel_engines_reset_default_submission(struct drm_i915_private *i915);
 
 bool intel_engine_can_store_dword(struct intel_engine_cs *engine);
 
+struct intel_engine_cs *
+intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance);
+
 #endif /* _INTEL_RINGBUFFER_H_ */
include/uapi/drm/i915_drm.h +48 -0

54 lines not on this page · raw message

Signature · 6 lines
2.9.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author maintainer
#5 lore raw

PATCH v6 3/10 drm/i915/pmu: Suspend sampling when GPU is idle

In reply to Tvrtko Ursulin

From: Tvrtko Ursulin <[email protected]>

If only a subset of events is enabled we can afford to suspend the sampling timer when the GPU is idle and so save some cycles and power.

v2: Rebase and limit timer even more.
v3: Rebase.
v4: Rebase.
v5: Skip action if perf PMU failed to register.
v6: Checkpatch cleanup.
v7:
* Add a common helper to start the timer if needed. (Chris Wilson)
* Add comment explaining bitwise logic in pmu_needs_timer.
v8: Fix some comments styles. (Chris Wilson)
v9: Rebase.

---
 drivers/gpu/drm/i915/i915_drv.h         |  4 ++
 drivers/gpu/drm/i915/i915_gem.c         |  1 +
 drivers/gpu/drm/i915/i915_gem_request.c |  1 +
 drivers/gpu/drm/i915/i915_pmu.c         | 88 +++++++++++++++++++++++++++++----
 drivers/gpu/drm/i915/i915_pmu.h         |  4 ++
 5 files changed, 88 insertions(+), 10 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +4 -0
index 1f3fa46e10d3..1d0ed191eed4 100644
@@ -3952,9 +3952,13 @@ extern void i915_perf_unregister(struct drm_i915_private *dev_priv);
 #ifdef CONFIG_PERF_EVENTS
 void i915_pmu_register(struct drm_i915_private *i915);
 void i915_pmu_unregister(struct drm_i915_private *i915);
+void i915_pmu_gt_idle(struct drm_i915_private *i915);
+void i915_pmu_gt_active(struct drm_i915_private *i915);
 #else
 static inline void i915_pmu_register(struct drm_i915_private *i915) {}
 static inline void i915_pmu_unregister(struct drm_i915_private *i915) {}
+static inline void i915_pmu_gt_idle(struct drm_i915_private *i915) {}
+static inline void i915_pmu_gt_active(struct drm_i915_private *i915) {}
 #endif
 
 /* i915_suspend.c */
drivers/gpu/drm/i915/i915_gem.c +1 -0
index 73eeb6b1f1cd..18f9f0b541b8 100644
@@ -3191,6 +3191,7 @@ i915_gem_idle_work_handler(struct work_struct *work)
 
 	intel_engines_mark_idle(dev_priv);
 	i915_gem_timelines_mark_idle(dev_priv);
+	i915_pmu_gt_idle(dev_priv);
 
 	GEM_BUG_ON(!dev_priv->gt.awake);
 	dev_priv->gt.awake = false;
drivers/gpu/drm/i915/i915_gem_request.c +1 -0
index 4eb1a76731b2..43249be1f97c 100644
@@ -258,6 +258,7 @@ static void mark_busy(struct drm_i915_private *i915)
 	i915_update_gfx_val(i915);
 	if (INTEL_GEN(i915) >= 6)
 		gen6_rps_busy(i915);
+	i915_pmu_gt_active(i915);
 
 	queue_delayed_work(i915->wq,
 			   &i915->gt.retire_work,
drivers/gpu/drm/i915/i915_pmu.c +78 -10

119 lines not on this page · raw message

drivers/gpu/drm/i915/i915_pmu.h +4 -0
index 0f884dd3496a..89be7eb4af1c 100644
@@ -83,6 +83,10 @@ struct i915_pmu {
 	 */
 	unsigned int enable_count[I915_PMU_MASK_BITS];
 	/**
+	 * @timer_enabled: Should the internal sampling timer be running.
+	 */
+	bool timer_enabled;
+	/**
 	 * @sample: Current and previous (raw) counters for sampling events.
 	 *
 	 * These counters are updated from the i915 PMU sampling timer.
Signature · 6 lines
2.9.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author maintainer
#6 lore raw

PATCH v6 4/10 drm/i915: Wrap context schedule notification

In reply to Tvrtko Ursulin

From: Tvrtko Ursulin <[email protected]>

No functional change just something which will be handy in the following patch.

---
 drivers/gpu/drm/i915/intel_lrc.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)
drivers/gpu/drm/i915/intel_lrc.c +14 -3
index 61cac26a8b05..80ceb08f0d50 100644
@@ -363,6 +363,18 @@ execlists_context_status_change(struct drm_i915_gem_request *rq,
 				   status, rq);
 }
 
+static inline void
+execlists_context_schedule_in(struct drm_i915_gem_request *rq)
+{
+	execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_IN);
+}
+
+static inline void
+execlists_context_schedule_out(struct drm_i915_gem_request *rq)
+{
+	execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT);
+}
+
 static void
 execlists_update_context_pdps(struct i915_hw_ppgtt *ppgtt, u32 *reg_state)
 {
@@ -408,7 +420,7 @@ static void execlists_submit_ports(struct intel_engine_cs *engine)
 		if (rq) {
 			GEM_BUG_ON(count > !n);
 			if (!count++)
-				execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_IN);
+				execlists_context_schedule_in(rq);
 			port_set(&port[n], port_pack(rq, count));
 			desc = execlists_update_context(rq);
 			GEM_DEBUG_EXEC(port[n].context_id = upper_32_bits(desc));
@@ -753,8 +765,7 @@ static void intel_lrc_irq_handler(unsigned long data)
 			if (--count == 0) {
 				GEM_BUG_ON(status & GEN8_CTX_STATUS_PREEMPTED);
 				GEM_BUG_ON(!i915_gem_request_completed(rq));
-				execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT);
-
+				execlists_context_schedule_out(rq);
 				trace_i915_gem_request_out(rq);
 				i915_gem_request_put(rq);
 
Signature · 6 lines
2.9.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author maintainer
#7 lore raw

PATCH v6 5/10 drm/i915: Engine busy time tracking

In reply to Tvrtko Ursulin

From: Tvrtko Ursulin <[email protected]>

Track total time requests have been executing on the hardware.

We add new kernel API to allow software tracking of time GPU engines are spending executing requests.

Both per-engine and global API is added with the latter also being exported for use by external users.

v2:
* Squashed with the internal API.
* Dropped static key.
* Made per-engine.
* Store time in monotonic ktime.

v3: Moved stats clearing to disable.

v4:
* Comments.
* Don't export the API just yet.

v5: Whitespace cleanup.

v6:
* Rename ref to active.
* Drop engine aggregate stats for now.
* Account initial busy period after enabling stats.

v7:
* Rebase.

v8:
* Move context in notification after the notifier. (Chris Wilson)

---
 drivers/gpu/drm/i915/intel_engine_cs.c  | 84 ++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_lrc.c        |  2 +
 drivers/gpu/drm/i915/intel_ringbuffer.h | 92 +++++++++++++++++++++++++++++++++
 3 files changed, 178 insertions(+)
drivers/gpu/drm/i915/intel_engine_cs.c +84 -0
index 35c117c3fa0d..8db83f504d70 100644
@@ -234,6 +234,8 @@ intel_engine_setup(struct drm_i915_private *dev_priv,
 	/* Nothing to do here, execute in order of dependencies */
 	engine->schedule = NULL;
 
+	spin_lock_init(&engine->stats.lock);
+
 	ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier);
 
 	dev_priv->engine_class[info->class][info->instance] = engine;
@@ -1613,6 +1615,88 @@ intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance)
 	return i915->engine_class[class][instance];
 }
 
+/**
+ * intel_enable_engine_stats() - Enable engine busy tracking on engine
+ * @engine: engine to enable stats collection
+ *
+ * Start collecting the engine busyness data for @engine.
+ *
+ * Returns 0 on success or a negative error code.
+ */
+int intel_enable_engine_stats(struct intel_engine_cs *engine)
+{
+	unsigned long flags;
+
+	if (!i915_modparams.enable_execlists)
+		return -ENODEV;
+
+	spin_lock_irqsave(&engine->stats.lock, flags);
+	if (engine->stats.enabled == ~0)
+		goto busy;
+	if (engine->stats.enabled++ == 0)
+		engine->stats.enabled_at = ktime_get();
+	spin_unlock_irqrestore(&engine->stats.lock, flags);
+
+	return 0;
+
+busy:
+	spin_unlock_irqrestore(&engine->stats.lock, flags);
+
+	return -EBUSY;
+}
+
+/**
+ * intel_disable_engine_stats() - Disable engine busy tracking on engine
+ * @engine: engine to disable stats collection
+ *
+ * Stops collecting the engine busyness data for @engine.
+ */
+void intel_disable_engine_stats(struct intel_engine_cs *engine)
+{
+	unsigned long flags;
+
+	if (!i915_modparams.enable_execlists)
+		return;
+
+	spin_lock_irqsave(&engine->stats.lock, flags);
+	WARN_ON_ONCE(engine->stats.enabled == 0);
+	if (--engine->stats.enabled == 0) {
+		engine->stats.enabled_at = 0;
+		engine->stats.active = 0;
+		engine->stats.start = 0;
+		engine->stats.total = 0;
+	}
+	spin_unlock_irqrestore(&engine->stats.lock, flags);
+}
+
+/**
+ * intel_engine_get_busy_time() - Return current accumulated engine busyness
+ * @engine: engine to report on
+ *
+ * Returns accumulated time @engine was busy since engine stats were enabled.
+ */
+ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine)
+{
+	ktime_t total;
+	unsigned long flags;
+
+	spin_lock_irqsave(&engine->stats.lock, flags);
+
+	total = engine->stats.total;
+
+	/*
+	 * If the engine is executing something at the moment
+	 * add it to the total.
+	 */
+	if (engine->stats.active)
+		total = ktime_add(total,
+				  ktime_sub(ktime_get(), engine->stats.start));
+
+	spin_unlock_irqrestore(&engine->stats.lock, flags);
+
+	return total;
+}
+
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftests/mock_engine.c"
 #endif
drivers/gpu/drm/i915/intel_lrc.c +2 -0
index 80ceb08f0d50..7b32e2ce65af 100644
@@ -367,11 +367,13 @@ static inline void
 execlists_context_schedule_in(struct drm_i915_gem_request *rq)
 {
 	execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_IN);
+	intel_engine_context_in(rq->engine);
 }
 
 static inline void
 execlists_context_schedule_out(struct drm_i915_gem_request *rq)
 {
+	intel_engine_context_out(rq->engine);
 	execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT);
 }
 
drivers/gpu/drm/i915/intel_ringbuffer.h +92 -0

102 lines not on this page · raw message

Signature · 6 lines
2.9.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Reviewed-by on v6 5/10
#8 lore raw

Re: [PATCH 05/10] drm/i915: Engine busy time tracking

Quoting Tvrtko Ursulin (2017-09-29 13:34:55)

Quoted 29 lines

From: Tvrtko Ursulin <[email protected]>

Track total time requests have been executing on the hardware.

We add new kernel API to allow software tracking of time GPU engines are spending executing requests.

Both per-engine and global API is added with the latter also being exported for use by external users.

v2:
* Squashed with the internal API.
* Dropped static key.
* Made per-engine.
* Store time in monotonic ktime.

v3: Moved stats clearing to disable.

v4:
* Comments.
* Don't export the API just yet.

v5: Whitespace cleanup.

v6:
* Rename ref to active.
* Drop engine aggregate stats for now.
* Account initial busy period after enabling stats.

Quoted 7 lines

v7:
* Rebase.

v8:
* Move context in notification after the notifier. (Chris Wilson)

-Chris
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

author maintainer
#9 lore raw

PATCH v6 6/10 drm/i915/pmu: Wire up engine busy stats to PMU

In reply to Tvrtko Ursulin

From: Tvrtko Ursulin <[email protected]>

We can use engine busy stats instead of the sampling timer for better accuracy.

By doing this we replace the stohastic sampling with busyness metric derived directly from engine activity. This is context switch interrupt driven, so as accurate as we can get from software tracking.

As a secondary benefit, we can also not run the sampling timer in cases only busyness metric is enabled.

v2: Rebase.
v3:
* Rebase, comments.
* Leave engine busyness controls out of workers.
v4: Checkpatch cleanup.
v5: Added comment to pmu_needs_timer change. v6:
* Rebase.
* Fix style of some comments. (Chris Wilson)
v7: Rebase and commit message update. (Chris Wilson)

---
 drivers/gpu/drm/i915/i915_pmu.c         | 37 +++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_ringbuffer.h |  5 +++++
 2 files changed, 40 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/i915_pmu.c +35 -2
index f341c904c159..93c0e7ec7d75 100644
@@ -90,6 +90,11 @@ static unsigned int event_enabled_bit(struct perf_event *event)
 	return config_enabled_bit(event->attr.config);
 }
 
+static bool supports_busy_stats(void)
+{
+	return i915_modparams.enable_execlists;
+}
+
 static bool pmu_needs_timer(struct drm_i915_private *i915, bool gpu_active)
 {
 	u64 enable;
@@ -115,6 +120,12 @@ static bool pmu_needs_timer(struct drm_i915_private *i915, bool gpu_active)
 	 */
 	if (!gpu_active)
 		enable &= ~ENGINE_SAMPLE_MASK;
+	/*
+	 * Also there is software busyness tracking available we do not
+	 * need the timer for I915_SAMPLE_BUSY counter.
+	 */
+	else if (supports_busy_stats())
+		enable &= ~BIT(I915_SAMPLE_BUSY);
 
 	/*
 	 * If some bits remain it means we need the sampling timer running.
@@ -362,6 +373,9 @@ static u64 __i915_pmu_event_read(struct perf_event *event)
 
 		if (WARN_ON_ONCE(!engine)) {
 			/* Do nothing */
+		} else if (sample == I915_SAMPLE_BUSY &&
+			   engine->pmu.busy_stats) {
+			val = ktime_to_ns(intel_engine_get_busy_time(engine));
 		} else {
 			val = engine->pmu.sample[sample].cur;
 		}
@@ -398,6 +412,12 @@ static void i915_pmu_event_read(struct perf_event *event)
 	local64_add(new - prev, &event->count);
 }
 
+static bool engine_needs_busy_stats(struct intel_engine_cs *engine)
+{
+	return supports_busy_stats() &&
+	       (engine->pmu.enable & BIT(I915_SAMPLE_BUSY));
+}
+
 static void i915_pmu_enable(struct perf_event *event)
 {
 	struct drm_i915_private *i915 =
@@ -437,7 +457,14 @@ static void i915_pmu_enable(struct perf_event *event)
 
 		GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
 		GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0);
-		engine->pmu.enable_count[sample]++;
+		if (engine->pmu.enable_count[sample]++ == 0) {
+			if (engine_needs_busy_stats(engine) &&
+			    !engine->pmu.busy_stats) {
+				engine->pmu.busy_stats =
+					intel_enable_engine_stats(engine) == 0;
+				WARN_ON_ONCE(!engine->pmu.busy_stats);
+			}
+		}
 	}
 
 	/*
@@ -473,8 +500,14 @@ static void i915_pmu_disable(struct perf_event *event)
 		 * Decrement the reference count and clear the enabled
 		 * bitmask when the last listener on an event goes away.
 		 */
-		if (--engine->pmu.enable_count[sample] == 0)
+		if (--engine->pmu.enable_count[sample] == 0) {
 			engine->pmu.enable &= ~BIT(sample);
+			if (!engine_needs_busy_stats(engine) &&
+			    engine->pmu.busy_stats) {
+				engine->pmu.busy_stats = false;
+				intel_disable_engine_stats(engine);
+			}
+		}
 	}
 
 	GEM_BUG_ON(bit >= I915_PMU_MASK_BITS);
drivers/gpu/drm/i915/intel_ringbuffer.h +5 -0
index ee738c7694e5..0f8ccb243407 100644
@@ -351,6 +351,11 @@ struct intel_engine_cs {
 		 * Our internal timer stores the current counters in this field.
 		 */
 		struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX];
+		/**
+		 * @busy_stats: Has enablement of engine stats tracking been
+		 * 		requested.
+		 */
+		bool busy_stats;
 	} pmu;
 
 	/*
Signature · 6 lines
2.9.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#10 lore raw

Re: [PATCH 06/10] drm/i915/pmu: Wire up engine busy stats to PMU

Quoted 9 lines · Tvrtko Ursulin

From: Tvrtko Ursulin <[email protected]>

We can use engine busy stats instead of the sampling timer for better accuracy.

By doing this we replace the stohastic sampling with busyness metric derived directly from engine activity. This is context switch interrupt driven, so as accurate as we can get from software tracking.

To quantify the precision benefit with a graph:

https://people.freedesktop.org/~tursulin/sampling-vs-busy-stats.png

This represents the render engine busyness on neverball menu screen looping a few times. PMU sampling interval is 100ms. It was generated from a special build with both PMU counters running in parallel so the data is absolutely aligned.

Anomaly of busyness going over 100% is caused by me not bothering to use the actual timestamps got from PMU, but using fixed interval (perf stat -I 100). But I don't think it matters for the rough comparison and looking at the noise and error in the sampling version.

Quoted 2 lines

As a secondary benefit, we can also not run the sampling timer in cases only busyness metric is enabled.

For this one data is not showing anything significant. I've seen the i915_sample function use <0.1% of CPU time but that's it. Probably with the original version which used MMIO it was much worse.

Regards,

Tvrtko

Quoted 109 lines

v2: Rebase.
v3:
* Rebase, comments.
* Leave engine busyness controls out of workers.
v4: Checkpatch cleanup.
v5: Added comment to pmu_needs_timer change. v6:
* Rebase.
* Fix style of some comments. (Chris Wilson)
v7: Rebase and commit message update. (Chris Wilson)

---
  drivers/gpu/drm/i915/i915_pmu.c         | 37 +++++++++++++++++++++++++++++++--
  drivers/gpu/drm/i915/intel_ringbuffer.h |  5 +++++
  2 files changed, 40 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/i915_pmu.c +35 -2
index f341c904c159..93c0e7ec7d75 100644
@@ -90,6 +90,11 @@ static unsigned int event_enabled_bit(struct perf_event *event)
  	return config_enabled_bit(event->attr.config);
  }
 
+static bool supports_busy_stats(void)
+{
+	return i915_modparams.enable_execlists;
+}
+
  static bool pmu_needs_timer(struct drm_i915_private *i915, bool gpu_active)
  {
  	u64 enable;
@@ -115,6 +120,12 @@ static bool pmu_needs_timer(struct drm_i915_private *i915, bool gpu_active)
  	 */
  	if (!gpu_active)
  		enable &= ~ENGINE_SAMPLE_MASK;
+	/*
+	 * Also there is software busyness tracking available we do not
+	 * need the timer for I915_SAMPLE_BUSY counter.
+	 */
+	else if (supports_busy_stats())
+		enable &= ~BIT(I915_SAMPLE_BUSY);
 
  	/*
  	 * If some bits remain it means we need the sampling timer running.
@@ -362,6 +373,9 @@ static u64 __i915_pmu_event_read(struct perf_event *event)
 
  		if (WARN_ON_ONCE(!engine)) {
  			/* Do nothing */
+		} else if (sample == I915_SAMPLE_BUSY &&
+			   engine->pmu.busy_stats) {
+			val = ktime_to_ns(intel_engine_get_busy_time(engine));
  		} else {
  			val = engine->pmu.sample[sample].cur;
  		}
@@ -398,6 +412,12 @@ static void i915_pmu_event_read(struct perf_event *event)
  	local64_add(new - prev, &event->count);
  }
 
+static bool engine_needs_busy_stats(struct intel_engine_cs *engine)
+{
+	return supports_busy_stats() &&
+	       (engine->pmu.enable & BIT(I915_SAMPLE_BUSY));
+}
+
  static void i915_pmu_enable(struct perf_event *event)
  {
  	struct drm_i915_private *i915 =
@@ -437,7 +457,14 @@ static void i915_pmu_enable(struct perf_event *event)
 
  		GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
  		GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0);
-		engine->pmu.enable_count[sample]++;
+		if (engine->pmu.enable_count[sample]++ == 0) {
+			if (engine_needs_busy_stats(engine) &&
+			    !engine->pmu.busy_stats) {
+				engine->pmu.busy_stats =
+					intel_enable_engine_stats(engine) == 0;
+				WARN_ON_ONCE(!engine->pmu.busy_stats);
+			}
+		}
  	}
 
  	/*
@@ -473,8 +500,14 @@ static void i915_pmu_disable(struct perf_event *event)
  		 * Decrement the reference count and clear the enabled
  		 * bitmask when the last listener on an event goes away.
  		 */
-		if (--engine->pmu.enable_count[sample] == 0)
+		if (--engine->pmu.enable_count[sample] == 0) {
  			engine->pmu.enable &= ~BIT(sample);
+			if (!engine_needs_busy_stats(engine) &&
+			    engine->pmu.busy_stats) {
+				engine->pmu.busy_stats = false;
+				intel_disable_engine_stats(engine);
+			}
+		}
  	}
 
  	GEM_BUG_ON(bit >= I915_PMU_MASK_BITS);
drivers/gpu/drm/i915/intel_ringbuffer.h +0 -0
index ee738c7694e5..0f8ccb243407 100644
@@ -351,6 +351,11 @@ struct intel_engine_cs {
  		 * Our internal timer stores the current counters in this field.

drivers/gpu/drm/i915/intel_ringbuffer.h struct intel_engine_cs { · line 361

Quoted 10 lines
drivers/gpu/drm/i915/intel_ringbuffer.h +5 -0
  		 */
  		struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX];
+		/**
+		 * @busy_stats: Has enablement of engine stats tracking been
+		 * 		requested.
+		 */
+		bool busy_stats;
  	} pmu;
 
  	/*

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#11 lore raw

Re: [PATCH 06/10] drm/i915/pmu: Wire up engine busy stats to PMU

Nice data, thank you!

-----Original Message-----
From: Tvrtko Ursulin [mailto:[email protected]]
Sent: Wednesday, October 4, 2017 10:35 AM
To: Tvrtko Ursulin <[email protected]>; [email protected]
Cc: Chris Wilson <[email protected]>; Rogozhkin, Dmitry V <[email protected]>
Subject: Re: [Intel-gfx] [PATCH 06/10] drm/i915/pmu: Wire up engine busy stats to PMU

Quoted 8 lines · Tvrtko Ursulin

From: Tvrtko Ursulin <[email protected]>

We can use engine busy stats instead of the sampling timer for better accuracy.

By doing this we replace the stohastic sampling with busyness metric derived directly from engine activity. This is context switch interrupt driven, so as accurate as we can get from software tracking.

To quantify the precision benefit with a graph:

https://people.freedesktop.org/~tursulin/sampling-vs-busy-stats.png

This represents the render engine busyness on neverball menu screen looping a few times. PMU sampling interval is 100ms. It was generated from a special build with both PMU counters running in parallel so the data is absolutely aligned.

Anomaly of busyness going over 100% is caused by me not bothering to use the actual timestamps got from PMU, but using fixed interval (perf stat -I 100). But I don't think it matters for the rough comparison and looking at the noise and error in the sampling version.

Quoted 2 lines

As a secondary benefit, we can also not run the sampling timer in cases only busyness metric is enabled.

For this one data is not showing anything significant. I've seen the i915_sample function use <0.1% of CPU time but that's it. Probably with the original version which used MMIO it was much worse.

Regards,

Tvrtko

Quoted 109 lines

v2: Rebase.
v3:
* Rebase, comments.
* Leave engine busyness controls out of workers.
v4: Checkpatch cleanup.
v5: Added comment to pmu_needs_timer change. v6:
* Rebase.
* Fix style of some comments. (Chris Wilson)
v7: Rebase and commit message update. (Chris Wilson)

---
  drivers/gpu/drm/i915/i915_pmu.c         | 37 +++++++++++++++++++++++++++++++--
  drivers/gpu/drm/i915/intel_ringbuffer.h |  5 +++++
  2 files changed, 40 insertions(+), 2 deletions(-)
(quoted diff) +0 -0

b/drivers/gpu/drm/i915/i915_pmu.c index f341c904c159..93c0e7ec7d75 100644

drivers/gpu/drm/i915/i915_pmu.c +12 -0
@@ -90,6 +90,11 @@ static unsigned int event_enabled_bit(struct perf_event *event)
  	return config_enabled_bit(event->attr.config);
  }
 
+static bool supports_busy_stats(void) {
+	return i915_modparams.enable_execlists; }
+
  static bool pmu_needs_timer(struct drm_i915_private *i915, bool gpu_active)
  {
  	u64 enable;
@@ -115,6 +120,12 @@ static bool pmu_needs_timer(struct drm_i915_private *i915, bool gpu_active)
  	 */
  	if (!gpu_active)
  		enable &= ~ENGINE_SAMPLE_MASK;
+	/*
+	 * Also there is software busyness tracking available we do not
+	 * need the timer for I915_SAMPLE_BUSY counter.
+	 */
+	else if (supports_busy_stats())
+		enable &= ~BIT(I915_SAMPLE_BUSY);
 
  	/*
  	 * If some bits remain it means we need the sampling timer running.
@@ -362,6 +373,9 @@ static u64 __i915_pmu_event_read(struct perf_event 
 *event)
 
  		if (WARN_ON_ONCE(!engine)) {
  			/* Do nothing */
+		} else if (sample == I915_SAMPLE_BUSY &&
+			   engine->pmu.busy_stats) {
+			val = ktime_to_ns(intel_engine_get_busy_time(engine));
  		} else {
  			val = engine->pmu.sample[sample].cur;
  		}
drivers/gpu/drm/i915/i915_pmu.c +12 -1
@@ -398,6 +412,12 @@ static void i915_pmu_event_read(struct perf_event *event)
  	local64_add(new - prev, &event->count);
  }
 
+static bool engine_needs_busy_stats(struct intel_engine_cs *engine) {
+	return supports_busy_stats() &&
+	       (engine->pmu.enable & BIT(I915_SAMPLE_BUSY)); }
+
  static void i915_pmu_enable(struct perf_event *event)
  {
  	struct drm_i915_private *i915 =
@@ -437,7 +457,14 @@ static void i915_pmu_enable(struct perf_event 
 *event)
 
  		GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
  		GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0);
-		engine->pmu.enable_count[sample]++;
+		if (engine->pmu.enable_count[sample]++ == 0) {
+			if (engine_needs_busy_stats(engine) &&
+			    !engine->pmu.busy_stats) {
+				engine->pmu.busy_stats =
+					intel_enable_engine_stats(engine) == 0;
+				WARN_ON_ONCE(!engine->pmu.busy_stats);
+			}
+		}
  	}
 

/*

drivers/gpu/drm/i915/i915_pmu.c +7 -1
@@ -473,8 +500,14 @@ static void i915_pmu_disable(struct perf_event *event)
  		 * Decrement the reference count and clear the enabled
  		 * bitmask when the last listener on an event goes away.
  		 */
-		if (--engine->pmu.enable_count[sample] == 0)
+		if (--engine->pmu.enable_count[sample] == 0) {
  			engine->pmu.enable &= ~BIT(sample);
+			if (!engine_needs_busy_stats(engine) &&
+			    engine->pmu.busy_stats) {
+				engine->pmu.busy_stats = false;
+				intel_disable_engine_stats(engine);
+			}
+		}
  	}
 
  	GEM_BUG_ON(bit >= I915_PMU_MASK_BITS); diff --git 

a/drivers/gpu/drm/i915/intel_ringbuffer.h
b/drivers/gpu/drm/i915/intel_ringbuffer.h
index ee738c7694e5..0f8ccb243407 100644

drivers/gpu/drm/i915/intel_ringbuffer.h +0 -0
@@ -351,6 +351,11 @@ struct intel_engine_cs {
  		 * Our internal timer stores the current counters in this field.

drivers/gpu/drm/i915/intel_ringbuffer.h struct intel_engine_cs { · line 361

Quoted 10 lines
drivers/gpu/drm/i915/intel_ringbuffer.h +5 -0
  		 */
  		struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX];
+		/**
+		 * @busy_stats: Has enablement of engine stats tracking been
+		 * 		requested.
+		 */
+		bool busy_stats;
  	} pmu;
 
  	/*

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

author maintainer
#12 lore raw

PATCH v6 7/10 drm/i915: Gate engine stats collection with a static key

In reply to Tvrtko Ursulin

From: Tvrtko Ursulin <[email protected]>

This reduces the cost of the software engine busyness tracking to a single no-op instruction when there are no listeners.

We add a new i915 ordered workqueue to be used only for tasks not needing struct mutex.

v2: Rebase and some comments.
v3: Rebase.
v4: Checkpatch fixes.
v5: Rebase.
v6: Use system_long_wq to avoid being blocked by struct_mutex
users.
v7: Fix bad conflict resolution from last rebase. (Dmitry Rogozhkin)
v8: Rebase.
v9:
* Fix race between unordered enable followed by disable. (Chris Wilson)
* Prettify order of local variable declarations. (Chris Wilson)

---
 drivers/gpu/drm/i915/i915_drv.c         |  13 +++-
 drivers/gpu/drm/i915/i915_drv.h         |   5 ++
 drivers/gpu/drm/i915/i915_pmu.c         |  57 ++++++++++++++++--
 drivers/gpu/drm/i915/intel_engine_cs.c  |  17 ++++++
 drivers/gpu/drm/i915/intel_ringbuffer.h | 101 ++++++++++++++++++++------------
 5 files changed, 150 insertions(+), 43 deletions(-)
drivers/gpu/drm/i915/i915_drv.c +12 -1
index 187c0fad1b79..1e43d594b59a 100644
@@ -795,12 +795,22 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv)
 	if (dev_priv->wq == NULL)
 		goto out_err;
 
+	/*
+	 * Ordered workqueue for tasks not needing the global mutex but
+	 * which still need to be serialized.
+	 */
+	dev_priv->wq_misc = alloc_ordered_workqueue("i915-misc", 0);
+	if (dev_priv->wq == NULL)
+		goto out_free_wq;
+
 	dev_priv->hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0);
 	if (dev_priv->hotplug.dp_wq == NULL)
-		goto out_free_wq;
+		goto out_free_wq_misc;
 
 	return 0;
 
+out_free_wq_misc:
+	destroy_workqueue(dev_priv->wq_misc);
 out_free_wq:
 	destroy_workqueue(dev_priv->wq);
 out_err:
@@ -821,6 +831,7 @@ static void i915_engines_cleanup(struct drm_i915_private *i915)
 static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
 {
 	destroy_workqueue(dev_priv->hotplug.dp_wq);
+	destroy_workqueue(dev_priv->wq_misc);
 	destroy_workqueue(dev_priv->wq);
 }
 
drivers/gpu/drm/i915/i915_drv.h +5 -0
index 1d0ed191eed4..a88f5be0229c 100644
@@ -2343,6 +2343,11 @@ struct drm_i915_private {
 	 */
 	struct workqueue_struct *wq;
 
+	/**
+	 * @wq_misc: Workqueue for serialized tasks not needing struct mutex.
+	 */
+	struct workqueue_struct *wq_misc;
+
 	/* Display functions */
 	struct drm_i915_display_funcs display;
 
drivers/gpu/drm/i915/i915_pmu.c +53 -4

97 lines not on this page · raw message

drivers/gpu/drm/i915/intel_engine_cs.c +17 -0
index 8db83f504d70..eaf1d31dbf31 100644
@@ -21,6 +21,7 @@
  * IN THE SOFTWARE.
  *
  */
+#include <linux/static_key.h>
 
 #include "i915_drv.h"
 #include "intel_ringbuffer.h"
@@ -1615,6 +1616,10 @@ intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance)
 	return i915->engine_class[class][instance];
 }
 
+DEFINE_STATIC_KEY_FALSE(i915_engine_stats_key);
+static DEFINE_MUTEX(i915_engine_stats_mutex);
+static int i915_engine_stats_ref;
+
 /**
  * intel_enable_engine_stats() - Enable engine busy tracking on engine
  * @engine: engine to enable stats collection
@@ -1630,6 +1635,8 @@ int intel_enable_engine_stats(struct intel_engine_cs *engine)
 	if (!i915_modparams.enable_execlists)
 		return -ENODEV;
 
+	mutex_lock(&i915_engine_stats_mutex);
+
 	spin_lock_irqsave(&engine->stats.lock, flags);
 	if (engine->stats.enabled == ~0)
 		goto busy;
@@ -1637,10 +1644,16 @@ int intel_enable_engine_stats(struct intel_engine_cs *engine)
 		engine->stats.enabled_at = ktime_get();
 	spin_unlock_irqrestore(&engine->stats.lock, flags);
 
+	if (i915_engine_stats_ref++ == 0)
+		static_branch_enable(&i915_engine_stats_key);
+
+	mutex_unlock(&i915_engine_stats_mutex);
+
 	return 0;
 
 busy:
 	spin_unlock_irqrestore(&engine->stats.lock, flags);
+	mutex_unlock(&i915_engine_stats_mutex);
 
 	return -EBUSY;
 }
@@ -1658,6 +1671,7 @@ void intel_disable_engine_stats(struct intel_engine_cs *engine)
 	if (!i915_modparams.enable_execlists)
 		return;
 
+	mutex_lock(&i915_engine_stats_mutex);
 	spin_lock_irqsave(&engine->stats.lock, flags);
 	WARN_ON_ONCE(engine->stats.enabled == 0);
 	if (--engine->stats.enabled == 0) {
@@ -1667,6 +1681,9 @@ void intel_disable_engine_stats(struct intel_engine_cs *engine)
 		engine->stats.total = 0;
 	}
 	spin_unlock_irqrestore(&engine->stats.lock, flags);
+	if (--i915_engine_stats_ref == 0)
+		static_branch_disable(&i915_engine_stats_key);
+	mutex_unlock(&i915_engine_stats_mutex);
 }
 
 /**
drivers/gpu/drm/i915/intel_ringbuffer.h +63 -38

128 lines not on this page · raw message

Signature · 6 lines
2.9.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Reviewed-by on v6 7/10
#13 lore raw

Re: [PATCH 07/10] drm/i915: Gate engine stats collection with a static key

Quoting Tvrtko Ursulin (2017-09-29 13:34:57)

Quoted 8 lines

From: Tvrtko Ursulin <[email protected]>

This reduces the cost of the software engine busyness tracking to a single no-op instruction when there are no listeners.

We add a new i915 ordered workqueue to be used only for tasks not needing struct mutex.

Quoted 12 lines

v2: Rebase and some comments.
v3: Rebase.
v4: Checkpatch fixes.
v5: Rebase.
v6: Use system_long_wq to avoid being blocked by struct_mutex
users.
v7: Fix bad conflict resolution from last rebase. (Dmitry Rogozhkin)
v8: Rebase.
v9:
* Fix race between unordered enable followed by disable. (Chris Wilson)
* Prettify order of local variable declarations. (Chris Wilson)

Ok, I can't see a downside to enabling the optimisation even if it will be global and not per-device/per-engine.

Quoted 14 lines
---
 drivers/gpu/drm/i915/i915_drv.c         |  13 +++-
 drivers/gpu/drm/i915/i915_drv.h         |   5 ++
 drivers/gpu/drm/i915/i915_pmu.c         |  57 ++++++++++++++++--
 drivers/gpu/drm/i915/intel_engine_cs.c  |  17 ++++++
 drivers/gpu/drm/i915/intel_ringbuffer.h | 101 ++++++++++++++++++++------------
 5 files changed, 150 insertions(+), 43 deletions(-)
drivers/gpu/drm/i915/i915_drv.c +0 -0
index 187c0fad1b79..1e43d594b59a 100644

drivers/gpu/drm/i915/i915_drv.c static int i915_workqueues_init(struct drm_i915_private *dev_priv) · line 803

Quoted 9 lines
drivers/gpu/drm/i915/i915_drv.c +6 -0
@@ -795,12 +795,22 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv)
        if (dev_priv->wq == NULL)
                goto out_err;
 
+       /*
+        * Ordered workqueue for tasks not needing the global mutex but
+        * which still need to be serialized.
+        */
+       dev_priv->wq_misc = alloc_ordered_workqueue("i915-misc", 0);
+       if (dev_priv->wq == NULL)

if (!dev_priv->wq_misc) I think you mean ;)

drivers/gpu/drm/i915/i915_drv.c static int i915_workqueues_init(struct drm_i915_private *dev_priv) · line 804

Quoted 1 line
drivers/gpu/drm/i915/i915_drv.c +1 -0
+               goto out_free_wq;

Ok, Tried a few other names, liked none better.

Quoted 29 lines
drivers/gpu/drm/i915/i915_pmu.c +12 -3
index 93c0e7ec7d75..4c9b9ae09b23 100644
@@ -458,11 +458,20 @@ static void i915_pmu_enable(struct perf_event *event)
                GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
                GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0);
                if (engine->pmu.enable_count[sample]++ == 0) {
+                       /*
+                        * Enable engine busy stats tracking if needed or
+                        * alternatively cancel the scheduled disabling of the
+                        * same.
+                        *
+                        * If the delayed disable was pending, cancel it and in
+                        * this case no need to queue a new enable.
+                        */
                        if (engine_needs_busy_stats(engine) &&
                            !engine->pmu.busy_stats) {
-                               engine->pmu.busy_stats =
-                                       intel_enable_engine_stats(engine) == 0;
-                               WARN_ON_ONCE(!engine->pmu.busy_stats);
+                               engine->pmu.busy_stats = true;
+                               if (!cancel_delayed_work(&engine->pmu.disable_busy_stats))
+                                       queue_work(i915->wq_misc,
+                                                  &engine->pmu.enable_busy_stats);
                        }
                }
        }

drivers/gpu/drm/i915/i915_pmu.c static void i915_pmu_disable(struct perf_event *event) · line 522

Quoted 10 lines
drivers/gpu/drm/i915/i915_pmu.c +6 -1
@@ -505,7 +514,15 @@ static void i915_pmu_disable(struct perf_event *event)
                        if (!engine_needs_busy_stats(engine) &&
                            engine->pmu.busy_stats) {
                                engine->pmu.busy_stats = false;
-                               intel_disable_engine_stats(engine);
+                               /*
+                                * We request a delayed disable to handle the
+                                * rapid on/off cycles on events which can
+                                * happen when tools like perf stat start in a
+                                * nicer way.
+                                */

Ah, so this is where the work ordering plays a key role. A comment that we depend on strict ordering within the workqueue to prevent the delayed disable overtaking the enable worker (even when the workqueue jumps between cpus).

Quoted 57 lines
drivers/gpu/drm/i915/i915_pmu.c +30 -0
+                               queue_delayed_work(i915->wq_misc,
+                                                  &engine->pmu.disable_busy_stats,
+                                                  round_jiffies_up_relative(HZ));
                        }
                }
        }
@@ -689,8 +706,26 @@ static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
        return 0;
 }
 
+static void __enable_busy_stats(struct work_struct *work)
+{
+       struct intel_engine_cs *engine =
+               container_of(work, typeof(*engine), pmu.enable_busy_stats);
+
+       WARN_ON_ONCE(intel_enable_engine_stats(engine));
+}
+
+static void __disable_busy_stats(struct work_struct *work)
+{
+       struct intel_engine_cs *engine =
+              container_of(work, typeof(*engine), pmu.disable_busy_stats.work);
+
+       intel_disable_engine_stats(engine);
+}
+
 void i915_pmu_register(struct drm_i915_private *i915)
 {
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
        int ret;
 
        if (INTEL_GEN(i915) <= 2) {
@@ -725,6 +760,12 @@ void i915_pmu_register(struct drm_i915_private *i915)
        i915->pmu.timer.function = i915_sample;
        i915->pmu.enable = 0;
 
+       for_each_engine(engine, i915, id) {
+               INIT_WORK(&engine->pmu.enable_busy_stats, __enable_busy_stats);
+               INIT_DELAYED_WORK(&engine->pmu.disable_busy_stats,
+                                 __disable_busy_stats);
+       }
+
        ret = perf_pmu_register(&i915->pmu.base, "i915", -1);
        if (ret == 0)
                return;
@@ -743,6 +784,9 @@ void i915_pmu_register(struct drm_i915_private *i915)
 
 void i915_pmu_unregister(struct drm_i915_private *i915)
 {
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+
        if (!i915->pmu.base.event_init)
                return;
 

drivers/gpu/drm/i915/i915_pmu.c void i915_pmu_unregister(struct drm_i915_private *i915) · line 801

Quoted 4 lines
drivers/gpu/drm/i915/i915_pmu.c +1 -0
@@ -754,6 +798,11 @@ void i915_pmu_unregister(struct drm_i915_private *i915)
 
        hrtimer_cancel(&i915->pmu.timer);
 
+       for_each_engine(engine, i915, id) {

GEM_BUG_ON(engine->pmu.busy_stats);

(Or a dose of PMU_BUG_ON?)

drivers/gpu/drm/i915/i915_pmu.c void i915_pmu_unregister(struct drm_i915_private *i915) · line 803

Quoted 2 lines
drivers/gpu/drm/i915/i915_pmu.c +2 -0
+               flush_work(&engine->pmu.enable_busy_stats);
+               flush_delayed_work(&engine->pmu.disable_busy_stats);

And then you only need to flush the disable_busy_stats, but no harm in both.

-Chris
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#14 lore raw

Re: [PATCH 07/10] drm/i915: Gate engine stats collection with a static key

Quoted 22 lines · Chris Wilson

Quoting Tvrtko Ursulin (2017-09-29 13:34:57)

Quoted 8 lines

From: Tvrtko Ursulin <[email protected]>

This reduces the cost of the software engine busyness tracking to a single no-op instruction when there are no listeners.

We add a new i915 ordered workqueue to be used only for tasks not needing struct mutex.

Quoted 12 lines

v2: Rebase and some comments.
v3: Rebase.
v4: Checkpatch fixes.
v5: Rebase.
v6: Use system_long_wq to avoid being blocked by struct_mutex
users.
v7: Fix bad conflict resolution from last rebase. (Dmitry Rogozhkin)
v8: Rebase.
v9:
* Fix race between unordered enable followed by disable. (Chris Wilson)
* Prettify order of local variable declarations. (Chris Wilson)

Quoted 2 lines

Ok, I can't see a downside to enabling the optimisation even if it will be global and not per-device/per-engine.

For this one I did a quick test with gem_exec_nop and I've seen around 0.5% reduction in time spend in intel_lrc_irq_handler in the case where PMU is not active.

So it is a bit underwhelming and unless I can get different results after re-measuring a few times, I'd say it is not worth the complication of putting this in. At least it is there in history so it can be pulled in if needed.

Regards,

Tvrtko

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#15 lore raw

Re: [PATCH 07/10] drm/i915: Gate engine stats collection with a static key

Quoting Tvrtko Ursulin (2017-10-04 18:38:09)

Quoted 24 lines · Chris Wilson
Quoted 22 lines

Quoting Tvrtko Ursulin (2017-09-29 13:34:57)

Quoted 20 lines

From: Tvrtko Ursulin <[email protected]>

This reduces the cost of the software engine busyness tracking to a single no-op instruction when there are no listeners.

We add a new i915 ordered workqueue to be used only for tasks not needing struct mutex.

v2: Rebase and some comments.
v3: Rebase.
v4: Checkpatch fixes.
v5: Rebase.
v6: Use system_long_wq to avoid being blocked by struct_mutex
users.
v7: Fix bad conflict resolution from last rebase. (Dmitry Rogozhkin)
v8: Rebase.
v9:
* Fix race between unordered enable followed by disable. (Chris Wilson)
* Prettify order of local variable declarations. (Chris Wilson)

Quoted 6 lines
Quoted 2 lines

Ok, I can't see a downside to enabling the optimisation even if it will be global and not per-device/per-engine.

For this one I did a quick test with gem_exec_nop and I've seen around 0.5% reduction in time spend in intel_lrc_irq_handler in the case where PMU is not active.

Hmm, gem_exec_nop isn't going to be favourable as there we are just extending the busyness coverage of an engine. I think you want something like gem_sync/sequential (or gem_exec_whisper), as there each engine will be starting and stopping, and delays between engines will accumulate.
-Chris
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#16 lore raw

Re: [PATCH 07/10] drm/i915: Gate engine stats collection with a static key

Quoted 32 lines · Chris Wilson

Quoting Tvrtko Ursulin (2017-10-04 18:38:09)

Quoted 24 lines · Chris Wilson
Quoted 22 lines

Quoting Tvrtko Ursulin (2017-09-29 13:34:57)

Quoted 20 lines

From: Tvrtko Ursulin <[email protected]>

This reduces the cost of the software engine busyness tracking to a single no-op instruction when there are no listeners.

We add a new i915 ordered workqueue to be used only for tasks not needing struct mutex.

v2: Rebase and some comments.
v3: Rebase.
v4: Checkpatch fixes.
v5: Rebase.
v6: Use system_long_wq to avoid being blocked by struct_mutex
users.
v7: Fix bad conflict resolution from last rebase. (Dmitry Rogozhkin)
v8: Rebase.
v9:
* Fix race between unordered enable followed by disable. (Chris Wilson)
* Prettify order of local variable declarations. (Chris Wilson)

Quoted 6 lines
Quoted 2 lines

Ok, I can't see a downside to enabling the optimisation even if it will be global and not per-device/per-engine.

For this one I did a quick test with gem_exec_nop and I've seen around 0.5% reduction in time spend in intel_lrc_irq_handler in the case where PMU is not active.

Quoted 5 lines

Hmm, gem_exec_nop isn't going to be favourable as there we are just extending the busyness coverage of an engine. I think you want something like gem_sync/sequential (or gem_exec_whisper), as there each engine will be starting and stopping, and delays between engines will accumulate.

Not sure if we are on the same page. Here I was referring to the CPU usage in the "irq" (tasklet) handler. gem_exec_nop generates a good number of interrupts (8k/s) and shows up in the profile at ~1.8% CPU without the static branch optimisation, and ~1.3% with it.

Regards,

Tvrtko
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#17 lore raw

Re: [PATCH 07/10] drm/i915: Gate engine stats collection with a static key

Quoting Tvrtko Ursulin (2017-10-05 08:07:03)

Quoted 40 lines · Chris Wilson
Quoted 32 lines

Quoting Tvrtko Ursulin (2017-10-04 18:38:09)

Quoted 24 lines · Chris Wilson
Quoted 22 lines

Quoting Tvrtko Ursulin (2017-09-29 13:34:57)

Quoted 20 lines

From: Tvrtko Ursulin <[email protected]>

This reduces the cost of the software engine busyness tracking to a single no-op instruction when there are no listeners.

We add a new i915 ordered workqueue to be used only for tasks not needing struct mutex.

v2: Rebase and some comments.
v3: Rebase.
v4: Checkpatch fixes.
v5: Rebase.
v6: Use system_long_wq to avoid being blocked by struct_mutex
users.
v7: Fix bad conflict resolution from last rebase. (Dmitry Rogozhkin)
v8: Rebase.
v9:
* Fix race between unordered enable followed by disable. (Chris Wilson)
* Prettify order of local variable declarations. (Chris Wilson)

Quoted 6 lines
Quoted 2 lines

Ok, I can't see a downside to enabling the optimisation even if it will be global and not per-device/per-engine.

For this one I did a quick test with gem_exec_nop and I've seen around 0.5% reduction in time spend in intel_lrc_irq_handler in the case where PMU is not active.

Quoted 5 lines

Hmm, gem_exec_nop isn't going to be favourable as there we are just extending the busyness coverage of an engine. I think you want something like gem_sync/sequential (or gem_exec_whisper), as there each engine will be starting and stopping, and delays between engines will accumulate.

Quoted 4 lines

Not sure if we are on the same page. Here I was referring to the CPU usage in the "irq" (tasklet) handler. gem_exec_nop generates a good number of interrupts (8k/s) and shows up in the profile at ~1.8% CPU without the static branch optimisation, and ~1.3% with it.

I'm just suggesting that some of the other tests are more sensitive to delays incurred there, where that ~50% difference in CPU cycles may be visible to userspace. They may make a more convincing argument? -Chris
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

author maintainer
#18 lore raw

PATCH v10 7/10 drm/i915: Gate engine stats collection with a static key

In reply to Chris Wilson

From: Tvrtko Ursulin <[email protected]>

This reduces the cost of the software engine busyness tracking to a single no-op instruction when there are no listeners.

We add a new i915 ordered workqueue to be used only for tasks not needing struct mutex.

v2: Rebase and some comments.
v3: Rebase.
v4: Checkpatch fixes.
v5: Rebase.
v6: Use system_long_wq to avoid being blocked by struct_mutex
users.
v7: Fix bad conflict resolution from last rebase. (Dmitry Rogozhkin)
v8: Rebase.
v9:
* Fix race between unordered enable followed by disable. (Chris Wilson)
* Prettify order of local variable declarations. (Chris Wilson)
v10:
Chris Wilson:
* Fix workqueue allocation failure handling.
* Expand comment about critical workqueue ordering.
* Add some GEM_BUG_ONs to document impossible conditions.

---
 drivers/gpu/drm/i915/i915_drv.c         |  13 +++-
 drivers/gpu/drm/i915/i915_drv.h         |   5 ++
 drivers/gpu/drm/i915/i915_pmu.c         |  65 ++++++++++++++++++--
 drivers/gpu/drm/i915/intel_engine_cs.c  |  17 ++++++
 drivers/gpu/drm/i915/intel_ringbuffer.h | 101 ++++++++++++++++++++------------
 5 files changed, 158 insertions(+), 43 deletions(-)
drivers/gpu/drm/i915/i915_drv.c +12 -1
index d373a840566a..3853038c6fdd 100644
@@ -804,12 +804,22 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv)
 	if (dev_priv->wq == NULL)
 		goto out_err;
 
+	/*
+	 * Ordered workqueue for tasks not needing the global mutex but
+	 * which still need to be serialized.
+	 */
+	dev_priv->wq_misc = alloc_ordered_workqueue("i915-misc", 0);
+	if (dev_priv->wq_misc == NULL)
+		goto out_free_wq;
+
 	dev_priv->hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0);
 	if (dev_priv->hotplug.dp_wq == NULL)
-		goto out_free_wq;
+		goto out_free_wq_misc;
 
 	return 0;
 
+out_free_wq_misc:
+	destroy_workqueue(dev_priv->wq_misc);
 out_free_wq:
 	destroy_workqueue(dev_priv->wq);
 out_err:
@@ -830,6 +840,7 @@ static void i915_engines_cleanup(struct drm_i915_private *i915)
 static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
 {
 	destroy_workqueue(dev_priv->hotplug.dp_wq);
+	destroy_workqueue(dev_priv->wq_misc);
 	destroy_workqueue(dev_priv->wq);
 }
 
drivers/gpu/drm/i915/i915_drv.h +5 -0
index 2dabe671bb50..efa3a8423cca 100644
@@ -2349,6 +2349,11 @@ struct drm_i915_private {
 	 */
 	struct workqueue_struct *wq;
 
+	/**
+	 * @wq_misc: Workqueue for serialized tasks not needing struct mutex.
+	 */
+	struct workqueue_struct *wq_misc;
+
 	/* Display functions */
 	struct drm_i915_display_funcs display;
 
drivers/gpu/drm/i915/i915_pmu.c +61 -4

105 lines not on this page · raw message

drivers/gpu/drm/i915/intel_engine_cs.c +17 -0
index 53d3b8f3c222..cbfde1149822 100644
@@ -21,6 +21,7 @@
  * IN THE SOFTWARE.
  *
  */
+#include <linux/static_key.h>
 
 #include "i915_drv.h"
 #include "intel_ringbuffer.h"
@@ -1653,6 +1654,10 @@ intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance)
 	return i915->engine_class[class][instance];
 }
 
+DEFINE_STATIC_KEY_FALSE(i915_engine_stats_key);
+static DEFINE_MUTEX(i915_engine_stats_mutex);
+static int i915_engine_stats_ref;
+
 /**
  * intel_enable_engine_stats() - Enable engine busy tracking on engine
  * @engine: engine to enable stats collection
@@ -1668,6 +1673,8 @@ int intel_enable_engine_stats(struct intel_engine_cs *engine)
 	if (!i915_modparams.enable_execlists)
 		return -ENODEV;
 
+	mutex_lock(&i915_engine_stats_mutex);
+
 	spin_lock_irqsave(&engine->stats.lock, flags);
 	if (engine->stats.enabled == ~0)
 		goto busy;
@@ -1675,10 +1682,16 @@ int intel_enable_engine_stats(struct intel_engine_cs *engine)
 		engine->stats.enabled_at = ktime_get();
 	spin_unlock_irqrestore(&engine->stats.lock, flags);
 
+	if (i915_engine_stats_ref++ == 0)
+		static_branch_enable(&i915_engine_stats_key);
+
+	mutex_unlock(&i915_engine_stats_mutex);
+
 	return 0;
 
 busy:
 	spin_unlock_irqrestore(&engine->stats.lock, flags);
+	mutex_unlock(&i915_engine_stats_mutex);
 
 	return -EBUSY;
 }
@@ -1696,6 +1709,7 @@ void intel_disable_engine_stats(struct intel_engine_cs *engine)
 	if (!i915_modparams.enable_execlists)
 		return;
 
+	mutex_lock(&i915_engine_stats_mutex);
 	spin_lock_irqsave(&engine->stats.lock, flags);
 	WARN_ON_ONCE(engine->stats.enabled == 0);
 	if (--engine->stats.enabled == 0) {
@@ -1705,6 +1719,9 @@ void intel_disable_engine_stats(struct intel_engine_cs *engine)
 		engine->stats.total = 0;
 	}
 	spin_unlock_irqrestore(&engine->stats.lock, flags);
+	if (--i915_engine_stats_ref == 0)
+		static_branch_disable(&i915_engine_stats_key);
+	mutex_unlock(&i915_engine_stats_mutex);
 }
 
 /**
drivers/gpu/drm/i915/intel_ringbuffer.h +63 -38

128 lines not on this page · raw message

Signature · 6 lines
2.9.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author maintainer
#19 lore raw

PATCH v6 8/10 drm/i915/pmu: Add interrupt count metric

In reply to Tvrtko Ursulin

From: Tvrtko Ursulin <[email protected]>

For clients like intel-gpu-overlay it is easier to read the count via the perf API than having to parse /proc.

---
 drivers/gpu/drm/i915/i915_pmu.c | 23 +++++++++++++++++++++++
 include/uapi/drm/i915_drm.h     |  4 +++-
 2 files changed, 26 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_pmu.c +23 -0
index 4c9b9ae09b23..4c37c8b3cc54 100644
@@ -276,6 +276,22 @@ static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer)
 	return HRTIMER_RESTART;
 }
 
+static u64 count_interrupts(struct drm_i915_private *i915)
+{
+	/* open-coded kstat_irqs() */
+	struct irq_desc *desc = irq_to_desc(i915->drm.pdev->irq);
+	u64 sum = 0;
+	int cpu;
+
+	if (!desc || !desc->kstat_irqs)
+		return 0;
+
+	for_each_possible_cpu(cpu)
+		sum += *per_cpu_ptr(desc->kstat_irqs, cpu);
+
+	return sum;
+}
+
 static void i915_pmu_event_destroy(struct perf_event *event)
 {
 	WARN_ON(event->parent);
@@ -342,6 +358,8 @@ static int i915_pmu_event_init(struct perf_event *event)
 			if (INTEL_GEN(i915) < 6)
 				ret = -ENODEV;
 			break;
+		case I915_PMU_INTERRUPTS:
+			break;
 		default:
 			ret = -ENOENT;
 			break;
@@ -391,6 +409,9 @@ static u64 __i915_pmu_event_read(struct perf_event *event)
 			   div_u64(i915->pmu.sample[__I915_SAMPLE_FREQ_REQ].cur,
 				   FREQUENCY);
 			break;
+		case I915_PMU_INTERRUPTS:
+			val = count_interrupts(i915);
+			break;
 		}
 	}
 
@@ -643,6 +664,8 @@ static struct attribute *i915_pmu_events_attrs[] = {
 	I915_EVENT(actual-frequency,    I915_PMU_ACTUAL_FREQUENCY,    "MHz"),
 	I915_EVENT(requested-frequency, I915_PMU_REQUESTED_FREQUENCY, "MHz"),
 
+	I915_EVENT_ATTR(interrupts, I915_PMU_INTERRUPTS),
+
 	NULL,
 };
 
include/uapi/drm/i915_drm.h +3 -1
index 9f139f8ad19a..22b3e5e5bef8 100644
@@ -132,7 +132,9 @@ enum drm_i915_pmu_engine_sample {
 #define I915_PMU_ACTUAL_FREQUENCY	__I915_PMU_OTHER(0)
 #define I915_PMU_REQUESTED_FREQUENCY	__I915_PMU_OTHER(1)
 
-#define I915_PMU_LAST I915_PMU_REQUESTED_FREQUENCY
+#define I915_PMU_INTERRUPTS		__I915_PMU_OTHER(2)
+
+#define I915_PMU_LAST I915_PMU_INTERRUPTS
 
 /* Each region is a minimum of 16k, and there are at most 255 of them.
  */
Signature · 6 lines
2.9.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Reviewed-by on v6 8/10
#20 lore raw

Re: [PATCH 08/10] drm/i915/pmu: Add interrupt count metric

Quoting Tvrtko Ursulin (2017-09-29 13:34:58)

Quoted 6 lines

From: Tvrtko Ursulin <[email protected]>

For clients like intel-gpu-overlay it is easier to read the count via the perf API than having to parse /proc.

I may be biased, but

-Chris
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

author maintainer
#21 lore raw

PATCH v6 9/10 drm/i915: Convert intel_rc6_residency_us to ns

In reply to Tvrtko Ursulin

From: Tvrtko Ursulin <[email protected]>

Will be used for exposing the PMU counters.

v2:
* Move intel_runtime_pm_get/put to the callers. (Chris Wilson)
* Restore full unit conversion precision.

---
 drivers/gpu/drm/i915/i915_drv.h   |  8 +++++++-
 drivers/gpu/drm/i915/i915_sysfs.c |  9 +++++++--
 drivers/gpu/drm/i915/intel_pm.c   | 27 +++++++++++++--------------
 3 files changed, 27 insertions(+), 17 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +7 -1
index a88f5be0229c..d5d0a8dbcf67 100644
@@ -4162,11 +4162,17 @@ void vlv_phy_reset_lanes(struct intel_encoder *encoder);
 
 int intel_gpu_freq(struct drm_i915_private *dev_priv, int val);
 int intel_freq_opcode(struct drm_i915_private *dev_priv, int val);
-u64 intel_rc6_residency_us(struct drm_i915_private *dev_priv,
+u64 intel_rc6_residency_ns(struct drm_i915_private *dev_priv,
 			   const i915_reg_t reg);
 
 u32 intel_get_cagf(struct drm_i915_private *dev_priv, u32 rpstat1);
 
+static inline u64 intel_rc6_residency_us(struct drm_i915_private *dev_priv,
+					 const i915_reg_t reg)
+{
+	return DIV_ROUND_UP_ULL(intel_rc6_residency_ns(dev_priv, reg), 1000);
+}
+
 #define I915_READ8(reg)		dev_priv->uncore.funcs.mmio_readb(dev_priv, (reg), true)
 #define I915_WRITE8(reg, val)	dev_priv->uncore.funcs.mmio_writeb(dev_priv, (reg), (val), true)
 
drivers/gpu/drm/i915/i915_sysfs.c +7 -2
index 3bcf1c8c0dd9..2f74ae55332d 100644
@@ -42,8 +42,13 @@ static inline struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
 static u32 calc_residency(struct drm_i915_private *dev_priv,
 			  i915_reg_t reg)
 {
-	return DIV_ROUND_CLOSEST_ULL(intel_rc6_residency_us(dev_priv, reg),
-				     1000);
+	u64 res;
+
+	intel_runtime_pm_get(dev_priv);
+	res = intel_rc6_residency_us(dev_priv, reg);
+	intel_runtime_pm_put(dev_priv);
+
+	return DIV_ROUND_CLOSEST_ULL(res, 1000);
 }
 
 static ssize_t
drivers/gpu/drm/i915/intel_pm.c +13 -14
index c682ae4c98e9..e765c553e17e 100644
@@ -9343,36 +9343,35 @@ static u64 vlv_residency_raw(struct drm_i915_private *dev_priv,
 	return lower | (u64)upper << 8;
 }
 
-u64 intel_rc6_residency_us(struct drm_i915_private *dev_priv,
+u64 intel_rc6_residency_ns(struct drm_i915_private *dev_priv,
 			   const i915_reg_t reg)
 {
-	u64 time_hw, units, div;
+	u64 time_hw;
+	u32 mul, div;
 
 	if (!intel_enable_rc6())
 		return 0;
 
-	intel_runtime_pm_get(dev_priv);
-
 	/* On VLV and CHV, residency time is in CZ units rather than 1.28us */
 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-		units = 1000;
+		mul = 1000000;
 		div = dev_priv->czclk_freq;
-
 		time_hw = vlv_residency_raw(dev_priv, reg);
-	} else if (IS_GEN9_LP(dev_priv)) {
-		units = 1000;
-		div = 1200;		/* 833.33ns */
 
-		time_hw = I915_READ(reg);
 	} else {
-		units = 128000; /* 1.28us */
-		div = 100000;
+		/* 833.33ns units on Gen9LP, 1.28us elsewhere. */
+		if (IS_GEN9_LP(dev_priv)) {
+			mul = 10000;
+			div = 12;
+		} else {
+			mul = 1280;
+			div = 1;
+		}
 
 		time_hw = I915_READ(reg);
 	}
 
-	intel_runtime_pm_put(dev_priv);
-	return DIV_ROUND_UP_ULL(time_hw * units, div);
+	return DIV_ROUND_UP_ULL(time_hw * mul, div);
 }
 
 u32 intel_get_cagf(struct drm_i915_private *dev_priv, u32 rpstat)
Signature · 6 lines
2.9.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author maintainer
#22 lore raw

PATCH v6 10/10 drm/i915/pmu: Add RC6 residency metrics

In reply to Tvrtko Ursulin

From: Tvrtko Ursulin <[email protected]>

For clients like intel-gpu-overlay it is easier to read the counters via the perf API than having to parse sysfs.

---
 drivers/gpu/drm/i915/i915_pmu.c | 31 +++++++++++++++++++++++++++++++
 include/uapi/drm/i915_drm.h     |  6 +++++-
 2 files changed, 36 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_pmu.c +31 -0
index 4c37c8b3cc54..32b6c3c170e9 100644
@@ -360,6 +360,15 @@ static int i915_pmu_event_init(struct perf_event *event)
 			break;
 		case I915_PMU_INTERRUPTS:
 			break;
+		case I915_PMU_RC6_RESIDENCY:
+			if (!HAS_RC6(i915))
+				ret = -ENODEV;
+			break;
+		case I915_PMU_RC6p_RESIDENCY:
+		case I915_PMU_RC6pp_RESIDENCY:
+			if (!HAS_RC6p(i915))
+				ret = -ENODEV;
+			break;
 		default:
 			ret = -ENOENT;
 			break;
@@ -412,6 +421,24 @@ static u64 __i915_pmu_event_read(struct perf_event *event)
 		case I915_PMU_INTERRUPTS:
 			val = count_interrupts(i915);
 			break;
+		case I915_PMU_RC6_RESIDENCY:
+			intel_runtime_pm_get(i915);
+			val = intel_rc6_residency_ns(i915,
+						     IS_VALLEYVIEW(i915) ?
+						     VLV_GT_RENDER_RC6 :
+						     GEN6_GT_GFX_RC6);
+			intel_runtime_pm_put(i915);
+			break;
+		case I915_PMU_RC6p_RESIDENCY:
+			intel_runtime_pm_get(i915);
+			val = intel_rc6_residency_ns(i915, GEN6_GT_GFX_RC6p);
+			intel_runtime_pm_put(i915);
+			break;
+		case I915_PMU_RC6pp_RESIDENCY:
+			intel_runtime_pm_get(i915);
+			val = intel_rc6_residency_ns(i915, GEN6_GT_GFX_RC6pp);
+			intel_runtime_pm_put(i915);
+			break;
 		}
 	}
 
@@ -666,6 +693,10 @@ static struct attribute *i915_pmu_events_attrs[] = {
 
 	I915_EVENT_ATTR(interrupts, I915_PMU_INTERRUPTS),
 
+	I915_EVENT(rc6-residency,   I915_PMU_RC6_RESIDENCY,   "ns"),
+	I915_EVENT(rc6p-residency,  I915_PMU_RC6p_RESIDENCY,  "ns"),
+	I915_EVENT(rc6pp-residency, I915_PMU_RC6pp_RESIDENCY, "ns"),
+
 	NULL,
 };
 
include/uapi/drm/i915_drm.h +5 -1
index 22b3e5e5bef8..e6f8e0a5bd63 100644
@@ -134,7 +134,11 @@ enum drm_i915_pmu_engine_sample {
 
 #define I915_PMU_INTERRUPTS		__I915_PMU_OTHER(2)
 
-#define I915_PMU_LAST I915_PMU_INTERRUPTS
+#define I915_PMU_RC6_RESIDENCY		__I915_PMU_OTHER(3)
+#define I915_PMU_RC6p_RESIDENCY		__I915_PMU_OTHER(4)
+#define I915_PMU_RC6pp_RESIDENCY	__I915_PMU_OTHER(5)
+
+#define I915_PMU_LAST I915_PMU_RC6pp_RESIDENCY
 
 /* Each region is a minimum of 16k, and there are at most 255 of them.
  */
Signature · 6 lines
2.9.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Reviewed-by on v6 10/10
#23 lore raw

Re: [PATCH 10/10] drm/i915/pmu: Add RC6 residency metrics

Quoting Tvrtko Ursulin (2017-09-29 13:35:00)

Quoted 6 lines

From: Tvrtko Ursulin <[email protected]>

For clients like intel-gpu-overlay it is easier to read the counters via the perf API than having to parse sysfs.

-Chris
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#24 lore raw

✗ Fi.CI.BAT: failure for i915 PMU and engine busy stats (rev14)

In reply to Tvrtko Ursulin
== Series Details ==

== Series Details ==

Series: i915 PMU and engine busy stats (rev14)
URL : https://patchwork.freedesktop.org/series/27488/
State : failure

== Summary ==

Series 27488v14 i915 PMU and engine busy stats
https://patchwork.freedesktop.org/api/1.0/series/27488/revisions/14/mbox/

Test chamelium:

        Subgroup hdmi-crc-fast:
                dmesg-warn -> PASS       (fi-skl-6700k) fdo#103019
Test gem_exec_suspend:
        Subgroup basic-s3:
                pass       -> DMESG-FAIL (fi-kbl-7560u) fdo#103039
        Subgroup basic-s4-devices:
                pass       -> DMESG-FAIL (fi-kbl-7560u)
Test gem_flink_basic:
        Subgroup bad-flink:
                pass       -> DMESG-WARN (fi-kbl-7560u)
        Subgroup bad-open:
                pass       -> DMESG-WARN (fi-kbl-7560u)
        Subgroup basic:
                pass       -> DMESG-WARN (fi-kbl-7560u)
        Subgroup double-flink:
                pass       -> DMESG-WARN (fi-kbl-7560u)
        Subgroup flink-lifetime:
                pass       -> DMESG-WARN (fi-kbl-7560u)
Test gem_linear_blits:
        Subgroup basic:
                pass       -> INCOMPLETE (fi-kbl-7560u)
Test kms_busy:
        Subgroup basic-flip-c:
                incomplete -> PASS       (fi-bxt-j4205) fdo#102035
Test drv_module_reload:
        Subgroup basic-reload:
                pass       -> DMESG-WARN (fi-glk-1) fdo#102777 +1

fdo#103019 https://bugs.freedesktop.org/show_bug.cgi?id=103019
fdo#103039 https://bugs.freedesktop.org/show_bug.cgi?id=103039
fdo#102035 https://bugs.freedesktop.org/show_bug.cgi?id=102035
fdo#102777 https://bugs.freedesktop.org/show_bug.cgi?id=102777

fi-bdw-5557u     total:289  pass:268  dwarn:0   dfail:0   fail:0   skip:21  time:442s
fi-bdw-gvtdvm    total:289  pass:265  dwarn:0   dfail:0   fail:0   skip:24  time:472s
fi-blb-e6850     total:289  pass:224  dwarn:1   dfail:0   fail:0   skip:64  time:416s
fi-bsw-n3050     total:289  pass:243  dwarn:0   dfail:0   fail:0   skip:46  time:524s
fi-bwr-2160      total:289  pass:184  dwarn:0   dfail:0   fail:0   skip:105 time:278s
fi-bxt-dsi       total:289  pass:259  dwarn:0   dfail:0   fail:0   skip:30  time:498s
fi-bxt-j4205     total:289  pass:260  dwarn:0   dfail:0   fail:0   skip:29  time:512s
fi-byt-j1900     total:289  pass:254  dwarn:1   dfail:0   fail:0   skip:34  time:504s
fi-byt-n2820     total:289  pass:250  dwarn:1   dfail:0   fail:0   skip:38  time:491s
fi-cfl-s         total:289  pass:256  dwarn:1   dfail:0   fail:0   skip:32  time:575s
fi-cnl-y         total:289  pass:261  dwarn:1   dfail:0   fail:0   skip:27  time:654s
fi-elk-e7500     total:289  pass:230  dwarn:0   dfail:0   fail:0   skip:59  time:419s
fi-glk-1         total:289  pass:259  dwarn:1   dfail:0   fail:0   skip:29  time:567s
fi-hsw-4770      total:289  pass:263  dwarn:0   dfail:0   fail:0   skip:26  time:426s
fi-hsw-4770r     total:289  pass:263  dwarn:0   dfail:0   fail:0   skip:26  time:409s
fi-ilk-650       total:289  pass:229  dwarn:0   dfail:0   fail:0   skip:60  time:442s
fi-ivb-3520m     total:289  pass:261  dwarn:0   dfail:0   fail:0   skip:28  time:491s
fi-ivb-3770      total:289  pass:261  dwarn:0   dfail:0   fail:0   skip:28  time:466s
fi-kbl-7500u     total:289  pass:264  dwarn:1   dfail:0   fail:0   skip:24  time:479s
fi-kbl-7560u     total:125  pass:105  dwarn:5   dfail:2   fail:0   skip:12 
fi-kbl-r         total:289  pass:262  dwarn:0   dfail:0   fail:0   skip:27  time:591s
fi-pnv-d510      total:289  pass:223  dwarn:1   dfail:0   fail:0   skip:65  time:539s
fi-skl-6260u     total:289  pass:269  dwarn:0   dfail:0   fail:0   skip:20  time:458s
fi-skl-6700k     total:289  pass:265  dwarn:0   dfail:0   fail:0   skip:24  time:757s
fi-skl-6770hq    total:289  pass:269  dwarn:0   dfail:0   fail:0   skip:20  time:499s
fi-skl-gvtdvm    total:289  pass:266  dwarn:0   dfail:0   fail:0   skip:23  time:480s
fi-snb-2520m     total:289  pass:251  dwarn:0   dfail:0   fail:0   skip:38  time:567s
fi-snb-2600      total:289  pass:250  dwarn:0   dfail:0   fail:0   skip:39  time:425s

e650b9cdaff616445f38986379b1c0c4b03a4282 drm-tip: 2017y-09m-29d-11h-52m-41s UTC integration manifest d6bb4ffe272c drm/i915/pmu: Add RC6 residency metrics
8367371570b8 drm/i915: Convert intel_rc6_residency_us to ns
41cfb8c88854 drm/i915/pmu: Add interrupt count metric
d750c96fcf70 drm/i915: Gate engine stats collection with a static key
951856e5e46e drm/i915/pmu: Wire up engine busy stats to PMU
a96eb19281ca drm/i915: Engine busy time tracking
6e78d3fa10e4 drm/i915: Wrap context schedule notification
1b32e7bd3062 drm/i915/pmu: Suspend sampling when GPU is idle
9f7bf32a6f5f drm/i915/pmu: Expose a PMU interface for perf queries
c262c1085fcd drm/i915: Extract intel_get_cagf

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_5860/
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#25 lore raw

✗ Fi.CI.BAT: failure for i915 PMU and engine busy stats (rev16)

In reply to Tvrtko Ursulin
== Series Details ==

== Series Details ==

Series: i915 PMU and engine busy stats (rev16)
URL : https://patchwork.freedesktop.org/series/27488/
State : failure

== Summary ==

Series 27488v16 i915 PMU and engine busy stats
https://patchwork.freedesktop.org/api/1.0/series/27488/revisions/16/mbox/

Test gem_exec_suspend:

        Subgroup basic-s3:
                pass       -> INCOMPLETE (fi-byt-j1900)
                pass       -> INCOMPLETE (fi-glk-1)
                pass       -> INCOMPLETE (fi-cnl-y) fdo#103070
Test kms_flip:
        Subgroup basic-flip-vs-dpms:
                dmesg-warn -> PASS       (fi-skl-6700hq)
Test kms_pipe_crc_basic:
        Subgroup suspend-read-crc-pipe-b:
                dmesg-warn -> PASS       (fi-byt-n2820) fdo#101705
Test drv_module_reload:
        Subgroup basic-no-display:
                pass       -> DMESG-WARN (fi-cfl-s) fdo#103022

fdo#103070 https://bugs.freedesktop.org/show_bug.cgi?id=103070
fdo#101705 https://bugs.freedesktop.org/show_bug.cgi?id=101705
fdo#103022 https://bugs.freedesktop.org/show_bug.cgi?id=103022

fi-bdw-5557u     total:289  pass:268  dwarn:0   dfail:0   fail:0   skip:21  time:457s
fi-bdw-gvtdvm    total:289  pass:265  dwarn:0   dfail:0   fail:0   skip:24  time:471s
fi-blb-e6850     total:289  pass:223  dwarn:1   dfail:0   fail:0   skip:65  time:397s
fi-bsw-n3050     total:289  pass:243  dwarn:0   dfail:0   fail:0   skip:46  time:563s
fi-bwr-2160      total:289  pass:183  dwarn:0   dfail:0   fail:0   skip:106 time:288s
fi-bxt-dsi       total:289  pass:259  dwarn:0   dfail:0   fail:0   skip:30  time:534s
fi-bxt-j4205     total:289  pass:260  dwarn:0   dfail:0   fail:0   skip:29  time:528s
fi-byt-j1900     total:118  pass:96   dwarn:0   dfail:0   fail:0   skip:21 
fi-byt-n2820     total:289  pass:250  dwarn:0   dfail:0   fail:0   skip:39  time:528s
fi-cfl-s         total:289  pass:255  dwarn:2   dfail:0   fail:0   skip:32  time:563s
fi-cnl-y         total:118  pass:97   dwarn:0   dfail:0   fail:0   skip:20 
fi-elk-e7500     total:289  pass:229  dwarn:0   dfail:0   fail:0   skip:60  time:435s
fi-glk-1         total:118  pass:96   dwarn:0   dfail:0   fail:0   skip:21 
fi-hsw-4770      total:289  pass:262  dwarn:0   dfail:0   fail:0   skip:27  time:442s
fi-hsw-4770r     total:289  pass:262  dwarn:0   dfail:0   fail:0   skip:27  time:426s
fi-ilk-650       total:289  pass:228  dwarn:0   dfail:0   fail:0   skip:61  time:465s
fi-ivb-3520m     total:289  pass:260  dwarn:0   dfail:0   fail:0   skip:29  time:506s
fi-ivb-3770      total:289  pass:260  dwarn:0   dfail:0   fail:0   skip:29  time:478s
fi-kbl-7500u     total:289  pass:264  dwarn:1   dfail:0   fail:0   skip:24  time:503s
fi-kbl-7560u     total:289  pass:270  dwarn:0   dfail:0   fail:0   skip:19  time:583s
fi-kbl-7567u     total:289  pass:265  dwarn:4   dfail:0   fail:0   skip:20  time:490s
fi-kbl-r         total:289  pass:262  dwarn:0   dfail:0   fail:0   skip:27  time:596s
fi-pnv-d510      total:289  pass:222  dwarn:1   dfail:0   fail:0   skip:66  time:657s
fi-skl-6260u     total:289  pass:269  dwarn:0   dfail:0   fail:0   skip:20  time:473s
fi-skl-6700hq    total:289  pass:263  dwarn:0   dfail:0   fail:0   skip:26  time:664s
fi-skl-6700k     total:289  pass:265  dwarn:0   dfail:0   fail:0   skip:24  time:531s
fi-skl-6770hq    total:289  pass:269  dwarn:0   dfail:0   fail:0   skip:20  time:520s
fi-skl-gvtdvm    total:289  pass:266  dwarn:0   dfail:0   fail:0   skip:23  time:472s
fi-snb-2520m     total:289  pass:250  dwarn:0   dfail:0   fail:0   skip:39  time:587s
fi-snb-2600      total:289  pass:249  dwarn:0   dfail:0   fail:0   skip:40  time:434s

e364976751b3f78eb32ea957eb40deb0682393e5 drm-tip: 2017y-10m-06d-06h-41m-16s UTC integration manifest 8b2f2f5623d7 drm/i915/pmu: Add RC6 residency metrics
eb861d1dc957 drm/i915: Convert intel_rc6_residency_us to ns
897633f8f9f2 drm/i915/pmu: Add interrupt count metric
86bd77cec41b drm/i915: Gate engine stats collection with a static key
2415b9d8811e drm/i915/pmu: Wire up engine busy stats to PMU
c864c4e86478 drm/i915: Engine busy time tracking
3e371cf95ca1 drm/i915: Wrap context schedule notification
21a4b6b25293 drm/i915/pmu: Suspend sampling when GPU is idle
1432134e24be drm/i915/pmu: Expose a PMU interface for perf queries
1cdb0d8827d6 drm/i915: Extract intel_get_cagf

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_5911/
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx