Commit 6a77c6bb authored by Umesh Nerlige Ramappa's avatar Umesh Nerlige Ramappa Committed by Jani Nikula

i915/perf: Start hrtimer only if sampling the OA buffer

SAMPLE_OA parameter enables sampling of OA buffer and results in a call
to init the OA buffer which initializes the OA unit head/tail pointers.
The OA_EXPONENT parameter controls the periodicity of the OA reports in
the OA buffer and results in starting a hrtimer.

Before gen12, all use cases required the use of the OA buffer and i915
enforced this setting when vetting out the parameters passed. In these
platforms the hrtimer was enabled if OA_EXPONENT was passed. This worked
fine since it was implied that SAMPLE_OA is always passed.

With gen12, this changed. Users can use perf without enabling the OA
buffer as in OAR use cases. While an OAR use case should ideally not
start the hrtimer, we see that passing an OA_EXPONENT parameter will
start the hrtimer even though SAMPLE_OA is not specified. This results
in an uninitialized OA buffer, so the head/tail pointers used to track
the buffer are zero.

This itself does not fail, but if we ran a use-case that SAMPLED the OA
buffer previously, then the OA_TAIL register is still pointing to an old
value. When the timer callback runs, it ends up calculating a
wrong/large number of available reports. Since we do a spinlock_irq_save
and start processing a large number of reports, NMI watchdog fires and
causes a crash.

Start the timer only if SAMPLE_OA is specified.

v2:
- Drop SAMPLE OA check when appending samples (Ashutosh)
- Prevent read if OA buffer is not being sampled

Fixes: 00a7f0d7 ("drm/i915/tgl: Add perf support on TGL")
Signed-off-by: default avatarUmesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
Reviewed-by: default avatarAshutosh Dixit <ashutosh.dixit@intel.com>
Signed-off-by: default avatarLionel Landwerlin <lionel.g.landwerlin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210305210947.58751-1-umesh.nerlige.ramappa@intel.com
(cherry picked from commit be0bdd67)
Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
parent 8e62438a
...@@ -603,7 +603,6 @@ static int append_oa_sample(struct i915_perf_stream *stream, ...@@ -603,7 +603,6 @@ static int append_oa_sample(struct i915_perf_stream *stream,
{ {
int report_size = stream->oa_buffer.format_size; int report_size = stream->oa_buffer.format_size;
struct drm_i915_perf_record_header header; struct drm_i915_perf_record_header header;
u32 sample_flags = stream->sample_flags;
header.type = DRM_I915_PERF_RECORD_SAMPLE; header.type = DRM_I915_PERF_RECORD_SAMPLE;
header.pad = 0; header.pad = 0;
...@@ -617,10 +616,8 @@ static int append_oa_sample(struct i915_perf_stream *stream, ...@@ -617,10 +616,8 @@ static int append_oa_sample(struct i915_perf_stream *stream,
return -EFAULT; return -EFAULT;
buf += sizeof(header); buf += sizeof(header);
if (sample_flags & SAMPLE_OA_REPORT) { if (copy_to_user(buf, report, report_size))
if (copy_to_user(buf, report, report_size)) return -EFAULT;
return -EFAULT;
}
(*offset) += header.size; (*offset) += header.size;
...@@ -2682,7 +2679,7 @@ static void i915_oa_stream_enable(struct i915_perf_stream *stream) ...@@ -2682,7 +2679,7 @@ static void i915_oa_stream_enable(struct i915_perf_stream *stream)
stream->perf->ops.oa_enable(stream); stream->perf->ops.oa_enable(stream);
if (stream->periodic) if (stream->sample_flags & SAMPLE_OA_REPORT)
hrtimer_start(&stream->poll_check_timer, hrtimer_start(&stream->poll_check_timer,
ns_to_ktime(stream->poll_oa_period), ns_to_ktime(stream->poll_oa_period),
HRTIMER_MODE_REL_PINNED); HRTIMER_MODE_REL_PINNED);
...@@ -2745,7 +2742,7 @@ static void i915_oa_stream_disable(struct i915_perf_stream *stream) ...@@ -2745,7 +2742,7 @@ static void i915_oa_stream_disable(struct i915_perf_stream *stream)
{ {
stream->perf->ops.oa_disable(stream); stream->perf->ops.oa_disable(stream);
if (stream->periodic) if (stream->sample_flags & SAMPLE_OA_REPORT)
hrtimer_cancel(&stream->poll_check_timer); hrtimer_cancel(&stream->poll_check_timer);
} }
...@@ -3028,7 +3025,7 @@ static ssize_t i915_perf_read(struct file *file, ...@@ -3028,7 +3025,7 @@ static ssize_t i915_perf_read(struct file *file,
* disabled stream as an error. In particular it might otherwise lead * disabled stream as an error. In particular it might otherwise lead
* to a deadlock for blocking file descriptors... * to a deadlock for blocking file descriptors...
*/ */
if (!stream->enabled) if (!stream->enabled || !(stream->sample_flags & SAMPLE_OA_REPORT))
return -EIO; return -EIO;
if (!(file->f_flags & O_NONBLOCK)) { if (!(file->f_flags & O_NONBLOCK)) {
......
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