@@ -182,6 +182,9 @@ i915-y += i915_perf.o \
i915_oa_cnl.o \
i915_oa_icl.o
+# tracing
+i915-$(CONFIG_TRACEPOINTS) += i915_tracing.o
+
ifeq ($(CONFIG_DRM_I915_GVT),y)
i915-y += intel_gvt.o
include $(src)/gvt/Makefile
@@ -1281,6 +1281,9 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
*/
if (INTEL_INFO(dev_priv)->num_pipes)
drm_kms_helper_poll_init(dev);
+
+ /* Notify our tracepoints driver has been registered. */
+ i915_tracing_register(dev_priv);
}
/**
@@ -1292,6 +1295,8 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
intel_fbdev_unregister(dev_priv);
intel_audio_deinit(dev_priv);
+ i915_tracing_unregister(dev_priv);
+
/*
* After flushing the fbdev (incl. a late async config which will
* have delayed queuing of a hotplug event), then flush the hotplug
@@ -2141,6 +2141,8 @@ struct drm_i915_private {
struct i915_pmu pmu;
+ struct list_head tracing_link;
+
/*
* NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
* will be rejected. Instead look for a better place.
@@ -1157,10 +1157,10 @@ static void notify_ring(struct intel_engine_cs *engine)
const u32 seqno = intel_engine_get_seqno(engine);
struct i915_request *rq = NULL;
struct task_struct *tsk = NULL;
- struct intel_wait *wait;
+ struct intel_wait *wait = NULL;
if (unlikely(!engine->breadcrumbs.irq_armed))
- return;
+ goto out;
rcu_read_lock();
@@ -1219,6 +1219,7 @@ static void notify_ring(struct intel_engine_cs *engine)
rcu_read_unlock();
+out:
trace_intel_engine_notify(engine, wait);
}
@@ -8,6 +8,7 @@
#include <drm/drmP.h>
#include "i915_drv.h"
+#include "i915_tracing.h"
#include "intel_drv.h"
#include "intel_ringbuffer.h"
@@ -780,29 +781,32 @@ trace_i915_request_out(struct i915_request *rq)
#endif
#endif
-TRACE_EVENT(intel_engine_notify,
- TP_PROTO(struct intel_engine_cs *engine, bool waiters),
- TP_ARGS(engine, waiters),
-
- TP_STRUCT__entry(
- __field(u32, dev)
- __field(u16, class)
- __field(u16, instance)
- __field(u32, seqno)
- __field(bool, waiters)
- ),
-
- TP_fast_assign(
- __entry->dev = engine->i915->drm.primary->index;
- __entry->class = engine->uabi_class;
- __entry->instance = engine->instance;
- __entry->seqno = intel_engine_get_seqno(engine);
- __entry->waiters = waiters;
- ),
-
- TP_printk("dev=%u, engine=%u:%u, seqno=%u, waiters=%u",
- __entry->dev, __entry->class, __entry->instance,
- __entry->seqno, __entry->waiters)
+TRACE_EVENT_FN(intel_engine_notify,
+ TP_PROTO(struct intel_engine_cs *engine, bool waiters),
+ TP_ARGS(engine, waiters),
+
+ TP_STRUCT__entry(
+ __field(u32, dev)
+ __field(u16, class)
+ __field(u16, instance)
+ __field(u32, seqno)
+ __field(bool, waiters)
+ ),
+
+ TP_fast_assign(
+ __entry->dev = engine->i915->drm.primary->index;
+ __entry->class = engine->uabi_class;
+ __entry->instance = engine->instance;
+ __entry->seqno = intel_engine_get_seqno(engine);
+ __entry->waiters = waiters;
+ ),
+
+ TP_printk("dev=%u, engine=%u:%u, seqno=%u, waiters=%u",
+ __entry->dev, __entry->class, __entry->instance,
+ __entry->seqno, __entry->waiters),
+
+ intel_engine_notify_tracepoint_register,
+ intel_engine_notify_tracepoint_unregister
);
DEFINE_EVENT(i915_request, i915_request_retire,
new file mode 100644
@@ -0,0 +1,137 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright © 2018 Intel Corporation
+ *
+ */
+
+#include "i915_tracing.h"
+
+#include "i915_drv.h"
+#include "intel_ringbuffer.h"
+
+static DEFINE_MUTEX(driver_list_lock);
+static LIST_HEAD(driver_list);
+static bool notify_enabled;
+
+static void __i915_enable_notify(struct drm_i915_private *i915)
+{
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+
+ intel_runtime_pm_get(i915);
+
+ for_each_engine(engine, i915, id)
+ intel_engine_pin_breadcrumbs_irq(engine);
+
+ intel_runtime_pm_put(i915);
+}
+
+static void __i915_disable_notify(struct drm_i915_private *i915)
+{
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+
+ intel_runtime_pm_get(i915);
+
+ for_each_engine(engine, i915, id)
+ intel_engine_unpin_breadcrumbs_irq(engine);
+
+ intel_runtime_pm_put(i915);
+}
+
+/**
+ * i915_tracing_register - registers driver tracepoints support
+ * @i915: the drm_i915_private device
+ *
+ * Registers the tracepoints support from the driver registration path.
+ *
+ * Puts the driver on the local list and enables the unconditional notifications
+ * for the intel_engine_notify tracepoint if they should be enabled.
+ */
+void i915_tracing_register(struct drm_i915_private *i915)
+{
+ INIT_LIST_HEAD(&i915->tracing_link);
+
+ mutex_lock(&driver_list_lock);
+
+ list_add_tail(&i915->tracing_link, &driver_list);
+
+ if (notify_enabled)
+ __i915_enable_notify(i915);
+
+ mutex_unlock(&driver_list_lock);
+}
+
+/**
+ * i915_tracing_unregister - unregisters driver tracepoints support
+ * @i915: the drm_i915_private device
+ *
+ * Un-registers the tracepoints support from the driver un-registration path.
+ *
+ * Removes the driver from the local list and disables the unconditional
+ * notifications for the intel_engine_notify tracepoint if they were enabled.
+ */
+void i915_tracing_unregister(struct drm_i915_private *i915)
+{
+ mutex_lock(&driver_list_lock);
+
+ if (notify_enabled)
+ __i915_disable_notify(i915);
+
+ list_del(&i915->tracing_link);
+
+ mutex_unlock(&driver_list_lock);
+}
+
+/**
+ * intel_engine_notify_tracepoint_register - tracepoint registration callback
+ *
+ * This is called as the intel_engine_notify registration callback, ie. when
+ * the tracepoint is first activated.
+ */
+int intel_engine_notify_tracepoint_register(void)
+{
+ struct drm_i915_private *i915;
+
+ mutex_lock(&driver_list_lock);
+
+ GEM_BUG_ON(notify_enabled);
+
+ /*
+ * Enable user interrupts / constant intel_engine_notify notifications.
+ */
+ list_for_each_entry(i915, &driver_list, tracing_link)
+ __i915_enable_notify(i915);
+
+ notify_enabled = true;
+
+ mutex_unlock(&driver_list_lock);
+
+ return 0;
+}
+
+/**
+ * intel_engine_notify_tracepoint_unregister - tracepoint unregistration callback
+ *
+ * This is called as the intel_engine_notify unregistration callback, ie. when
+ * the last listener of this tracepoint goes away.
+ */
+void intel_engine_notify_tracepoint_unregister(void)
+{
+ struct drm_i915_private *i915;
+
+ mutex_lock(&driver_list_lock);
+
+ GEM_BUG_ON(!notify_enabled);
+
+ /*
+ * Disable user interrupts / constant intel_engine_notify notifications.
+ */
+ list_for_each_entry(i915, &driver_list, tracing_link)
+ __i915_disable_notify(i915);
+
+ notify_enabled = false;
+
+ mutex_unlock(&driver_list_lock);
+}
new file mode 100644
@@ -0,0 +1,30 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright © 2018 Intel Corporation
+ *
+ */
+#ifndef _I915_TRACING_H_
+#define _I915_TRACING_H_
+
+struct drm_i915_private;
+
+#if IS_ENABLED(CONFIG_TRACEPOINTS)
+
+void i915_tracing_register(struct drm_i915_private *i915);
+void i915_tracing_unregister(struct drm_i915_private *i915);
+
+int intel_engine_notify_tracepoint_register(void);
+void intel_engine_notify_tracepoint_unregister(void);
+
+#else
+
+static inline void i915_tracing_register(struct drm_i915_private *i915) { }
+static inline void i915_tracing_unregister(struct drm_i915_private *i915) { }
+
+static inline int intel_engine_notify_tracepoint_register(void) { return 0; }
+static inline void intel_engine_notify_tracepoint_unregister(void) { }
+
+#endif
+
+#endif