Looks good to me, thanks for the test case (btw maybe it's worth
mentioning in the commit message that the test fails without doing
gt.resume?)

Reviewed-by: Jakub Bartmiński <jakub.bartmin...@intel.com>

On Thu, 2018-08-30 at 14:48 +0100, Chris Wilson wrote:
> Although we cannot do a full system-level test of suspend/hibernate
> from
> deep with the kernel selftests, we can exercise the GEM subsystem in
> isolation and simulate the external effects (such as losing stolen
> contents and trashing the register state).
> 
> v2: Don't forget to hold rpm
> v3: Suspend the GTT mappings, and more rpm!
> 
> Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk>
> Cc: Jakub Bartmiński <jakub.bartmin...@intel.com>
> Cc: Matthew Auld <matthew.william.a...@gmail.com>
> Cc: Joonas Lahtinen <joonas.lahti...@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_gem.c               |   1 +
>  drivers/gpu/drm/i915/selftests/i915_gem.c     | 221
> ++++++++++++++++++
>  .../drm/i915/selftests/i915_live_selftests.h  |   1 +
>  3 files changed, 223 insertions(+)
>  create mode 100644 drivers/gpu/drm/i915/selftests/i915_gem.c
> 
> diff --git a/drivers/gpu/drm/i915/i915_gem.c
> b/drivers/gpu/drm/i915/i915_gem.c
> index 0453eb42a1a3..7b7bbfe59697 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -6207,4 +6207,5 @@ int i915_gem_object_attach_phys(struct
> drm_i915_gem_object *obj, int align)
>  #include "selftests/huge_pages.c"
>  #include "selftests/i915_gem_object.c"
>  #include "selftests/i915_gem_coherency.c"
> +#include "selftests/i915_gem.c"
>  #endif
> diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c
> b/drivers/gpu/drm/i915/selftests/i915_gem.c
> new file mode 100644
> index 000000000000..e9cfc1fb0c07
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/selftests/i915_gem.c
> @@ -0,0 +1,221 @@
> +/*
> + * SPDX-License-Identifier: MIT
> + *
> + * Copyright © 2018 Intel Corporation
> + */
> +
> +#include <linux/random.h>
> +
> +#include "../i915_selftest.h"
> +
> +#include "mock_context.h"
> +#include "igt_flush_test.h"
> +
> +static int switch_to_context(struct drm_i915_private *i915,
> +                          struct i915_gem_context *ctx)
> +{
> +     struct intel_engine_cs *engine;
> +     enum intel_engine_id id;
> +     int err = 0;
> +
> +     intel_runtime_pm_get(i915);
> +
> +     for_each_engine(engine, i915, id) {
> +             struct i915_request *rq;
> +
> +             rq = i915_request_alloc(engine, ctx);
> +             if (IS_ERR(rq)) {
> +                     err = PTR_ERR(rq);
> +                     break;
> +             }
> +
> +             i915_request_add(rq);
> +     }
> +
> +     intel_runtime_pm_put(i915);
> +
> +     return err;
> +}
> +
> +static int pm_prepare(struct drm_i915_private *i915)
> +{
> +     int err = 0;
> +
> +     if (i915_gem_suspend(i915)) {
> +             pr_err("i915_gem_suspend failed\n");
> +             err = -EINVAL;
> +     }
> +
> +     return err;
> +}
> +
> +static void trash_stolen(struct drm_i915_private *i915)
> +{
> +     struct i915_ggtt *ggtt = &i915->ggtt;
> +     const u64 slot = ggtt->error_capture.start;
> +     const resource_size_t size = resource_size(&i915->dsm);
> +     unsigned long page;
> +     u32 prng = 0x12345678;
> +
> +     for (page = 0; page < size; page += PAGE_SIZE) {
> +             const dma_addr_t dma = i915->dsm.start + page;
> +             u32 __iomem *s;
> +             int x;
> +
> +             ggtt->vm.insert_page(&ggtt->vm, dma, slot,
> I915_CACHE_NONE, 0);
> +
> +             s = io_mapping_map_atomic_wc(&ggtt->iomap, slot);
> +             for (x = 0; x < PAGE_SIZE / sizeof(u32); x++) {
> +                     prng = next_pseudo_random32(prng);
> +                     iowrite32(prng, &s[x]);
> +             }
> +             io_mapping_unmap_atomic(s);
> +     }
> +
> +     ggtt->vm.clear_range(&ggtt->vm, slot, PAGE_SIZE);
> +}
> +
> +static void simulate_hibernate(struct drm_i915_private *i915)
> +{
> +     intel_runtime_pm_get(i915);
> +
> +     /*
> +      * As a final sting in the tail, invalidate stolen. Under a
> real S4,
> +      * stolen is lost and needs to be refilled on resume.
> However, under
> +      * CI we merely do S4-device testing (as full S4 is too
> unreliable
> +      * for automated testing across a cluster), so to simulate
> the effect
> +      * of stolen being trashed across S4, we trash it ourselves.
> +      */
> +     trash_stolen(i915);
> +
> +     intel_runtime_pm_put(i915);
> +}
> +
> +static void pm_resume(struct drm_i915_private *i915)
> +{
> +     /*
> +      * Both suspend and hibernate follow the same wakeup path
> and assume
> +      * that runtime-pm just works.
> +      */
> +     intel_runtime_pm_get(i915);
> +
> +     intel_engines_sanitize(i915);
> +     i915_gem_sanitize(i915);
> +     i915_gem_resume(i915);
> +
> +     intel_runtime_pm_put(i915);
> +}
> +
> +static void pm_suspend(struct drm_i915_private *i915)
> +{
> +     intel_runtime_pm_get(i915);
> +
> +     i915_gem_suspend_gtt_mappings(i915);
> +     i915_gem_suspend_late(i915);
> +
> +     intel_runtime_pm_put(i915);
> +}
> +
> +static int igt_gem_suspend(void *arg)
> +{
> +     struct drm_i915_private *i915 = arg;
> +     struct i915_gem_context *ctx;
> +     struct drm_file *file;
> +     int err;
> +
> +     file = mock_file(i915);
> +     if (IS_ERR(file))
> +             return PTR_ERR(file);
> +
> +     err = -ENOMEM;
> +     mutex_lock(&i915->drm.struct_mutex);
> +     ctx = live_context(i915, file);
> +     if (!IS_ERR(ctx))
> +             err = switch_to_context(i915, ctx);
> +     mutex_unlock(&i915->drm.struct_mutex);
> +     if (err)
> +             goto out;
> +
> +     err = pm_prepare(i915);
> +     if (err)
> +             goto out;
> +
> +     pm_suspend(i915);
> +
> +     /* Here be dragons! Note that with S3RST any S3 may become
> S4! */
> +     simulate_hibernate(i915);
> +
> +     pm_resume(i915);
> +
> +     mutex_lock(&i915->drm.struct_mutex);
> +     err = switch_to_context(i915, ctx);
> +     if (igt_flush_test(i915, I915_WAIT_LOCKED))
> +             err = -EIO;
> +     mutex_unlock(&i915->drm.struct_mutex);
> +out:
> +     mock_file_free(i915, file);
> +     return err;
> +}
> +
> +static void pm_hibernate(struct drm_i915_private *i915)
> +{
> +     intel_runtime_pm_get(i915);
> +
> +     i915_gem_suspend_gtt_mappings(i915);
> +
> +     i915_gem_freeze(i915);
> +     i915_gem_freeze_late(i915);
> +
> +     intel_runtime_pm_put(i915);
> +}
> +
> +static int igt_gem_hibernate(void *arg)
> +{
> +     struct drm_i915_private *i915 = arg;
> +     struct i915_gem_context *ctx;
> +     struct drm_file *file;
> +     int err;
> +
> +     file = mock_file(i915);
> +     if (IS_ERR(file))
> +             return PTR_ERR(file);
> +
> +     err = -ENOMEM;
> +     mutex_lock(&i915->drm.struct_mutex);
> +     ctx = live_context(i915, file);
> +     if (!IS_ERR(ctx))
> +             err = switch_to_context(i915, ctx);
> +     mutex_unlock(&i915->drm.struct_mutex);
> +     if (err)
> +             goto out;
> +
> +     err = pm_prepare(i915);
> +     if (err)
> +             goto out;
> +
> +     pm_hibernate(i915);
> +
> +     /* Here be dragons! */
> +     simulate_hibernate(i915);
> +
> +     pm_resume(i915);
> +
> +     mutex_lock(&i915->drm.struct_mutex);
> +     err = switch_to_context(i915, ctx);
> +     if (igt_flush_test(i915, I915_WAIT_LOCKED))
> +             err = -EIO;
> +     mutex_unlock(&i915->drm.struct_mutex);
> +out:
> +     mock_file_free(i915, file);
> +     return err;
> +}
> +
> +int i915_gem_live_selftests(struct drm_i915_private *i915)
> +{
> +     static const struct i915_subtest tests[] = {
> +             SUBTEST(igt_gem_suspend),
> +             SUBTEST(igt_gem_hibernate),
> +     };
> +
> +     return i915_subtests(tests, i915);
> +}
> diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> index a00e2bd08bce..a15713cae3b3 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> @@ -17,6 +17,7 @@ selftest(objects, i915_gem_object_live_selftests)
>  selftest(dmabuf, i915_gem_dmabuf_live_selftests)
>  selftest(coherency, i915_gem_coherency_live_selftests)
>  selftest(gtt, i915_gem_gtt_live_selftests)
> +selftest(gem, i915_gem_live_selftests)
>  selftest(evict, i915_gem_evict_live_selftests)
>  selftest(hugepages, i915_gem_huge_page_live_selftests)
>  selftest(contexts, i915_gem_context_live_selftests)

Attachment: smime.p7s
Description: S/MIME cryptographic signature

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to