summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/i915_perf.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_perf.c')
-rw-r--r--drivers/gpu/drm/i915/i915_perf.c140
1 files changed, 104 insertions, 36 deletions
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index e62ad69606f6..85ad62dbabfa 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -302,7 +302,7 @@ static u32 i915_oa_max_sample_rate = 100000;
* code assumes all reports have a power-of-two size and ~(size - 1) can
* be used as a mask to align the OA tail pointer.
*/
-static const struct i915_oa_format hsw_oa_formats[I915_OA_FORMAT_MAX] = {
+static const struct i915_oa_format oa_formats[I915_OA_FORMAT_MAX] = {
[I915_OA_FORMAT_A13] = { 0, 64 },
[I915_OA_FORMAT_A29] = { 1, 128 },
[I915_OA_FORMAT_A13_B8_C8] = { 2, 128 },
@@ -311,17 +311,9 @@ static const struct i915_oa_format hsw_oa_formats[I915_OA_FORMAT_MAX] = {
[I915_OA_FORMAT_A45_B8_C8] = { 5, 256 },
[I915_OA_FORMAT_B4_C8_A16] = { 6, 128 },
[I915_OA_FORMAT_C4_B8] = { 7, 64 },
-};
-
-static const struct i915_oa_format gen8_plus_oa_formats[I915_OA_FORMAT_MAX] = {
[I915_OA_FORMAT_A12] = { 0, 64 },
[I915_OA_FORMAT_A12_B8_C8] = { 2, 128 },
[I915_OA_FORMAT_A32u40_A4u32_B8_C8] = { 5, 256 },
- [I915_OA_FORMAT_C4_B8] = { 7, 64 },
-};
-
-static const struct i915_oa_format gen12_oa_formats[I915_OA_FORMAT_MAX] = {
- [I915_OA_FORMAT_A32u40_A4u32_B8_C8] = { 5, 256 },
};
#define SAMPLE_OA_REPORT (1<<0)
@@ -730,11 +722,6 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
(IS_GEN(stream->perf->i915, 12) ?
OAREPORT_REASON_MASK_EXTENDED :
OAREPORT_REASON_MASK));
- if (reason == 0) {
- if (__ratelimit(&stream->perf->spurious_report_rs))
- DRM_NOTE("Skipping spurious, invalid OA report\n");
- continue;
- }
ctx_id = report32[2] & stream->specific_ctx_id_mask;
@@ -1586,7 +1573,7 @@ static int alloc_oa_buffer(struct i915_perf_stream *stream)
stream->oa_buffer.vma = vma;
stream->oa_buffer.vaddr =
- i915_gem_object_pin_map(bo, I915_MAP_WB);
+ i915_gem_object_pin_map_unlocked(bo, I915_MAP_WB);
if (IS_ERR(stream->oa_buffer.vaddr)) {
ret = PTR_ERR(stream->oa_buffer.vaddr);
goto err_unpin;
@@ -1640,6 +1627,7 @@ static int alloc_noa_wait(struct i915_perf_stream *stream)
const u32 base = stream->engine->mmio_base;
#define CS_GPR(x) GEN8_RING_CS_GPR(base, x)
u32 *batch, *ts0, *cs, *jump;
+ struct i915_gem_ww_ctx ww;
int ret, i;
enum {
START_TS,
@@ -1657,15 +1645,21 @@ static int alloc_noa_wait(struct i915_perf_stream *stream)
return PTR_ERR(bo);
}
+ i915_gem_ww_ctx_init(&ww, true);
+retry:
+ ret = i915_gem_object_lock(bo, &ww);
+ if (ret)
+ goto out_ww;
+
/*
* We pin in GGTT because we jump into this buffer now because
* multiple OA config BOs will have a jump to this address and it
* needs to be fixed during the lifetime of the i915/perf stream.
*/
- vma = i915_gem_object_ggtt_pin(bo, NULL, 0, 0, PIN_HIGH);
+ vma = i915_gem_object_ggtt_pin_ww(bo, &ww, NULL, 0, 0, PIN_HIGH);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
- goto err_unref;
+ goto out_ww;
}
batch = cs = i915_gem_object_pin_map(bo, I915_MAP_WB);
@@ -1799,12 +1793,19 @@ static int alloc_noa_wait(struct i915_perf_stream *stream)
__i915_gem_object_release_map(bo);
stream->noa_wait = vma;
- return 0;
+ goto out_ww;
err_unpin:
i915_vma_unpin_and_release(&vma, 0);
-err_unref:
- i915_gem_object_put(bo);
+out_ww:
+ if (ret == -EDEADLK) {
+ ret = i915_gem_ww_ctx_backoff(&ww);
+ if (!ret)
+ goto retry;
+ }
+ i915_gem_ww_ctx_fini(&ww);
+ if (ret)
+ i915_gem_object_put(bo);
return ret;
}
@@ -1847,6 +1848,7 @@ alloc_oa_config_buffer(struct i915_perf_stream *stream,
{
struct drm_i915_gem_object *obj;
struct i915_oa_config_bo *oa_bo;
+ struct i915_gem_ww_ctx ww;
size_t config_length = 0;
u32 *cs;
int err;
@@ -1867,10 +1869,16 @@ alloc_oa_config_buffer(struct i915_perf_stream *stream,
goto err_free;
}
+ i915_gem_ww_ctx_init(&ww, true);
+retry:
+ err = i915_gem_object_lock(obj, &ww);
+ if (err)
+ goto out_ww;
+
cs = i915_gem_object_pin_map(obj, I915_MAP_WB);
if (IS_ERR(cs)) {
err = PTR_ERR(cs);
- goto err_oa_bo;
+ goto out_ww;
}
cs = write_cs_mi_lri(cs,
@@ -1898,19 +1906,28 @@ alloc_oa_config_buffer(struct i915_perf_stream *stream,
NULL);
if (IS_ERR(oa_bo->vma)) {
err = PTR_ERR(oa_bo->vma);
- goto err_oa_bo;
+ goto out_ww;
}
oa_bo->oa_config = i915_oa_config_get(oa_config);
llist_add(&oa_bo->node, &stream->oa_config_bos);
- return oa_bo;
+out_ww:
+ if (err == -EDEADLK) {
+ err = i915_gem_ww_ctx_backoff(&ww);
+ if (!err)
+ goto retry;
+ }
+ i915_gem_ww_ctx_fini(&ww);
-err_oa_bo:
- i915_gem_object_put(obj);
+ if (err)
+ i915_gem_object_put(obj);
err_free:
- kfree(oa_bo);
- return ERR_PTR(err);
+ if (err) {
+ kfree(oa_bo);
+ return ERR_PTR(err);
+ }
+ return oa_bo;
}
static struct i915_vma *
@@ -3521,6 +3538,18 @@ static u64 oa_exponent_to_ns(struct i915_perf *perf, int exponent)
2ULL << exponent);
}
+static __always_inline bool
+oa_format_valid(struct i915_perf *perf, enum drm_i915_oa_format format)
+{
+ return test_bit(format, perf->format_mask);
+}
+
+static __always_inline void
+oa_format_add(struct i915_perf *perf, enum drm_i915_oa_format format)
+{
+ __set_bit(format, perf->format_mask);
+}
+
/**
* read_properties_unlocked - validate + copy userspace stream open properties
* @perf: i915 perf instance
@@ -3612,7 +3641,7 @@ static int read_properties_unlocked(struct i915_perf *perf,
value);
return -EINVAL;
}
- if (!perf->oa_formats[value].size) {
+ if (!oa_format_valid(perf, value)) {
DRM_DEBUG("Unsupported OA report format %llu\n",
value);
return -EINVAL;
@@ -4256,6 +4285,50 @@ static struct ctl_table dev_root[] = {
{}
};
+static void oa_init_supported_formats(struct i915_perf *perf)
+{
+ struct drm_i915_private *i915 = perf->i915;
+ enum intel_platform platform = INTEL_INFO(i915)->platform;
+
+ switch (platform) {
+ case INTEL_HASWELL:
+ oa_format_add(perf, I915_OA_FORMAT_A13);
+ oa_format_add(perf, I915_OA_FORMAT_A13);
+ oa_format_add(perf, I915_OA_FORMAT_A29);
+ oa_format_add(perf, I915_OA_FORMAT_A13_B8_C8);
+ oa_format_add(perf, I915_OA_FORMAT_B4_C8);
+ oa_format_add(perf, I915_OA_FORMAT_A45_B8_C8);
+ oa_format_add(perf, I915_OA_FORMAT_B4_C8_A16);
+ oa_format_add(perf, I915_OA_FORMAT_C4_B8);
+ break;
+
+ case INTEL_BROADWELL:
+ case INTEL_CHERRYVIEW:
+ case INTEL_SKYLAKE:
+ case INTEL_BROXTON:
+ case INTEL_KABYLAKE:
+ case INTEL_GEMINILAKE:
+ case INTEL_COFFEELAKE:
+ case INTEL_COMETLAKE:
+ case INTEL_CANNONLAKE:
+ case INTEL_ICELAKE:
+ case INTEL_ELKHARTLAKE:
+ case INTEL_JASPERLAKE:
+ case INTEL_TIGERLAKE:
+ case INTEL_ROCKETLAKE:
+ case INTEL_DG1:
+ case INTEL_ALDERLAKE_S:
+ oa_format_add(perf, I915_OA_FORMAT_A12);
+ oa_format_add(perf, I915_OA_FORMAT_A12_B8_C8);
+ oa_format_add(perf, I915_OA_FORMAT_A32u40_A4u32_B8_C8);
+ oa_format_add(perf, I915_OA_FORMAT_C4_B8);
+ break;
+
+ default:
+ MISSING_CASE(platform);
+ }
+}
+
/**
* i915_perf_init - initialize i915-perf state on module bind
* @i915: i915 device instance
@@ -4271,6 +4344,7 @@ void i915_perf_init(struct drm_i915_private *i915)
/* XXX const struct i915_perf_ops! */
+ perf->oa_formats = oa_formats;
if (IS_HASWELL(i915)) {
perf->ops.is_valid_b_counter_reg = gen7_is_valid_b_counter_addr;
perf->ops.is_valid_mux_reg = hsw_is_valid_mux_addr;
@@ -4281,8 +4355,6 @@ void i915_perf_init(struct drm_i915_private *i915)
perf->ops.oa_disable = gen7_oa_disable;
perf->ops.read = gen7_oa_read;
perf->ops.oa_hw_tail_read = gen7_oa_hw_tail_read;
-
- perf->oa_formats = hsw_oa_formats;
} else if (HAS_LOGICAL_RING_CONTEXTS(i915)) {
/* Note: that although we could theoretically also support the
* legacy ringbuffer mode on BDW (and earlier iterations of
@@ -4293,8 +4365,6 @@ void i915_perf_init(struct drm_i915_private *i915)
perf->ops.read = gen8_oa_read;
if (IS_GEN_RANGE(i915, 8, 9)) {
- perf->oa_formats = gen8_plus_oa_formats;
-
perf->ops.is_valid_b_counter_reg =
gen7_is_valid_b_counter_addr;
perf->ops.is_valid_mux_reg =
@@ -4325,8 +4395,6 @@ void i915_perf_init(struct drm_i915_private *i915)
perf->gen8_valid_ctx_bit = BIT(16);
}
} else if (IS_GEN_RANGE(i915, 10, 11)) {
- perf->oa_formats = gen8_plus_oa_formats;
-
perf->ops.is_valid_b_counter_reg =
gen7_is_valid_b_counter_addr;
perf->ops.is_valid_mux_reg =
@@ -4349,8 +4417,6 @@ void i915_perf_init(struct drm_i915_private *i915)
}
perf->gen8_valid_ctx_bit = BIT(16);
} else if (IS_GEN(i915, 12)) {
- perf->oa_formats = gen12_oa_formats;
-
perf->ops.is_valid_b_counter_reg =
gen12_is_valid_b_counter_addr;
perf->ops.is_valid_mux_reg =
@@ -4405,6 +4471,8 @@ void i915_perf_init(struct drm_i915_private *i915)
500 * 1000 /* 500us */);
perf->i915 = i915;
+
+ oa_init_supported_formats(perf);
}
}