Commit 9677a9f3 authored by Umesh Nerlige Ramappa's avatar Umesh Nerlige Ramappa Committed by John Harrison

drm/i915/perf: Move gt-specific data from i915->perf to gt->perf

Make perf part of gt as the OAG buffer is specific to a gt. The refactor
eventually simplifies programming the right OA buffer and the right HW
registers when supporting multiple gts.
Signed-off-by: default avatarUmesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
Reviewed-by: default avatarLionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: default avatarAshutosh Dixit <ashutosh.dixit@intel.com>
Signed-off-by: default avatarJohn Harrison <John.C.Harrison@Intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221026222102.5526-8-umesh.nerlige.ramappa@intel.com
parent a5a6d92f
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "intel_gsc.h" #include "intel_gsc.h"
#include "i915_vma.h" #include "i915_vma.h"
#include "i915_perf_types.h"
#include "intel_engine_types.h" #include "intel_engine_types.h"
#include "intel_gt_buffer_pool_types.h" #include "intel_gt_buffer_pool_types.h"
#include "intel_hwconfig.h" #include "intel_hwconfig.h"
...@@ -289,6 +290,8 @@ struct intel_gt { ...@@ -289,6 +290,8 @@ struct intel_gt {
/* sysfs defaults per gt */ /* sysfs defaults per gt */
struct gt_defaults defaults; struct gt_defaults defaults;
struct kobject *sysfs_defaults; struct kobject *sysfs_defaults;
struct i915_perf_gt perf;
}; };
struct intel_gt_definition { struct intel_gt_definition {
......
...@@ -677,8 +677,8 @@ u32 intel_sseu_make_rpcs(struct intel_gt *gt, ...@@ -677,8 +677,8 @@ u32 intel_sseu_make_rpcs(struct intel_gt *gt,
* If i915/perf is active, we want a stable powergating configuration * If i915/perf is active, we want a stable powergating configuration
* on the system. Use the configuration pinned by i915/perf. * on the system. Use the configuration pinned by i915/perf.
*/ */
if (i915->perf.exclusive_stream) if (gt->perf.exclusive_stream)
req_sseu = &i915->perf.sseu; req_sseu = &gt->perf.sseu;
slices = hweight8(req_sseu->slice_mask); slices = hweight8(req_sseu->slice_mask);
subslices = hweight8(req_sseu->subslice_mask); subslices = hweight8(req_sseu->subslice_mask);
......
...@@ -1565,8 +1565,9 @@ free_noa_wait(struct i915_perf_stream *stream) ...@@ -1565,8 +1565,9 @@ free_noa_wait(struct i915_perf_stream *stream)
static void i915_oa_stream_destroy(struct i915_perf_stream *stream) static void i915_oa_stream_destroy(struct i915_perf_stream *stream)
{ {
struct i915_perf *perf = stream->perf; struct i915_perf *perf = stream->perf;
struct intel_gt *gt = stream->engine->gt;
if (WARN_ON(stream != perf->exclusive_stream)) if (WARN_ON(stream != gt->perf.exclusive_stream))
return; return;
/* /*
...@@ -1575,7 +1576,7 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream) ...@@ -1575,7 +1576,7 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream)
* *
* See i915_oa_init_reg_state() and lrc_configure_all_contexts() * See i915_oa_init_reg_state() and lrc_configure_all_contexts()
*/ */
WRITE_ONCE(perf->exclusive_stream, NULL); WRITE_ONCE(gt->perf.exclusive_stream, NULL);
perf->ops.disable_metric_set(stream); perf->ops.disable_metric_set(stream);
free_oa_buffer(stream); free_oa_buffer(stream);
...@@ -2566,10 +2567,11 @@ oa_configure_all_contexts(struct i915_perf_stream *stream, ...@@ -2566,10 +2567,11 @@ oa_configure_all_contexts(struct i915_perf_stream *stream,
{ {
struct drm_i915_private *i915 = stream->perf->i915; struct drm_i915_private *i915 = stream->perf->i915;
struct intel_engine_cs *engine; struct intel_engine_cs *engine;
struct intel_gt *gt = stream->engine->gt;
struct i915_gem_context *ctx, *cn; struct i915_gem_context *ctx, *cn;
int err; int err;
lockdep_assert_held(&stream->perf->lock); lockdep_assert_held(&gt->perf.lock);
/* /*
* The OA register config is setup through the context image. This image * The OA register config is setup through the context image. This image
...@@ -3090,6 +3092,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, ...@@ -3090,6 +3092,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
{ {
struct drm_i915_private *i915 = stream->perf->i915; struct drm_i915_private *i915 = stream->perf->i915;
struct i915_perf *perf = stream->perf; struct i915_perf *perf = stream->perf;
struct intel_gt *gt;
int format_size; int format_size;
int ret; int ret;
...@@ -3098,6 +3101,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, ...@@ -3098,6 +3101,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
"OA engine not specified\n"); "OA engine not specified\n");
return -EINVAL; return -EINVAL;
} }
gt = props->engine->gt;
/* /*
* If the sysfs metrics/ directory wasn't registered for some * If the sysfs metrics/ directory wasn't registered for some
...@@ -3128,7 +3132,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, ...@@ -3128,7 +3132,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
* counter reports and marshal to the appropriate client * counter reports and marshal to the appropriate client
* we currently only allow exclusive access * we currently only allow exclusive access
*/ */
if (perf->exclusive_stream) { if (gt->perf.exclusive_stream) {
drm_dbg(&stream->perf->i915->drm, drm_dbg(&stream->perf->i915->drm,
"OA unit already in use\n"); "OA unit already in use\n");
return -EBUSY; return -EBUSY;
...@@ -3208,8 +3212,8 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, ...@@ -3208,8 +3212,8 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
stream->ops = &i915_oa_stream_ops; stream->ops = &i915_oa_stream_ops;
perf->sseu = props->sseu; stream->engine->gt->perf.sseu = props->sseu;
WRITE_ONCE(perf->exclusive_stream, stream); WRITE_ONCE(gt->perf.exclusive_stream, stream);
ret = i915_perf_stream_enable_sync(stream); ret = i915_perf_stream_enable_sync(stream);
if (ret) { if (ret) {
...@@ -3231,7 +3235,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, ...@@ -3231,7 +3235,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
return 0; return 0;
err_enable: err_enable:
WRITE_ONCE(perf->exclusive_stream, NULL); WRITE_ONCE(gt->perf.exclusive_stream, NULL);
perf->ops.disable_metric_set(stream); perf->ops.disable_metric_set(stream);
free_oa_buffer(stream); free_oa_buffer(stream);
...@@ -3261,7 +3265,7 @@ void i915_oa_init_reg_state(const struct intel_context *ce, ...@@ -3261,7 +3265,7 @@ void i915_oa_init_reg_state(const struct intel_context *ce,
return; return;
/* perf.exclusive_stream serialised by lrc_configure_all_contexts() */ /* perf.exclusive_stream serialised by lrc_configure_all_contexts() */
stream = READ_ONCE(engine->i915->perf.exclusive_stream); stream = READ_ONCE(engine->gt->perf.exclusive_stream);
if (stream && GRAPHICS_VER(stream->perf->i915) < 12) if (stream && GRAPHICS_VER(stream->perf->i915) < 12)
gen8_update_reg_state_unlocked(ce, stream); gen8_update_reg_state_unlocked(ce, stream);
} }
...@@ -3290,7 +3294,7 @@ static ssize_t i915_perf_read(struct file *file, ...@@ -3290,7 +3294,7 @@ static ssize_t i915_perf_read(struct file *file,
loff_t *ppos) loff_t *ppos)
{ {
struct i915_perf_stream *stream = file->private_data; struct i915_perf_stream *stream = file->private_data;
struct i915_perf *perf = stream->perf; struct intel_gt *gt = stream->engine->gt;
size_t offset = 0; size_t offset = 0;
int ret; int ret;
...@@ -3314,14 +3318,14 @@ static ssize_t i915_perf_read(struct file *file, ...@@ -3314,14 +3318,14 @@ static ssize_t i915_perf_read(struct file *file,
if (ret) if (ret)
return ret; return ret;
mutex_lock(&perf->lock); mutex_lock(&gt->perf.lock);
ret = stream->ops->read(stream, buf, count, &offset); ret = stream->ops->read(stream, buf, count, &offset);
mutex_unlock(&perf->lock); mutex_unlock(&gt->perf.lock);
} while (!offset && !ret); } while (!offset && !ret);
} else { } else {
mutex_lock(&perf->lock); mutex_lock(&gt->perf.lock);
ret = stream->ops->read(stream, buf, count, &offset); ret = stream->ops->read(stream, buf, count, &offset);
mutex_unlock(&perf->lock); mutex_unlock(&gt->perf.lock);
} }
/* We allow the poll checking to sometimes report false positive EPOLLIN /* We allow the poll checking to sometimes report false positive EPOLLIN
...@@ -3368,7 +3372,7 @@ static enum hrtimer_restart oa_poll_check_timer_cb(struct hrtimer *hrtimer) ...@@ -3368,7 +3372,7 @@ static enum hrtimer_restart oa_poll_check_timer_cb(struct hrtimer *hrtimer)
* &i915_perf_stream_ops->poll_wait to call poll_wait() with a wait queue that * &i915_perf_stream_ops->poll_wait to call poll_wait() with a wait queue that
* will be woken for new stream data. * will be woken for new stream data.
* *
* Note: The &perf->lock mutex has been taken to serialize * Note: The &gt->perf.lock mutex has been taken to serialize
* with any non-file-operation driver hooks. * with any non-file-operation driver hooks.
* *
* Returns: any poll events that are ready without sleeping * Returns: any poll events that are ready without sleeping
...@@ -3409,12 +3413,12 @@ static __poll_t i915_perf_poll_locked(struct i915_perf_stream *stream, ...@@ -3409,12 +3413,12 @@ static __poll_t i915_perf_poll_locked(struct i915_perf_stream *stream,
static __poll_t i915_perf_poll(struct file *file, poll_table *wait) static __poll_t i915_perf_poll(struct file *file, poll_table *wait)
{ {
struct i915_perf_stream *stream = file->private_data; struct i915_perf_stream *stream = file->private_data;
struct i915_perf *perf = stream->perf; struct intel_gt *gt = stream->engine->gt;
__poll_t ret; __poll_t ret;
mutex_lock(&perf->lock); mutex_lock(&gt->perf.lock);
ret = i915_perf_poll_locked(stream, file, wait); ret = i915_perf_poll_locked(stream, file, wait);
mutex_unlock(&perf->lock); mutex_unlock(&gt->perf.lock);
return ret; return ret;
} }
...@@ -3513,7 +3517,7 @@ static long i915_perf_config_locked(struct i915_perf_stream *stream, ...@@ -3513,7 +3517,7 @@ static long i915_perf_config_locked(struct i915_perf_stream *stream,
* @cmd: the ioctl request * @cmd: the ioctl request
* @arg: the ioctl data * @arg: the ioctl data
* *
* Note: The &perf->lock mutex has been taken to serialize * Note: The &gt->perf.lock mutex has been taken to serialize
* with any non-file-operation driver hooks. * with any non-file-operation driver hooks.
* *
* Returns: zero on success or a negative error code. Returns -EINVAL for * Returns: zero on success or a negative error code. Returns -EINVAL for
...@@ -3553,12 +3557,12 @@ static long i915_perf_ioctl(struct file *file, ...@@ -3553,12 +3557,12 @@ static long i915_perf_ioctl(struct file *file,
unsigned long arg) unsigned long arg)
{ {
struct i915_perf_stream *stream = file->private_data; struct i915_perf_stream *stream = file->private_data;
struct i915_perf *perf = stream->perf; struct intel_gt *gt = stream->engine->gt;
long ret; long ret;
mutex_lock(&perf->lock); mutex_lock(&gt->perf.lock);
ret = i915_perf_ioctl_locked(stream, cmd, arg); ret = i915_perf_ioctl_locked(stream, cmd, arg);
mutex_unlock(&perf->lock); mutex_unlock(&gt->perf.lock);
return ret; return ret;
} }
...@@ -3570,7 +3574,7 @@ static long i915_perf_ioctl(struct file *file, ...@@ -3570,7 +3574,7 @@ static long i915_perf_ioctl(struct file *file,
* Frees all resources associated with the given i915 perf @stream, disabling * Frees all resources associated with the given i915 perf @stream, disabling
* any associated data capture in the process. * any associated data capture in the process.
* *
* Note: The &perf->lock mutex has been taken to serialize * Note: The &gt->perf.lock mutex has been taken to serialize
* with any non-file-operation driver hooks. * with any non-file-operation driver hooks.
*/ */
static void i915_perf_destroy_locked(struct i915_perf_stream *stream) static void i915_perf_destroy_locked(struct i915_perf_stream *stream)
...@@ -3602,10 +3606,11 @@ static int i915_perf_release(struct inode *inode, struct file *file) ...@@ -3602,10 +3606,11 @@ static int i915_perf_release(struct inode *inode, struct file *file)
{ {
struct i915_perf_stream *stream = file->private_data; struct i915_perf_stream *stream = file->private_data;
struct i915_perf *perf = stream->perf; struct i915_perf *perf = stream->perf;
struct intel_gt *gt = stream->engine->gt;
mutex_lock(&perf->lock); mutex_lock(&gt->perf.lock);
i915_perf_destroy_locked(stream); i915_perf_destroy_locked(stream);
mutex_unlock(&perf->lock); mutex_unlock(&gt->perf.lock);
/* Release the reference the perf stream kept on the driver. */ /* Release the reference the perf stream kept on the driver. */
drm_dev_put(&perf->i915->drm); drm_dev_put(&perf->i915->drm);
...@@ -3638,7 +3643,7 @@ static const struct file_operations fops = { ...@@ -3638,7 +3643,7 @@ static const struct file_operations fops = {
* See i915_perf_ioctl_open() for interface details. * See i915_perf_ioctl_open() for interface details.
* *
* Implements further stream config validation and stream initialization on * Implements further stream config validation and stream initialization on
* behalf of i915_perf_open_ioctl() with the &perf->lock mutex * behalf of i915_perf_open_ioctl() with the &gt->perf.lock mutex
* taken to serialize with any non-file-operation driver hooks. * taken to serialize with any non-file-operation driver hooks.
* *
* Note: at this point the @props have only been validated in isolation and * Note: at this point the @props have only been validated in isolation and
...@@ -4022,7 +4027,7 @@ static int read_properties_unlocked(struct i915_perf *perf, ...@@ -4022,7 +4027,7 @@ static int read_properties_unlocked(struct i915_perf *perf,
* mutex to avoid an awkward lockdep with mmap_lock. * mutex to avoid an awkward lockdep with mmap_lock.
* *
* Most of the implementation details are handled by * Most of the implementation details are handled by
* i915_perf_open_ioctl_locked() after taking the &perf->lock * i915_perf_open_ioctl_locked() after taking the &gt->perf.lock
* mutex for serializing with any non-file-operation driver hooks. * mutex for serializing with any non-file-operation driver hooks.
* *
* Return: A newly opened i915 Perf stream file descriptor or negative * Return: A newly opened i915 Perf stream file descriptor or negative
...@@ -4033,6 +4038,7 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data, ...@@ -4033,6 +4038,7 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data,
{ {
struct i915_perf *perf = &to_i915(dev)->perf; struct i915_perf *perf = &to_i915(dev)->perf;
struct drm_i915_perf_open_param *param = data; struct drm_i915_perf_open_param *param = data;
struct intel_gt *gt;
struct perf_open_properties props; struct perf_open_properties props;
u32 known_open_flags; u32 known_open_flags;
int ret; int ret;
...@@ -4059,9 +4065,11 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data, ...@@ -4059,9 +4065,11 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data,
if (ret) if (ret)
return ret; return ret;
mutex_lock(&perf->lock); gt = props.engine->gt;
mutex_lock(&gt->perf.lock);
ret = i915_perf_open_ioctl_locked(perf, param, &props, file); ret = i915_perf_open_ioctl_locked(perf, param, &props, file);
mutex_unlock(&perf->lock); mutex_unlock(&gt->perf.lock);
return ret; return ret;
} }
...@@ -4077,6 +4085,7 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data, ...@@ -4077,6 +4085,7 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data,
void i915_perf_register(struct drm_i915_private *i915) void i915_perf_register(struct drm_i915_private *i915)
{ {
struct i915_perf *perf = &i915->perf; struct i915_perf *perf = &i915->perf;
struct intel_gt *gt = to_gt(i915);
if (!perf->i915) if (!perf->i915)
return; return;
...@@ -4085,13 +4094,13 @@ void i915_perf_register(struct drm_i915_private *i915) ...@@ -4085,13 +4094,13 @@ void i915_perf_register(struct drm_i915_private *i915)
* i915_perf_open_ioctl(); considering that we register after * i915_perf_open_ioctl(); considering that we register after
* being exposed to userspace. * being exposed to userspace.
*/ */
mutex_lock(&perf->lock); mutex_lock(&gt->perf.lock);
perf->metrics_kobj = perf->metrics_kobj =
kobject_create_and_add("metrics", kobject_create_and_add("metrics",
&i915->drm.primary->kdev->kobj); &i915->drm.primary->kdev->kobj);
mutex_unlock(&perf->lock); mutex_unlock(&gt->perf.lock);
} }
/** /**
...@@ -4768,7 +4777,11 @@ void i915_perf_init(struct drm_i915_private *i915) ...@@ -4768,7 +4777,11 @@ void i915_perf_init(struct drm_i915_private *i915)
} }
if (perf->ops.enable_metric_set) { if (perf->ops.enable_metric_set) {
mutex_init(&perf->lock); struct intel_gt *gt;
int i;
for_each_gt(gt, i915, i)
mutex_init(&gt->perf.lock);
/* Choose a representative limit */ /* Choose a representative limit */
oa_sample_rate_hard_limit = to_gt(i915)->clock_frequency / 2; oa_sample_rate_hard_limit = to_gt(i915)->clock_frequency / 2;
......
...@@ -380,6 +380,26 @@ struct i915_oa_ops { ...@@ -380,6 +380,26 @@ struct i915_oa_ops {
u32 (*oa_hw_tail_read)(struct i915_perf_stream *stream); u32 (*oa_hw_tail_read)(struct i915_perf_stream *stream);
}; };
struct i915_perf_gt {
/*
* Lock associated with anything below within this structure.
*/
struct mutex lock;
/**
* @sseu: sseu configuration selected to run while perf is active,
* applies to all contexts.
*/
struct intel_sseu sseu;
/*
* @exclusive_stream: The stream currently using the OA unit. This is
* sometimes accessed outside a syscall associated to its file
* descriptor.
*/
struct i915_perf_stream *exclusive_stream;
};
struct i915_perf { struct i915_perf {
struct drm_i915_private *i915; struct drm_i915_private *i915;
...@@ -397,25 +417,6 @@ struct i915_perf { ...@@ -397,25 +417,6 @@ struct i915_perf {
*/ */
struct idr metrics_idr; struct idr metrics_idr;
/*
* Lock associated with anything below within this structure
* except exclusive_stream.
*/
struct mutex lock;
/*
* The stream currently using the OA unit. If accessed
* outside a syscall associated to its file
* descriptor.
*/
struct i915_perf_stream *exclusive_stream;
/**
* @sseu: sseu configuration selected to run while perf is active,
* applies to all contexts.
*/
struct intel_sseu sseu;
/** /**
* For rate limiting any notifications of spurious * For rate limiting any notifications of spurious
* invalid OA reports * invalid OA reports
......
...@@ -102,6 +102,12 @@ test_stream(struct i915_perf *perf) ...@@ -102,6 +102,12 @@ test_stream(struct i915_perf *perf)
I915_OA_FORMAT_A32u40_A4u32_B8_C8 : I915_OA_FORMAT_C4_B8, I915_OA_FORMAT_A32u40_A4u32_B8_C8 : I915_OA_FORMAT_C4_B8,
}; };
struct i915_perf_stream *stream; struct i915_perf_stream *stream;
struct intel_gt *gt;
if (!props.engine)
return NULL;
gt = props.engine->gt;
if (!oa_config) if (!oa_config)
return NULL; return NULL;
...@@ -116,12 +122,12 @@ test_stream(struct i915_perf *perf) ...@@ -116,12 +122,12 @@ test_stream(struct i915_perf *perf)
stream->perf = perf; stream->perf = perf;
mutex_lock(&perf->lock); mutex_lock(&gt->perf.lock);
if (i915_oa_stream_init(stream, &param, &props)) { if (i915_oa_stream_init(stream, &param, &props)) {
kfree(stream); kfree(stream);
stream = NULL; stream = NULL;
} }
mutex_unlock(&perf->lock); mutex_unlock(&gt->perf.lock);
i915_oa_config_put(oa_config); i915_oa_config_put(oa_config);
...@@ -130,11 +136,11 @@ test_stream(struct i915_perf *perf) ...@@ -130,11 +136,11 @@ test_stream(struct i915_perf *perf)
static void stream_destroy(struct i915_perf_stream *stream) static void stream_destroy(struct i915_perf_stream *stream)
{ {
struct i915_perf *perf = stream->perf; struct intel_gt *gt = stream->engine->gt;
mutex_lock(&perf->lock); mutex_lock(&gt->perf.lock);
i915_perf_destroy_locked(stream); i915_perf_destroy_locked(stream);
mutex_unlock(&perf->lock); mutex_unlock(&gt->perf.lock);
} }
static int live_sanitycheck(void *arg) static int live_sanitycheck(void *arg)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment