* [RFC 1/8] drm/i915: Have globally unique context ids, as opposed to drm file specific
2015-07-15 8:46 [RFC 0/8] Introduce framework to forward multi context OA snapshots sourab.gupta
@ 2015-07-15 8:46 ` sourab.gupta
2015-07-15 9:54 ` Chris Wilson
2015-07-15 8:46 ` [RFC 2/8] drm/i915: Introduce mode for capture of multi ctx OA reports synchronized with RCS sourab.gupta
` (6 subsequent siblings)
7 siblings, 1 reply; 17+ messages in thread
From: sourab.gupta @ 2015-07-15 8:46 UTC (permalink / raw)
To: intel-gfx; +Cc: Insoo Woo, Peter Zijlstra, Jabin Wu, Sourab Gupta
From: Sourab Gupta <sourab.gupta@intel.com>
Currently the context ids are specific to a drm file instance, as opposed
to being globally unique. There are some usecases, which may require
globally unique context ids. For e.g. a system level GPU profiler tool may
lean upon the context ids to associate the performance snapshots with
individual contexts. If the context ids are unique, it may do so without
relying on any additional information such as pid and drm fd.
This patch proposes an implementation of globally unique context ids, by
conceptually moving the idr table for holding the context ids, into device
private structure instead of file private structure. The case of default
context id for drm file (which is given by id=0) is handled by storing the
same in file private during context creation, and retrieving as and when
required.
This patch is proposed an an enabler for the patches following in the
series. In particular, I'm looking for feedback on the pros and cons of
having a globally unique context id, and any specific inputs on this
particular implementation. This implementation can be improved upon, if
agreed upon conceptually.
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
---
drivers/gpu/drm/i915/i915_debugfs.c | 4 +--
drivers/gpu/drm/i915/i915_drv.h | 4 ++-
drivers/gpu/drm/i915/i915_gem_context.c | 53 +++++++++++++++++++++++----------
3 files changed, 41 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 47636f3..38e0026 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2254,12 +2254,10 @@ static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev)
}
list_for_each_entry_reverse(file, &dev->filelist, lhead) {
- struct drm_i915_file_private *file_priv = file->driver_priv;
-
seq_printf(m, "proc: %s\n",
get_pid_task(file->pid, PIDTYPE_PID)->comm);
- idr_for_each(&file_priv->context_idr, per_file_ctx, m);
}
+ idr_for_each(&dev_priv->context_idr, per_file_ctx, m);
seq_printf(m, "ECOCHK: 0x%08x\n", I915_READ(GAM_ECOCHK));
}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 50977f0..baa0234 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -320,7 +320,7 @@ struct drm_i915_file_private {
*/
#define DRM_I915_THROTTLE_JIFFIES msecs_to_jiffies(20)
} mm;
- struct idr context_idr;
+ u32 first_ctx_id;
struct intel_rps_client {
struct list_head link;
@@ -1754,6 +1754,8 @@ struct drm_i915_private {
struct intel_opregion opregion;
struct intel_vbt_data vbt;
+ struct idr context_idr;
+
bool preserve_bios_swizzle;
/* overlay */
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index d9ccad5..6b572c1 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -212,7 +212,8 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size)
static struct intel_context *
__create_hw_context(struct drm_device *dev,
- struct drm_i915_file_private *file_priv)
+ struct drm_i915_file_private *file_priv,
+ bool is_first_ctx)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_context *ctx;
@@ -237,10 +238,12 @@ __create_hw_context(struct drm_device *dev,
/* Default context will never have a file_priv */
if (file_priv != NULL) {
- ret = idr_alloc(&file_priv->context_idr, ctx,
+ ret = idr_alloc(&dev_priv->context_idr, ctx,
DEFAULT_CONTEXT_HANDLE, 0, GFP_KERNEL);
if (ret < 0)
goto err_out;
+ if (is_first_ctx)
+ file_priv->first_ctx_id = ret;
} else
ret = DEFAULT_CONTEXT_HANDLE;
@@ -267,7 +270,8 @@ err_out:
*/
static struct intel_context *
i915_gem_create_context(struct drm_device *dev,
- struct drm_i915_file_private *file_priv)
+ struct drm_i915_file_private *file_priv,
+ bool is_first_ctx)
{
const bool is_global_default_ctx = file_priv == NULL;
struct intel_context *ctx;
@@ -275,7 +279,7 @@ i915_gem_create_context(struct drm_device *dev,
BUG_ON(!mutex_is_locked(&dev->struct_mutex));
- ctx = __create_hw_context(dev, file_priv);
+ ctx = __create_hw_context(dev, file_priv, is_first_ctx);
if (IS_ERR(ctx))
return ctx;
@@ -348,6 +352,14 @@ void i915_gem_context_reset(struct drm_device *dev)
}
}
+static int context_idr_cleanup(int id, void *p, void *data)
+{
+ struct intel_context *ctx = p;
+
+ i915_gem_context_unreference(ctx);
+ return 0;
+}
+
int i915_gem_context_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -371,8 +383,9 @@ int i915_gem_context_init(struct drm_device *dev)
dev_priv->hw_context_size = 0;
}
}
+ idr_init(&dev_priv->context_idr);
- ctx = i915_gem_create_context(dev, NULL);
+ ctx = i915_gem_create_context(dev, NULL, false);
if (IS_ERR(ctx)) {
DRM_ERROR("Failed to create default global context (error %ld)\n",
PTR_ERR(ctx));
@@ -398,6 +411,9 @@ void i915_gem_context_fini(struct drm_device *dev)
struct intel_context *dctx = dev_priv->ring[RCS].default_context;
int i;
+ idr_for_each(&dev_priv->context_idr, context_idr_cleanup, NULL);
+ idr_destroy(&dev_priv->context_idr);
+
if (dctx->legacy_hw_ctx.rcs_state) {
/* The only known way to stop the gpu from accessing the hw context is
* to reset it. Do this as the very last operation to avoid confusing
@@ -465,11 +481,14 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv)
return 0;
}
-static int context_idr_cleanup(int id, void *p, void *data)
+static int cleanup_file_contexts(int id, void *p, void *data)
{
struct intel_context *ctx = p;
+ struct drm_i915_file_private *file_priv = data;
+
+ if (ctx->file_priv == file_priv)
+ i915_gem_context_unreference(ctx);
- i915_gem_context_unreference(ctx);
return 0;
}
@@ -478,14 +497,11 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file)
struct drm_i915_file_private *file_priv = file->driver_priv;
struct intel_context *ctx;
- idr_init(&file_priv->context_idr);
-
mutex_lock(&dev->struct_mutex);
- ctx = i915_gem_create_context(dev, file_priv);
+ ctx = i915_gem_create_context(dev, file_priv, true);
mutex_unlock(&dev->struct_mutex);
if (IS_ERR(ctx)) {
- idr_destroy(&file_priv->context_idr);
return PTR_ERR(ctx);
}
@@ -495,17 +511,21 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file)
void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
{
struct drm_i915_file_private *file_priv = file->driver_priv;
+ struct drm_i915_private *dev_priv = file_priv->dev_priv;
- idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
- idr_destroy(&file_priv->context_idr);
+ idr_for_each(&dev_priv->context_idr, cleanup_file_contexts, file_priv);
}
struct intel_context *
i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id)
{
+ struct drm_i915_private *dev_priv = file_priv->dev_priv;
struct intel_context *ctx;
- ctx = (struct intel_context *)idr_find(&file_priv->context_idr, id);
+ if (id == 0)
+ id = file_priv->first_ctx_id;
+
+ ctx = (struct intel_context *)idr_find(&dev_priv->context_idr, id);
if (!ctx)
return ERR_PTR(-ENOENT);
@@ -862,7 +882,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
if (ret)
return ret;
- ctx = i915_gem_create_context(dev, file_priv);
+ ctx = i915_gem_create_context(dev, file_priv, false);
mutex_unlock(&dev->struct_mutex);
if (IS_ERR(ctx))
return PTR_ERR(ctx);
@@ -878,6 +898,7 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_gem_context_destroy *args = data;
struct drm_i915_file_private *file_priv = file->driver_priv;
+ struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_context *ctx;
int ret;
@@ -894,7 +915,7 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
return PTR_ERR(ctx);
}
- idr_remove(&ctx->file_priv->context_idr, ctx->user_handle);
+ idr_remove(&dev_priv->context_idr, ctx->user_handle);
i915_gem_context_unreference(ctx);
mutex_unlock(&dev->struct_mutex);
--
1.8.5.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [RFC 1/8] drm/i915: Have globally unique context ids, as opposed to drm file specific
2015-07-15 8:46 ` [RFC 1/8] drm/i915: Have globally unique context ids, as opposed to drm file specific sourab.gupta
@ 2015-07-15 9:54 ` Chris Wilson
2015-07-15 10:31 ` Chris Wilson
0 siblings, 1 reply; 17+ messages in thread
From: Chris Wilson @ 2015-07-15 9:54 UTC (permalink / raw)
To: sourab.gupta; +Cc: Peter Zijlstra, intel-gfx, Jabin Wu, Insoo Woo
On Wed, Jul 15, 2015 at 02:16:56PM +0530, sourab.gupta@intel.com wrote:
> From: Sourab Gupta <sourab.gupta@intel.com>
>
> Currently the context ids are specific to a drm file instance, as opposed
> to being globally unique. There are some usecases, which may require
> globally unique context ids. For e.g. a system level GPU profiler tool may
> lean upon the context ids to associate the performance snapshots with
> individual contexts. If the context ids are unique, it may do so without
> relying on any additional information such as pid and drm fd.
>
> This patch proposes an implementation of globally unique context ids, by
> conceptually moving the idr table for holding the context ids, into device
> private structure instead of file private structure. The case of default
> context id for drm file (which is given by id=0) is handled by storing the
> same in file private during context creation, and retrieving as and when
> required.
>
> This patch is proposed an an enabler for the patches following in the
> series. In particular, I'm looking for feedback on the pros and cons of
> having a globally unique context id, and any specific inputs on this
> particular implementation. This implementation can be improved upon, if
> agreed upon conceptually.
Simpler: use a cyclic idr for global context ids. The importance here is
that for the common case we have a more friendly per-file small lookup
table and reporting, also the code should be more understandable with a
separate user_handle and guid.
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC 1/8] drm/i915: Have globally unique context ids, as opposed to drm file specific
2015-07-15 9:54 ` Chris Wilson
@ 2015-07-15 10:31 ` Chris Wilson
2015-07-15 12:36 ` Daniel Vetter
0 siblings, 1 reply; 17+ messages in thread
From: Chris Wilson @ 2015-07-15 10:31 UTC (permalink / raw)
To: sourab.gupta, intel-gfx, Robert Bragg, Zhenyu Wang,
Jon Bloomfield, Peter Zijlstra, Jabin Wu, Insoo Woo
On Wed, Jul 15, 2015 at 10:54:28AM +0100, Chris Wilson wrote:
> On Wed, Jul 15, 2015 at 02:16:56PM +0530, sourab.gupta@intel.com wrote:
> > From: Sourab Gupta <sourab.gupta@intel.com>
> >
> > Currently the context ids are specific to a drm file instance, as opposed
> > to being globally unique. There are some usecases, which may require
> > globally unique context ids. For e.g. a system level GPU profiler tool may
> > lean upon the context ids to associate the performance snapshots with
> > individual contexts. If the context ids are unique, it may do so without
> > relying on any additional information such as pid and drm fd.
> >
> > This patch proposes an implementation of globally unique context ids, by
> > conceptually moving the idr table for holding the context ids, into device
> > private structure instead of file private structure. The case of default
> > context id for drm file (which is given by id=0) is handled by storing the
> > same in file private during context creation, and retrieving as and when
> > required.
> >
> > This patch is proposed an an enabler for the patches following in the
> > series. In particular, I'm looking for feedback on the pros and cons of
> > having a globally unique context id, and any specific inputs on this
> > particular implementation. This implementation can be improved upon, if
> > agreed upon conceptually.
>
> Simpler: use a cyclic idr for global context ids. The importance here is
> that for the common case we have a more friendly per-file small lookup
> table and reporting, also the code should be more understandable with a
> separate user_handle and guid.
I should emphasize that we really do want to keep user_handle inside a
per-file namespace.
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC 1/8] drm/i915: Have globally unique context ids, as opposed to drm file specific
2015-07-15 10:31 ` Chris Wilson
@ 2015-07-15 12:36 ` Daniel Vetter
0 siblings, 0 replies; 17+ messages in thread
From: Daniel Vetter @ 2015-07-15 12:36 UTC (permalink / raw)
To: Chris Wilson, sourab.gupta, intel-gfx, Robert Bragg, Zhenyu Wang,
Jon Bloomfield, Peter Zijlstra, Jabin Wu, Insoo Woo
On Wed, Jul 15, 2015 at 11:31:32AM +0100, Chris Wilson wrote:
> On Wed, Jul 15, 2015 at 10:54:28AM +0100, Chris Wilson wrote:
> > On Wed, Jul 15, 2015 at 02:16:56PM +0530, sourab.gupta@intel.com wrote:
> > > From: Sourab Gupta <sourab.gupta@intel.com>
> > >
> > > Currently the context ids are specific to a drm file instance, as opposed
> > > to being globally unique. There are some usecases, which may require
> > > globally unique context ids. For e.g. a system level GPU profiler tool may
> > > lean upon the context ids to associate the performance snapshots with
> > > individual contexts. If the context ids are unique, it may do so without
> > > relying on any additional information such as pid and drm fd.
> > >
> > > This patch proposes an implementation of globally unique context ids, by
> > > conceptually moving the idr table for holding the context ids, into device
> > > private structure instead of file private structure. The case of default
> > > context id for drm file (which is given by id=0) is handled by storing the
> > > same in file private during context creation, and retrieving as and when
> > > required.
> > >
> > > This patch is proposed an an enabler for the patches following in the
> > > series. In particular, I'm looking for feedback on the pros and cons of
> > > having a globally unique context id, and any specific inputs on this
> > > particular implementation. This implementation can be improved upon, if
> > > agreed upon conceptually.
> >
> > Simpler: use a cyclic idr for global context ids. The importance here is
> > that for the common case we have a more friendly per-file small lookup
> > table and reporting, also the code should be more understandable with a
> > separate user_handle and guid.
>
> I should emphasize that we really do want to keep user_handle inside a
> per-file namespace.
Yeah agreed, if we need some global internal ID because we need it in the
hw somewhere then that should be tracked in a separate hw_id field, and
allocated from a separate idr. That would also allow us to correctly
implement any restrictions the hw has (iirc we don't have the full 32bit
for ctx id, but not sure).
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 17+ messages in thread
* [RFC 2/8] drm/i915: Introduce mode for capture of multi ctx OA reports synchronized with RCS
2015-07-15 8:46 [RFC 0/8] Introduce framework to forward multi context OA snapshots sourab.gupta
2015-07-15 8:46 ` [RFC 1/8] drm/i915: Have globally unique context ids, as opposed to drm file specific sourab.gupta
@ 2015-07-15 8:46 ` sourab.gupta
2015-07-15 8:46 ` [RFC 3/8] drm/i915: Add mechanism for forwarding CS based OA counter snapshots through perf sourab.gupta
` (5 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: sourab.gupta @ 2015-07-15 8:46 UTC (permalink / raw)
To: intel-gfx; +Cc: Insoo Woo, Peter Zijlstra, Jabin Wu, Sourab Gupta
From: Sourab Gupta <sourab.gupta@intel.com>
This patch introduces a mode of capturing OA counter reports belonging to
multiple contexts, which can be mapped back to individual contexts. The OA
reports captured in this way are synchronized with Render command stream.
There may be usecases wherein we need more than periodic OA capture mode
which is supported by perf_event currently. We may need to insert RCS
synchronized commands to capture the OA counter snapshots.
This mode is primarily used for two usecases:
- Ability to capture system wide metrics, alongwith the ability to map
the reports back to individual contexts.
- Ability to inject tags for work, into the reports. This provides
visibility into the multiple stages of work within single context.
The OA reports generated in this way will be forwarded to userspace after
appending a footer, which will have this metadata information. This will
enable the usecases mentioned above.
This patch introduces an additional field in the oa attr structure for
supporting this capture mode. The data thus captured needs to be stored in
a separate buffer, which will be different from the buffer used otherwise
for periodic OA capture mode. Again this buffer address will not need to be
mapped to OA unit register addresses such as OASTATUS1, OASTATUS2 and
OABUFFER.
The subsequent patches introduce the mechanism for forwarding reports to
userspace, handling the command synchronization and mechanism for
inserting corresponding commands into the ringbuffer.
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 9 ++
drivers/gpu/drm/i915/i915_oa_perf.c | 173 +++++++++++++++++++++++++++---------
include/uapi/drm/i915_drm.h | 3 +-
3 files changed, 143 insertions(+), 42 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index baa0234..740148d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1930,6 +1930,7 @@ struct drm_i915_private {
bool event_active;
bool periodic;
+ bool multiple_ctx_mode;
u32 period_exponent;
u32 metrics_set;
@@ -1944,6 +1945,14 @@ struct drm_i915_private {
int format_size;
spinlock_t flush_lock;
} oa_buffer;
+
+ /* Fields for multiple context capture mode */
+ struct {
+ struct drm_i915_gem_object *obj;
+ u8 *addr;
+ int format;
+ int format_size;
+ } oa_rcs_buffer;
} oa_pmu;
#endif
diff --git a/drivers/gpu/drm/i915/i915_oa_perf.c b/drivers/gpu/drm/i915/i915_oa_perf.c
index e7e0b2b..b79582b 100644
--- a/drivers/gpu/drm/i915/i915_oa_perf.c
+++ b/drivers/gpu/drm/i915/i915_oa_perf.c
@@ -166,19 +166,39 @@ static void flush_oa_snapshots(struct drm_i915_private *dev_priv,
}
static void
-oa_buffer_destroy(struct drm_i915_private *i915)
+oa_rcs_buffer_destroy(struct drm_i915_private *i915)
{
+ unsigned long lock_flags;
+
mutex_lock(&i915->dev->struct_mutex);
+ vunmap(i915->oa_pmu.oa_rcs_buffer.addr);
+ i915_gem_object_ggtt_unpin(i915->oa_pmu.oa_rcs_buffer.obj);
+ drm_gem_object_unreference(&i915->oa_pmu.oa_rcs_buffer.obj->base);
+ mutex_unlock(&i915->dev->struct_mutex);
+ spin_lock_irqsave(&i915->oa_pmu.lock, lock_flags);
+ i915->oa_pmu.oa_rcs_buffer.obj = NULL;
+ i915->oa_pmu.oa_rcs_buffer.addr = NULL;
+ spin_unlock_irqrestore(&i915->oa_pmu.lock, lock_flags);
+}
+
+static void
+oa_buffer_destroy(struct drm_i915_private *i915)
+{
+ unsigned long lock_flags;
+
+ mutex_lock(&i915->dev->struct_mutex);
vunmap(i915->oa_pmu.oa_buffer.addr);
i915_gem_object_ggtt_unpin(i915->oa_pmu.oa_buffer.obj);
drm_gem_object_unreference(&i915->oa_pmu.oa_buffer.obj->base);
+ mutex_unlock(&i915->dev->struct_mutex);
+ spin_lock_irqsave(&i915->oa_pmu.lock, lock_flags);
i915->oa_pmu.oa_buffer.obj = NULL;
i915->oa_pmu.oa_buffer.gtt_offset = 0;
i915->oa_pmu.oa_buffer.addr = NULL;
+ spin_unlock_irqrestore(&i915->oa_pmu.lock, lock_flags);
- mutex_unlock(&i915->dev->struct_mutex);
}
static void i915_oa_event_destroy(struct perf_event *event)
@@ -207,6 +227,9 @@ static void i915_oa_event_destroy(struct perf_event *event)
I915_WRITE(GDT_CHICKEN_BITS, (I915_READ(GDT_CHICKEN_BITS) &
~GT_NOA_ENABLE));
+ if (dev_priv->oa_pmu.multiple_ctx_mode)
+ oa_rcs_buffer_destroy(dev_priv);
+
oa_buffer_destroy(dev_priv);
BUG_ON(dev_priv->oa_pmu.exclusive_event != event);
@@ -216,6 +239,59 @@ static void i915_oa_event_destroy(struct perf_event *event)
intel_runtime_pm_put(dev_priv);
}
+static int alloc_obj(struct drm_i915_private *dev_priv,
+ struct drm_i915_gem_object **obj)
+{
+ struct drm_i915_gem_object *bo;
+ int ret;
+
+ /* NB: We over allocate the OA buffer due to the way raw sample data
+ * gets copied from the gpu mapped circular buffer into the perf
+ * circular buffer so that only one copy is required.
+ *
+ * For each perf sample (raw->size + 4) needs to be 8 byte aligned,
+ * where the 4 corresponds to the 32bit raw->size member that's
+ * added to the sample header that userspace sees.
+ *
+ * Due to the + 4 for the size member: when we copy a report to the
+ * userspace facing perf buffer we always copy an additional 4 bytes
+ * from the subsequent report to make up for the miss alignment, but
+ * when a report is at the end of the gpu mapped buffer we need to
+ * read 4 bytes past the end of the buffer.
+ */
+ intel_runtime_pm_get(dev_priv);
+
+ ret = i915_mutex_lock_interruptible(dev_priv->dev);
+ if (ret)
+ goto out;
+
+ bo = i915_gem_alloc_object(dev_priv->dev, OA_BUFFER_SIZE + PAGE_SIZE);
+ if (bo == NULL) {
+ DRM_ERROR("Failed to allocate OA buffer\n");
+ ret = -ENOMEM;
+ goto unlock;
+ }
+ ret = i915_gem_object_set_cache_level(bo, I915_CACHE_LLC);
+ if (ret)
+ goto err_unref;
+
+ /* PreHSW required 512K alignment, HSW requires 16M */
+ ret = i915_gem_obj_ggtt_pin(bo, SZ_16M, 0);
+ if (ret)
+ goto err_unref;
+
+ *obj = bo;
+ goto unlock;
+
+err_unref:
+ drm_gem_object_unreference(&bo->base);
+unlock:
+ mutex_unlock(&dev_priv->dev->struct_mutex);
+out:
+ intel_runtime_pm_put(dev_priv);
+ return ret;
+}
+
static void *vmap_oa_buffer(struct drm_i915_gem_object *obj)
{
int i;
@@ -257,42 +333,13 @@ static int init_oa_buffer(struct perf_event *event)
BUG_ON(!IS_HASWELL(dev_priv->dev));
BUG_ON(dev_priv->oa_pmu.oa_buffer.obj);
- ret = i915_mutex_lock_interruptible(dev_priv->dev);
- if (ret)
- return ret;
-
spin_lock_init(&dev_priv->oa_pmu.oa_buffer.flush_lock);
- /* NB: We over allocate the OA buffer due to the way raw sample data
- * gets copied from the gpu mapped circular buffer into the perf
- * circular buffer so that only one copy is required.
- *
- * For each perf sample (raw->size + 4) needs to be 8 byte aligned,
- * where the 4 corresponds to the 32bit raw->size member that's
- * added to the sample header that userspace sees.
- *
- * Due to the + 4 for the size member: when we copy a report to the
- * userspace facing perf buffer we always copy an additional 4 bytes
- * from the subsequent report to make up for the miss alignment, but
- * when a report is at the end of the gpu mapped buffer we need to
- * read 4 bytes past the end of the buffer.
- */
- bo = i915_gem_alloc_object(dev_priv->dev, OA_BUFFER_SIZE + PAGE_SIZE);
- if (bo == NULL) {
- DRM_ERROR("Failed to allocate OA buffer\n");
- ret = -ENOMEM;
- goto unlock;
- }
- dev_priv->oa_pmu.oa_buffer.obj = bo;
-
- ret = i915_gem_object_set_cache_level(bo, I915_CACHE_LLC);
+ ret = alloc_obj(dev_priv, &bo);
if (ret)
- goto err_unref;
+ return ret;
- /* PreHSW required 512K alignment, HSW requires 16M */
- ret = i915_gem_obj_ggtt_pin(bo, SZ_16M, 0);
- if (ret)
- goto err_unref;
+ dev_priv->oa_pmu.oa_buffer.obj = bo;
dev_priv->oa_pmu.oa_buffer.gtt_offset = i915_gem_obj_ggtt_offset(bo);
dev_priv->oa_pmu.oa_buffer.addr = vmap_oa_buffer(bo);
@@ -309,14 +356,30 @@ static int init_oa_buffer(struct perf_event *event)
dev_priv->oa_pmu.oa_buffer.gtt_offset,
dev_priv->oa_pmu.oa_buffer.addr);
- goto unlock;
+ return 0;
+}
-err_unref:
- drm_gem_object_unreference(&bo->base);
+static int init_oa_rcs_buffer(struct perf_event *event)
+{
+ struct drm_i915_private *dev_priv =
+ container_of(event->pmu, typeof(*dev_priv), oa_pmu.pmu);
+ struct drm_i915_gem_object *bo;
+ int ret;
-unlock:
- mutex_unlock(&dev_priv->dev->struct_mutex);
- return ret;
+ BUG_ON(dev_priv->oa_pmu.oa_rcs_buffer.obj);
+
+ ret = alloc_obj(dev_priv, &bo);
+ if (ret)
+ return ret;
+
+ dev_priv->oa_pmu.oa_rcs_buffer.obj = bo;
+
+ dev_priv->oa_pmu.oa_rcs_buffer.addr = vmap_oa_buffer(bo);
+
+ DRM_DEBUG_DRIVER("OA RCS Buffer initialized, vaddr = %p",
+ dev_priv->oa_pmu.oa_rcs_buffer.addr);
+
+ return 0;
}
static enum hrtimer_restart hrtimer_sample(struct hrtimer *hrtimer)
@@ -427,6 +490,7 @@ static int i915_oa_event_init(struct perf_event *event)
container_of(event->pmu, typeof(*dev_priv), oa_pmu.pmu);
drm_i915_oa_attr_t oa_attr;
u64 report_format;
+ unsigned long lock_flags;
int ret = 0;
if (event->attr.type != event->pmu->type)
@@ -439,11 +503,28 @@ static int i915_oa_event_init(struct perf_event *event)
/* To avoid the complexity of having to accurately filter
* counter snapshots and marshal to the appropriate client
* we currently only allow exclusive access */
- if (dev_priv->oa_pmu.oa_buffer.obj)
+ spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
+ if (dev_priv->oa_pmu.oa_buffer.obj) {
+ spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
return -EBUSY;
+ }
+ spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
+
+ /*
+ * In case of multiple context mode, we need to check for
+ * CAP_SYS_ADMIN capability as we need to profile all the running
+ * contexts
+ */
+ if (oa_attr.multiple_context_mode) {
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ dev_priv->oa_pmu.multiple_ctx_mode = true;
+ }
report_format = oa_attr.format;
dev_priv->oa_pmu.oa_buffer.format = report_format;
+ if (oa_attr.multiple_context_mode)
+ dev_priv->oa_pmu.oa_rcs_buffer.format = report_format;
dev_priv->oa_pmu.metrics_set = oa_attr.metrics_set;
if (IS_HASWELL(dev_priv->dev)) {
@@ -457,6 +538,9 @@ static int i915_oa_event_init(struct perf_event *event)
return -EINVAL;
dev_priv->oa_pmu.oa_buffer.format_size = snapshot_size;
+ if (oa_attr.multiple_context_mode)
+ dev_priv->oa_pmu.oa_rcs_buffer.format_size =
+ snapshot_size;
if (oa_attr.metrics_set > I915_OA_METRICS_SET_MAX)
return -EINVAL;
@@ -465,6 +549,7 @@ static int i915_oa_event_init(struct perf_event *event)
return -ENODEV;
}
+
/* Since we are limited to an exponential scale for
* programming the OA sampling period we don't allow userspace
* to pass a precise attr.sample_period. */
@@ -528,6 +613,12 @@ static int i915_oa_event_init(struct perf_event *event)
if (ret)
return ret;
+ if (oa_attr.multiple_context_mode) {
+ ret = init_oa_rcs_buffer(event);
+ if (ret)
+ return ret;
+ }
+
BUG_ON(dev_priv->oa_pmu.exclusive_event);
dev_priv->oa_pmu.exclusive_event = event;
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 992e1e9..dcf7c87 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -92,7 +92,8 @@ typedef struct _drm_i915_oa_attr {
__u32 ctx_id;
__u64 single_context : 1,
- __reserved_1 : 63;
+ multiple_context_mode:1,
+ __reserved_1:62;
} drm_i915_oa_attr_t;
/* Header for PERF_RECORD_DEVICE type events */
--
1.8.5.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 17+ messages in thread* [RFC 3/8] drm/i915: Add mechanism for forwarding CS based OA counter snapshots through perf
2015-07-15 8:46 [RFC 0/8] Introduce framework to forward multi context OA snapshots sourab.gupta
2015-07-15 8:46 ` [RFC 1/8] drm/i915: Have globally unique context ids, as opposed to drm file specific sourab.gupta
2015-07-15 8:46 ` [RFC 2/8] drm/i915: Introduce mode for capture of multi ctx OA reports synchronized with RCS sourab.gupta
@ 2015-07-15 8:46 ` sourab.gupta
2015-07-15 8:46 ` [RFC 4/8] drm/i915: Forward periodic and CS based OA reports sorted acc to timestamps sourab.gupta
` (4 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: sourab.gupta @ 2015-07-15 8:46 UTC (permalink / raw)
To: intel-gfx; +Cc: Insoo Woo, Peter Zijlstra, Jabin Wu, Sourab Gupta
From: Sourab Gupta <sourab.gupta@intel.com>
This patch adds the mechanism for forwarding the CS based OA snapshots
through the perf event interface.
The OA snapshots will be captured in a gem buffer object. The metadata
information (ctx_id right now) pertaining to snapshot is maintained in a
list, which has offsets into the gem buffer object for each snapshot
captured.
Each snapshot collected is forwarded as a separate perf sample. The perf
sample will have raw OA report followed by metadata information pertaining
to that sample. The size of the OA report is the one specified during
event init.
In order to track whether the gpu has completed processing the node, a
field pertaining to corresponding gem request is added. The request is
expected to be referenced whenever the gpu command is submitted.
While forwarding the samples, we check whether the gem request is completed
and dereference the corresponding request. The need to dereference the
request necessitates a worker here, which will be scheduled when the
hrtimer triggers.
While flushing the samples, we have to wait for the requests already
scheduled, before forwarding the samples. This wait is in a lockless
fashion.
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 11 ++++
drivers/gpu/drm/i915/i915_oa_perf.c | 128 +++++++++++++++++++++++++++++++++++-
include/uapi/drm/i915_drm.h | 5 ++
3 files changed, 143 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 740148d..eb72f95 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1653,6 +1653,13 @@ struct i915_oa_reg {
u32 value;
};
+struct i915_oa_rcs_node {
+ struct list_head head;
+ struct drm_i915_gem_request *req;
+ u32 offset;
+ u32 ctx_id;
+};
+
extern const struct i915_oa_reg i915_oa_3d_mux_config_hsw[];
extern const int i915_oa_3d_mux_config_hsw_len;
extern const struct i915_oa_reg i915_oa_3d_b_counter_config_hsw[];
@@ -1952,7 +1959,11 @@ struct drm_i915_private {
u8 *addr;
int format;
int format_size;
+ u32 node_size;
+ u32 node_count;
} oa_rcs_buffer;
+ struct list_head node_list;
+ struct work_struct work_timer;
} oa_pmu;
#endif
diff --git a/drivers/gpu/drm/i915/i915_oa_perf.c b/drivers/gpu/drm/i915/i915_oa_perf.c
index b79582b..a4fdca3 100644
--- a/drivers/gpu/drm/i915/i915_oa_perf.c
+++ b/drivers/gpu/drm/i915/i915_oa_perf.c
@@ -58,6 +58,14 @@ static u32 forward_oa_snapshots(struct drm_i915_private *dev_priv,
u8 *snapshot;
u32 taken;
+ /*
+ * Schedule a worker to forward the RCS based OA reports collected.
+ * A worker is needed since it requires device mutex to be taken
+ * which can't be done here because of atomic context
+ */
+ if (dev_priv->oa_pmu.multiple_ctx_mode)
+ schedule_work(&dev_priv->oa_pmu.work_timer);
+
head -= dev_priv->oa_pmu.oa_buffer.gtt_offset;
tail -= dev_priv->oa_pmu.oa_buffer.gtt_offset;
@@ -165,6 +173,103 @@ static void flush_oa_snapshots(struct drm_i915_private *dev_priv,
spin_unlock_irqrestore(&dev_priv->oa_pmu.oa_buffer.flush_lock, flags);
}
+int i915_oa_rcs_wait_gpu(struct drm_i915_private *dev_priv)
+{
+ struct i915_oa_rcs_node *last_entry;
+ unsigned long lock_flags;
+ int ret;
+
+ /*
+ * Wait for the last scheduled request to complete. This would
+ * implicitly wait for the prior submitted requests. The refcount
+ * of the requests is not decremented here.
+ */
+ spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
+
+ if (list_empty(&dev_priv->oa_pmu.node_list)) {
+ spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
+ return 0;
+ }
+ last_entry = list_last_entry(&dev_priv->oa_pmu.node_list,
+ struct i915_oa_rcs_node, head);
+ spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
+
+ if (last_entry && last_entry->req) {
+ ret = __i915_wait_request(last_entry->req, atomic_read(
+ &dev_priv->gpu_error.reset_counter),
+ dev_priv->mm.interruptible, NULL, NULL);
+ if (ret) {
+ DRM_ERROR("failed to wait\n");
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static void forward_one_oa_rcs_sample(struct drm_i915_private *dev_priv,
+ struct i915_oa_rcs_node *node)
+{
+ struct perf_sample_data data;
+ struct perf_event *event = dev_priv->oa_pmu.exclusive_event;
+ int format_size, snapshot_size;
+ u8 *snapshot;
+ struct drm_i915_oa_node_ctx_id *ctx_info;
+ struct perf_raw_record raw;
+
+ format_size = dev_priv->oa_pmu.oa_rcs_buffer.format_size;
+ snapshot_size = format_size + sizeof(*ctx_info);
+ snapshot = dev_priv->oa_pmu.oa_rcs_buffer.addr + node->offset;
+
+ ctx_info = (struct drm_i915_oa_node_ctx_id *)(snapshot + format_size);
+ ctx_info->ctx_id = node->ctx_id;
+
+ perf_sample_data_init(&data, 0, event->hw.last_period);
+
+ /* Note: the combined u32 raw->size member + raw data itself must be 8
+ * byte aligned. (See note in init_oa_buffer for more details) */
+ raw.size = snapshot_size + 4;
+ raw.data = snapshot;
+
+ data.raw = &raw;
+
+ perf_event_overflow(event, &data, &dev_priv->oa_pmu.dummy_regs);
+}
+
+void forward_oa_rcs_snapshots_work(struct work_struct *__work)
+{
+ struct drm_i915_private *dev_priv =
+ container_of(__work, typeof(*dev_priv), oa_pmu.work_timer);
+ struct i915_oa_rcs_node *entry, *next;
+ struct drm_i915_gem_request *req;
+ unsigned long lock_flags;
+ int ret;
+
+ list_for_each_entry_safe
+ (entry, next, &dev_priv->oa_pmu.node_list, head) {
+ req = entry->req;
+ if (req && i915_gem_request_completed(req, true)) {
+ forward_one_oa_rcs_sample(dev_priv, entry);
+ ret = i915_mutex_lock_interruptible(dev_priv->dev);
+ if (ret)
+ break;
+ i915_gem_request_assign(&entry->req, NULL);
+ mutex_unlock(&dev_priv->dev->struct_mutex);
+ } else
+ break;
+
+ /*
+ * Do we instead need to protect whole loop? If so, we would
+ * need to *list_move_tail* to a deferred list, from where
+ * i915 device mutex could be taken to deference the requests,
+ * and free the node.
+ */
+ spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
+ list_del(&entry->head);
+ spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
+ kfree(entry);
+ }
+}
+
static void
oa_rcs_buffer_destroy(struct drm_i915_private *i915)
{
@@ -364,7 +469,7 @@ static int init_oa_rcs_buffer(struct perf_event *event)
struct drm_i915_private *dev_priv =
container_of(event->pmu, typeof(*dev_priv), oa_pmu.pmu);
struct drm_i915_gem_object *bo;
- int ret;
+ int ret, node_size;
BUG_ON(dev_priv->oa_pmu.oa_rcs_buffer.obj);
@@ -375,6 +480,16 @@ static int init_oa_rcs_buffer(struct perf_event *event)
dev_priv->oa_pmu.oa_rcs_buffer.obj = bo;
dev_priv->oa_pmu.oa_rcs_buffer.addr = vmap_oa_buffer(bo);
+ INIT_LIST_HEAD(&dev_priv->oa_pmu.node_list);
+
+ node_size = dev_priv->oa_pmu.oa_rcs_buffer.format_size +
+ sizeof(struct drm_i915_oa_node_ctx_id);
+
+ /* node size has to be aligned to 64 bytes, since only 64 byte aligned
+ * addresses can be given to OA unit for dumping OA reports */
+ node_size = ALIGN(node_size, 64);
+ dev_priv->oa_pmu.oa_rcs_buffer.node_size = node_size;
+ dev_priv->oa_pmu.oa_rcs_buffer.node_count = bo->base.size / node_size;
DRM_DEBUG_DRIVER("OA RCS Buffer initialized, vaddr = %p",
dev_priv->oa_pmu.oa_rcs_buffer.addr);
@@ -849,7 +964,13 @@ static int i915_oa_event_flush(struct perf_event *event)
if (event->attr.sample_period) {
struct drm_i915_private *i915 =
container_of(event->pmu, typeof(*i915), oa_pmu.pmu);
+ int ret;
+ if (i915->oa_pmu.multiple_ctx_mode) {
+ ret = i915_oa_rcs_wait_gpu(i915);
+ if (ret)
+ return ret;
+ }
flush_oa_snapshots(i915, true);
}
@@ -945,6 +1066,8 @@ void i915_oa_pmu_register(struct drm_device *dev)
hrtimer_init(&i915->oa_pmu.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
i915->oa_pmu.timer.function = hrtimer_sample;
+ INIT_WORK(&i915->oa_pmu.work_timer, forward_oa_rcs_snapshots_work);
+
spin_lock_init(&i915->oa_pmu.lock);
i915->oa_pmu.pmu.capabilities = PERF_PMU_CAP_IS_DEVICE;
@@ -974,6 +1097,9 @@ void i915_oa_pmu_unregister(struct drm_device *dev)
if (i915->oa_pmu.pmu.event_init == NULL)
return;
+ if (i915->oa_pmu.multiple_ctx_mode)
+ cancel_work_sync(&i915->oa_pmu.work_timer);
+
unregister_sysctl_table(i915->oa_pmu.sysctl_header);
perf_pmu_unregister(&i915->oa_pmu.pmu);
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index dcf7c87..e97b2fd 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -123,6 +123,11 @@ enum drm_i915_oa_event_type {
I915_OA_RECORD_MAX, /* non-ABI */
};
+struct drm_i915_oa_node_ctx_id {
+ __u32 ctx_id;
+ __u32 pad;
+};
+
/* Each region is a minimum of 16k, and there are at most 255 of them.
*/
#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use
--
1.8.5.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 17+ messages in thread* [RFC 4/8] drm/i915: Forward periodic and CS based OA reports sorted acc to timestamps
2015-07-15 8:46 [RFC 0/8] Introduce framework to forward multi context OA snapshots sourab.gupta
` (2 preceding siblings ...)
2015-07-15 8:46 ` [RFC 3/8] drm/i915: Add mechanism for forwarding CS based OA counter snapshots through perf sourab.gupta
@ 2015-07-15 8:46 ` sourab.gupta
2015-07-15 8:47 ` [RFC 5/8] drm/i915: Handle event stop and destroy for commands in flight sourab.gupta
` (3 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: sourab.gupta @ 2015-07-15 8:46 UTC (permalink / raw)
To: intel-gfx; +Cc: Insoo Woo, Peter Zijlstra, Jabin Wu, Sourab Gupta
From: Sourab Gupta <sourab.gupta@intel.com>
The periodic reports and the RCS based reports are collected in two
separate buffers. While forwarding to userspace, these have to be sent to
single perf event ringbuffer. From a userspace perspective, it is good to
have the reports in the single buffer in order to their timestamps.
This patch addresses this problem by forwarding the periodic OA reports
with a lower timestamp, whenever we are forwarding the Command streamer
based report.
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
---
drivers/gpu/drm/i915/i915_oa_perf.c | 38 ++++++++++++++++++++++---------------
1 file changed, 23 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_oa_perf.c b/drivers/gpu/drm/i915/i915_oa_perf.c
index a4fdca3..491496b 100644
--- a/drivers/gpu/drm/i915/i915_oa_perf.c
+++ b/drivers/gpu/drm/i915/i915_oa_perf.c
@@ -48,8 +48,7 @@ static void forward_one_oa_snapshot_to_event(struct drm_i915_private *dev_priv,
}
static u32 forward_oa_snapshots(struct drm_i915_private *dev_priv,
- u32 head,
- u32 tail)
+ u32 head, u32 tail, u64 gpu_ts)
{
struct perf_event *exclusive_event = dev_priv->oa_pmu.exclusive_event;
int snapshot_size = dev_priv->oa_pmu.oa_buffer.format_size;
@@ -58,14 +57,6 @@ static u32 forward_oa_snapshots(struct drm_i915_private *dev_priv,
u8 *snapshot;
u32 taken;
- /*
- * Schedule a worker to forward the RCS based OA reports collected.
- * A worker is needed since it requires device mutex to be taken
- * which can't be done here because of atomic context
- */
- if (dev_priv->oa_pmu.multiple_ctx_mode)
- schedule_work(&dev_priv->oa_pmu.work_timer);
-
head -= dev_priv->oa_pmu.oa_buffer.gtt_offset;
tail -= dev_priv->oa_pmu.oa_buffer.gtt_offset;
@@ -75,12 +66,19 @@ static u32 forward_oa_snapshots(struct drm_i915_private *dev_priv,
*/
while ((taken = OA_TAKEN(tail, head))) {
+ u64 snapshot_ts;
+
/* The tail increases in 64 byte increments, not in
* format_size steps. */
if (taken < snapshot_size)
break;
snapshot = oa_buf_base + (head & mask);
+
+ snapshot_ts = *(u64 *)(snapshot + 4);
+ if (snapshot_ts > gpu_ts)
+ break;
+
head += snapshot_size;
/* We currently only allow exclusive access to the counters
@@ -122,7 +120,7 @@ static void log_oa_status(struct drm_i915_private *dev_priv,
}
static void flush_oa_snapshots(struct drm_i915_private *dev_priv,
- bool skip_if_flushing)
+ bool skip_if_flushing, u64 gpu_ts)
{
unsigned long flags;
u32 oastatus2;
@@ -165,7 +163,7 @@ static void flush_oa_snapshots(struct drm_i915_private *dev_priv,
GEN7_OASTATUS1_REPORT_LOST));
}
- head = forward_oa_snapshots(dev_priv, head, tail);
+ head = forward_oa_snapshots(dev_priv, head, tail, gpu_ts);
I915_WRITE(GEN7_OASTATUS2, (head & GEN7_OASTATUS2_HEAD_MASK) |
GEN7_OASTATUS2_GGTT);
@@ -215,6 +213,7 @@ static void forward_one_oa_rcs_sample(struct drm_i915_private *dev_priv,
u8 *snapshot;
struct drm_i915_oa_node_ctx_id *ctx_info;
struct perf_raw_record raw;
+ u64 snapshot_ts;
format_size = dev_priv->oa_pmu.oa_rcs_buffer.format_size;
snapshot_size = format_size + sizeof(*ctx_info);
@@ -223,6 +222,10 @@ static void forward_one_oa_rcs_sample(struct drm_i915_private *dev_priv,
ctx_info = (struct drm_i915_oa_node_ctx_id *)(snapshot + format_size);
ctx_info->ctx_id = node->ctx_id;
+ /* Flush the periodic snapshots till the ts of this OA report */
+ snapshot_ts = *(u64 *)(snapshot + 4);
+ flush_oa_snapshots(dev_priv, true, snapshot_ts);
+
perf_sample_data_init(&data, 0, event->hw.last_period);
/* Note: the combined u32 raw->size member + raw data itself must be 8
@@ -502,7 +505,10 @@ static enum hrtimer_restart hrtimer_sample(struct hrtimer *hrtimer)
struct drm_i915_private *i915 =
container_of(hrtimer, typeof(*i915), oa_pmu.timer);
- flush_oa_snapshots(i915, true);
+ if (i915->oa_pmu.multiple_ctx_mode)
+ schedule_work(&i915->oa_pmu.work_timer);
+ else
+ flush_oa_snapshots(i915, true, U64_MAX);
hrtimer_forward_now(hrtimer, ns_to_ktime(PERIOD));
return HRTIMER_RESTART;
@@ -931,7 +937,9 @@ static void i915_oa_event_stop(struct perf_event *event, int flags)
if (event->attr.sample_period) {
hrtimer_cancel(&dev_priv->oa_pmu.timer);
- flush_oa_snapshots(dev_priv, false);
+ if (dev_priv->oa_pmu.multiple_ctx_mode)
+ schedule_work(&dev_priv->oa_pmu.work_timer);
+ flush_oa_snapshots(dev_priv, false, U64_MAX);
}
event->hw.state = PERF_HES_STOPPED;
@@ -971,7 +979,7 @@ static int i915_oa_event_flush(struct perf_event *event)
if (ret)
return ret;
}
- flush_oa_snapshots(i915, true);
+ flush_oa_snapshots(i915, true, U64_MAX);
}
return 0;
--
1.8.5.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 17+ messages in thread* [RFC 5/8] drm/i915: Handle event stop and destroy for commands in flight
2015-07-15 8:46 [RFC 0/8] Introduce framework to forward multi context OA snapshots sourab.gupta
` (3 preceding siblings ...)
2015-07-15 8:46 ` [RFC 4/8] drm/i915: Forward periodic and CS based OA reports sorted acc to timestamps sourab.gupta
@ 2015-07-15 8:47 ` sourab.gupta
2015-07-15 8:47 ` [RFC 6/8] drm/i915: Insert commands for capture of OA counters in the ring sourab.gupta
` (2 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: sourab.gupta @ 2015-07-15 8:47 UTC (permalink / raw)
To: intel-gfx; +Cc: Insoo Woo, Peter Zijlstra, Jabin Wu, Sourab Gupta
From: Sourab Gupta <sourab.gupta@intel.com>
In the periodic OA sampling mode, the event stop would stop forwarding
samples to userspace, and disables OA synchronously. The buffer is
destroyed eventually in event destroy callback. But when we have in flight
RPC commands scheduled on GPU (like in this case), the handling of OA
disabling and buffer destruction has to take those into account. This patch
handles the event stop & destroy conditions after accounting for GPU
commands in flight using the OA unit.
Now, the event stop would just set the event state, and stop forwarding
data to userspace. From userspace perspective, for all purposes, the event
sampling is stopped. This is true for periodic OA samples also. The OA unit
is not disabled here, since there may be RPC commands scheduled on GPU.
A subsequent event start (without event destroy) would start forwarding
samples again.
The event destroy releases the local copy of the RCS buffer. But since, it
is expected that the active reference of buffer is taken while inserting
commands, we can rest assured that buffer is freed up only after GPU is
done with it.
Still there is a need to schedule a worker from event destroy, because we
need to do some further stuff listed below (in this order)
- free up request references
- disable OA unit
- dereference periodic OA buffer (as this is not managed by active ref)
- runtime_pm_put + forcewake_put
The ideal solution here would be to have a callback when the last request
is finished on GPU, so that we can do this stuff there (WIP:Chris'
retire-notification mechanism). Till the time, an async worker thread
will do.
A subsequent event init would have to wait for previously submitted RPC
commands to complete or return -EBUSY. Currently, for the sake of
simplicity, we are returning -EBUSY.
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 11 ++-
drivers/gpu/drm/i915/i915_oa_perf.c | 186 +++++++++++++++++++++++++++++++-----
2 files changed, 171 insertions(+), 26 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index eb72f95..b3d5f7e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1653,10 +1653,18 @@ struct i915_oa_reg {
u32 value;
};
+enum i915_oa_event_state {
+ I915_OA_EVENT_INIT,
+ I915_OA_EVENT_STARTED,
+ I915_OA_EVENT_STOP_IN_PROGRESS,
+ I915_OA_EVENT_STOPPED,
+};
+
struct i915_oa_rcs_node {
struct list_head head;
struct drm_i915_gem_request *req;
u32 offset;
+ bool discard;
u32 ctx_id;
};
@@ -1934,7 +1942,7 @@ struct drm_i915_private {
struct perf_event *exclusive_event;
struct intel_context *specific_ctx;
- bool event_active;
+ enum i915_oa_event_state event_state;
bool periodic;
bool multiple_ctx_mode;
@@ -1964,6 +1972,7 @@ struct drm_i915_private {
} oa_rcs_buffer;
struct list_head node_list;
struct work_struct work_timer;
+ struct work_struct work_event_destroy;
} oa_pmu;
#endif
diff --git a/drivers/gpu/drm/i915/i915_oa_perf.c b/drivers/gpu/drm/i915/i915_oa_perf.c
index 491496b..c1e3bea 100644
--- a/drivers/gpu/drm/i915/i915_oa_perf.c
+++ b/drivers/gpu/drm/i915/i915_oa_perf.c
@@ -83,7 +83,7 @@ static u32 forward_oa_snapshots(struct drm_i915_private *dev_priv,
/* We currently only allow exclusive access to the counters
* so only have one event to forward too... */
- if (dev_priv->oa_pmu.event_active)
+ if (dev_priv->oa_pmu.event_state == I915_OA_EVENT_STARTED)
forward_one_oa_snapshot_to_event(dev_priv, snapshot,
exclusive_event);
}
@@ -128,6 +128,9 @@ static void flush_oa_snapshots(struct drm_i915_private *dev_priv,
u32 head;
u32 tail;
+ if (dev_priv->oa_pmu.event_state == I915_OA_EVENT_STOPPED)
+ return;
+
/* Can either flush via hrtimer callback or pmu methods/fops */
if (skip_if_flushing) {
@@ -204,6 +207,36 @@ int i915_oa_rcs_wait_gpu(struct drm_i915_private *dev_priv)
return 0;
}
+void i915_oa_rcs_release_request_ref(struct drm_i915_private *dev_priv)
+{
+ struct i915_oa_rcs_node *entry, *next;
+ struct drm_i915_gem_request *req;
+ unsigned long lock_flags;
+ int ret;
+
+ list_for_each_entry_safe
+ (entry, next, &dev_priv->oa_pmu.node_list, head) {
+ req = entry->req;
+ if (req) {
+ ret = i915_mutex_lock_interruptible(dev_priv->dev);
+ if (ret)
+ break;
+ i915_gem_request_assign(&entry->req, NULL);
+ mutex_unlock(&dev_priv->dev->struct_mutex);
+ }
+
+ /*
+ * This fn won't be running concurrently with forward snapshots
+ * work fn. These are the only two places where list entries
+ * will be deleted. So no need of protecting full loop?
+ */
+ spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
+ list_del(&entry->head);
+ spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
+ kfree(entry);
+ }
+}
+
static void forward_one_oa_rcs_sample(struct drm_i915_private *dev_priv,
struct i915_oa_rcs_node *node)
{
@@ -247,11 +280,19 @@ void forward_oa_rcs_snapshots_work(struct work_struct *__work)
unsigned long lock_flags;
int ret;
+ spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
+ if (dev_priv->oa_pmu.event_state != I915_OA_EVENT_STARTED) {
+ spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
+ return;
+ }
+ spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
+
list_for_each_entry_safe
(entry, next, &dev_priv->oa_pmu.node_list, head) {
req = entry->req;
if (req && i915_gem_request_completed(req, true)) {
- forward_one_oa_rcs_sample(dev_priv, entry);
+ if (!entry->discard)
+ forward_one_oa_rcs_sample(dev_priv, entry);
ret = i915_mutex_lock_interruptible(dev_priv->dev);
if (ret)
break;
@@ -317,16 +358,101 @@ static void i915_oa_event_destroy(struct perf_event *event)
WARN_ON(event->parent);
- /* Stop updating oacontrol via _oa_context_pin_[un]notify()... */
+ if (dev_priv->oa_pmu.multiple_ctx_mode) {
+ /* Stop updating oacontrol via _oa_context_pin_[un]notify() */
+ spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
+ dev_priv->oa_pmu.specific_ctx = NULL;
+ spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
+
+ cancel_work_sync(&dev_priv->oa_pmu.work_timer);
+ schedule_work(&dev_priv->oa_pmu.work_event_destroy);
+
+ BUG_ON(dev_priv->oa_pmu.exclusive_event != event);
+ dev_priv->oa_pmu.exclusive_event = NULL;
+
+ /* We can deference our local copy of rcs buffer here, since
+ * an active reference of buffer would be taken while
+ * inserting commands. So the buffer would be freed up only
+ * after GPU is done with it.
+ */
+ oa_rcs_buffer_destroy(dev_priv);
+ } else {
+ /* Stop updating oacontrol via _oa_context_pin_[un]notify() */
+ spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
+ dev_priv->oa_pmu.specific_ctx = NULL;
+ spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
+
+ /* Don't let the compiler start resetting OA, PM and clock
+ * gating state before we've stopped update_oacontrol()
+ */
+ barrier();
+
+ BUG_ON(dev_priv->oa_pmu.exclusive_event != event);
+ dev_priv->oa_pmu.exclusive_event = NULL;
+
+ oa_buffer_destroy(dev_priv);
+
+ I915_WRITE(GEN6_UCGCTL1, (I915_READ(GEN6_UCGCTL1) &
+ ~GEN6_CSUNIT_CLOCK_GATE_DISABLE));
+ I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) |
+ GEN7_DOP_CLOCK_GATE_ENABLE));
+
+ I915_WRITE(GDT_CHICKEN_BITS, (I915_READ(GDT_CHICKEN_BITS) &
+ ~GT_NOA_ENABLE));
+
+ intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
+ intel_runtime_pm_put(dev_priv);
+ dev_priv->oa_pmu.event_state = I915_OA_EVENT_INIT;
+ }
+}
+
+void i915_oa_rcs_event_destroy_work(struct work_struct *__work)
+{
+ struct drm_i915_private *dev_priv =
+ container_of(__work, typeof(*dev_priv),
+ oa_pmu.work_event_destroy);
+ unsigned long lock_flags;
+ int ret;
+
+ /* Stop updating oacontrol via _oa_context_pin_[un]notify()
+ * TODO: Is this reqd here?
+ */
spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
dev_priv->oa_pmu.specific_ctx = NULL;
spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
- /* Don't let the compiler start resetting OA, PM and clock gating
- * state before we've stopped update_oacontrol()
+ /* Don't let the compiler start resetting OA, PM and clock
+ * gating state before we've stopped update_oacontrol()
*/
barrier();
+ ret = i915_oa_rcs_wait_gpu(dev_priv);
+ if (ret)
+ goto out;
+
+ i915_oa_rcs_release_request_ref(dev_priv);
+
+out:
+ /* Disable OA unit */
+ I915_WRITE(GEN7_OACONTROL, 0);
+
+ /* The periodic OA buffer has to be destroyed here, since
+ * this can be done only after OA unit is disabled. There is no active
+ * reference tracking mechanism for periodic OA buffer. So we can only
+ * dereference it in the worker after we've disabled OA unit (which we
+ * can do after we're sure to have completed the in flight GPU cmds)
+ */
+ /* TODO: Once we have callbacks in place on completion of request
+ * (i.e. when retire-notification patches land), we can take the active
+ * reference on LRI request(submitted for disabling OA) during event
+ * stop/destroy, and perform these actions, in the callback instead of
+ * work fn
+ */
+
+ oa_buffer_destroy(dev_priv);
+
+ spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
+
I915_WRITE(GEN6_UCGCTL1, (I915_READ(GEN6_UCGCTL1) &
~GEN6_CSUNIT_CLOCK_GATE_DISABLE));
I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) |
@@ -335,16 +461,10 @@ static void i915_oa_event_destroy(struct perf_event *event)
I915_WRITE(GDT_CHICKEN_BITS, (I915_READ(GDT_CHICKEN_BITS) &
~GT_NOA_ENABLE));
- if (dev_priv->oa_pmu.multiple_ctx_mode)
- oa_rcs_buffer_destroy(dev_priv);
-
- oa_buffer_destroy(dev_priv);
-
- BUG_ON(dev_priv->oa_pmu.exclusive_event != event);
- dev_priv->oa_pmu.exclusive_event = NULL;
-
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
intel_runtime_pm_put(dev_priv);
+ dev_priv->oa_pmu.event_state = I915_OA_EVENT_INIT;
+ spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
}
static int alloc_obj(struct drm_i915_private *dev_priv,
@@ -625,7 +745,8 @@ static int i915_oa_event_init(struct perf_event *event)
* counter snapshots and marshal to the appropriate client
* we currently only allow exclusive access */
spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
- if (dev_priv->oa_pmu.oa_buffer.obj) {
+ if (dev_priv->oa_pmu.oa_buffer.obj ||
+ dev_priv->oa_pmu.event_state != I915_OA_EVENT_INIT) {
spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
return -EBUSY;
}
@@ -790,7 +911,8 @@ static void update_oacontrol(struct drm_i915_private *dev_priv)
{
BUG_ON(!spin_is_locked(&dev_priv->oa_pmu.lock));
- if (dev_priv->oa_pmu.event_active) {
+ if ((dev_priv->oa_pmu.event_state == I915_OA_EVENT_STARTED) ||
+ (dev_priv->oa_pmu.event_state == I915_OA_EVENT_STOP_IN_PROGRESS)) {
unsigned long ctx_id = 0;
bool pinning_ok = false;
@@ -900,7 +1022,7 @@ static void i915_oa_event_start(struct perf_event *event, int flags)
spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
- dev_priv->oa_pmu.event_active = true;
+ dev_priv->oa_pmu.event_state = I915_OA_EVENT_STARTED;
update_oacontrol(dev_priv);
/* Reset the head ptr to ensure we don't forward reports relating
@@ -927,14 +1049,6 @@ static void i915_oa_event_stop(struct perf_event *event, int flags)
container_of(event->pmu, typeof(*dev_priv), oa_pmu.pmu);
unsigned long lock_flags;
- spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
-
- dev_priv->oa_pmu.event_active = false;
- update_oacontrol(dev_priv);
-
- mmiowb();
- spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
-
if (event->attr.sample_period) {
hrtimer_cancel(&dev_priv->oa_pmu.timer);
if (dev_priv->oa_pmu.multiple_ctx_mode)
@@ -942,6 +1056,23 @@ static void i915_oa_event_stop(struct perf_event *event, int flags)
flush_oa_snapshots(dev_priv, false, U64_MAX);
}
+ if (dev_priv->oa_pmu.multiple_ctx_mode) {
+ struct i915_oa_rcs_node *entry;
+
+ spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
+
+ dev_priv->oa_pmu.event_state = I915_OA_EVENT_STOP_IN_PROGRESS;
+ list_for_each_entry(entry, &dev_priv->oa_pmu.node_list, head)
+ entry->discard = true;
+
+ spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
+ } else {
+ spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
+ dev_priv->oa_pmu.event_state = I915_OA_EVENT_STOPPED;
+ update_oacontrol(dev_priv);
+ mmiowb();
+ spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
+ }
event->hw.state = PERF_HES_STOPPED;
}
@@ -1075,10 +1206,13 @@ void i915_oa_pmu_register(struct drm_device *dev)
i915->oa_pmu.timer.function = hrtimer_sample;
INIT_WORK(&i915->oa_pmu.work_timer, forward_oa_rcs_snapshots_work);
+ INIT_WORK(&i915->oa_pmu.work_event_destroy,
+ i915_oa_rcs_event_destroy_work);
spin_lock_init(&i915->oa_pmu.lock);
i915->oa_pmu.pmu.capabilities = PERF_PMU_CAP_IS_DEVICE;
+ i915->oa_pmu.event_state = I915_OA_EVENT_INIT;
/* Effectively disallow opening an event with a specific pid
* since we aren't interested in processes running on the cpu...
@@ -1105,8 +1239,10 @@ void i915_oa_pmu_unregister(struct drm_device *dev)
if (i915->oa_pmu.pmu.event_init == NULL)
return;
- if (i915->oa_pmu.multiple_ctx_mode)
+ if (i915->oa_pmu.multiple_ctx_mode) {
cancel_work_sync(&i915->oa_pmu.work_timer);
+ cancel_work_sync(&i915->oa_pmu.work_event_destroy);
+ }
unregister_sysctl_table(i915->oa_pmu.sysctl_header);
--
1.8.5.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 17+ messages in thread* [RFC 6/8] drm/i915: Insert commands for capture of OA counters in the ring
2015-07-15 8:46 [RFC 0/8] Introduce framework to forward multi context OA snapshots sourab.gupta
` (4 preceding siblings ...)
2015-07-15 8:47 ` [RFC 5/8] drm/i915: Handle event stop and destroy for commands in flight sourab.gupta
@ 2015-07-15 8:47 ` sourab.gupta
2015-07-15 10:26 ` Chris Wilson
2015-07-15 8:47 ` [RFC 7/8] drm/i915: Add support for having pid output with OA report sourab.gupta
2015-07-15 8:47 ` [RFC 8/8] drm/i915: Add support to add execbuffer tags to OA counter reports sourab.gupta
7 siblings, 1 reply; 17+ messages in thread
From: sourab.gupta @ 2015-07-15 8:47 UTC (permalink / raw)
To: intel-gfx; +Cc: Insoo Woo, Peter Zijlstra, Jabin Wu, Sourab Gupta
From: Sourab Gupta <sourab.gupta@intel.com>
This patch adds the routines which insert commands for capturing OA
snapshots into the ringbuffer of RCS engine.
The command MI_REPORT_PERF_COUNT can be used to capture snapshots of OA
counters, which is inserted at BB boundaries.
While inserting the commands, we keep a reference of associated request.
This will be released when we are forwarding the samples to userspace
(or when the event is being destroyed).
Also, an active reference of the destination buffer is taken here, so that
we can be assured that the buffer is freed up only after GPU is done with
it, even if the local reference of the buffer is released.
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 11 +++++
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 6 +++
drivers/gpu/drm/i915/i915_oa_perf.c | 77 ++++++++++++++++++++++++++++++
3 files changed, 94 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b3d5f7e..fb296ae 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1660,6 +1660,11 @@ enum i915_oa_event_state {
I915_OA_EVENT_STOPPED,
};
+enum i915_profile_mode {
+ I915_PROFILE_OA = 0,
+ I915_PROFILE_MAX,
+};
+
struct i915_oa_rcs_node {
struct list_head head;
struct drm_i915_gem_request *req;
@@ -1974,6 +1979,9 @@ struct drm_i915_private {
struct work_struct work_timer;
struct work_struct work_event_destroy;
} oa_pmu;
+
+ void (*insert_profile_cmd[I915_PROFILE_MAX])
+ (struct intel_ringbuffer *ringbuf, u32 ctx_id);
#endif
/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */
@@ -3154,6 +3162,7 @@ void i915_oa_context_pin_notify(struct drm_i915_private *dev_priv,
struct intel_context *context);
void i915_oa_context_unpin_notify(struct drm_i915_private *dev_priv,
struct intel_context *context);
+void i915_insert_profiling_cmd(struct intel_ringbuffer *ringbuf, u32 ctx_id);
#else
static inline void
i915_oa_context_pin_notify(struct drm_i915_private *dev_priv,
@@ -3161,6 +3170,8 @@ i915_oa_context_pin_notify(struct drm_i915_private *dev_priv,
static inline void
i915_oa_context_unpin_notify(struct drm_i915_private *dev_priv,
struct intel_context *context) {}
+void i915_insert_profiling_cmd(struct intel_ringbuffer *ringbuf,
+ u32 ctx_id) {};
#endif
/* i915_gem_evict.c */
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 3336e1c..2f8971b 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1317,6 +1317,9 @@ i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file,
goto error;
}
+ i915_insert_profiling_cmd(ring->buffer,
+ i915_execbuffer2_get_context_id(*args));
+
exec_len = args->batch_len;
if (cliprects) {
for (i = 0; i < args->num_cliprects; i++) {
@@ -1339,6 +1342,9 @@ i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file,
return ret;
}
+ i915_insert_profiling_cmd(ring->buffer,
+ i915_execbuffer2_get_context_id(*args));
+
trace_i915_gem_ring_dispatch(intel_ring_get_request(ring), dispatch_flags);
i915_gem_execbuffer_move_to_active(vmas, ring);
diff --git a/drivers/gpu/drm/i915/i915_oa_perf.c b/drivers/gpu/drm/i915/i915_oa_perf.c
index c1e3bea..9966e54 100644
--- a/drivers/gpu/drm/i915/i915_oa_perf.c
+++ b/drivers/gpu/drm/i915/i915_oa_perf.c
@@ -25,6 +25,78 @@ static int hsw_perf_format_sizes[] = {
64 /* C4_B8_HSW */
};
+void i915_insert_profiling_cmd(struct intel_ringbuffer *ringbuf, u32 ctx_id)
+{
+ struct intel_engine_cs *ring = ringbuf->ring;
+ struct drm_i915_private *dev_priv = ring->dev->dev_private;
+ int i;
+
+ for (i = I915_PROFILE_OA; i < I915_PROFILE_MAX; i++) {
+ if (dev_priv->insert_profile_cmd[i])
+ dev_priv->insert_profile_cmd[i](ringbuf, ctx_id);
+ }
+}
+
+void i915_oa_insert_cmd(struct intel_ringbuffer *ringbuf, u32 ctx_id)
+{
+ struct intel_engine_cs *ring = ringbuf->ring;
+ struct drm_i915_private *dev_priv = ring->dev->dev_private;
+ struct drm_i915_gem_object *obj = dev_priv->oa_pmu.oa_rcs_buffer.obj;
+ struct i915_oa_rcs_node *entry;
+ unsigned long lock_flags;
+ u32 addr = 0;
+ int ret;
+
+ /* OA counters are only supported on the render ring */
+ if (ring->id != RCS)
+ return;
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (entry == NULL) {
+ DRM_ERROR("alloc failed\n");
+ return;
+ }
+ entry->ctx_id = ctx_id;
+ i915_gem_request_assign(&entry->req, ring->outstanding_lazy_request);
+
+ spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
+ if (list_empty(&dev_priv->oa_pmu.node_list))
+ entry->offset = 0;
+ else {
+ struct i915_oa_rcs_node *last_entry;
+ int max_offset = dev_priv->oa_pmu.oa_rcs_buffer.node_count *
+ dev_priv->oa_pmu.oa_rcs_buffer.node_size;
+
+ last_entry = list_last_entry(&dev_priv->oa_pmu.node_list,
+ struct i915_oa_rcs_node, head);
+ entry->offset = last_entry->offset +
+ dev_priv->oa_pmu.oa_rcs_buffer.node_size;
+
+ if (entry->offset > max_offset)
+ entry->offset = 0;
+ }
+ list_add_tail(&entry->head, &dev_priv->oa_pmu.node_list);
+ spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
+
+ addr = i915_gem_obj_ggtt_offset(obj) + entry->offset;
+
+ /* addr should be 64 byte aligned */
+ BUG_ON(addr & 0x3f);
+
+ ret = intel_ring_begin(ring, 4);
+ if (ret)
+ return;
+
+ intel_ring_emit(ring, MI_REPORT_PERF_COUNT | (1<<0));
+ intel_ring_emit(ring, addr | MI_REPORT_PERF_COUNT_GGTT);
+ intel_ring_emit(ring, ring->outstanding_lazy_request->seqno);
+ intel_ring_emit(ring, MI_NOOP);
+ intel_ring_advance(ring);
+
+ obj->base.write_domain = I915_GEM_DOMAIN_RENDER;
+ i915_vma_move_to_active(i915_gem_obj_to_ggtt(obj), ring);
+}
+
static void forward_one_oa_snapshot_to_event(struct drm_i915_private *dev_priv,
u8 *snapshot,
struct perf_event *event)
@@ -1025,6 +1097,10 @@ static void i915_oa_event_start(struct perf_event *event, int flags)
dev_priv->oa_pmu.event_state = I915_OA_EVENT_STARTED;
update_oacontrol(dev_priv);
+ if (dev_priv->oa_pmu.multiple_ctx_mode)
+ dev_priv->insert_profile_cmd[I915_PROFILE_OA] =
+ i915_oa_insert_cmd;
+
/* Reset the head ptr to ensure we don't forward reports relating
* to a previous perf event */
oastatus1 = I915_READ(GEN7_OASTATUS1);
@@ -1061,6 +1137,7 @@ static void i915_oa_event_stop(struct perf_event *event, int flags)
spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
+ dev_priv->insert_profile_cmd[I915_PROFILE_OA] = NULL;
dev_priv->oa_pmu.event_state = I915_OA_EVENT_STOP_IN_PROGRESS;
list_for_each_entry(entry, &dev_priv->oa_pmu.node_list, head)
entry->discard = true;
--
1.8.5.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [RFC 6/8] drm/i915: Insert commands for capture of OA counters in the ring
2015-07-15 8:47 ` [RFC 6/8] drm/i915: Insert commands for capture of OA counters in the ring sourab.gupta
@ 2015-07-15 10:26 ` Chris Wilson
0 siblings, 0 replies; 17+ messages in thread
From: Chris Wilson @ 2015-07-15 10:26 UTC (permalink / raw)
To: sourab.gupta; +Cc: Peter Zijlstra, intel-gfx, Jabin Wu, Insoo Woo
On Wed, Jul 15, 2015 at 02:17:01PM +0530, sourab.gupta@intel.com wrote:
> +void i915_oa_insert_cmd(struct intel_ringbuffer *ringbuf, u32 ctx_id)
You need to pass in the request here instead.
A better name would be i915_oa_emit_perf_report(). insert_cmd() is a
little too generic (i.e. which cmd do you mean?).
> +{
> + struct intel_engine_cs *ring = ringbuf->ring;
> + struct drm_i915_private *dev_priv = ring->dev->dev_private;
> + struct drm_i915_gem_object *obj = dev_priv->oa_pmu.oa_rcs_buffer.obj;
> + struct i915_oa_rcs_node *entry;
> + unsigned long lock_flags;
> + u32 addr = 0;
> + int ret;
> +
> + /* OA counters are only supported on the render ring */
> + if (ring->id != RCS)
> + return;
> +
> + entry = kzalloc(sizeof(*entry), GFP_KERNEL);
> + if (entry == NULL) {
> + DRM_ERROR("alloc failed\n");
> + return;
> + }
> + entry->ctx_id = ctx_id;
> + i915_gem_request_assign(&entry->req, ring->outstanding_lazy_request);
> +
> + spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
> + if (list_empty(&dev_priv->oa_pmu.node_list))
> + entry->offset = 0;
> + else {
> + struct i915_oa_rcs_node *last_entry;
> + int max_offset = dev_priv->oa_pmu.oa_rcs_buffer.node_count *
> + dev_priv->oa_pmu.oa_rcs_buffer.node_size;
> +
> + last_entry = list_last_entry(&dev_priv->oa_pmu.node_list,
> + struct i915_oa_rcs_node, head);
> + entry->offset = last_entry->offset +
> + dev_priv->oa_pmu.oa_rcs_buffer.node_size;
> +
> + if (entry->offset > max_offset)
> + entry->offset = 0;
> + }
> + list_add_tail(&entry->head, &dev_priv->oa_pmu.node_list);
> + spin_unlock_irqrestore(&dev_priv->oa_pmu.lock, lock_flags);
> +
> + addr = i915_gem_obj_ggtt_offset(obj) + entry->offset;
Don't do more than one i915_gem_obj_to_ggtt() please (preferably none
and just keep hold of your pinned vma from the start).
> + /* addr should be 64 byte aligned */
> + BUG_ON(addr & 0x3f);
> +
> + ret = intel_ring_begin(ring, 4);
> + if (ret)
> + return;
You've commited the request to the sample list, but have just erred out.
> +
> + intel_ring_emit(ring, MI_REPORT_PERF_COUNT | (1<<0));
> + intel_ring_emit(ring, addr | MI_REPORT_PERF_COUNT_GGTT);
> + intel_ring_emit(ring, ring->outstanding_lazy_request->seqno);
> + intel_ring_emit(ring, MI_NOOP);
> + intel_ring_advance(ring);
> +
> + obj->base.write_domain = I915_GEM_DOMAIN_RENDER;
> + i915_vma_move_to_active(i915_gem_obj_to_ggtt(obj), ring);
That's the magic I have been looking for.
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 17+ messages in thread
* [RFC 7/8] drm/i915: Add support for having pid output with OA report
2015-07-15 8:46 [RFC 0/8] Introduce framework to forward multi context OA snapshots sourab.gupta
` (5 preceding siblings ...)
2015-07-15 8:47 ` [RFC 6/8] drm/i915: Insert commands for capture of OA counters in the ring sourab.gupta
@ 2015-07-15 8:47 ` sourab.gupta
2015-07-15 8:47 ` [RFC 8/8] drm/i915: Add support to add execbuffer tags to OA counter reports sourab.gupta
7 siblings, 0 replies; 17+ messages in thread
From: sourab.gupta @ 2015-07-15 8:47 UTC (permalink / raw)
To: intel-gfx; +Cc: Insoo Woo, Peter Zijlstra, Jabin Wu, Sourab Gupta
From: Sourab Gupta <sourab.gupta@intel.com>
This patch introduces flags and adds support for having pid output with the
OA reports generated through the RCS commands.
When the userspace expresses its interest in listening to the pid through
an oa_attr field during event init, the OA reports generated would have an
additional field appended with the pid information. The patches enables
this framework, which can be expanded upon to introduce further fields in
the OA report metadata.
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 3 +++
drivers/gpu/drm/i915/i915_oa_perf.c | 19 ++++++++++++++++++-
include/uapi/drm/i915_drm.h | 8 +++++++-
3 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index fb296ae..337a721 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1671,6 +1671,7 @@ struct i915_oa_rcs_node {
u32 offset;
bool discard;
u32 ctx_id;
+ u32 pid;
};
extern const struct i915_oa_reg i915_oa_3d_mux_config_hsw[];
@@ -1978,6 +1979,8 @@ struct drm_i915_private {
struct list_head node_list;
struct work_struct work_timer;
struct work_struct work_event_destroy;
+#define I915_OA_SAMPLE_PID (1<<0)
+ int sample_info_flags;
} oa_pmu;
void (*insert_profile_cmd[I915_PROFILE_MAX])
diff --git a/drivers/gpu/drm/i915/i915_oa_perf.c b/drivers/gpu/drm/i915/i915_oa_perf.c
index 9966e54..15920d1291 100644
--- a/drivers/gpu/drm/i915/i915_oa_perf.c
+++ b/drivers/gpu/drm/i915/i915_oa_perf.c
@@ -57,6 +57,8 @@ void i915_oa_insert_cmd(struct intel_ringbuffer *ringbuf, u32 ctx_id)
return;
}
entry->ctx_id = ctx_id;
+ if (dev_priv->oa_pmu.sample_info_flags & I915_OA_SAMPLE_PID)
+ entry->pid = current->pid;
i915_gem_request_assign(&entry->req, ring->outstanding_lazy_request);
spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
@@ -315,8 +317,9 @@ static void forward_one_oa_rcs_sample(struct drm_i915_private *dev_priv,
struct perf_sample_data data;
struct perf_event *event = dev_priv->oa_pmu.exclusive_event;
int format_size, snapshot_size;
- u8 *snapshot;
+ u8 *snapshot, *current_ptr;
struct drm_i915_oa_node_ctx_id *ctx_info;
+ struct drm_i915_oa_node_pid *pid_info;
struct perf_raw_record raw;
u64 snapshot_ts;
@@ -326,6 +329,14 @@ static void forward_one_oa_rcs_sample(struct drm_i915_private *dev_priv,
ctx_info = (struct drm_i915_oa_node_ctx_id *)(snapshot + format_size);
ctx_info->ctx_id = node->ctx_id;
+ current_ptr = snapshot + snapshot_size;
+
+ if (dev_priv->oa_pmu.sample_info_flags & I915_OA_SAMPLE_PID) {
+ pid_info = (struct drm_i915_oa_node_pid *)current_ptr;
+ pid_info->pid = node->pid;
+ snapshot_size += sizeof(*pid_info);
+ current_ptr = snapshot + snapshot_size;
+ }
/* Flush the periodic snapshots till the ts of this OA report */
snapshot_ts = *(u64 *)(snapshot + 4);
@@ -680,6 +691,9 @@ static int init_oa_rcs_buffer(struct perf_event *event)
node_size = dev_priv->oa_pmu.oa_rcs_buffer.format_size +
sizeof(struct drm_i915_oa_node_ctx_id);
+ if (dev_priv->oa_pmu.sample_info_flags & I915_OA_SAMPLE_PID)
+ node_size += sizeof(struct drm_i915_oa_node_pid);
+
/* node size has to be aligned to 64 bytes, since only 64 byte aligned
* addresses can be given to OA unit for dumping OA reports */
node_size = ALIGN(node_size, 64);
@@ -833,6 +847,9 @@ static int i915_oa_event_init(struct perf_event *event)
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
dev_priv->oa_pmu.multiple_ctx_mode = true;
+ if (oa_attr.sample_pid)
+ dev_priv->oa_pmu.sample_info_flags |=
+ I915_OA_SAMPLE_PID;
}
report_format = oa_attr.format;
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index e97b2fd..65e8297 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -93,7 +93,8 @@ typedef struct _drm_i915_oa_attr {
__u64 single_context : 1,
multiple_context_mode:1,
- __reserved_1:62;
+ sample_pid:1,
+ __reserved_1:61;
} drm_i915_oa_attr_t;
/* Header for PERF_RECORD_DEVICE type events */
@@ -128,6 +129,11 @@ struct drm_i915_oa_node_ctx_id {
__u32 pad;
};
+struct drm_i915_oa_node_pid {
+ __u32 pid;
+ __u32 pad;
+};
+
/* Each region is a minimum of 16k, and there are at most 255 of them.
*/
#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use
--
1.8.5.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 17+ messages in thread* [RFC 8/8] drm/i915: Add support to add execbuffer tags to OA counter reports
2015-07-15 8:46 [RFC 0/8] Introduce framework to forward multi context OA snapshots sourab.gupta
` (6 preceding siblings ...)
2015-07-15 8:47 ` [RFC 7/8] drm/i915: Add support for having pid output with OA report sourab.gupta
@ 2015-07-15 8:47 ` sourab.gupta
2015-07-15 10:02 ` Chris Wilson
` (2 more replies)
7 siblings, 3 replies; 17+ messages in thread
From: sourab.gupta @ 2015-07-15 8:47 UTC (permalink / raw)
To: intel-gfx; +Cc: Insoo Woo, Peter Zijlstra, Jabin Wu, Sourab Gupta
From: Sourab Gupta <sourab.gupta@intel.com>
This patch enables userspace to specify tags (per workload), provided via
execbuffer ioctl, which could be added to OA reports, to help associate
reports with the corresponding workloads.
There may be multiple stages within a single context, from a userspace
perspective. An ability is needed to individually associate the OA reports
with their corresponding workloads(execbuffers), which may not be possible
solely with ctx_id or pid information. This patch enables such a mechanism.
In this patch, rsvd2 field of execbuffer arguments is being utilized for
passing the tag. A new bitfield in execbuffer flags is introduced in order
to inform kernel of the tag being passed in execbuffer arguments.
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 9 ++++++---
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 8 ++++++--
drivers/gpu/drm/i915/i915_oa_perf.c | 23 ++++++++++++++++++++---
include/uapi/drm/i915_drm.h | 21 ++++++++++++++++++---
4 files changed, 50 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 337a721..9409b4a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1672,6 +1672,7 @@ struct i915_oa_rcs_node {
bool discard;
u32 ctx_id;
u32 pid;
+ u32 tag;
};
extern const struct i915_oa_reg i915_oa_3d_mux_config_hsw[];
@@ -1980,11 +1981,12 @@ struct drm_i915_private {
struct work_struct work_timer;
struct work_struct work_event_destroy;
#define I915_OA_SAMPLE_PID (1<<0)
+#define I915_OA_SAMPLE_TAG (1<<1)
int sample_info_flags;
} oa_pmu;
void (*insert_profile_cmd[I915_PROFILE_MAX])
- (struct intel_ringbuffer *ringbuf, u32 ctx_id);
+ (struct intel_ringbuffer *ringbuf, u32 ctx_id, int tag);
#endif
/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */
@@ -3165,7 +3167,8 @@ void i915_oa_context_pin_notify(struct drm_i915_private *dev_priv,
struct intel_context *context);
void i915_oa_context_unpin_notify(struct drm_i915_private *dev_priv,
struct intel_context *context);
-void i915_insert_profiling_cmd(struct intel_ringbuffer *ringbuf, u32 ctx_id);
+void i915_insert_profiling_cmd(struct intel_ringbuffer *ringbuf, u32 ctx_id,
+ int tag);
#else
static inline void
i915_oa_context_pin_notify(struct drm_i915_private *dev_priv,
@@ -3174,7 +3177,7 @@ static inline void
i915_oa_context_unpin_notify(struct drm_i915_private *dev_priv,
struct intel_context *context) {}
void i915_insert_profiling_cmd(struct intel_ringbuffer *ringbuf,
- u32 ctx_id) {};
+ u32 ctx_id, int tag) {};
#endif
/* i915_gem_evict.c */
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 2f8971b..53d228c 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1203,6 +1203,7 @@ i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file,
u64 exec_len;
int instp_mode;
u32 instp_mask;
+ u32 tag = 0;
int i, ret = 0;
if (args->num_cliprects != 0) {
@@ -1317,8 +1318,11 @@ i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file,
goto error;
}
+ if (args->flags & I915_EXEC_TAG)
+ tag = i915_execbuffer2_get_tag(*args);
+
i915_insert_profiling_cmd(ring->buffer,
- i915_execbuffer2_get_context_id(*args));
+ i915_execbuffer2_get_context_id(*args), tag);
exec_len = args->batch_len;
if (cliprects) {
@@ -1343,7 +1347,7 @@ i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file,
}
i915_insert_profiling_cmd(ring->buffer,
- i915_execbuffer2_get_context_id(*args));
+ i915_execbuffer2_get_context_id(*args), tag);
trace_i915_gem_ring_dispatch(intel_ring_get_request(ring), dispatch_flags);
diff --git a/drivers/gpu/drm/i915/i915_oa_perf.c b/drivers/gpu/drm/i915/i915_oa_perf.c
index 15920d1291..839ebb4 100644
--- a/drivers/gpu/drm/i915/i915_oa_perf.c
+++ b/drivers/gpu/drm/i915/i915_oa_perf.c
@@ -25,7 +25,8 @@ static int hsw_perf_format_sizes[] = {
64 /* C4_B8_HSW */
};
-void i915_insert_profiling_cmd(struct intel_ringbuffer *ringbuf, u32 ctx_id)
+void i915_insert_profiling_cmd(struct intel_ringbuffer *ringbuf, u32 ctx_id,
+ int tag)
{
struct intel_engine_cs *ring = ringbuf->ring;
struct drm_i915_private *dev_priv = ring->dev->dev_private;
@@ -33,11 +34,11 @@ void i915_insert_profiling_cmd(struct intel_ringbuffer *ringbuf, u32 ctx_id)
for (i = I915_PROFILE_OA; i < I915_PROFILE_MAX; i++) {
if (dev_priv->insert_profile_cmd[i])
- dev_priv->insert_profile_cmd[i](ringbuf, ctx_id);
+ dev_priv->insert_profile_cmd[i](ringbuf, ctx_id, tag);
}
}
-void i915_oa_insert_cmd(struct intel_ringbuffer *ringbuf, u32 ctx_id)
+void i915_oa_insert_cmd(struct intel_ringbuffer *ringbuf, u32 ctx_id, int tag)
{
struct intel_engine_cs *ring = ringbuf->ring;
struct drm_i915_private *dev_priv = ring->dev->dev_private;
@@ -59,6 +60,8 @@ void i915_oa_insert_cmd(struct intel_ringbuffer *ringbuf, u32 ctx_id)
entry->ctx_id = ctx_id;
if (dev_priv->oa_pmu.sample_info_flags & I915_OA_SAMPLE_PID)
entry->pid = current->pid;
+ if (dev_priv->oa_pmu.sample_info_flags & I915_OA_SAMPLE_TAG)
+ entry->tag = tag;
i915_gem_request_assign(&entry->req, ring->outstanding_lazy_request);
spin_lock_irqsave(&dev_priv->oa_pmu.lock, lock_flags);
@@ -320,6 +323,7 @@ static void forward_one_oa_rcs_sample(struct drm_i915_private *dev_priv,
u8 *snapshot, *current_ptr;
struct drm_i915_oa_node_ctx_id *ctx_info;
struct drm_i915_oa_node_pid *pid_info;
+ struct drm_i915_oa_node_tag *tag_info;
struct perf_raw_record raw;
u64 snapshot_ts;
@@ -338,6 +342,13 @@ static void forward_one_oa_rcs_sample(struct drm_i915_private *dev_priv,
current_ptr = snapshot + snapshot_size;
}
+ if (dev_priv->oa_pmu.sample_info_flags & I915_OA_SAMPLE_TAG) {
+ tag_info = (struct drm_i915_oa_node_tag *)current_ptr;
+ tag_info->tag = node->tag;
+ snapshot_size += sizeof(*tag_info);
+ current_ptr = snapshot + snapshot_size;
+ }
+
/* Flush the periodic snapshots till the ts of this OA report */
snapshot_ts = *(u64 *)(snapshot + 4);
flush_oa_snapshots(dev_priv, true, snapshot_ts);
@@ -694,6 +705,9 @@ static int init_oa_rcs_buffer(struct perf_event *event)
if (dev_priv->oa_pmu.sample_info_flags & I915_OA_SAMPLE_PID)
node_size += sizeof(struct drm_i915_oa_node_pid);
+ if (dev_priv->oa_pmu.sample_info_flags & I915_OA_SAMPLE_TAG)
+ node_size += sizeof(struct drm_i915_oa_node_tag);
+
/* node size has to be aligned to 64 bytes, since only 64 byte aligned
* addresses can be given to OA unit for dumping OA reports */
node_size = ALIGN(node_size, 64);
@@ -850,6 +864,9 @@ static int i915_oa_event_init(struct perf_event *event)
if (oa_attr.sample_pid)
dev_priv->oa_pmu.sample_info_flags |=
I915_OA_SAMPLE_PID;
+ if (oa_attr.sample_tag)
+ dev_priv->oa_pmu.sample_info_flags |=
+ I915_OA_SAMPLE_TAG;
}
report_format = oa_attr.format;
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 65e8297..1084178 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -94,7 +94,8 @@ typedef struct _drm_i915_oa_attr {
__u64 single_context : 1,
multiple_context_mode:1,
sample_pid:1,
- __reserved_1:61;
+ sample_tag:1,
+ __reserved_1:60;
} drm_i915_oa_attr_t;
/* Header for PERF_RECORD_DEVICE type events */
@@ -134,6 +135,11 @@ struct drm_i915_oa_node_pid {
__u32 pad;
};
+struct drm_i915_oa_node_tag {
+ __u32 tag;
+ __u32 pad;
+};
+
/* Each region is a minimum of 16k, and there are at most 255 of them.
*/
#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use
@@ -802,7 +808,7 @@ struct drm_i915_gem_execbuffer2 {
#define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */
__u64 flags;
__u64 rsvd1; /* now used for context info */
- __u64 rsvd2;
+ __u64 rsvd2; /* used for tag */
};
/** Resets the SO write offset registers for transform feedback on gen7. */
@@ -840,7 +846,12 @@ struct drm_i915_gem_execbuffer2 {
#define I915_EXEC_BSD_RING1 (1<<13)
#define I915_EXEC_BSD_RING2 (2<<13)
-#define __I915_EXEC_UNKNOWN_FLAGS -(1<<15)
+/** Inform the kernel that tag is passed through rsvd2 field of
+ * execbuffer args
+ */
+#define I915_EXEC_TAG (1<<15)
+
+#define __I915_EXEC_UNKNOWN_FLAGS -(1<<16)
#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff)
#define i915_execbuffer2_set_context_id(eb2, context) \
@@ -848,6 +859,10 @@ struct drm_i915_gem_execbuffer2 {
#define i915_execbuffer2_get_context_id(eb2) \
((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK)
+#define I915_EXEC_TAG_MASK (0xffffffff)
+#define i915_execbuffer2_get_tag(eb2) \
+ ((eb2).rsvd2 & I915_EXEC_TAG_MASK)
+
struct drm_i915_gem_pin {
/** Handle of the buffer to be pinned. */
__u32 handle;
--
1.8.5.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [RFC 8/8] drm/i915: Add support to add execbuffer tags to OA counter reports
2015-07-15 8:47 ` [RFC 8/8] drm/i915: Add support to add execbuffer tags to OA counter reports sourab.gupta
@ 2015-07-15 10:02 ` Chris Wilson
2015-07-15 10:04 ` Chris Wilson
2015-07-15 10:06 ` Chris Wilson
2 siblings, 0 replies; 17+ messages in thread
From: Chris Wilson @ 2015-07-15 10:02 UTC (permalink / raw)
To: sourab.gupta; +Cc: Peter Zijlstra, intel-gfx, Jabin Wu, Insoo Woo
On Wed, Jul 15, 2015 at 02:17:03PM +0530, sourab.gupta@intel.com wrote:
> @@ -802,7 +808,7 @@ struct drm_i915_gem_execbuffer2 {
> #define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */
> __u64 flags;
> __u64 rsvd1; /* now used for context info */
> - __u64 rsvd2;
> + __u64 rsvd2; /* used for tag */
Only the bottom 32bits of rsvd1 are ctx_id. tag seems a natural
complement to ctx_id and could be fitted into the top 32bits of rsvd1.
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [RFC 8/8] drm/i915: Add support to add execbuffer tags to OA counter reports
2015-07-15 8:47 ` [RFC 8/8] drm/i915: Add support to add execbuffer tags to OA counter reports sourab.gupta
2015-07-15 10:02 ` Chris Wilson
@ 2015-07-15 10:04 ` Chris Wilson
2015-07-15 10:06 ` Chris Wilson
2 siblings, 0 replies; 17+ messages in thread
From: Chris Wilson @ 2015-07-15 10:04 UTC (permalink / raw)
To: sourab.gupta; +Cc: Peter Zijlstra, intel-gfx, Jabin Wu, Insoo Woo
On Wed, Jul 15, 2015 at 02:17:03PM +0530, sourab.gupta@intel.com wrote:
> +/** Inform the kernel that tag is passed through rsvd2 field of
> + * execbuffer args
> + */
> +#define I915_EXEC_TAG (1<<15)
No need. The tag is always passed along, if this flag isn't set then it
is always 0. If it is, userspace had to use non-zero tag to discriminate
anyway.
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC 8/8] drm/i915: Add support to add execbuffer tags to OA counter reports
2015-07-15 8:47 ` [RFC 8/8] drm/i915: Add support to add execbuffer tags to OA counter reports sourab.gupta
2015-07-15 10:02 ` Chris Wilson
2015-07-15 10:04 ` Chris Wilson
@ 2015-07-15 10:06 ` Chris Wilson
2 siblings, 0 replies; 17+ messages in thread
From: Chris Wilson @ 2015-07-15 10:06 UTC (permalink / raw)
To: sourab.gupta; +Cc: Peter Zijlstra, intel-gfx, Jabin Wu, Insoo Woo
On Wed, Jul 15, 2015 at 02:17:03PM +0530, sourab.gupta@intel.com wrote:
> From: Sourab Gupta <sourab.gupta@intel.com>
>
> This patch enables userspace to specify tags (per workload), provided via
> execbuffer ioctl, which could be added to OA reports, to help associate
> reports with the corresponding workloads.
>
> There may be multiple stages within a single context, from a userspace
> perspective. An ability is needed to individually associate the OA reports
> with their corresponding workloads(execbuffers), which may not be possible
> solely with ctx_id or pid information. This patch enables such a mechanism.
>
> In this patch, rsvd2 field of execbuffer arguments is being utilized for
> passing the tag. A new bitfield in execbuffer flags is introduced in order
> to inform kernel of the tag being passed in execbuffer arguments.
>
> Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
> ---
> drivers/gpu/drm/i915/i915_drv.h | 9 ++++++---
> drivers/gpu/drm/i915/i915_gem_execbuffer.c | 8 ++++++--
> drivers/gpu/drm/i915/i915_oa_perf.c | 23 ++++++++++++++++++++---
> include/uapi/drm/i915_drm.h | 21 ++++++++++++++++++---
> 4 files changed, 50 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 337a721..9409b4a 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1672,6 +1672,7 @@ struct i915_oa_rcs_node {
> bool discard;
> u32 ctx_id;
> u32 pid;
> + u32 tag;
> };
>
> @@ -3165,7 +3167,8 @@ void i915_oa_context_pin_notify(struct drm_i915_private *dev_priv,
> struct intel_context *context);
> void i915_oa_context_unpin_notify(struct drm_i915_private *dev_priv,
> struct intel_context *context);
> -void i915_insert_profiling_cmd(struct intel_ringbuffer *ringbuf, u32 ctx_id);
> +void i915_insert_profiling_cmd(struct intel_ringbuffer *ringbuf, u32 ctx_id,
> + int tag);
Sloppy. Is the ABI signed or unsigned? Arbitrary width or fixed?
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 17+ messages in thread