[PATCH 46/46] drm/i915: Guard unpark/park with the gt.active_mutex
Chris Wilson
chris at chris-wilson.co.uk
Fri Mar 1 15:06:56 UTC 2019
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_debugfs.c | 9 ++++----
drivers/gpu/drm/i915/i915_drv.h | 3 ++-
drivers/gpu/drm/i915/i915_gem.c | 23 ++++++++++---------
drivers/gpu/drm/i915/i915_gem_evict.c | 3 ++-
drivers/gpu/drm/i915/i915_request.c | 23 ++++++++++++++-----
.../gpu/drm/i915/selftests/i915_gem_context.c | 4 ++--
.../gpu/drm/i915/selftests/i915_gem_object.c | 12 +++++-----
.../gpu/drm/i915/selftests/mock_gem_device.c | 3 ++-
8 files changed, 48 insertions(+), 32 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 48afa85220a4..4ee66fbfbee4 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2028,7 +2028,8 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
seq_printf(m, "RPS enabled? %d\n", rps->enabled);
seq_printf(m, "GPU busy? %s [%d requests]\n",
- yesno(dev_priv->gt.awake), dev_priv->gt.active_requests);
+ yesno(dev_priv->gt.awake),
+ atomic_read(&dev_priv->gt.active_requests));
seq_printf(m, "Boosts outstanding? %d\n",
atomic_read(&rps->num_waiters));
seq_printf(m, "Interactive? %d\n", READ_ONCE(rps->power.interactive));
@@ -2049,7 +2050,7 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
if (INTEL_GEN(dev_priv) >= 6 &&
rps->enabled &&
- dev_priv->gt.active_requests) {
+ atomic_read(&dev_priv->gt.active_requests)) {
u32 rpup, rpupei;
u32 rpdown, rpdownei;
@@ -3081,7 +3082,7 @@ static int i915_engine_info(struct seq_file *m, void *unused)
seq_printf(m, "GT awake? %s\n", yesno(dev_priv->gt.awake));
seq_printf(m, "Global active requests: %d\n",
- dev_priv->gt.active_requests);
+ atomic_read(&dev_priv->gt.active_requests));
seq_printf(m, "CS timestamp frequency: %u kHz\n",
RUNTIME_INFO(dev_priv)->cs_timestamp_frequency_khz);
@@ -3928,7 +3929,7 @@ i915_drop_caches_set(void *data, u64 val)
if (val & DROP_IDLE) {
do {
- if (READ_ONCE(i915->gt.active_requests))
+ if (atomic_read(&i915->gt.active_requests))
flush_delayed_work(&i915->gt.retire_work);
drain_delayed_work(&i915->gt.idle_work);
} while (READ_ONCE(i915->gt.awake));
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index fb5d465d0e45..5eccae4fbef9 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1994,11 +1994,12 @@ struct drm_i915_private {
struct list_head hwsp_free_list;
} timelines;
+ atomic_t active_requests;
+ struct mutex active_mutex;
struct list_head active_rings;
struct list_head closed_vma;
unsigned long active_engines;
unsigned long idle_barriers;
- u32 active_requests;
/**
* Is the GPU currently considered idle, or busy executing
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 8e6248fd8908..32b8072151a1 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -108,7 +108,7 @@ static void __i915_gem_park(struct drm_i915_private *i915)
GEM_TRACE("\n");
lockdep_assert_held(&i915->drm.struct_mutex);
- GEM_BUG_ON(i915->gt.active_requests);
+ GEM_BUG_ON(atomic_read(&i915->gt.active_requests));
GEM_BUG_ON(i915->gt.idle_barriers);
GEM_BUG_ON(!list_empty(&i915->gt.active_rings));
@@ -150,7 +150,7 @@ void i915_gem_park(struct drm_i915_private *i915)
GEM_TRACE("\n");
lockdep_assert_held(&i915->drm.struct_mutex);
- GEM_BUG_ON(i915->gt.active_requests);
+ GEM_BUG_ON(atomic_read(&i915->gt.active_requests));
if (!i915->gt.awake)
return;
@@ -163,8 +163,7 @@ void i915_gem_unpark(struct drm_i915_private *i915)
{
GEM_TRACE("\n");
- lockdep_assert_held(&i915->drm.struct_mutex);
- GEM_BUG_ON(!i915->gt.active_requests);
+ lockdep_assert_held(&i915->gt.active_mutex);
assert_rpm_wakelock_held(i915);
if (i915->gt.awake)
@@ -2910,13 +2909,13 @@ i915_gem_idle_work_handler(struct work_struct *work)
if (!READ_ONCE(gt->awake))
return;
- if (READ_ONCE(gt->active_requests))
+ if (atomic_read(>->active_requests))
return;
rearm_hangcheck =
cancel_delayed_work_sync(&i915->gpu_error.hangcheck_work);
- if (!mutex_trylock(&i915->drm.struct_mutex)) {
+ if (!mutex_trylock(&i915->gt.active_mutex)) {
/* Currently busy, come back later */
mod_delayed_work(i915->wq,
>->idle_work,
@@ -2930,8 +2929,9 @@ i915_gem_idle_work_handler(struct work_struct *work)
* while we are idle (such as the GPU being power cycled), no users
* will be harmed.
*/
- if (!gt->active_requests && !work_pending(>->idle_work.work)) {
- ++gt->active_requests; /* don't requeue idle */
+ if (!atomic_read(>->active_requests) &&
+ !work_pending(>->idle_work.work)) {
+ atomic_inc(>->active_requests); /* don't requeue idle */
if (!switch_to_kernel_context_idle(i915,
i915->gt.active_engines)) {
@@ -2942,13 +2942,13 @@ i915_gem_idle_work_handler(struct work_struct *work)
}
i915_retire_requests(i915);
- if (!--gt->active_requests) {
+ if (atomic_dec_and_test(>->active_requests)) {
__i915_gem_park(i915);
rearm_hangcheck = false;
}
}
- mutex_unlock(&i915->drm.struct_mutex);
+ mutex_unlock(&i915->gt.active_mutex);
out_rearm:
if (rearm_hangcheck) {
@@ -3096,7 +3096,7 @@ wait_for_timelines(struct drm_i915_private *i915,
struct i915_gt_timelines *gt = &i915->gt.timelines;
struct i915_timeline *tl;
- if (!READ_ONCE(i915->gt.active_requests))
+ if (!atomic_read(&i915->gt.active_requests))
return timeout;
mutex_lock(>->mutex);
@@ -5038,6 +5038,7 @@ int i915_gem_init_early(struct drm_i915_private *dev_priv)
{
int err;
+ mutex_init(&dev_priv->gt.active_mutex);
INIT_LIST_HEAD(&dev_priv->gt.active_rings);
INIT_LIST_HEAD(&dev_priv->gt.closed_vma);
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index 43f61d7eb1d0..5f67c31badc6 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -38,7 +38,8 @@ I915_SELFTEST_DECLARE(static struct igt_evict_ctl {
static bool ggtt_is_idle(struct drm_i915_private *i915)
{
- return !i915->gt.active_requests && !i915->gt.idle_barriers;
+ return (!atomic_read(&i915->gt.active_requests) &&
+ !i915->gt.idle_barriers);
}
static int ggtt_flush(struct drm_i915_private *i915)
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
index 69d2767b15e1..9c82b15ca179 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -132,15 +132,26 @@ i915_request_remove_from_client(struct i915_request *request)
static void reserve_gt(struct drm_i915_private *i915)
{
- if (!i915->gt.active_requests++)
+ if (atomic_add_unless(&i915->gt.active_requests, 1, 0))
+ return;
+
+ mutex_lock(&i915->gt.active_mutex);
+ if (!atomic_read(&i915->gt.active_requests)) {
i915_gem_unpark(i915);
+ smp_mb__before_atomic();
+ }
+ atomic_inc(&i915->gt.active_requests);
+ mutex_unlock(&i915->gt.active_mutex);
}
static void unreserve_gt(struct drm_i915_private *i915)
{
- GEM_BUG_ON(!i915->gt.active_requests);
- if (!--i915->gt.active_requests)
- i915_gem_park(i915);
+ if (!atomic_dec_and_mutex_lock(&i915->gt.active_requests,
+ &i915->gt.active_mutex))
+ return;
+
+ i915_gem_park(i915);
+ mutex_unlock(&i915->gt.active_mutex);
}
static void advance_ring(struct i915_request *request)
@@ -686,7 +697,7 @@ i915_request_alloc(struct intel_context *ce, gfp_t gfp)
GEM_BUG_ON(rq->timeline->seqno != rq->fence.seqno);
__intel_context_pin(ce);
- rq->i915->gt.active_requests++;
+ atomic_inc(&rq->i915->gt.active_requests);
return rq;
@@ -1382,7 +1393,7 @@ void i915_retire_requests(struct drm_i915_private *i915)
lockdep_assert_held(&i915->drm.struct_mutex);
- if (!i915->gt.active_requests)
+ if (!atomic_read(&i915->gt.active_requests))
return;
list_for_each_entry_safe(ring, tmp, &i915->gt.active_rings, active_link)
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c
index 066da40974f5..a4b6d60682bd 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c
@@ -1658,9 +1658,9 @@ static int __igt_switch_to_kernel_context(struct drm_i915_private *i915,
return err;
}
- if (i915->gt.active_requests) {
+ if (atomic_read(&i915->gt.active_requests)) {
pr_err("%d active requests remain after switching to kernel context, pass %d (%s) on %s engine%s\n",
- i915->gt.active_requests,
+ atomic_read(&i915->gt.active_requests),
pass, from_idle ? "idle" : "busy",
__engine_name(i915, engines),
is_power_of_2(engines) ? "" : "s");
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/selftests/i915_gem_object.c
index aece5c8bcea9..e59544119b12 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_object.c
@@ -505,14 +505,14 @@ static void disable_retire_worker(struct drm_i915_private *i915)
{
i915_gem_shrinker_unregister(i915);
- mutex_lock(&i915->drm.struct_mutex);
- if (!i915->gt.active_requests++) {
+ mutex_lock(&i915->gt.active_mutex);
+ if (!atomic_fetch_inc(&i915->gt.active_requests)) {
intel_wakeref_t wakeref;
with_intel_runtime_pm(i915, wakeref)
i915_gem_unpark(i915);
}
- mutex_unlock(&i915->drm.struct_mutex);
+ mutex_unlock(&i915->gt.active_mutex);
cancel_delayed_work_sync(&i915->gt.retire_work);
cancel_delayed_work_sync(&i915->gt.idle_work);
@@ -615,12 +615,12 @@ static int igt_mmap_offset_exhaustion(void *arg)
out:
drm_mm_remove_node(&resv);
out_park:
- mutex_lock(&i915->drm.struct_mutex);
- if (--i915->gt.active_requests)
+ mutex_lock(&i915->gt.active_mutex);
+ if (atomic_dec_and_test(&i915->gt.active_requests))
queue_delayed_work(i915->wq, &i915->gt.retire_work, 0);
else
queue_delayed_work(i915->wq, &i915->gt.idle_work, 0);
- mutex_unlock(&i915->drm.struct_mutex);
+ mutex_unlock(&i915->gt.active_mutex);
i915_gem_shrinker_register(i915);
return err;
err_obj:
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
index a0925e4905ae..f19c3ca624b2 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
@@ -44,7 +44,7 @@ void mock_device_flush(struct drm_i915_private *i915)
mock_engine_flush(engine);
i915_retire_requests(i915);
- GEM_BUG_ON(i915->gt.active_requests);
+ GEM_BUG_ON(atomic_read(&i915->gt.active_requests));
}
static void mock_device_release(struct drm_device *dev)
@@ -202,6 +202,7 @@ struct drm_i915_private *mock_gem_device(void)
i915_timelines_init(i915);
+ mutex_init(&i915->gt.active_mutex);
INIT_LIST_HEAD(&i915->gt.active_rings);
INIT_LIST_HEAD(&i915->gt.closed_vma);
--
2.20.1
More information about the Intel-gfx-trybot
mailing list