Re: [PATCH i-g-t] i915/gem_mmap_offset: Partial mmap and munmap

2024-04-17 Thread Kamil Konieczny
Hi Andi,
On 2024-04-12 at 02:42:55 +0200, Andi Shyti wrote:
> From: Chris Wilson 
> 
> Based on a test case developed by Lionel Landwerlin, this exercises
> creation of partial mmaps using both direct methods of a partial mmap()
> (where the mmap() only covers a portion of the object) and
> munmap() to do the same.
> 
> Signed-off-by: Chris Wilson 
> Signed-off-by: Andi Shyti 
> ---
>  tests/intel/gem_mmap_offset.c | 84 +++
>  1 file changed, 84 insertions(+)
> 
> diff --git a/tests/intel/gem_mmap_offset.c b/tests/intel/gem_mmap_offset.c
> index 95d2158ca88f..0ba2f9591f85 100644
> --- a/tests/intel/gem_mmap_offset.c
> +++ b/tests/intel/gem_mmap_offset.c
> @@ -56,6 +56,8 @@
>   * SUBTEST: isolation
>   * SUBTEST: oob-read
>   * SUBTEST: open-flood
> + * SUBTEST: partial-mmap
> + * SUBTEST: partial-unmap
>   * SUBTEST: perf
>   * SUBTEST: pf-nonblock
>   * SUBTEST: ptrace
> @@ -874,6 +876,83 @@ static void blt_coherency(int i915)
>   igt_assert_f(compare_ok, "Problem with coherency, flush is too late\n");
>  }
>  
> +static void partial_mmap(int i915)
> +{
> + uint32_t handle;
> +
> + handle = gem_create(i915, SZ_2M);
> +
> + for_each_mmap_offset_type(i915, t) {
> + struct drm_i915_gem_mmap_offset arg = {
> + .handle = handle,
> + .flags = t->type,
> + };
> + uint32_t *ptr;
> +
> + if (mmap_offset_ioctl(i915, ))
> + continue;
> +
> + ptr = mmap(0, SZ_4K, PROT_WRITE, MAP_SHARED, i915, arg.offset);
> + if (ptr == MAP_FAILED)
> + continue;
> +
> + memset(ptr, 0xcc, SZ_4K);
> + munmap(ptr, SZ_4K);
> +
> + ptr = mmap(0, SZ_4K, PROT_READ, MAP_SHARED, i915, arg.offset + 
> SZ_2M - SZ_4K);
> + igt_assert(ptr != MAP_FAILED);
> +
> + for (uint32_t i = 0; i < SZ_4K / sizeof(uint32_t); i++)
> + igt_assert_eq_u32(ptr[i], 0);
> +
> + munmap(ptr, SZ_4K);
> + }
> +
> + gem_close(i915, handle);
> +}
> +
> +static void partial_unmap(int i915)
> +{
> + uint32_t handle;
> +
> + handle = gem_create(i915, SZ_2M);
> +
> + for_each_mmap_offset_type(i915, t) {
> + uint8_t *ptr_a, *ptr_b;
> +
> + /* mmap the same GEM BO twice */
> + ptr_a = __mmap_offset(i915, handle, 0, SZ_2M,
> + PROT_READ | PROT_WRITE,
> + t->type);
> + if (!ptr_a)
> + continue;
> +
> + ptr_b = __mmap_offset(i915, handle, 0, SZ_2M,
> + PROT_READ | PROT_WRITE,
> + t->type);
> + if (!ptr_b)
> + continue;

Nit here: before continue ptr_a should be unmaped.

Regards,
Kamil

> +
> + /* unmap the first mapping but the last 4k */
> + munmap(ptr_a, SZ_2M - SZ_4K);
> +
> + /* memset that remaining 4k with 0xcc */
> + memset(ptr_a + SZ_2M - SZ_4K, 0xcc, SZ_4K);
> +
> + /* memset the first page of the 2Mb with 0xdd */
> + memset(ptr_b, 0xdd, SZ_4K);
> +
> + for (uint32_t i = 0; i < SZ_4K; i++)
> + igt_assert_eq_u32(ptr_a[SZ_2M - SZ_4K + i], 0xcc);
> +
> + munmap(ptr_a + SZ_2M - SZ_4K, SZ_4K);
> + memset(ptr_b, 0, SZ_2M);
> + munmap(ptr_b, SZ_2M);
> + }
> +
> + gem_close(i915, handle);
> +}
> +
>  static int mmap_gtt_version(int i915)
>  {
>   int gtt_version = -1;
> @@ -931,6 +1010,11 @@ igt_main
>   igt_subtest_f("open-flood")
>   open_flood(i915, 20);
>  
> + igt_subtest_f("partial-mmap")
> + partial_mmap(i915);
> + igt_subtest_f("partial-unmap")
> + partial_unmap(i915);
> +
>   igt_subtest_with_dynamic("clear") {
>   for_each_memory_region(r, i915) {
>   igt_dynamic_f("%s", r->name)
> -- 
> 2.43.0
> 


Re: [PATCH i-g-t v3] lib/kunit: Read results from debugfs

2024-04-17 Thread Kamil Konieczny
Hi Janusz,
On 2024-04-15 at 19:31:59 +0200, Janusz Krzysztofik wrote:
> KUnit can provide KTAP reports from test modules via debugfs files, one
> per test suite.  Using that source of test results instead of extracting
> them from dmesg, where they may be interleaved with other kernel messages,
> seems more easy to handle and less error prone.  Switch to it.
> 
> If KUnit debugfs support is found not configured then fall back to legacy
> processing path.
> 
> v3: Try to open KUnit debugfs directory before applying KUnit filters we
> use for test case listing, otherwise those skip-all filters applied
> can break legacy path we may enter on missing KUnit debugfs support
> (detected by Kamil).
> v2: Check validity of debugfs argument before calling kunit_get_tests()
> (Kamil),
>   - replace multiple openat() + fdopen/fdopendir(), each followed by an
> error check, with less expensive fopen/opendir() of file/dir pathname
> components concatenated to a local buffer, protected from buffer
> overflow or truncation with a single check for enough buffer space
> (Lucas),
>   - avoid confusing 'if' statement condition (Lucas).
> 
> Signed-off-by: Janusz Krzysztofik 
> Cc: Kamil Konieczny 
> Reviewed-by: Lucas De Marchi 

Thank you for fixing legacy path, it works now.
With this,

Reviewed-by: Kamil Konieczny 

> ---
> @Lucas: I've assumed your R-b still applies, I hope you don't mind.
> 
>  lib/igt_kmod.c | 129 +++--
>  1 file changed, 93 insertions(+), 36 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index 6659c27eba..33f059199f 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -28,6 +28,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -39,6 +40,7 @@
>  
>  #include "igt_aux.h"
>  #include "igt_core.h"
> +#include "igt_debugfs.h"
>  #include "igt_kmod.h"
>  #include "igt_ktap.h"
>  #include "igt_sysfs.h"
> @@ -864,6 +866,19 @@ static int open_parameters(const char *module_name)
>   return open(path, O_RDONLY);
>  }
>  
> +static void kunit_debugfs_path(char *kunit_path)
> +{
> + const char *debugfs_path = igt_debugfs_mount();
> +
> + if (igt_debug_on(!debugfs_path))
> + return;
> +
> + if (igt_debug_on(strlen(debugfs_path) + strlen("/kunit/") >= PATH_MAX))
> + return;
> +
> + strcpy(stpcpy(kunit_path, debugfs_path), "/kunit/");
> +}
> +
>  static bool kunit_set_filtering(const char *filter_glob, const char *filter,
>   const char *filter_action)
>  {
> @@ -1071,21 +1086,41 @@ static void kunit_results_free(struct igt_list_head 
> *results,
>   free(*suite_name);
>  }
>  
> -static int kunit_get_results(struct igt_list_head *results, int kmsg_fd,
> -  struct igt_ktap_results **ktap)
> +static int kunit_get_results(struct igt_list_head *results, const char 
> *debugfs_path,
> +  const char *suite, struct igt_ktap_results **ktap)
>  {
> + char results_path[PATH_MAX];
> + FILE *results_stream;
> + char *buf = NULL;
> + size_t size = 0;
> + ssize_t len;
>   int err;
>  
> + if (igt_debug_on(strlen(debugfs_path) + strlen(suite) + 
> strlen("/results") >= PATH_MAX))
> + return -ENOSPC;
> +
> + strcpy(stpcpy(stpcpy(results_path, debugfs_path), suite), "/results");
> + results_stream = fopen(results_path, "r");
> + if (igt_debug_on(!results_stream))
> + return -errno;
> +
>   *ktap = igt_ktap_alloc(results);
> - if (igt_debug_on(!*ktap))
> - return -ENOMEM;
> + if (igt_debug_on(!*ktap)) {
> + err = -ENOMEM;
> + goto out_fclose;
> + }
>  
> - do
> - igt_debug_on((err = kunit_kmsg_result_get(results, NULL, 
> kmsg_fd, *ktap),
> -   err && err != -EINPROGRESS));
> - while (err == -EINPROGRESS);
> + while (len = getline(, , results_stream), len > 0) {
> + err = igt_ktap_parse(buf, *ktap);
> + if (err != -EINPROGRESS)
> + break;
> + }
> +
> + free(buf);
>  
>   igt_ktap_free(ktap);
> +out_fclose:
> + fclose(results_stream);
>  
>   return err;
>  }
> @@ -1101,7 +1136,13 @@ static void __igt_kunit_legacy(struct igt_ktest *tst,
>   pthread_mutexattr_t attr;
>   IGT_LIST_HEAD(results);
>   unsigned long taints;
> -

Re: [PATCH i-g-t] lib/kunit: Read results from debugfs

2024-03-28 Thread Kamil Konieczny
Hi Janusz,
On 2024-03-27 at 23:26:03 +0100, Janusz Krzysztofik wrote:
> On Wednesday, 27 March 2024 18:27:50 CET Kamil Konieczny wrote:
> > Hi Janusz,
> > On 2024-03-27 at 12:22:54 +0100, Janusz Krzysztofik wrote:
> > > KUnit can provide KTAP reports from test modules via debugfs files, one
> > > per test suite.  Using that source of test results instead of extracting
> > > them from dmesg, where they may be interleaved with other kernel messages,
> > > seems more easy to handle and less error prone.  Switch to it.
> > > 
> > > If KUnit debugfs support is found not configured then fall back to legacy
> > > processing path.
> > > 
> > > Signed-off-by: Janusz Krzysztofik 
> > > ---
> > >  lib/igt_kmod.c | 143 -
> > >  1 file changed, 105 insertions(+), 38 deletions(-)
> > > 
> > > diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> > > index 1ec9c8a602..a5b170ca9c 100644
> > > --- a/lib/igt_kmod.c
> > > +++ b/lib/igt_kmod.c
> > > @@ -28,6 +28,7 @@
> > >  #include 
> > >  #include 
> > >  #include 
> > > +#include 
> > >  #include 
> > >  #include 
> > >  #include 
> > > @@ -39,6 +40,7 @@
> > >  
> > >  #include "igt_aux.h"
> > >  #include "igt_core.h"
> > > +#include "igt_debugfs.h"
> > >  #include "igt_kmod.h"
> > >  #include "igt_ktap.h"
> > >  #include "igt_sysfs.h"
> > > @@ -864,6 +866,31 @@ static int open_parameters(const char *module_name)
> > >   return open(path, O_RDONLY);
> > >  }
> > >  
> > > +static DIR *kunit_debugfs_open(void)
> > > +{
> > > + const char *debugfs_path = igt_debugfs_mount();
> > > + int debugfs_fd, kunit_fd;
> > > + DIR *kunit_dir;
> > > +
> > > + if (igt_debug_on(!debugfs_path))
> > > + return NULL;
> > > +
> > > + debugfs_fd = open(debugfs_path, O_DIRECTORY);
> > > + if (igt_debug_on(debugfs_fd < 0))
> > > + return NULL;
> > > +
> > > + kunit_fd = openat(debugfs_fd, "kunit", O_DIRECTORY);
> > > + close(debugfs_fd);
> > > + if (igt_debug_on(kunit_fd < 0))
> > > + return NULL;
> > > +
> > > + kunit_dir = fdopendir(kunit_fd);
> > > + if (igt_debug_on(!kunit_dir))
> > > + close(kunit_fd);
> > 
> > imho here:
> > close(kunit_fd);
> > igt_debug_on(!kunit_dir);
> 
> No, we are not allowed to close it.  fdopendir(3) states:
> "After  a  successful  call to fdopendir(), fd is used internally by the 
>  implementation, and should not otherwise be used by the application."
> 

You are right, thank you for explanation and pointing me to man page.

Regards,
Kamil

> > 
> > > +
> > > + return kunit_dir;
> > > +}
> > > +
> > >  static bool kunit_set_filtering(const char *filter_glob, const char 
> > > *filter,
> > >   const char *filter_action)
> > >  {
> > > @@ -1071,23 +1098,48 @@ static void kunit_results_free(struct 
> > > igt_list_head *results,
> > >   free(*suite_name);
> > >  }
> > >  
> > > -static int kunit_get_results(struct igt_list_head *results, int kmsg_fd,
> > > -  struct igt_ktap_results **ktap)
> > > +static int kunit_get_results(struct igt_list_head *results, int 
> > > debugfs_fd,
> > > +  const char *suite, struct igt_ktap_results **ktap)
> > >  {
> > > - int err;
> > > + FILE *results_stream;
> > > + int ret, results_fd;
> > > + char *buf = NULL;
> > > + size_t size = 0;
> > > + ssize_t len;
> > > +
> > > + if (igt_debug_on((ret = openat(debugfs_fd, suite, O_DIRECTORY), ret < 
> > > 0)))
> > > + return ret;
> > > +
> > > + results_fd = openat(ret, "results", O_RDONLY);
> > > + close(ret);
> > > + if (igt_debug_on(results_fd < 0))
> > > + return results_fd;
> > > +
> > > + results_stream = fdopen(results_fd, "r");
> > > + if (igt_debug_on(!results_stream)) {
> > > + close(results_fd);
> > > + return -errno;
> > > + }
> > >  
> > >   *ktap = igt_ktap_alloc(results);
> > > - if (igt_debug_on(!*ktap))
> &g

Re: [PATCH i-g-t] lib/kunit: Read results from debugfs

2024-03-27 Thread Kamil Konieczny
Hi Janusz,
On 2024-03-27 at 12:22:54 +0100, Janusz Krzysztofik wrote:
> KUnit can provide KTAP reports from test modules via debugfs files, one
> per test suite.  Using that source of test results instead of extracting
> them from dmesg, where they may be interleaved with other kernel messages,
> seems more easy to handle and less error prone.  Switch to it.
> 
> If KUnit debugfs support is found not configured then fall back to legacy
> processing path.
> 
> Signed-off-by: Janusz Krzysztofik 
> ---
>  lib/igt_kmod.c | 143 -
>  1 file changed, 105 insertions(+), 38 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index 1ec9c8a602..a5b170ca9c 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -28,6 +28,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -39,6 +40,7 @@
>  
>  #include "igt_aux.h"
>  #include "igt_core.h"
> +#include "igt_debugfs.h"
>  #include "igt_kmod.h"
>  #include "igt_ktap.h"
>  #include "igt_sysfs.h"
> @@ -864,6 +866,31 @@ static int open_parameters(const char *module_name)
>   return open(path, O_RDONLY);
>  }
>  
> +static DIR *kunit_debugfs_open(void)
> +{
> + const char *debugfs_path = igt_debugfs_mount();
> + int debugfs_fd, kunit_fd;
> + DIR *kunit_dir;
> +
> + if (igt_debug_on(!debugfs_path))
> + return NULL;
> +
> + debugfs_fd = open(debugfs_path, O_DIRECTORY);
> + if (igt_debug_on(debugfs_fd < 0))
> + return NULL;
> +
> + kunit_fd = openat(debugfs_fd, "kunit", O_DIRECTORY);
> + close(debugfs_fd);
> + if (igt_debug_on(kunit_fd < 0))
> + return NULL;
> +
> + kunit_dir = fdopendir(kunit_fd);
> + if (igt_debug_on(!kunit_dir))
> + close(kunit_fd);

imho here:
close(kunit_fd);
igt_debug_on(!kunit_dir);

> +
> + return kunit_dir;
> +}
> +
>  static bool kunit_set_filtering(const char *filter_glob, const char *filter,
>   const char *filter_action)
>  {
> @@ -1071,23 +1098,48 @@ static void kunit_results_free(struct igt_list_head 
> *results,
>   free(*suite_name);
>  }
>  
> -static int kunit_get_results(struct igt_list_head *results, int kmsg_fd,
> -  struct igt_ktap_results **ktap)
> +static int kunit_get_results(struct igt_list_head *results, int debugfs_fd,
> +  const char *suite, struct igt_ktap_results **ktap)
>  {
> - int err;
> + FILE *results_stream;
> + int ret, results_fd;
> + char *buf = NULL;
> + size_t size = 0;
> + ssize_t len;
> +
> + if (igt_debug_on((ret = openat(debugfs_fd, suite, O_DIRECTORY), ret < 
> 0)))
> + return ret;
> +
> + results_fd = openat(ret, "results", O_RDONLY);
> + close(ret);
> + if (igt_debug_on(results_fd < 0))
> + return results_fd;
> +
> + results_stream = fdopen(results_fd, "r");
> + if (igt_debug_on(!results_stream)) {
> + close(results_fd);
> + return -errno;
> + }
>  
>   *ktap = igt_ktap_alloc(results);
> - if (igt_debug_on(!*ktap))
> - return -ENOMEM;
> + if (igt_debug_on(!*ktap)) {
> + ret = -ENOMEM;
> + goto out_fclose;
> + }
> +
> + while (len = getline(, , results_stream), len > 0) {
> + ret = igt_ktap_parse(buf, *ktap);
> + if (ret != -EINPROGRESS)
> + break;
> + }
>  
> - do
> - igt_debug_on((err = kunit_kmsg_result_get(results, NULL, 
> kmsg_fd, *ktap),
> -   err && err != -EINPROGRESS));
> - while (err == -EINPROGRESS);
> + free(buf);
>  
>   igt_ktap_free(ktap);
> +out_fclose:
> + fclose(results_stream);
>  
> - return err;
> + return ret;
>  }
>  
>  static void __igt_kunit_legacy(struct igt_ktest *tst,
> @@ -1101,7 +1153,13 @@ static void __igt_kunit_legacy(struct igt_ktest *tst,
>   pthread_mutexattr_t attr;
>   IGT_LIST_HEAD(results);
>   unsigned long taints;
> - int ret;
> + int flags, ret;
> +
> + igt_skip_on_f(tst->kmsg < 0, "Could not open /dev/kmsg\n");
> +
> + igt_skip_on((flags = fcntl(tst->kmsg, F_GETFL, 0), flags < 0));
> + igt_skip_on_f(fcntl(tst->kmsg, F_SETFL, flags & ~O_NONBLOCK) == -1,
> +   "Could not set /dev/kmsg to blocking mode\n");
>  
>   igt_skip_on(lseek(tst->kmsg, 0, SEEK_END) < 0);
>  
> @@ -1224,30 +1282,20 @@ static void __igt_kunit_legacy(struct igt_ktest *tst,
>   igt_skip_on_f(ret, "KTAP parser failed\n");
>  }
>  
> -static void kunit_get_tests_timeout(int signal)
> -{
> - igt_skip("Timed out while trying to extract a list of KUnit test cases 
> from /dev/kmsg\n");
> -}
> -
>  static bool kunit_get_tests(struct igt_list_head *tests,
>   struct igt_ktest *tst,
>   const char *suite,
>   const 

Re: [PATCH i-g-t v3 5/5] lib/kunit: Minimize code duplication

2024-03-25 Thread Kamil Konieczny
Hi Janusz,
On 2024-03-18 at 11:13:31 +0100, Janusz Krzysztofik wrote:
> A new helper has been introduced recently, used for fetching KTAP results
> of a single test case.  Since that helper is called for that purpose
> only after the test module is loaded with all other test cases filtered
> out, its actual implementation is as simple as collecting all results from
> a single KTAP report, no matter how many test suites and test cases it
> covers.  Then, it's a good candidate for reuse in other scenarios when a
> single KTAP report is handled, e.g., when we collect a list of test cases
> from a single test suite or test module.  Go for it.
> 
> v3: Rebased on top of changes to struct igt_ktap_results pointer handling.
> v2: Rebased on invalid test suite name workaround.
> 
> Signed-off-by: Janusz Krzysztofik 
> Cc: Jonathan Cavitt 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_kmod.c | 9 +
>  1 file changed, 1 insertion(+), 8 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index c495d11b16..8979a5928b 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -1262,21 +1262,14 @@ static bool kunit_get_tests(struct igt_list_head 
> *tests,
>   igt_skip_on(modprobe(tst->kmod, opts));
>   igt_skip_on(igt_kernel_tainted());
>  
> - *ktap = igt_ktap_alloc(tests);
> - igt_require(*ktap);
> -
>   igt_skip_on(sigaction(SIGALRM, , saved));
>   alarm(10);
>  
> - do
> - err = kunit_kmsg_result_get(tests, NULL, tst->kmsg, *ktap);
> - while (err == -EINPROGRESS);
> + err = kunit_get_results(tests, tst->kmsg, ktap);
>  
>   alarm(0);
>   igt_debug_on(sigaction(SIGALRM, saved, NULL));
>  
> - igt_ktap_free(ktap);
> -
>   igt_skip_on_f(err,
> "KTAP parser failed while getting a list of test 
> cases\n");
>  
> -- 
> 2.43.0
> 


Re: [PATCH i-g-t v3 4/5] lib/kunit: Execute test cases synchronously

2024-03-25 Thread Kamil Konieczny
Hi Janusz,
On 2024-03-18 at 11:13:30 +0100, Janusz Krzysztofik wrote:
> Up to now we were loading a KUnit test module in test execution mode only
> once per subtest, in background, and then, in parallel with execution of
> test cases while the module was loading, we were looking through dmesg for
> KTAP results from each expected test case.  As a consequence, our IGT
> messages were more or less delayed, never in full sync with kernel
> messages.  Moreover, parsing of KTAP results from already completed test
> cases could be abandoned on a failure from loading the test module or
> kernel taint caused by a subsequent test case.  Also, parsing of KTAP
> results from all subsequent test cases could be abandoned on a failure of
> the parser caused by any test case.  Other than that, if a user requested
> a single dynamic sub-subtest, all test cases were executed anyway while
> results from only one of them that corresponded to the selected dynamic
> sub-subtest were reported.  That way, kernel messages from unrelated test
> cases, not only the selected one, could contribute to dmesg-fail or dmesg-
> warn CI results from that sub-subtest.
> 
> Since recent KUnit implementation is capable of executing only those test
> cases that match a user filter, stop executing all of them asynchronously
> and parsing their KTAP results as they appear.  Instead, reload the test
> module once per each dynamic sub-subtest with a filter that selects a
> specific test case and wait for its completion.  If successful and no
> kernel taint has occurred then parse the whole KTAP report from a single
> test case it has produced and translate it to IGT result of that single
> corresponding sub-subtest.
> 
> With that in place, we no longer need to skip the whole subtest on a
> failure from module loading or KTAP reading or parsing.  Since such event
> is now local to execution of an individual test case, only fail its
> corresponding dynamic sub-subtests and continue with subsequent ones.
> However, still omit execution of subsequent test cases once the kernel
> gets tainted.
> 
> v3: Refresh on top of changes to struct igt_ktap_results pointer handling,
>   - use "for(;;) {}" instead of "do {} while();" when processing results
> from parametrized test cases (Kamil).
> v2: Refresh on top of changes to KUnit filters handling,
>   - include the code of a new helper from a previously separate patch,
>   - actually limit the scope of the helper to fetching a KTAP report from
> a file descriptor, and let the caller decide on how other steps, like
> setting up filters or loading a test module, and errors they return
> are handled,
>   - similar to kernel taint handling, just omit any remaining dynamic sub-
> subtests if unloading the test module fails,
>   - update commit description with a more detailed justification of why we
> need these changes.
> 
> Signed-off-by: Janusz Krzysztofik 
> Cc: Mauro Carvalho Chehab 
> Cc: Jonathan Cavitt 
> Cc: Kamil Konieczny 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_kmod.c | 156 +
>  1 file changed, 54 insertions(+), 102 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index f0e4d5ec76..c495d11b16 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -1070,6 +1070,25 @@ static void kunit_results_free(struct igt_list_head 
> *results,
>   free(*suite_name);
>  }
>  
> +static int kunit_get_results(struct igt_list_head *results, int kmsg_fd,
> +  struct igt_ktap_results **ktap)
> +{
> + int err;
> +
> + *ktap = igt_ktap_alloc(results);
> + if (igt_debug_on(!*ktap))
> + return -ENOMEM;
> +
> + do
> + igt_debug_on((err = kunit_kmsg_result_get(results, NULL, 
> kmsg_fd, *ktap),
> +   err && err != -EINPROGRESS));
> + while (err == -EINPROGRESS);
> +
> + igt_ktap_free(ktap);
> +
> + return err;
> +}
> +
>  static void __igt_kunit_legacy(struct igt_ktest *tst,
>  const char *subtest,
>  const char *opts)
> @@ -1277,82 +1296,52 @@ static void __igt_kunit(struct igt_ktest *tst,
>   struct igt_list_head *tests,
>   struct igt_ktap_results **ktap)
>  {
> - struct modprobe_data modprobe = { tst->kmod, opts, 0, pthread_self(), };
> - char *suite_name = NULL, *case_name = NULL;
> - struct igt_ktap_result *t, *r = NULL;
> - pthread_mutexattr_t attr;
> - IGT_LIST_HEAD(results);
> - int ret = -EINPROGRESS;
> - unsigned long taints;
> -
> - igt_skip_on

Re: [PATCH i-g-t] tools/intel_gpu_top: Fix near full percentage bar formatting

2024-03-22 Thread Kamil Konieczny
Hi Tvrtko,
On 2024-01-18 at 08:48:38 +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Fix a bug where 1) the end vertical separator element would not be printed
> if the progress bar portion was all filled by the progress bar characters
> (no trailing spaces), and 2) the numerical overlay would be skipped to.
> 
> The bug would also shift the layout of following UI elements since the
> progress bar would not be consuming all the allocated horizontal space.
> 
> Signed-off-by: Tvrtko Ursulin 
> Reported-by: anonymoustranquill...@proton.me

Reviewed-by: Kamil Konieczny 

> ---
>  tools/intel_gpu_top.c | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index 046ead15a122..5b4f94d7de7a 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -1015,9 +1015,8 @@ print_percentage_bar(double percent, double max, int 
> max_len, bool numeric)
>   printf("%s", bars[i]);
>  
>   len -= (bar_len + (w - 1)) / w;
> - if (len < 1)
> - return;
> - n_spaces(len);
> + if (len >= 1)
> + n_spaces(len);
>  
>   putchar('|');
>  
> -- 
> 2.40.1
> 


Re: [PATCH i-g-t v3 3/5] lib/kunit: Time out promptly on missing KTAP report

2024-03-19 Thread Kamil Konieczny
Hi Janusz,
On 2024-03-18 at 11:13:29 +0100, Janusz Krzysztofik wrote:
> If a test provides a subtest name that doesn't match any test suites
> provided by the requested KUnit test module then no KTAP report appears in
> dmesg, not even an empty one as one may expect.  As a consequence, we now
> loop endlessly around reading potential lines of the missing report from
> /dev/kmsg, until killed by IGT runner on timeout.
> 
> When trying to collect names of test cases from a KTAP report generated in
> all skip mode, set an alarm that fires up 10 seconds after we start
> waiting for the report, interrupts blocking read() if pending, and
> terminates the subtest with SKIP result.
> 
> As soon as we have collected a non-empty list of test cases, we may as
> well expect a non-empty KTAP report from actual execution of those test
> cases, assuming successful load of the KUnit test module in execution
> mode.  Then, there is no need to set up a similar timeout before we start
> to extract and parse that report.
> 
> Suggested-by: Kamil Konieczny 
> Signed-off-by: Janusz Krzysztofik 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_kmod.c | 13 +
>  1 file changed, 13 insertions(+)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index 8a6824ea7e..f0e4d5ec76 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -1204,12 +1204,19 @@ static void __igt_kunit_legacy(struct igt_ktest *tst,
>   igt_skip_on_f(ret, "KTAP parser failed\n");
>  }
>  
> +static void kunit_get_tests_timeout(int signal)
> +{
> + igt_skip("Timed out while trying to extract a list of KUnit test cases 
> from /dev/kmsg\n");
> +}
> +
>  static bool kunit_get_tests(struct igt_list_head *tests,
>   struct igt_ktest *tst,
>   const char *suite,
>   const char *opts,
>   struct igt_ktap_results **ktap)
>  {
> + struct sigaction sigalrm = { .sa_handler = kunit_get_tests_timeout, },
> +  *saved;
>   struct igt_ktap_result *r, *rn;
>   unsigned long taints;
>   int flags, err;
> @@ -1239,10 +1246,16 @@ static bool kunit_get_tests(struct igt_list_head 
> *tests,
>   *ktap = igt_ktap_alloc(tests);
>   igt_require(*ktap);
>  
> + igt_skip_on(sigaction(SIGALRM, , saved));
> + alarm(10);
> +
>   do
>   err = kunit_kmsg_result_get(tests, NULL, tst->kmsg, *ktap);
>   while (err == -EINPROGRESS);
>  
> + alarm(0);
> + igt_debug_on(sigaction(SIGALRM, saved, NULL));
> +
>   igt_ktap_free(ktap);
>  
>   igt_skip_on_f(err,
> -- 
> 2.43.0
> 


Re: [PATCH i-g-t v3 2/5] lib/kunit: Let igt_ktap_free() take care of pointer reset

2024-03-19 Thread Kamil Konieczny
Hi Janusz,
On 2024-03-18 at 11:13:28 +0100, Janusz Krzysztofik wrote:
> Users who store a pointer to struct igt_ktap_results, obtained from
> igt_ktap_alloc(), in a central location and then call igt_ktap_free() when
> no longer needed, now have to reset that pointer to NULL to avoid double
> free on final cleanup.  For their convenience, teach igt_ktap_free() to
> accept that location as an argument and reset the pointer after freeing
> the structure.
> 
> Signed-off-by: Janusz Krzysztofik 

LGTM,
Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_kmod.c  | 12 +---
>  lib/igt_ktap.c  |  5 +++--
>  lib/igt_ktap.h  |  2 +-
>  lib/tests/igt_ktap_parser.c | 24 
>  4 files changed, 21 insertions(+), 22 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index ca20012a97..8a6824ea7e 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -1094,7 +1094,7 @@ static void __igt_kunit_legacy(struct igt_ktest *tst,
>  
>   if (igt_debug_on(pthread_create(, NULL,
>   modprobe_task, ))) {
> - igt_ktap_free(ktap);
> + igt_ktap_free();
>   igt_skip("Failed to create a modprobe thread\n");
>   }
>  
> @@ -1197,7 +1197,7 @@ static void __igt_kunit_legacy(struct igt_ktest *tst,
>   break;
>   }
>  
> - igt_ktap_free(ktap);
> + igt_ktap_free();
>  
>   igt_skip_on(modprobe.err);
>   igt_skip_on(igt_kernel_tainted());
> @@ -1243,8 +1243,7 @@ static bool kunit_get_tests(struct igt_list_head *tests,
>   err = kunit_kmsg_result_get(tests, NULL, tst->kmsg, *ktap);
>   while (err == -EINPROGRESS);
>  
> - igt_ktap_free(*ktap);
> - *ktap = NULL;
> + igt_ktap_free(ktap);
>  
>   igt_skip_on_f(err,
> "KTAP parser failed while getting a list of test 
> cases\n");
> @@ -1405,8 +1404,7 @@ static void __igt_kunit(struct igt_ktest *tst,
>   }
>   }
>  
> - igt_ktap_free(*ktap);
> - *ktap = NULL;
> + igt_ktap_free(ktap);
>  
>   igt_skip_on(modprobe.err);
>   igt_skip_on(igt_kernel_tainted());
> @@ -1487,7 +1485,7 @@ void igt_kunit(const char *module_name, const char 
> *suite, const char *opts)
>   igt_fixture {
>   char *suite_name = NULL, *case_name = NULL;
>  
> - igt_ktap_free(ktap);
> + igt_ktap_free();
>  
>   kunit_results_free(, _name, _name);
>  
> diff --git a/lib/igt_ktap.c b/lib/igt_ktap.c
> index aa7ea84476..300fb2bb5a 100644
> --- a/lib/igt_ktap.c
> +++ b/lib/igt_ktap.c
> @@ -310,7 +310,8 @@ struct igt_ktap_results *igt_ktap_alloc(struct 
> igt_list_head *results)
>   return ktap;
>  }
>  
> -void igt_ktap_free(struct igt_ktap_results *ktap)
> +void igt_ktap_free(struct igt_ktap_results **ktap)
>  {
> - free(ktap);
> + free(*ktap);
> + *ktap = NULL;
>  }
> diff --git a/lib/igt_ktap.h b/lib/igt_ktap.h
> index c422636bfc..7684e859b3 100644
> --- a/lib/igt_ktap.h
> +++ b/lib/igt_ktap.h
> @@ -41,6 +41,6 @@ struct igt_ktap_results;
>  
>  struct igt_ktap_results *igt_ktap_alloc(struct igt_list_head *results);
>  int igt_ktap_parse(const char *buf, struct igt_ktap_results *ktap);
> -void igt_ktap_free(struct igt_ktap_results *ktap);
> +void igt_ktap_free(struct igt_ktap_results **ktap);
>  
>  #endif /* IGT_KTAP_H */
> diff --git a/lib/tests/igt_ktap_parser.c b/lib/tests/igt_ktap_parser.c
> index 6357bdf6a5..8c2d16080d 100644
> --- a/lib/tests/igt_ktap_parser.c
> +++ b/lib/tests/igt_ktap_parser.c
> @@ -45,7 +45,7 @@ static void ktap_list(void)
>   igt_assert_eq(igt_ktap_parse("ok 4 test_case_4 # SKIP\n", ktap), 
> -EINPROGRESS);
>   igt_assert_eq(igt_ktap_parse("ok 3 test_suite_3\n", ktap), 0);
>  
> - igt_ktap_free(ktap);
> + igt_ktap_free();
>  
>   igt_assert_eq(igt_list_length(), 8);
>  
> @@ -107,7 +107,7 @@ static void ktap_results(void)
>   igt_assert_eq(igt_ktap_parse("ok 1 test_case\n", ktap), 
> -EINPROGRESS);
>   igt_assert_eq(igt_ktap_parse("not ok 1 test_suite\n", ktap), 0);
>  
> - igt_ktap_free(ktap);
> + igt_ktap_free();
>  
>   igt_assert_eq(igt_list_length(), 2);
>  
> @@ -162,7 +162,7 @@ static void ktap_success(void)
>   igt_assert_eq(igt_ktap_parse("not ok 1 test_suite\n", ktap), 0);
>   igt_assert_eq(igt_list_length(), 2);
>  
> - igt_ktap_free(ktap);
> + igt_ktap_free();
>  
>   result = igt_list_last_entry(, result, link);
>   igt_li

Re: [PATCH i-g-t v3 1/5] lib/kunit: Store igt_ktap_results pointer in a central location

2024-03-19 Thread Kamil Konieczny
Hi Janusz,
On 2024-03-18 at 11:13:27 +0100, Janusz Krzysztofik wrote:
> To give more freedom to future enhancements of KUnit library (legacy path
> excluded) in using IGT fails and skips, maintain a pointer to struct
> igt_ktap_results, allocated by several functions, in a single central
> location, and free it from a closing igt_fixture section before return.
> 
> Signed-off-by: Janusz Krzysztofik 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_kmod.c | 35 ---
>  1 file changed, 20 insertions(+), 15 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index b4b8848983..ca20012a97 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -1207,10 +1207,10 @@ static void __igt_kunit_legacy(struct igt_ktest *tst,
>  static bool kunit_get_tests(struct igt_list_head *tests,
>   struct igt_ktest *tst,
>   const char *suite,
> - const char *opts)
> + const char *opts,
> + struct igt_ktap_results **ktap)
>  {
>   struct igt_ktap_result *r, *rn;
> - struct igt_ktap_results *ktap;
>   unsigned long taints;
>   int flags, err;
>  
> @@ -1236,14 +1236,15 @@ static bool kunit_get_tests(struct igt_list_head 
> *tests,
>   igt_skip_on(modprobe(tst->kmod, opts));
>   igt_skip_on(igt_kernel_tainted());
>  
> - ktap = igt_ktap_alloc(tests);
> - igt_require(ktap);
> + *ktap = igt_ktap_alloc(tests);
> + igt_require(*ktap);
>  
>   do
> - err = kunit_kmsg_result_get(tests, NULL, tst->kmsg, ktap);
> + err = kunit_kmsg_result_get(tests, NULL, tst->kmsg, *ktap);
>   while (err == -EINPROGRESS);
>  
> - igt_ktap_free(ktap);
> + igt_ktap_free(*ktap);
> + *ktap = NULL;
>  
>   igt_skip_on_f(err,
> "KTAP parser failed while getting a list of test 
> cases\n");
> @@ -1261,12 +1262,12 @@ static void __igt_kunit(struct igt_ktest *tst,
>   const char *subtest,
>   const char *suite,
>   const char *opts,
> - struct igt_list_head *tests)
> + struct igt_list_head *tests,
> + struct igt_ktap_results **ktap)
>  {
>   struct modprobe_data modprobe = { tst->kmod, opts, 0, pthread_self(), };
>   char *suite_name = NULL, *case_name = NULL;
>   struct igt_ktap_result *t, *r = NULL;
> - struct igt_ktap_results *ktap;
>   pthread_mutexattr_t attr;
>   IGT_LIST_HEAD(results);
>   int ret = -EINPROGRESS;
> @@ -1274,8 +1275,8 @@ static void __igt_kunit(struct igt_ktest *tst,
>  
>   igt_skip_on(lseek(tst->kmsg, 0, SEEK_END) < 0);
>  
> - ktap = igt_ktap_alloc();
> - igt_require(ktap);
> + *ktap = igt_ktap_alloc();
> + igt_require(*ktap);
>  
>   igt_list_for_each_entry(t, tests, link) {
>   igt_dynamic_f("%s%s%s",
> @@ -1302,7 +1303,7 @@ static void __igt_kunit(struct igt_ktest *tst,
>   igt_assert(igt_list_empty());
>   igt_assert_eq(ret, -EINPROGRESS);
>   ret = kunit_kmsg_result_get(, ,
> - tst->kmsg, ktap);
> + tst->kmsg, *ktap);
>   igt_fail_on(igt_list_empty());
>  
>   r = igt_list_first_entry(, r, link);
> @@ -1324,7 +1325,7 @@ static void __igt_kunit(struct igt_ktest *tst,
>   ret = kunit_kmsg_result_get(,
>   ,
>   tst->kmsg,
> - ktap);
> + *ktap);
>   igt_fail_on(igt_list_empty());
>   }
>  
> @@ -1404,7 +1405,8 @@ static void __igt_kunit(struct igt_ktest *tst,
>   }
>   }
>  
> - igt_ktap_free(ktap);
> + igt_ktap_free(*ktap);
> + *ktap = NULL;
>  
>   igt_skip_on(modprobe.err);
>   igt_skip_on(igt_kernel_tainted());
> @@ -1427,6 +1429,7 @@ static void __igt_kunit(struct igt_ktest *tst,
>  void igt_kunit(const char *module_name, const char *suite, const char *opts)
>  {
>   struct igt_ktest tst = { .kmsg = -1, };
> + struct igt_ktap_results *ktap = NULL;
>   const char *subtest =

Re: [PATCH i-g-t v2 1/2] lib/kunit: Execute test cases synchronously

2024-03-14 Thread Kamil Konieczny
Hi Janusz,
On 2024-02-27 at 16:10:41 +0100, Janusz Krzysztofik wrote:
> Up to now we were loading a KUnit test module in test execution mode only
> once per subtest, in background, and then, in parallel with execution of
> test cases while the module was loading, we were looking through dmesg for
> KTAP results from each expected test case.  As a consequence, our IGT
> messages were more or less delayed, never in full sync with kernel
> messages.  Moreover, parsing of KTAP results from already completed test
> cases could be abandoned on a failure from loading the test module or
> kernel taint caused by a subsequent test case.  Also, parsing of KTAP
> results from all subsequent test cases could be abandoned on a failure of
> the parser caused by any test case.  Other than that, if a user requested
> a single dynamic sub-subtest, all test cases were executed anyway while
> results from only one of them that corresponded to the selected dynamic
> sub-subtest were reported.  That way, kernel messages from unrelated test
> cases, not only the selected one, could contribute to dmesg-fail or dmesg-
> warn CI results from that sub-subtest.
> 
> Since recent KUnit implementation is capable of executing only those test
> cases that match a user filter, stop executing all of them asynchronously

Could you do that with igt_until_timeout(timeout) guards?
So our test listing/executing will end in reasonable time, even
when it will stuck in system call?

Regards,
Kamil

> and parsing their KTAP results as they appear.  Instead, reload the test
> module once per each dynamic sub-subtest with a filter that selects a
> specific test case and wait for its completion.  If successful and no
> kernel taint has occurred then parse the whole KTAP report from a single
> test case it has produced and translate it to IGT result of that single
> corresponding sub-subtest.
> 
> With that in place, we no longer need to skip the whole subtest on a
> failure from module loading or KTAP reading or parsing.  Since such event
> is now local to execution of an individual test case, only fail its
> corresponding dynamic sub-subtests and continue with subsequent ones.
> However, still omit execution of subsequent test cases once the kernel
> gets tainted.
> 
> v2: Refresh on top of changes to KUnit filters handling,
>   - include the code of a new helper from a previously separate patch,
>   - actually limit the scope of the helper to fetching a KTAP report from
> a file descriptor, and let the caller decide on how other steps, like
> setting up filters or loading a test module, and errors they return
> are handled,
>   - similar to kernel taint handling, just omit any remaining dynamic sub-
> subtests if unloading the test module fails,
>   - update commit description with a more detailed justification of why we
> need these changes.
> 
> Signed-off-by: Janusz Krzysztofik 
> Cc: Mauro Carvalho Chehab 
> ---
>  lib/igt_kmod.c | 157 -
>  1 file changed, 52 insertions(+), 105 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index cc242838fa..e9e00ac5b2 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -1018,6 +1018,25 @@ static void kunit_results_free(struct igt_list_head 
> *results,
>   free(*suite_name);
>  }
>  
> +static int kunit_get_results(struct igt_list_head *results, int kmsg_fd)
> +{
> + struct igt_ktap_results *ktap;
> + int err;
> +
> + ktap = igt_ktap_alloc(results);
> + if (igt_debug_on(!ktap))
> + return -ENOMEM;
> +
> + do
> + igt_debug_on((err = kunit_kmsg_result_get(results, NULL, 
> kmsg_fd, ktap),
> +   err && err != -EINPROGRESS));
> + while (err == -EINPROGRESS);
> +
> + igt_ktap_free(ktap);
> +
> + return err;
> +}
> +
>  static void __igt_kunit_legacy(struct igt_ktest *tst,
>  const char *subtest,
>  const char *opts)
> @@ -1211,86 +1230,51 @@ static void __igt_kunit(struct igt_ktest *tst,
>   const char *opts,
>   struct igt_list_head *tests)
>  {
> - struct modprobe_data modprobe = { tst->kmod, opts, 0, pthread_self(), };
> - char *suite_name = NULL, *case_name = NULL;
> - struct igt_ktap_result *t, *r = NULL;
> - struct igt_ktap_results *ktap;
> - pthread_mutexattr_t attr;
> - IGT_LIST_HEAD(results);
> - int ret = -EINPROGRESS;
> - unsigned long taints;
> -
> - igt_skip_on(lseek(tst->kmsg, 0, SEEK_END) < 0);
> -
> - ktap = igt_ktap_alloc();
> - igt_require(ktap);
> + struct igt_ktap_result *t;
>  
>   igt_list_for_each_entry(t, tests, link) {
> + char *suite_name = NULL, *case_name = NULL;
> + IGT_LIST_HEAD(results);
> + unsigned long taints;
> +
>   igt_dynamic_f("%s%s%s",
> strcmp(t->suite_name, subtest) ?  

Re: [PATCH i-g-t v2 1/2] lib/kunit: Execute test cases synchronously

2024-03-07 Thread Kamil Konieczny
Hi Janusz,
On 2024-02-27 at 16:10:41 +0100, Janusz Krzysztofik wrote:
> Up to now we were loading a KUnit test module in test execution mode only
> once per subtest, in background, and then, in parallel with execution of
> test cases while the module was loading, we were looking through dmesg for
> KTAP results from each expected test case.  As a consequence, our IGT
> messages were more or less delayed, never in full sync with kernel
> messages.  Moreover, parsing of KTAP results from already completed test
> cases could be abandoned on a failure from loading the test module or
> kernel taint caused by a subsequent test case.  Also, parsing of KTAP
> results from all subsequent test cases could be abandoned on a failure of
> the parser caused by any test case.  Other than that, if a user requested
> a single dynamic sub-subtest, all test cases were executed anyway while
> results from only one of them that corresponded to the selected dynamic
> sub-subtest were reported.  That way, kernel messages from unrelated test
> cases, not only the selected one, could contribute to dmesg-fail or dmesg-
> warn CI results from that sub-subtest.
> 
> Since recent KUnit implementation is capable of executing only those test
> cases that match a user filter, stop executing all of them asynchronously
> and parsing their KTAP results as they appear.  Instead, reload the test
> module once per each dynamic sub-subtest with a filter that selects a
> specific test case and wait for its completion.  If successful and no
> kernel taint has occurred then parse the whole KTAP report from a single
> test case it has produced and translate it to IGT result of that single
> corresponding sub-subtest.
> 
> With that in place, we no longer need to skip the whole subtest on a
> failure from module loading or KTAP reading or parsing.  Since such event
> is now local to execution of an individual test case, only fail its
> corresponding dynamic sub-subtests and continue with subsequent ones.
> However, still omit execution of subsequent test cases once the kernel
> gets tainted.
> 
> v2: Refresh on top of changes to KUnit filters handling,
>   - include the code of a new helper from a previously separate patch,
>   - actually limit the scope of the helper to fetching a KTAP report from
> a file descriptor, and let the caller decide on how other steps, like
> setting up filters or loading a test module, and errors they return
> are handled,
>   - similar to kernel taint handling, just omit any remaining dynamic sub-
> subtests if unloading the test module fails,
>   - update commit description with a more detailed justification of why we
> need these changes.
> 
> Signed-off-by: Janusz Krzysztofik 
> Cc: Mauro Carvalho Chehab 
> ---
>  lib/igt_kmod.c | 157 -
>  1 file changed, 52 insertions(+), 105 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index cc242838fa..e9e00ac5b2 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -1018,6 +1018,25 @@ static void kunit_results_free(struct igt_list_head 
> *results,
>   free(*suite_name);
>  }
>  
> +static int kunit_get_results(struct igt_list_head *results, int kmsg_fd)
> +{
> + struct igt_ktap_results *ktap;
> + int err;
> +
> + ktap = igt_ktap_alloc(results);
> + if (igt_debug_on(!ktap))
> + return -ENOMEM;
> +
> + do
> + igt_debug_on((err = kunit_kmsg_result_get(results, NULL, 
> kmsg_fd, ktap),
> +   err && err != -EINPROGRESS));
> + while (err == -EINPROGRESS);
> +
> + igt_ktap_free(ktap);
> +
> + return err;
> +}
> +
>  static void __igt_kunit_legacy(struct igt_ktest *tst,
>  const char *subtest,
>  const char *opts)
> @@ -1211,86 +1230,51 @@ static void __igt_kunit(struct igt_ktest *tst,
>   const char *opts,
>   struct igt_list_head *tests)
>  {
> - struct modprobe_data modprobe = { tst->kmod, opts, 0, pthread_self(), };
> - char *suite_name = NULL, *case_name = NULL;
> - struct igt_ktap_result *t, *r = NULL;
> - struct igt_ktap_results *ktap;
> - pthread_mutexattr_t attr;
> - IGT_LIST_HEAD(results);
> - int ret = -EINPROGRESS;
> - unsigned long taints;
> -
> - igt_skip_on(lseek(tst->kmsg, 0, SEEK_END) < 0);
> -
> - ktap = igt_ktap_alloc();
> - igt_require(ktap);
> + struct igt_ktap_result *t;
>  
>   igt_list_for_each_entry(t, tests, link) {
> + char *suite_name = NULL, *case_name = NULL;
> + IGT_LIST_HEAD(results);
> + unsigned long taints;
> +
>   igt_dynamic_f("%s%s%s",
> strcmp(t->suite_name, subtest) ?  t->suite_name : 
> "",
> strcmp(t->suite_name, subtest) ? "-" : "",
> t->case_name) {
> + struct 

Re: [PATCH i-g-t v2 2/2] lib/kunit: Minimize code duplication

2024-03-07 Thread Kamil Konieczny
Hi Janusz,
On 2024-02-27 at 16:10:42 +0100, Janusz Krzysztofik wrote:
> A new helper has been introduced recently, used for fetching KTAP results
> of a single test case.  Since that helper is called for that purpose
> only after the test module is loaded with all other test cases filtered
> out, its actual implementation is as simple as collecting all results from
> a single KTAP report, no matter how many test suites and test cases it
> covers.  Then, it's a good candidate for reuse in other scenarios when a
> single KTAP report is handled, e.g., when we collect a list of test cases
> from a single test suite or test module.  Go for it.
> 
> Signed-off-by: Janusz Krzysztofik 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_kmod.c | 15 ++-
>  1 file changed, 2 insertions(+), 13 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index e9e00ac5b2..86cf50d5b7 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -1177,9 +1177,8 @@ static bool kunit_get_tests(struct igt_list_head *tests,
>   const char *opts)
>  {
>   struct igt_ktap_result *r, *rn;
> - struct igt_ktap_results *ktap;
>   unsigned long taints;
> - int flags, err;
> + int flags;
>  
>   igt_skip_on_f(tst->kmsg < 0, "Could not open /dev/kmsg\n");
>  
> @@ -1203,17 +1202,7 @@ static bool kunit_get_tests(struct igt_list_head 
> *tests,
>   igt_skip_on(modprobe(tst->kmod, opts));
>   igt_skip_on(igt_kernel_tainted());
>  
> - ktap = igt_ktap_alloc(tests);
> - igt_require(ktap);
> -
> - do
> - err = kunit_kmsg_result_get(tests, NULL, tst->kmsg, ktap);
> - while (err == -EINPROGRESS);
> -
> - igt_ktap_free(ktap);
> -
> - igt_skip_on_f(err,
> -   "KTAP parser failed while getting a list of test 
> cases\n");
> + igt_skip_on(kunit_get_results(tests, tst->kmsg));
>  
>   igt_list_for_each_entry_safe(r, rn, tests, link)
>   igt_require_f(r->code == IGT_EXIT_SKIP,
> -- 
> 2.43.0
> 


Re: [PATCH i-g-t] tests/perf_pmu: Set defaults before frequency test

2024-01-12 Thread Kamil Konieczny
Hi Vinay,
On 2024-01-11 at 14:20:54 -0800, Vinay Belgaumkar wrote:
> Seeing random issues where this test skips due to invalid
> boost freq at the start. Also ensure that we restore the frequencies at the 
> end.
> 
> v2: Use save/restore functions instead of exit_handler. Adding an
> exit_handler necessitated moving drm_close() into the handler. However,
> the module-reload subtest at the end expects drm-fd to be closed.
> Also setup expected frequencies (Kamil) and address other nits (Kamil)
> 
> Link: https://gitlab.freedesktop.org/drm/intel/-/issues/9432
> Cc: Kamil Konieczny 
> Signed-off-by: Vinay Belgaumkar 

Reviewed-by: Kamil Konieczny 

> ---
>  tests/intel/perf_pmu.c | 62 +-
>  1 file changed, 61 insertions(+), 1 deletion(-)
> 
> diff --git a/tests/intel/perf_pmu.c b/tests/intel/perf_pmu.c
> index c6e6a8b77..4ae2b60ae 100644
> --- a/tests/intel/perf_pmu.c
> +++ b/tests/intel/perf_pmu.c
> @@ -2454,12 +2454,69 @@ static void pmu_read(int i915)
>   for_each_if((e)->class == I915_ENGINE_CLASS_RENDER) \
>   igt_dynamic_f("%s", e->name)
>  
> +int fd = -1;
> +uint32_t *stash_min, *stash_max, *stash_boost;
> +
> +static void save_sysfs_freq(int i915)
> +{
> + int gt, num_gts, sysfs, tmp;
> + uint32_t rpn_freq, rp0_freq;
> +
> + num_gts = igt_sysfs_get_num_gt(i915);
> +
> + stash_min = (uint32_t *)malloc(sizeof(uint32_t) * num_gts);
> + stash_max = (uint32_t *)malloc(sizeof(uint32_t) * num_gts);
> + stash_boost = (uint32_t *)malloc(sizeof(uint32_t) * num_gts);
> +
> + /* Save boost, min and max across GTs */
> + i915_for_each_gt(i915, tmp, gt) {
> + sysfs = igt_sysfs_gt_open(i915, gt);
> + igt_require(sysfs >= 0);
> +
> + stash_min[gt] = igt_sysfs_get_u32(sysfs, "rps_min_freq_mhz");
> + stash_max[gt] = igt_sysfs_get_u32(sysfs, "rps_max_freq_mhz");
> + stash_boost[gt] = igt_sysfs_get_u32(sysfs, 
> "rps_boost_freq_mhz");
> + igt_debug("GT: %d, min: %d, max: %d, boost:%d\n",
> +   gt, stash_min[gt], stash_max[gt], stash_boost[gt]);
> +
> + rpn_freq = igt_sysfs_get_u32(sysfs, "rps_RPn_freq_mhz");
> + rp0_freq = igt_sysfs_get_u32(sysfs, "rps_RP0_freq_mhz");
> +
> + /* Set pre-conditions, in case frequencies are in non-default 
> state */
> + igt_require(__igt_sysfs_set_u32(sysfs, "rps_max_freq_mhz", 
> rp0_freq));
> + igt_require(__igt_sysfs_set_u32(sysfs, "rps_boost_freq_mhz", 
> rp0_freq));
> + igt_require(__igt_sysfs_set_u32(sysfs, "rps_min_freq_mhz", 
> rpn_freq));
> +
> + close(sysfs);
> + }
> +}
> +
> +static void restore_sysfs_freq(int i915)
> +{
> + int sysfs, gt, tmp;
> +
> + /* Restore frequencies */
> + i915_for_each_gt(fd, tmp, gt) {
> + sysfs = igt_sysfs_gt_open(fd, gt);
> + igt_require(sysfs >= 0);
> +
> + igt_require(__igt_sysfs_set_u32(sysfs, "rps_max_freq_mhz", 
> stash_max[gt]));
> + igt_require(__igt_sysfs_set_u32(sysfs, "rps_min_freq_mhz", 
> stash_min[gt]));
> + igt_require(__igt_sysfs_set_u32(sysfs, "rps_boost_freq_mhz", 
> stash_boost[gt]));
> +
> + close(sysfs);
> + }
> + free(stash_min);
> + free(stash_max);
> + free(stash_boost);
> +}
> +
>  igt_main
>  {
>   const struct intel_execution_engine2 *e;
>   unsigned int num_engines = 0;
>   const intel_ctx_t *ctx = NULL;
> - int gt, tmp, fd = -1;
> + int gt, tmp;
>   int num_gt = 0;
>  
>   /**
> @@ -2664,12 +2721,15 @@ igt_main
>* Test GPU frequency.
>*/
>   igt_subtest_with_dynamic("frequency") {
> + save_sysfs_freq(fd);
> +
>   i915_for_each_gt(fd, tmp, gt) {
>   igt_dynamic_f("gt%u", gt)
>   test_frequency(fd, gt);
>   igt_dynamic_f("idle-gt%u", gt)
>   test_frequency_idle(fd, gt);
>   }
> + restore_sysfs_freq(fd);
>   }
>  
>   /**
> -- 
> 2.38.1
> 


Re: [PATCH i-g-t] tests/perf_pmu: Restore sysfs freq in exit handler

2024-01-05 Thread Kamil Konieczny
Hi Vinay,
On 2024-01-04 at 17:10:00 -0800, Vinay Belgaumkar wrote:

looks good, there are some nits, first about subject:

[PATCH i-g-t] tests/perf_pmu: Restore sysfs freq in exit handler

s!tests/perf_pmu:!tests/intel/perf_pmu:!
Also you can drop "sysfs", so it will look:

[PATCH i-g-t] tests/intel/perf_pmu: Restore freq in exit handler

> Seeing random issues where this test starts with invalid values.

Btw if issue is it starts with invalid values maybe culprit is in
some previous test, not this one? What about setting freq values
to defaults first? This can be done in separate patch.

I looked into log from test here:
https://intel-gfx-ci.01.org/tree/drm-tip/drmtip_1438/bat-dg2-11/igt_runner10.txt
and here:
https://intel-gfx-ci.01.org/tree/drm-tip/drmtip_1438/bat-dg2-11/igt@perf_pmu@freque...@gt0.html

One more thing, why is boost < max? Is it allowed? What about
just restore it to max (or other value?) before testing and
skipping only when min == max? But even then it seems like
restoring defaults should be first step before freq checks.

For more nits see below.

> Ensure that we restore the frequencies in case test exits early
> due to some system issues.
> 
> Link: https://gitlab.freedesktop.org/drm/intel/-/issues/9432
> Signed-off-by: Vinay Belgaumkar 
> ---
>  tests/intel/perf_pmu.c | 53 +-
>  1 file changed, 52 insertions(+), 1 deletion(-)
> 
> diff --git a/tests/intel/perf_pmu.c b/tests/intel/perf_pmu.c
> index c6e6a8b77..ceacc1d3d 100644
> --- a/tests/intel/perf_pmu.c
> +++ b/tests/intel/perf_pmu.c
> @@ -2454,12 +2454,59 @@ static void pmu_read(int i915)
>   for_each_if((e)->class == I915_ENGINE_CLASS_RENDER) \
>   igt_dynamic_f("%s", e->name)
>  
> +int fd = -1;
> +uint32_t *stash_min, *stash_max, *stash_boost;
> +
> +static void save_sysfs_freq(int i915)
> +{
> + int gt, num_gts, sysfs, tmp;
> +
> + num_gts = igt_sysfs_get_num_gt(i915);
> +
> + stash_min = (uint32_t *)malloc(sizeof(uint32_t) * num_gts);
> + stash_max = (uint32_t *)malloc(sizeof(uint32_t) * num_gts);
> + stash_boost = (uint32_t *)malloc(sizeof(uint32_t) * num_gts);
> +
> + /* Save boost, min and max across GTs */
> + i915_for_each_gt(i915, tmp, gt) {
> + sysfs = igt_sysfs_gt_open(i915, gt);
> + igt_require(sysfs >= 0);
> +
> + stash_min[gt] = igt_sysfs_get_u32(sysfs, "rps_min_freq_mhz");
> + stash_max[gt] = igt_sysfs_get_u32(sysfs, "rps_max_freq_mhz");
> + stash_boost[gt] = igt_sysfs_get_u32(sysfs, 
> "rps_boost_freq_mhz");
> + igt_debug("GT: %d, min: %d, max: %d, boost:%d\n",
> +   gt, stash_min[gt], stash_max[gt], stash_boost[gt]);
> +
> + close(sysfs);
> + }
> +}
> +
> +static void restore_sysfs_freq(int sig)
> +{
> + int sysfs, gt, tmp;
> +
> + /* Restore frequencies */
> + i915_for_each_gt(fd, tmp, gt) {
> + sysfs = igt_sysfs_gt_open(fd, gt);
> + igt_require(sysfs >= 0);
^
Don't use require at exit handler, better use continue.

> +
> + igt_require(__igt_sysfs_set_u32(sysfs, "rps_max_freq_mhz", 
> stash_max[gt]));
^
Same here.

> + igt_require(__igt_sysfs_set_u32(sysfs, "rps_min_freq_mhz", 
> stash_min[gt]));
^
Same.

> + igt_require(__igt_sysfs_set_u32(sysfs, "rps_boost_freq_mhz", 
> stash_boost[gt]));
^
Same.

> +
> + close(sysfs);
> + }
> + free(stash_min);
> + free(stash_max);

Free also stash_boost.

> +}
> +
>  igt_main
>  {
>   const struct intel_execution_engine2 *e;
>   unsigned int num_engines = 0;
>   const intel_ctx_t *ctx = NULL;
> - int gt, tmp, fd = -1;
> + int gt, tmp;
>   int num_gt = 0;
>  
>   /**
> @@ -2482,6 +2529,7 @@ igt_main
>  
>   i915_for_each_gt(fd, tmp, gt)
>   num_gt++;
> +

Remove this empty line.

Regards,
Kamil

>   }
>  
>   igt_describe("Verify i915 pmu dir exists and read all events");
> @@ -2664,6 +2712,9 @@ igt_main
>* Test GPU frequency.
>*/
>   igt_subtest_with_dynamic("frequency") {
> + save_sysfs_freq(fd);
> + igt_install_exit_handler(restore_sysfs_freq);
> +
>   i915_for_each_gt(fd, tmp, gt) {
>   igt_dynamic_f("gt%u", gt)
>   test_frequency(fd, gt);
> -- 
> 2.38.1
> 


Re: [Intel-gfx] [PATCH i-g-t 3/9] tests/i915/drm_fdinfo: Add some memory info tests

2023-11-03 Thread Kamil Konieczny
Hi Tvrtko,
On 2023-10-12 at 09:15:41 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> A few basic smoke tests to check per client memory info looks legit.
> 
> Signed-off-by: Tvrtko Ursulin 

Reviewed-by: Kamil Konieczny 

> ---
>  tests/intel/drm_fdinfo.c | 217 +++
>  1 file changed, 217 insertions(+)
> 
> diff --git a/tests/intel/drm_fdinfo.c b/tests/intel/drm_fdinfo.c
> index c4218b0d16e6..3ced658f2faa 100644
> --- a/tests/intel/drm_fdinfo.c
> +++ b/tests/intel/drm_fdinfo.c
> @@ -23,6 +23,7 @@
>   */
>  
>  #include 
> +#include 
>  
>  #include "igt.h"
>  #include "igt_core.h"
> @@ -76,6 +77,16 @@
>   *
>   * SUBTEST: virtual-idle
>   *
> + * SUBTEST: memory-info-idle
> + *
> + * SUBTEST: memory-info-active
> + *
> + * SUBTEST: memory-info-resident
> + *
> + * SUBTEST: memory-info-purgeable
> + *
> + * SUBTEST: memory-info-shared
> + *
>   * SUBTEST: context-close-stress
>   */
>  
> @@ -143,6 +154,11 @@ static unsigned int measured_usleep(unsigned int usec)
>  #define FLAG_HANG (8)
>  #define TEST_ISOLATION (16)
>  
> +#define TEST_ACTIVE TEST_BUSY
> +#define TEST_RESIDENT (32)
> +#define TEST_PURGEABLE (64)
> +#define TEST_SHARED (128)
> +
>  static void end_spin(int fd, igt_spin_t *spin, unsigned int flags)
>  {
>   if (!spin)
> @@ -772,6 +788,172 @@ static void stress_context_close(int i915)
>   igt_stop_helper();
>  }
>  
> +static size_t read_fdinfo(char *buf, const size_t sz, int at, const char 
> *name)
> +{
> + size_t count;
> + int fd;
> +
> + fd = openat(at, name, O_RDONLY);
> + if (fd < 0)
> + return 0;
> +
> + count = read(fd, buf, sz - 1);
> + if (count > 0)
> + buf[count - 1] = 0;
> + close(fd);
> +
> + return count > 0 ? count : 0;
> +}
> +
> +/*
> + * At least this much, but maybe less if we started with a driver internal
> + * baseline which can go away behind our back.
> + */
> +#define fdinfo_assert_gte(cur, prev, sz, base) \
> +({ \
> + int64_t __sz = (sz) - (base); \
> + int64_t __d = (cur) - (prev); \
> + igt_assert_f(__d >= __sz, \
> +  "prev=%"PRIu64" cur=%"PRIu64" delta=%"PRId64" sz=%"PRIu64" 
> baseline=%"PRIu64"\n%s\n", \
> +  (prev), (cur), __d, (sz), (base), fdinfo_buf); \
> +})
> +
> +#define fdinfo_assert_eq(cur, prev, sz, base) \
> +({ \
> + int64_t __d = (cur) - (prev); \
> + igt_assert_f(__d == 0, \
> +  "prev=%"PRIu64" cur=%"PRIu64" delta=%"PRId64" sz=%"PRIu64" 
> baseline=%"PRIu64"\n%s\n", \
> +  (prev), (cur), __d, (sz), (base), fdinfo_buf); \
> +})
> +
> +static void
> +test_memory(int i915, struct gem_memory_region *mr, unsigned int flags)
> +{
> + const unsigned int r = mr->ci.memory_class == I915_MEMORY_CLASS_SYSTEM 
> ? 0 : 1; /* See region map */
> + const uint64_t max_mem = 512ull * 1024 * 1024;
> + const uint64_t max_bo = 16ull * 1024 * 1024;
> + struct drm_client_fdinfo base_info, prev_info = { };
> + struct drm_client_fdinfo info = { };
> + char buf[64], fdinfo_buf[4096];
> + igt_spin_t *spin = NULL;
> + uint64_t total = 0, sz;
> + uint64_t ahnd;
> + int ret, dir;
> +
> + i915 = drm_reopen_driver(i915);
> +
> + ahnd = get_reloc_ahnd(i915, 0);
> +
> + ret = snprintf(buf, sizeof(buf), "%u", i915);
> + igt_assert(ret > 0 && ret < sizeof(buf));
> +
> + dir = open("/proc/self/fdinfo", O_DIRECTORY | O_RDONLY);
> + igt_assert_fd(dir);
> +
> + gem_quiescent_gpu(i915);
> + ret =  __igt_parse_drm_fdinfo(dir, buf, , NULL, 0, NULL, 0);
> + igt_assert(ret > 0);
> + igt_require(info.num_regions);
> + memcpy(_info, , sizeof(info));
> + memcpy(_info, , sizeof(info));
> +
> + while (total < max_mem) {
> + static const char *region_map[] = {
> + "system0",
> + "local0",
> + };
> + uint32_t bo;
> +
> + sz = random() % max_bo;
> + ret = __gem_create_in_memory_region_list(i915, , , 0,
> +  >ci, 1);
> + igt_assert_eq(ret, 0);
> + total += sz;
> +
> + if (flags & (TEST_RESIDENT | TEST_PURGEABLE | TEST_ACTIVE))
> + spin = igt_spin_new(i915,
>

Re: [Intel-gfx] [igt-dev] [PATCH i-g-t 9/9] tools/intel_gpu_top: Add ability to show memory region breakdown

2023-11-03 Thread Kamil Konieczny
Hi Tvrtko,
On 2023-10-12 at 09:15:47 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Similar as we can toggle between aggregated engines and clients, add the
> capability to toggle between aggregated and per memory region stats.
> 
> It starts in aggregated mode by default and interactive command 'm' and
> command line switch '-m' can be used to toggle that.
> 
> Both only affect the interactive view, while JSON output always contains
> separate memory regions.
> 
> Signed-off-by: Tvrtko Ursulin 

Reviewed-by: Kamil Konieczny 

> ---
>  man/intel_gpu_top.rst |  4 
>  tools/intel_gpu_top.c | 55 ++-
>  2 files changed, 48 insertions(+), 11 deletions(-)
> 
> diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
> index 9499f87f1b4d..44a54a5f219d 100644
> --- a/man/intel_gpu_top.rst
> +++ b/man/intel_gpu_top.rst
> @@ -55,6 +55,9 @@ OPTIONS
>  -p
> Default to showing physical engines instead of aggregated classes.
>  
> +-m
> +   Default to showing all memory regions separately.
> +
>  RUNTIME CONTROL
>  ===
>  
> @@ -68,6 +71,7 @@ Supported keys:
>  |'s'Toggle between sort modes (runtime, total runtime, pid, client 
> id).
>  |'i'Toggle display of clients which used no GPU time.
>  |'H'Toggle between per PID aggregation and individual clients.
> +|'m'Toggle between aggregated memory regions and full breakdown.
>  
>  DEVICE SELECTION
>  
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index 2c09895c79dd..046ead15a122 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -138,6 +138,7 @@ struct intel_clients {
>  
>  static struct termios termios_orig;
>  static bool class_view;
> +static bool aggregate_regions;
>  
>  /* Maps i915 fdinfo names to indices */
>  static const char *memory_region_map[] = {
> @@ -1050,6 +1051,7 @@ usage(const char *appname)
>   "\t[-L]List all cards.\n"
>   "\t[-d ]   Device filter, please check manual page for 
> more details.\n"
>   "\t[-p]Default to showing physical engines instead 
> of classes.\n"
> + "\t[-m]Default to showing all memory regions.\n"
>   "\n",
>   appname, DEFAULT_PERIOD_MS);
>   igt_device_print_filter_types();
> @@ -2032,6 +2034,7 @@ print_clients_header(struct igt_drm_clients *clients, 
> int lines,
>  
>   if (output_mode == INTERACTIVE) {
>   int len, num_active = 0;
> + unsigned int i;
>  
>   if (lines++ >= con_h)
>   return lines;
> @@ -2042,11 +2045,17 @@ print_clients_header(struct igt_drm_clients *clients, 
> int lines,
>   if (lines++ >= con_h || len >= con_w)
>   return lines;
>  
> - if (iclients->regions)
> - len += printf(" MEM  RSS ");
> + if (iclients->regions) {
> + if (aggregate_regions) {
> + len += printf(" MEM  RSS ");
> + } else {
> + len += printf(" RAM  RSS ");
> + if (iclients->regions->num_regions > 1)
> + len += printf("VRAM VRSS ");
> + }
> + }
>  
>   if (iclients->classes.num_engines) {
> - unsigned int i;
>   int width;
>  
>   for (i = 0; i <= iclients->classes.max_engine_id; i++) {
> @@ -2120,15 +2129,26 @@ print_client(struct igt_drm_client *c, struct engines 
> *engines, double t, int li
>   len = printf("%*s ", clients->max_pid_len, c->pid_str);
>  
>   if (iclients->regions) {
> - uint64_t sz;
> + if (aggregate_regions) {
> + uint64_t sz;
>  
> - for (sz = 0, i = 0; i <= c->regions->max_region_id; i++)
> - sz += c->memory[i].total;
> - len += print_size(sz);
> + for (sz = 0, i = 0;
> +  i <= c->regions->max_region_id; i++)
> + sz += c->memory[i].total;
> + len += print_size(sz);
>  
> - for (sz = 0, i = 0; i <= c->regions->max_regio

Re: [Intel-gfx] [igt-dev] [PATCH i-g-t 8/9] tools/intel_gpu_top: Add per client memory info

2023-11-03 Thread Kamil Konieczny
Hi Tvrtko,
On 2023-10-12 at 09:15:46 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> JSON output has the full breakdown but for now the interactive mode only
> shows total and resident aggregated for all memory regions.
> 
> Signed-off-by: Tvrtko Ursulin 

Reviewed-by: Kamil Konieczny 

> ---
>  tools/intel_gpu_top.c | 114 +-
>  1 file changed, 112 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index b2e81d5f9ffb..2c09895c79dd 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -133,11 +133,24 @@ struct intel_clients {
>   const char *pci_slot;
>   struct igt_drm_client_engines classes;
>   struct igt_drm_clients *clients;
> + struct igt_drm_client_regions *regions; /* Borrowed from first client */
>  };
>  
>  static struct termios termios_orig;
>  static bool class_view;
>  
> +/* Maps i915 fdinfo names to indices */
> +static const char *memory_region_map[] = {
> + "system0",
> + "local0",
> +};
> +
> +/* For JSON, 1:1 with indices above. */
> +static const char *json_memory_region_names[] = {
> + "system",
> + "local",
> +};
> +
>  __attribute__((format(scanf,3,4)))
>  static int igt_sysfs_scanf(int dir, const char *attr, const char *fmt, ...)
>  {
> @@ -882,6 +895,9 @@ static struct igt_drm_clients *display_clients(struct 
> igt_drm_clients *clients)
>   ac->val = calloc(c->engines->max_engine_id + 1,
>sizeof(ac->val[0]));
>   assert(ac->val);
> + ac->regions = c->regions;
> + ac->memory = calloc(c->regions->max_region_id + 1,
> + sizeof(ac->memory[0]));
>   ac->samples = 1;
>   }
>  
> @@ -896,6 +912,14 @@ static struct igt_drm_clients *display_clients(struct 
> igt_drm_clients *clients)
>  
>   for (i = 0; i <= c->engines->max_engine_id; i++)
>   ac->val[i] += c->val[i];
> +
> + for (i = 0; i <= c->regions->max_region_id; i++) {
> + ac->memory[i].total += c->memory[i].total;
> + ac->memory[i].shared += c->memory[i].shared;
> + ac->memory[i].resident += c->memory[i].resident;
> + ac->memory[i].purgeable += c->memory[i].purgeable;
> + ac->memory[i].active += c->memory[i].active;
> + }
>   }
>  
>   aggregated->num_clients = num;
> @@ -920,8 +944,10 @@ static void free_display_clients(struct igt_drm_clients 
> *clients)
>* "display" clients are not proper clients and have un-initialized
>* or borrowed fields which we don't want the library to try and free.
>*/
> - igt_for_each_drm_client(clients, c, tmp)
> + igt_for_each_drm_client(clients, c, tmp) {
>   free(c->val);
> + free(c->memory);
> + }
>  
>   free(clients->client);
>   free(clients);
> @@ -2016,6 +2042,9 @@ print_clients_header(struct igt_drm_clients *clients, 
> int lines,
>   if (lines++ >= con_h || len >= con_w)
>   return lines;
>  
> + if (iclients->regions)
> + len += printf(" MEM  RSS ");
> +
>   if (iclients->classes.num_engines) {
>   unsigned int i;
>   int width;
> @@ -2059,6 +2088,20 @@ print_clients_header(struct igt_drm_clients *clients, 
> int lines,
>  static bool numeric_clients;
>  static bool filter_idle;
>  
> +static int print_size(uint64_t sz)
> +{
> + char units[] = { ' ', 'K', 'M', 'G' };
> + unsigned int u;
> +
> + for (u = 0; u < ARRAY_SIZE(units) - 1; u++) {
> + if (sz & 1023 || sz < 1024)
> + break;
> + sz /= 1024;
> + }
> +
> + return printf("%7"PRIu64"%c ", sz, units[u]);
> +}
> +
>  static int
>  print_client(struct igt_drm_client *c, struct engines *engines, double t, 
> int lines,
>int con_w, int con_h, unsigned int period_us, int *class_w)
> @@ -2076,6 +2119,18 @@ print_client(struct igt_drm_client *c, struct engines 
> *engines, double t, int li
>  
>   len = printf("%*s ", clients->max_pid_len, c->pid_str);
>  
> + if (iclients->regions) {
&

Re: [Intel-gfx] [igt-dev] [PATCH i-g-t 7/9] tools/intel_gpu_top: Fully wrap clients operations

2023-11-03 Thread Kamil Konieczny
Hi Tvrtko,
On 2023-10-12 at 09:15:45 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Wrap all operations on clients via the Intel specific wrappers in order to
> simplify upcoming work.
> 
> Signed-off-by: Tvrtko Ursulin 

Reviewed-by: Kamil Konieczny 

> ---
>  tools/intel_gpu_top.c | 42 ++
>  1 file changed, 22 insertions(+), 20 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index 091fe28068dc..b2e81d5f9ffb 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -132,6 +132,7 @@ struct engines {
>  struct intel_clients {
>   const char *pci_slot;
>   struct igt_drm_client_engines classes;
> + struct igt_drm_clients *clients;
>  };
>  
>  static struct termios termios_orig;
> @@ -2436,19 +2437,22 @@ intel_init_clients(struct intel_clients *iclients,
>   iclients->classes.capacity[i] = engines->class[i].num_engines;
>   iclients->classes.names[i] = strdup(engines->class[i].name);
>   }
> +
> + iclients->clients = igt_drm_clients_init(iclients);
>  }
>  
>  static void intel_free_clients(struct intel_clients *iclients)
>  {
> + if (iclients->clients)
> + igt_drm_clients_free(iclients->clients);
> +
>   free((void *)iclients->pci_slot);
>   free(iclients->classes.capacity);
>   free(iclients->classes.names);
>  }
>  
> -int main(int argc, char **argv)
> +static void intel_scan_clients(struct intel_clients *iclients)
>  {
> - unsigned int period_us = DEFAULT_PERIOD_MS * 1000;
> - struct igt_drm_clients *clients = NULL;
>   static const char *engine_map[] = {
>   "render",
>   "copy",
> @@ -2456,6 +2460,15 @@ int main(int argc, char **argv)
>   "video-enhance",
>   "compute",
>   };
> +
> + igt_drm_clients_scan(iclients->clients, client_match,
> +  engine_map, ARRAY_SIZE(engine_map),
> +  NULL, 0);
> +}
> +
> +int main(int argc, char **argv)
> +{
> + unsigned int period_us = DEFAULT_PERIOD_MS * 1000;
>   bool physical_engines = false;
>   struct intel_clients iclients;
>   int con_w = -1, con_h = -1;
> @@ -2613,15 +2626,11 @@ int main(int argc, char **argv)
>  
>   init_engine_classes(engines);
>  
> - if (has_drm_fdinfo()) {
> + if (has_drm_fdinfo())
>   intel_init_clients(, , engines);
> - clients = igt_drm_clients_init();
> - }
>  
>   pmu_sample(engines);
> - igt_drm_clients_scan(clients, client_match,
> -  engine_map, ARRAY_SIZE(engine_map),
> -  NULL, 0);
> + intel_scan_clients();
>   gettime();
>  
>   if (output_mode == JSON)
> @@ -2652,12 +2661,8 @@ int main(int argc, char **argv)
>   pmu_sample(engines);
>   t = (double)(engines->ts.cur - engines->ts.prev) / 1e9;
>  
> - disp_clients =
> - display_clients(igt_drm_clients_scan(clients,
> -  client_match,
> -  engine_map,
> -  
> ARRAY_SIZE(engine_map),
> -  NULL, 0));
> + intel_scan_clients();
> + disp_clients = display_clients(iclients.clients);
>   scan_us = elapsed_us(, period_us);
>  
>   if (stop_top)
> @@ -2708,7 +2713,7 @@ int main(int argc, char **argv)
>   pops->close_struct();
>   }
>  
> - if (disp_clients != clients)
> + if (disp_clients != iclients.clients)
>   free_display_clients(disp_clients);
>  
>   if (stop_top)
> @@ -2723,10 +2728,7 @@ int main(int argc, char **argv)
>   if (output_mode == JSON)
>   printf("]\n");
>  
> - if (clients) {
> - igt_drm_clients_free(clients);
> - intel_free_clients();
> - }
> + intel_free_clients();
>  
>   free(codename);
>  err_pmu:
> -- 
> 2.39.2
> 


Re: [Intel-gfx] [igt-dev] [PATCH i-g-t 4/9] lib/igt_drm_fdinfo: Copy over region map name on match

2023-11-03 Thread Kamil Konieczny
Hi Tvrtko,
On 2023-10-12 at 09:15:42 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> I will need some record of which regions were found for intel_gpu_top so
> lets just copy over the region name from the map on the first match.
> 
> Signed-off-by: Tvrtko Ursulin 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_drm_fdinfo.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/lib/igt_drm_fdinfo.c b/lib/igt_drm_fdinfo.c
> index b72822894782..222ccbfb1fd6 100644
> --- a/lib/igt_drm_fdinfo.c
> +++ b/lib/igt_drm_fdinfo.c
> @@ -148,6 +148,10 @@ static int parse_region(char *line, struct 
> drm_client_fdinfo *info,
>   for (i = 0; i < region_entries; i++) {
>   if (!strncmp(name, region_map[i], name_len)) {
>   found = i;
> + if (!info->region_names[info->num_regions][0]) {
> + assert(name_len < 
> sizeof(info->region_names[i]));
> + strncpy(info->region_names[i], name, 
> name_len);
> + }
>   break;
>   }
>   }
> -- 
> 2.39.2
> 


Re: [Intel-gfx] [PATCH i-g-t 5/9] lib/igt_drm_clients: Fix client id type confusion

2023-11-03 Thread Kamil Konieczny
Hi Tvrtko,
On 2023-10-12 at 09:15:43 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Igt_drm_fdinfo defines it as an unsigned long so it is best that it
> matches here as well.
> 
> Signed-off-by: Tvrtko Ursulin 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_drm_clients.c | 2 +-
>  lib/igt_drm_clients.h | 2 +-
>  tools/intel_gpu_top.c | 2 +-
>  3 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/lib/igt_drm_clients.c b/lib/igt_drm_clients.c
> index 47ad137d5f1f..da51d7335b2b 100644
> --- a/lib/igt_drm_clients.c
> +++ b/lib/igt_drm_clients.c
> @@ -49,7 +49,7 @@ struct igt_drm_clients *igt_drm_clients_init(void 
> *private_data)
>  static struct igt_drm_client *
>  igt_drm_clients_find(struct igt_drm_clients *clients,
>enum igt_drm_client_status status,
> -  unsigned int drm_minor, unsigned int id)
> +  unsigned int drm_minor, unsigned long id)
>  {
>   unsigned int start, num;
>   struct igt_drm_client *c;
> diff --git a/lib/igt_drm_clients.h b/lib/igt_drm_clients.h
> index 07bd236d43bf..cd37f8508b20 100644
> --- a/lib/igt_drm_clients.h
> +++ b/lib/igt_drm_clients.h
> @@ -56,7 +56,7 @@ struct igt_drm_client {
>   enum igt_drm_client_status status;
>   struct igt_drm_client_regions *regions; /* Memory regions present in 
> this client, to map with memory usage. */
>   struct igt_drm_client_engines *engines; /* Engines used by this client, 
> to map with busynees data. */
> - unsigned int id; /* DRM client id from fdinfo. */
> + unsigned long id; /* DRM client id from fdinfo. */
>   unsigned int drm_minor; /* DRM minor of this client. */
>   unsigned int pid; /* PID which has this DRM fd open. */
>   char pid_str[10]; /* Cached PID representation. */
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index 00506c63db4e..34fa99235e11 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -2106,7 +2106,7 @@ print_client(struct igt_drm_client *c, struct engines 
> *engines, double t, int li
>   } else if (output_mode == JSON) {
>   char buf[64];
>  
> - snprintf(buf, sizeof(buf), "%u", c->id);
> + snprintf(buf, sizeof(buf), "%lu", c->id);
>   pops->open_struct(buf);
>  
>   __json_add_member("name", c->print_name);
> -- 
> 2.39.2
> 


Re: [Intel-gfx] [PATCH i-g-t 6/9] lib/igt_drm_clients: Allow passing in the memory region map

2023-11-03 Thread Kamil Konieczny
Hi Tvrtko,
On 2023-10-12 at 09:15:44 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Same concept as with the engine map, allowing callers to pass in fixed
> map of names to indices, simplifying their implementation and avoiding
> auto-detection while parsing.
> 
> Signed-off-by: Tvrtko Ursulin 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_drm_clients.c | 5 +++--
>  lib/igt_drm_clients.h | 3 ++-
>  tools/gputop.c| 4 ++--
>  tools/intel_gpu_top.c | 8 +---
>  4 files changed, 12 insertions(+), 8 deletions(-)
> 
> diff --git a/lib/igt_drm_clients.c b/lib/igt_drm_clients.c
> index da51d7335b2b..025d60c51503 100644
> --- a/lib/igt_drm_clients.c
> +++ b/lib/igt_drm_clients.c
> @@ -445,7 +445,8 @@ struct igt_drm_clients *
>  igt_drm_clients_scan(struct igt_drm_clients *clients,
>bool (*filter_client)(const struct igt_drm_clients *,
>  const struct drm_client_fdinfo *),
> -  const char **name_map, unsigned int map_entries)
> +  const char **name_map, unsigned int map_entries,
> +  const char **region_map, unsigned int region_entries)
>  {
>   struct dirent *proc_dent;
>   struct igt_drm_client *c;
> @@ -524,7 +525,7 @@ igt_drm_clients_scan(struct igt_drm_clients *clients,
>   if (!__igt_parse_drm_fdinfo(dirfd(fdinfo_dir),
>   fdinfo_dent->d_name, ,
>   name_map, map_entries,
> - NULL, 0))
> + region_map, region_entries))
>   continue;
>  
>   if (filter_client && !filter_client(clients, ))
> diff --git a/lib/igt_drm_clients.h b/lib/igt_drm_clients.h
> index cd37f8508b20..52888aedc25a 100644
> --- a/lib/igt_drm_clients.h
> +++ b/lib/igt_drm_clients.h
> @@ -93,7 +93,8 @@ struct igt_drm_clients *
>  igt_drm_clients_scan(struct igt_drm_clients *clients,
>bool (*filter_client)(const struct igt_drm_clients *,
>  const struct drm_client_fdinfo *),
> -  const char **name_map, unsigned int map_entries);
> +  const char **name_map, unsigned int map_entries,
> +  const char **region_map, unsigned int region_entries);
>  
>  struct igt_drm_clients *
>  igt_drm_clients_sort(struct igt_drm_clients *clients,
> diff --git a/tools/gputop.c b/tools/gputop.c
> index ea95e0333dd2..71e28f43ee4c 100644
> --- a/tools/gputop.c
> +++ b/tools/gputop.c
> @@ -253,7 +253,7 @@ int main(int argc, char **argv)
>   if (!clients)
>   exit(1);
>  
> - igt_drm_clients_scan(clients, NULL, NULL, 0);
> + igt_drm_clients_scan(clients, NULL, NULL, 0, NULL, 0);
>  
>   for (;;) {
>   struct igt_drm_client *c, *prevc = NULL;
> @@ -270,7 +270,7 @@ int main(int argc, char **argv)
>   }
>   }
>  
> - igt_drm_clients_scan(clients, NULL, NULL, 0);
> + igt_drm_clients_scan(clients, NULL, NULL, 0, NULL, 0);
>   igt_drm_clients_sort(clients, client_cmp);
>  
>   printf("\033[H\033[J");
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index 34fa99235e11..091fe28068dc 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -2619,8 +2619,9 @@ int main(int argc, char **argv)
>   }
>  
>   pmu_sample(engines);
> - igt_drm_clients_scan(clients, client_match, engine_map,
> -  ARRAY_SIZE(engine_map));
> + igt_drm_clients_scan(clients, client_match,
> +  engine_map, ARRAY_SIZE(engine_map),
> +  NULL, 0);
>   gettime();
>  
>   if (output_mode == JSON)
> @@ -2655,7 +2656,8 @@ int main(int argc, char **argv)
>   display_clients(igt_drm_clients_scan(clients,
>client_match,
>engine_map,
> -  
> ARRAY_SIZE(engine_map)));
> +  
> ARRAY_SIZE(engine_map),
> +  NULL, 0));
>   scan_us = elapsed_us(, period_us);
>  
>   if (stop_top)
> -- 
> 2.39.2
> 


Re: [Intel-gfx] [PATCH i-g-t 2/9] tests/i915/drm_fdinfo: Stress test context close versus fdinfo reads

2023-11-03 Thread Kamil Konieczny
Hi Tvrtko,
On 2023-10-12 at 09:15:40 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> A short smoke tests to exercise fdinfo reads in parallel to contexts
> getting created and destroyed.
> 
> Signed-off-by: Tvrtko Ursulin 
> ---
>  tests/intel/drm_fdinfo.c | 68 
>  1 file changed, 68 insertions(+)
> 
> diff --git a/tests/intel/drm_fdinfo.c b/tests/intel/drm_fdinfo.c
> index 344c44dce78b..c4218b0d16e6 100644
> --- a/tests/intel/drm_fdinfo.c
> +++ b/tests/intel/drm_fdinfo.c
> @@ -22,11 +22,14 @@
>   *
>   */
>  
> +#include 
> +
>  #include "igt.h"
>  #include "igt_core.h"
>  #include "igt_device.h"
>  #include "igt_drm_fdinfo.h"
>  #include "i915/gem.h"
> +#include "i915/gem_create.h"
>  #include "i915/gem_vm.h"
>  #include "intel_ctx.h"
>  /**
> @@ -72,6 +75,8 @@
>   * SUBTEST: virtual-busy-idle-all
>   *
>   * SUBTEST: virtual-idle
> + *
> + * SUBTEST: context-close-stress
>   */
>  
>  IGT_TEST_DESCRIPTION("Test the i915 drm fdinfo data");
> @@ -717,6 +722,56 @@ virtual_all(int i915, const intel_ctx_cfg_t *base_cfg, 
> unsigned int flags)
>   }
>  }
>  
> +static void stress_context_close(int i915)
> +{
> + const uint32_t bbe = MI_BATCH_BUFFER_END;
> + struct igt_helper_process reader = { };
> + struct drm_client_fdinfo info;
> + uint32_t batch;
> + int dir, ret;
> + char buf[64];
> +
> + ret = snprintf(buf, sizeof(buf), "%u", i915);
> + igt_assert(ret > 0 && ret < sizeof(buf));
> +
> + dir = open("/proc/self/fdinfo", O_DIRECTORY | O_RDONLY);
> + igt_assert_fd(dir);
> +
> + memset(, 0, sizeof(info));
> + ret = __igt_parse_drm_fdinfo(dir, buf, , NULL, 0, NULL, 0);
> + igt_assert(ret > 0);

You repeat this pattern later, it can be made into
function:

igt_parse_drm_fdinfo(dir, buf, *info, p1, i1, p2, i2)
{
memset(info, 0, sizeof(*info));
ret = __igt_parse_drm_fdinfo(dir, buf, info, p1, i1, p2, i2);
igt_assert(ret > 0);
}

> + igt_require(info.num_regions);
> +
> + batch = gem_create(i915, 4096);
> + gem_write(i915, batch, 0, , sizeof(bbe));
> +
> + igt_fork_helper() {
> +     for (;;) {
> + memset(, 0, sizeof(info));
> + ret = __igt_parse_drm_fdinfo(dir, buf, ,
> +  NULL, 0, NULL, 0);
> + igt_assert(ret > 0);

Here you repeat this.

With or without makeing this a function,
Reviewed-by: Kamil Konieczny 

> + }
> + }
> +
> + igt_until_timeout(10) {
> + struct drm_i915_gem_exec_object2 obj = {
> + .handle = batch,
> + };
> + struct drm_i915_gem_execbuffer2 eb = {
> + .buffers_ptr = to_user_pointer(),
> + .buffer_count = 1,
> + };
> +
> + eb.rsvd1 = gem_context_create(i915);
> + igt_assert(eb.rsvd1);
> + gem_execbuf(i915, );
> + gem_context_destroy(i915, eb.rsvd1);
> + }
> +
> + igt_stop_helper();
> +}
> +
>  #define test_each_engine(T, i915, ctx, e) \
>   igt_subtest_with_dynamic(T) for_each_ctx_engine(i915, ctx, e) \
>   igt_dynamic_f("%s", e->name)
> @@ -848,6 +903,19 @@ igt_main
>   test_each_engine("isolation", i915, ctx, e)
>   single(i915, ctx, e, TEST_BUSY | TEST_ISOLATION);
>  
> + igt_subtest_group {
> + int newfd;
> +
> + igt_fixture
> + newfd = drm_reopen_driver(i915);
> +
> + igt_subtest("context-close-stress")
> + stress_context_close(newfd);
> +
> + igt_fixture
> + drm_close_driver(newfd);
> + }
> +
>   igt_fixture {
>   intel_ctx_destroy(i915, ctx);
>   drm_close_driver(i915);
> -- 
> 2.39.2
> 


Re: [Intel-gfx] [PATCH i-g-t 1/9] tests/i915/drm_fdinfo: Check engine info is supported

2023-11-03 Thread Kamil Konieczny
Hi Tvrtko,
On 2023-10-12 at 09:15:39 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> On top of checking that parsing works, check that there are some engines
> present. This will be needed once the memory stats are added and so return
> value from __igt_parse_drm_fdinfo() will then be possible to be greater
> than zero even when engine stats are not supported.
> 
> Signed-off-by: Tvrtko Ursulin 

Reviewed-by: Kamil Konieczny 

> ---
>  tests/intel/drm_fdinfo.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/tests/intel/drm_fdinfo.c b/tests/intel/drm_fdinfo.c
> index aca19db50680..344c44dce78b 100644
> --- a/tests/intel/drm_fdinfo.c
> +++ b/tests/intel/drm_fdinfo.c
> @@ -737,6 +737,7 @@ igt_main
>  
>   igt_require_gem(i915);
>   igt_require(igt_parse_drm_fdinfo(i915, , NULL, 0, NULL, 
> 0));
> + igt_require(info.num_engines);
>  
>   ctx = intel_ctx_create_all_physical(i915);
>  
> -- 
> 2.39.2
> 


Re: [Intel-gfx] [PATCH i-g-t v3 10/11] lib/kunit: Fetch a list of test cases in advance

2023-10-20 Thread Kamil Konieczny
Hi Janusz,
On 2023-10-11 at 16:17:45 +0200, Janusz Krzysztofik wrote:
> Recent improvements to the kernel kunit framework allow us to obtain a
> list of test cases provided by a kunit test module without actually
> running them.  Use that feature to get a list of expected test cases
> before we enter a loop around igt_dynamic().  Once done, enter the
> igt_dynamic() section for each consecutive test case immediately, even
> before first line of a related KTAP report appears, then look for a result
> from that test case.  That should make our IGT results output still better
> synchronized with related kernel messages.
> 
> The list of test cases provided by a kunit test module can be obtained by
> loading the kunit base module with specific options, then loading the test
> module.  For that to be possible, take care of unloading the kunit base
> module before each kunit subtest (I was wrong when in one of my previous
> commit messages I suggested that on final unload of a kunit test module
> the kunit base module is unloaded automatically as its dependency,
> however, that didn't matter before, then no separate fix was required).
> Since that module can then be left loaded with non-default options if an
> error occurs, unload it explicitly before returning from igt_kunit().
> 
> There are two possible ways of getting a list of test cases: by loading
> the base kunit module with action=list module option, or by filtering
> out all test cases from being executed while asking for SKIP results from
> those filtered out.  Since the latter provides regular KTAP report that we
> can already parse perfectly, use it instead of trying to identify an
> unstructured list of test cases of unknown length submitted by the former.
> 
> If an IGT test that calls igt_kunit() provides a subtest name then use
> that name to filter out potential test cases that don't belong to the
> named test suite from the list.
> 
> To avoid loading any modules if no subtest is going to be executed (e.g.,
> if a nonexistent subtest has been requested), load the kunit modules in
> list mode from inside the igt_subtest_with_dynamic() section.  In order to
> be free to skip the whole subtest on unmet requirements that need to be
> verified after that list has been already populated, clean it up from a
> follow up igt_fixture section.
> 
> Since we may now finish processing of all test cases / dynamic sub-
> subtests before KTAP parsing completes, don't fail if we exit the loop of
> dynamic sub-subtests with -EINPROGRESS error code returned by the parser.
> 
> v3: Preserve backward compatibility with kernels that can't provide
> listings of kunit test cases when kunit core is built as a module.
> v2: Split out changes in handling of modprobe errors and kernel taints to
> separate patches (Kamil),
>   - fix some string duplicates referenced from filtered out test cases not
> freed,
>   - don't check if next result is needed before fetching one, obviously
> true in first dynamic sub-subtest, and we always free last result
> before looping to next sub-subtest,
>   - still break the loop of test cases on unexpected return codes from
> kunit_kmsg_get_result(),
>   - use kunit_results_free() helper,
>   - fix typos (Kamil),
>   - update commit description.
> 
> Signed-off-by: Janusz Krzysztofik 
> Acked-by: Kamil Konieczny  # v2

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_kmod.c | 277 ++---
>  1 file changed, 264 insertions(+), 13 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index 5d85732b08..c20c52d372 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -902,8 +902,9 @@ static void kunit_results_free(struct igt_list_head 
> *results,
>   free(*suite_name);
>  }
>  
> -static void
> -__igt_kunit(struct igt_ktest *tst, const char *name, const char *opts)
> +static void __igt_kunit_legacy(struct igt_ktest *tst,
> +const char *name,
> +const char *opts)
>  {
>   struct modprobe_data modprobe = { tst->kmod, opts, 0, pthread_self(), };
>   char *suite_name = NULL, *case_name = NULL;
> @@ -912,13 +913,7 @@ __igt_kunit(struct igt_ktest *tst, const char *name, 
> const char *opts)
>   pthread_mutexattr_t attr;
>   IGT_LIST_HEAD(results);
>   unsigned long taints;
> - int flags, ret;
> -
> - igt_skip_on_f(tst->kmsg < 0, "Could not open /dev/kmsg\n");
> -
> - igt_skip_on((flags = fcntl(tst->kmsg, F_GETFL, 0), flags < 0));
> - igt_skip_on_f(fcntl(tst->kmsg, F_SETFL, flags & ~O_NONBLOCK) == -1,
> -   "Could not set /dev/kmsg to blocking 

Re: [Intel-gfx] [PATCH i-g-t v3 05/11] lib/kunit: Parse KTAP report from the main process thread

2023-10-20 Thread Kamil Konieczny
Hi Janusz,
On 2023-10-11 at 16:17:40 +0200, Janusz Krzysztofik wrote:
> There was an attempt to parse KTAP reports in the background while a kunit
> test module is loading.  However, since dynamic sub-subtests can be
> executed only from the main thread, that attempt was not quite successful,
> as IGT results from all executed kunit test cases were generated only
> after loading of kunit test module completed.
> 
> Now that the parser maintains its state and we can call it separately for
> each input line of a KTAP report, it is perfectly possible to call the
> parser from the main thread while the module is loading in the background,
> and convert results from kunit test cases immediately to results of IGT
> dynamic sub-subtests by running an igt_dynamic() section for each result
> as soon as returned by the parser.
> 
> Drop igt_ktap_parser() thread and execute igt_dynamic() for each kunit
> result obtained from igt_ktap_parse() called from the main thread.
> 
> Also, drop no longer needed functions from igt_ktap soruces.
> 
> v4: Print debug message on pthread_kill() error once per loop (Mauro),
>   - move "parent" field of the structure near other pthread_* type fields
> (Kamil),
>   - drop unneeded explicit return from noop void function (Kamil),
>   - if (!err) looks strange, add a comment (Kamil),
>   - preserve a link to KTAP standard in a comment above the winning
> implementation of KTAP parser (Kamil).
> v3: Fix ktap structure not freed on lseek error,
>   - fix initial SIGCHLD handler not restored,
>   - fix missing handling of potential errors returned by sigaction,
>   - fix potential race of read() vs. ptherad_kill(), use robust mutex for
> synchronization with modprobe thread,
>   - fix potentially illegal use of igt_assert() called outside of
> dynamic sub-subtest section,
>   - fix unsupported exit code potentially passed to igt_fail(),
>   - no need to fail a dynamic sub-subtest on potential KTAP parser error
> after a valid result from the parser has been processed,
>   - fix trailing newlines missing from error messages,
>   - add more debug statements,
>   - integrate common code around kunit_result_free() into it.
> v2: Interrupt blocking read() on modprobe failure.
> 
> Signed-off-by: Janusz Krzysztofik 
> Acked-by: Mauro Carvalho Chehab  # v2

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_kmod.c | 264 +++
>  lib/igt_ktap.c | 569 +
>  lib/igt_ktap.h |  22 --
>  3 files changed, 226 insertions(+), 629 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index 426ae5b26f..93d9479219 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright © 2016 Intel Corporation
> + * Copyright © 2016-2023 Intel Corporation
>   *
>   * Permission is hereby granted, free of charge, to any person obtaining a
>   * copy of this software and associated documentation files (the "Software"),
> @@ -26,7 +26,12 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
>  #include 
> +#include 
> +
> +#include "assembler/brw_compat.h"/* [un]likely() */
>  
>  #include "igt_aux.h"
>  #include "igt_core.h"
> @@ -751,6 +756,9 @@ struct modprobe_data {
>   struct kmod_module *kmod;
>   const char *opts;
>   int err;
> + pthread_t parent;
> + pthread_mutex_t lock;
> + pthread_t thread;
>  };
>  
>  static void *modprobe_task(void *arg)
> @@ -759,16 +767,135 @@ static void *modprobe_task(void *arg)
>  
>   data->err = modprobe(data->kmod, data->opts);
>  
> + if (igt_debug_on(data->err)) {
> + bool once = false;
> + int err;
> +
> + while (err = pthread_mutex_trylock(>lock),
> +err && !igt_debug_on(err != EBUSY)) {
> + igt_debug_on(pthread_kill(data->parent, SIGCHLD) &&
> +  !once);
> + once = true;
> + }
> + } else {
> + /* let main thread use mutex to detect modprobe completion */
> + igt_debug_on(pthread_mutex_lock(>lock));
> + }
> +
>   return NULL;
>  }
>  
> +static void kunit_sigchld_handler(int signal)
> +{
> +}
> +
> +static int kunit_kmsg_result_get(struct igt_list_head *results,
> +  struct modprobe_data *modprobe,
> +  int fd, struct igt_ktap_results *ktap)
> +{
> + struct sigaction sigchld = { .sa_handler = kunit_sigchld_handler, },
> +   

Re: [Intel-gfx] [PATCH i-g-t v3 01/11] lib/ktap: Improve TODO workaround description

2023-10-12 Thread Kamil Konieczny
Hi Janusz,
On 2023-10-11 at 16:17:36 +0200, Janusz Krzysztofik wrote:
> A workaround was implemented in IGT KTAP parser so it could accepted KTAP
> reports with missing top level KTAP version and test suite plan headers.
> While the issue has been fixed by a kernel side commit c95e7c05c139
> ("kunit: Report the count of test suites in a module"), included in the
> mainline kernel since v6.6-rc1, we still need to keep that workaround in
> place to preserve IGT compatibility with LTS kernel version 6.1 as long as
> it is used by major Linux distributions.
> 
> Update the comment with a reference to the kernel side fix and a
> clarification on why we need to keep the workaround in place.
> 
> Signed-off-by: Janusz Krzysztofik 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_ktap.c | 13 ++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/lib/igt_ktap.c b/lib/igt_ktap.c
> index 5eac102417..3df4d6950d 100644
> --- a/lib/igt_ktap.c
> +++ b/lib/igt_ktap.c
> @@ -91,9 +91,16 @@ int igt_ktap_parse(const char *buf, struct 
> igt_ktap_results *ktap)
>  "%*1[ ]%*1[ ]%*1[ ]%*1[ ]KTAP%*[ 
> ]version%*[ ]%u %n",
>  , ) == 1 && len == strlen(buf))) {
>   /*
> -  * TODO: drop the following workaround as soon as
> -  * kernel side issue of missing lines with top level
> -  * KTAP version and test suite plan is fixed.
> +  * TODO: drop the following workaround, which addresses a kernel
> +  * side issue of missing lines that provide top level KTAP
> +  * version and test suite plan, as soon as no longer needed.
> +  *
> +  * The issue has been fixed in v6.6-rc1, commit c95e7c05c139
> +  * ("kunit: Report the count of test suites in a module"),
> +  * but we still need this workaround for as long as LTS kernel
> +  * version 6.1, with DRM selftests already converted to Kunit,
> +  * but without that missing Kunit headers issue fixed, is used
> +  * by major Linux distributions.
>*/
>   if (ktap->expect == KTAP_START) {
>   ktap->suite_count = 1;
> -- 
> 2.42.0
> 


Re: [Intel-gfx] [PATCH i-g-t v2 04/11] lib/kunit: Parse KTAP report from the main process thread

2023-10-11 Thread Kamil Konieczny
Hi Janusz,
On 2023-10-10 at 19:49:35 +0200, Janusz Krzysztofik wrote:
> Hi Kamil,
> 
> Thanks for review.
> 
> On Tuesday, 10 October 2023 17:59:56 CEST Kamil Konieczny wrote:
> > Hi Janusz,
> > On 2023-10-09 at 14:27:55 +0200, Janusz Krzysztofik wrote:
> > > There was an attempt to parse KTAP reports in the background while a kunit
> > > test module is loading.  However, since dynamic sub-subtests can be
> > > executed only from the main thread, that attempt was not quite successful,
> > > as IGT results from all executed kunit test cases were generated only
> > > after loading of kunit test module completed.
> > > 
> > > Now that the parser maintains its state and we can call it separately for
> > > each input line of a KTAP report, it is perfectly possible to call the
> > > parser from the main thread while the module is loading in the background,
> > > and convert results from kunit test cases immediately to results of IGT
> > > dynamic sub-subtests by running an igt_dynamic() section for each result
> > > as soon as returned by the parser.
> > > 
> > > Drop igt_ktap_parser() thread and execute igt_dynamic() for each kunit
> > > result obtained from igt_ktap_parse() called from the main thread.
> > > 
> > > Also, drop no longer needed functions from igt_ktap soruces.
> > > 
> > > v3: Fix ktap structure not freed on lseek error,
> > >   - fix initial SIGCHLD handler not restored,
> > >   - fix missing handling of potential errors returned by sigaction,
> > >   - fix potential race of read() vs. ptherad_kill(), use robust mutex for
> > > synchronization with modprobe thread,
> > >   - fix potentially illegal use of igt_assert() called outside of
> > > dynamic sub-subtest section,
> > >   - fix unsupported exit code potentially passed to igt_fail(),
> > >   - no need to fail a dynamic sub-subtest on potential KTAP parser error
> > > after a valid result from the parser has been processed,
> > >   - fix trailing newlines missing from error messages,
> > >   - add more debug statements,
> > >   - integrate common code around kunit_result_free() into it.
> > > v2: Interrupt blocking read() on modprobe failure.
> > > 
> > > Signed-off-by: Janusz Krzysztofik 
> > > Acked-by: Mauro Carvalho Chehab  # v2
> > > ---
> > >  lib/igt_kmod.c | 261 +++
> > >  lib/igt_ktap.c | 568 -
> > >  lib/igt_ktap.h |  22 --
> > >  3 files changed, 222 insertions(+), 629 deletions(-)
> > > 
> > > diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> > > index 426ae5b26f..7bca4cdaab 100644
> > > --- a/lib/igt_kmod.c
> > > +++ b/lib/igt_kmod.c
> > > @@ -1,5 +1,5 @@
> > >  /*
> > > - * Copyright © 2016 Intel Corporation
> > > + * Copyright © 2016-2023 Intel Corporation
> > >   *
> > >   * Permission is hereby granted, free of charge, to any person obtaining 
> > > a
> > >   * copy of this software and associated documentation files (the 
> > > "Software"),
> > > @@ -26,7 +26,12 @@
> > >  #include 
> > >  #include 
> > >  #include 
> > > +#include 
> > > +#include 
> > >  #include 
> > > +#include 
> > > +
> > > +#include "assembler/brw_compat.h"/* [un]likely() */
> >  ^
> > Do we really need this?
> 
> I think the correct question is if wee really need [un]likely().  I'm using 
> it 
> to document unlikely cases, which is a widely accepted method of documenting 
> cases like that, I believe.  Having that clarified, I hope you just tell me 
> if 
> you think we need those cases documented, and how, if not that way.
> 

Now I see, it is for unlikely() - ok it can stay.

> > 
> > >  
> > >  #include "igt_aux.h"
> > >  #include "igt_core.h"
> > > @@ -748,9 +753,12 @@ void igt_kselftest_get_tests(struct kmod_module 
> > > *kmod,
> > >  }
> > >  
> > >  struct modprobe_data {
> > > + pthread_t parent;
> > --- 
> > Please move it below to other related thread data.
> > Also consider a comment why(or for what purpose)
> > did you put this here.
> 
> No problem to move it to the bottom, if that's important to you, but 
> regarding 
> the comment, do you think that the purpose of this field of the structure, 
> compared to other fields, i

Re: [Intel-gfx] [PATCH i-g-t 3/4] tools/intel_gpu_top: Optimise interactive display a bit

2023-10-11 Thread Kamil Konieczny
Hi Tvrtko,
On 2023-10-11 at 09:38:44 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Padding the percentage bars and table columns with spaces happens quite a
> lot so lets do better than putchar at a time. Have a table of visually
> empty strings and build the required length out of those chunks.
> 
> While at it, also move the percentage bar table into its function scope.
> 
> v2:
>  * Fix checkpatch and use ARRAY_SIZE. (Kamil)
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Kamil Konieczny 

Reviewed-by: Kamil Konieczny 

> ---
>  tools/intel_gpu_top.c | 38 +-
>  1 file changed, 33 insertions(+), 5 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index b6d1014f00b8..006879c4ae67 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -926,14 +926,39 @@ static void free_display_clients(struct igt_drm_clients 
> *clients)
>   free(clients);
>  }
>  
> -static const char *bars[] = { " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█" };
> -
>  static int n_spaces(const int n)
>  {
> - int i;
> + static const char *spaces[] = {
> + " ",
> + "  ",
> + "   ",
> + "",
> + " ",
> + "  ",
> + "   ",
> + "",
> + " ",
> + "  ",
> + "   ",
> + "",
> + " ",
> + "  ",
> + "   ",
> + "",
> + " ",
> + "  ",
> + "   ",
> + };
> + int i, r = n;
>  
> - for (i = 0; i < n; i++)
> - putchar(' ');
> + while (r) {
> + if (r > ARRAY_SIZE(spaces))
> + i = ARRAY_SIZE(spaces) - 1;
> + else
> + i = r - 1;
> + fputs(spaces[i], stdout);
> + r -= i + 1;
> + }
>  
>   return n;
>  }
> @@ -941,6 +966,9 @@ static int n_spaces(const int n)
>  static void
>  print_percentage_bar(double percent, double max, int max_len, bool numeric)
>  {
> + static const char *bars[] = {
> + " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█"
> + };
>   int bar_len, i, len = max_len - 2;
>   const int w = 8;
>  
> -- 
> 2.39.2
> 


Re: [Intel-gfx] [PATCH i-g-t 4/4] tools/intel_gpu_top: Handle narrow terminals more gracefully

2023-10-10 Thread Kamil Konieczny
Hi Tvrtko,
On 2023-10-10 at 12:07:14 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Instead of asserting just skip trying to print columns when terminal is
> too narrow.
> 
> At the same time fix some type confusion to fix calculations going huge.
> 
> Signed-off-by: Tvrtko Ursulin 
> Closes: https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/issues/143

Did you tested this in screensaver? I mean running intel_gpu_top
in terminal windows under X (Gnome or other) and leaving desktop
unattanded, entering screen saver mode (possible with screen
turned off) and then re-enabling screen?

> ---
>  tools/intel_gpu_top.c | 12 +++-
>  1 file changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index 472ce3f13ba9..6d1397cb8214 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -926,7 +926,7 @@ static void free_display_clients(struct igt_drm_clients 
> *clients)
>   free(clients);
>  }
>  
> -static unsigned int n_spaces(const unsigned int n)
> +static int n_spaces(const int n)
- ^^^
Could you make it int at your first patch touching this function?

With or without this suggestion,
Reviewed-by: Kamil Konieczny 

Regards,
Kamil

>  {
>   static const char *spaces[] = {
>   " ",
> @@ -950,7 +950,7 @@ static unsigned int n_spaces(const unsigned int n)
>   "   ",
>  #define MAX_SPACES 19
>   };
> - unsigned int i, r = n;
> + int i, r = n;
>  
>   while (r) {
>   if (r > MAX_SPACES)
> @@ -972,7 +972,8 @@ print_percentage_bar(double percent, double max, int 
> max_len, bool numeric)
>   int bar_len, i, len = max_len - 2;
>   const int w = 8;
>  
> - assert(max_len > 0);
> + if (len < 2) /* For edge lines '|' */
> + return;
>  
>   bar_len = ceil(w * percent * len / max);
>   if (bar_len > w * len)
> @@ -986,6 +987,8 @@ print_percentage_bar(double percent, double max, int 
> max_len, bool numeric)
>   printf("%s", bars[i]);
>  
>   len -= (bar_len + (w - 1)) / w;
> + if (len < 1)
> + return;
>   n_spaces(len);
>  
>   putchar('|');
> @@ -2001,8 +2004,7 @@ print_clients_header(struct igt_drm_clients *clients, 
> int lines,
>4 : clients->max_name_len; /* At least "NAME" 
> */
>  
>   if (output_mode == INTERACTIVE) {
> - unsigned int num_active = 0;
> - int len;
> + int len, num_active = 0;
>  
>   if (lines++ >= con_h)
>   return lines;
> -- 
> 2.39.2
> 


Re: [Intel-gfx] [PATCH i-g-t 3/4] tools/intel_gpu_top: Optimise interactive display a bit

2023-10-10 Thread Kamil Konieczny
Hi Tvrtko,
On 2023-10-10 at 12:07:13 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Padding the percentage bars and table columns with spaces happens quite a
> lot so lets do better than putchar at a time. Have a table of visually
> empty strings and build the required length out of those chunks.
> 
> While at it, also move the percentage bar table into its function scope.
> 
> Signed-off-by: Tvrtko Ursulin 
> ---
>  tools/intel_gpu_top.c | 38 +-
>  1 file changed, 33 insertions(+), 5 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index c5abd0c92155..472ce3f13ba9 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -926,14 +926,40 @@ static void free_display_clients(struct igt_drm_clients 
> *clients)
>   free(clients);
>  }
>  
> -static const char *bars[] = { " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█" };
> -
>  static unsigned int n_spaces(const unsigned int n)
>  {
> - unsigned int i;
> + static const char *spaces[] = {
> + " ",
> + "  ",
> + "   ",
> + "",
> + " ",
> + "  ",
> + "   ",
> + "",
> + " ",
> + "  ",
> + "   ",
> + "",
> + " ",
> + "  ",
> + "   ",
> + "",
> + " ",
> + "  ",
> + "   ",
> +#define MAX_SPACES 19

imho better sizeof(spaces)

> + };
> + unsigned int i, r = n;
>  
> - for (i = 0; i < n; i++)
> - putchar(' ');
> + while (r) {
> + if (r > MAX_SPACES)
> + i = MAX_SPACES - 1;
> + else
> + i = r - 1;
> + fputs(spaces[i], stdout);
> + r -= i + 1;
> + }
>  
>   return n;
>  }
> @@ -941,6 +967,8 @@ static unsigned int n_spaces(const unsigned int n)
>  static void
>  print_percentage_bar(double percent, double max, int max_len, bool numeric)
>  {
> + static const char *bars[] =
> + { " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█" };

Please write it in one line or start with '= {' as checkpatch.pl
is complaining here.

Regards,
Kamil

>   int bar_len, i, len = max_len - 2;
>   const int w = 8;
>  
> -- 
> 2.39.2
> 


Re: [Intel-gfx] [igt-dev] [PATCH i-g-t 2/4] tools/intel_gpu_top: Fix client layout on first sample period

2023-10-10 Thread Kamil Konieczny
Hi Tvrtko,
On 2023-10-10 at 12:07:12 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> When I moved the client name to be last, I did not account for the fact
> current code skips showing engine utilisation until at least two sampling
> periods have passed. Consequence of this is that client name gets printed
> as the second field and not under the "NAME" column header.
> 
> Fix it by emitting spaces instead of engine utilisation until two samples
> have been collected.
> 
> Signed-off-by: Tvrtko Ursulin 

Reviewed-by: Kamil Konieczny 

> ---
>  tools/intel_gpu_top.c | 13 +
>  1 file changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index 60fe06917531..c5abd0c92155 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -928,12 +928,14 @@ static void free_display_clients(struct igt_drm_clients 
> *clients)
>  
>  static const char *bars[] = { " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█" };
>  
> -static void n_spaces(const unsigned int n)
> +static unsigned int n_spaces(const unsigned int n)
>  {
>   unsigned int i;
>  
>   for (i = 0; i < n; i++)
>   putchar(' ');
> +
> + return n;
>  }
>  
>  static void
> @@ -2043,14 +2045,17 @@ print_client(struct igt_drm_client *c, struct engines 
> *engines, double t, int li
>  
>   len = printf("%*s ", clients->max_pid_len, c->pid_str);
>  
> - for (i = 0;
> -  c->samples > 1 && i <= iclients->classes.max_engine_id;
> -  i++) {
> + for (i = 0; i <= iclients->classes.max_engine_id; i++) {
>   double pct, max;
>  
>   if (!iclients->classes.capacity[i])
>   continue;
>  
> + if (c->samples < 2) {
> + len += n_spaces(*class_w);
> + continue;
> + }
> +
>   pct = (double)c->val[i] / period_us / 1e3 * 100;
>  
>   /*
> -- 
> 2.39.2
> 


Re: [Intel-gfx] [PATCH i-g-t 1/4] tools/intel_gpu_top: Fix clients header width when no clients

2023-10-10 Thread Kamil Konieczny
Hi Tvrtko,
On 2023-10-10 at 12:07:11 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Recent refactoring broke the clients header in cases when there are no
> clients displayed. To fix it we need to account the width of the "NAME"
> label.
> 
> Signed-off-by: Tvrtko Ursulin 

Reviewed-by: Kamil Konieczny 

> ---
>  tools/intel_gpu_top.c | 7 ---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index 10601e66b18e..60fe06917531 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -1967,6 +1967,8 @@ print_clients_header(struct igt_drm_clients *clients, 
> int lines,
>int con_w, int con_h, int *class_w)
>  {
>   struct intel_clients *iclients = clients->private_data;
> + const int max_name_len = clients->max_name_len < 4 ?
> +  4 : clients->max_name_len; /* At least "NAME" 
> */
>  
>   if (output_mode == INTERACTIVE) {
>   unsigned int num_active = 0;
> @@ -1990,9 +1992,8 @@ print_clients_header(struct igt_drm_clients *clients, 
> int lines,
>   num_active++;
>   }
>  
> - *class_w = width =
> - (con_w - len - clients->max_name_len - 1) /
> - num_active;
> + *class_w = width = (con_w - len - max_name_len - 1) /
> +num_active;
>  
>   for (i = 0; i <= iclients->classes.max_engine_id; i++) {
>   const char *name = iclients->classes.names[i];
> -- 
> 2.39.2
> 


Re: [Intel-gfx] [PATCH i-g-t v2 04/11] lib/kunit: Parse KTAP report from the main process thread

2023-10-10 Thread Kamil Konieczny
Hi Janusz,
On 2023-10-09 at 14:27:55 +0200, Janusz Krzysztofik wrote:
> There was an attempt to parse KTAP reports in the background while a kunit
> test module is loading.  However, since dynamic sub-subtests can be
> executed only from the main thread, that attempt was not quite successful,
> as IGT results from all executed kunit test cases were generated only
> after loading of kunit test module completed.
> 
> Now that the parser maintains its state and we can call it separately for
> each input line of a KTAP report, it is perfectly possible to call the
> parser from the main thread while the module is loading in the background,
> and convert results from kunit test cases immediately to results of IGT
> dynamic sub-subtests by running an igt_dynamic() section for each result
> as soon as returned by the parser.
> 
> Drop igt_ktap_parser() thread and execute igt_dynamic() for each kunit
> result obtained from igt_ktap_parse() called from the main thread.
> 
> Also, drop no longer needed functions from igt_ktap soruces.
> 
> v3: Fix ktap structure not freed on lseek error,
>   - fix initial SIGCHLD handler not restored,
>   - fix missing handling of potential errors returned by sigaction,
>   - fix potential race of read() vs. ptherad_kill(), use robust mutex for
> synchronization with modprobe thread,
>   - fix potentially illegal use of igt_assert() called outside of
> dynamic sub-subtest section,
>   - fix unsupported exit code potentially passed to igt_fail(),
>   - no need to fail a dynamic sub-subtest on potential KTAP parser error
> after a valid result from the parser has been processed,
>   - fix trailing newlines missing from error messages,
>   - add more debug statements,
>   - integrate common code around kunit_result_free() into it.
> v2: Interrupt blocking read() on modprobe failure.
> 
> Signed-off-by: Janusz Krzysztofik 
> Acked-by: Mauro Carvalho Chehab  # v2
> ---
>  lib/igt_kmod.c | 261 +++
>  lib/igt_ktap.c | 568 -
>  lib/igt_ktap.h |  22 --
>  3 files changed, 222 insertions(+), 629 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index 426ae5b26f..7bca4cdaab 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright © 2016 Intel Corporation
> + * Copyright © 2016-2023 Intel Corporation
>   *
>   * Permission is hereby granted, free of charge, to any person obtaining a
>   * copy of this software and associated documentation files (the "Software"),
> @@ -26,7 +26,12 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
>  #include 
> +#include 
> +
> +#include "assembler/brw_compat.h"/* [un]likely() */
 ^
Do we really need this?

>  
>  #include "igt_aux.h"
>  #include "igt_core.h"
> @@ -748,9 +753,12 @@ void igt_kselftest_get_tests(struct kmod_module *kmod,
>  }
>  
>  struct modprobe_data {
> + pthread_t parent;
--- 
Please move it below to other related thread data.
Also consider a comment why(or for what purpose)
did you put this here.

>   struct kmod_module *kmod;
>   const char *opts;
>   int err;
> + pthread_mutex_t lock;
> + pthread_t thread;
>  };
>  
>  static void *modprobe_task(void *arg)
> @@ -759,16 +767,132 @@ static void *modprobe_task(void *arg)
>  
>   data->err = modprobe(data->kmod, data->opts);
>  
> + if (igt_debug_on(data->err)) {
> + int err;
> +
> + while (err = pthread_mutex_trylock(>lock),
> +err && !igt_debug_on(err != EBUSY))
> + igt_debug_on(pthread_kill(data->parent, SIGCHLD));
> + } else {
> + /* let main thread use mutex to detect modprobe completion */
> + igt_debug_on(pthread_mutex_lock(>lock));
> + }
> +
>   return NULL;
>  }
>  
> +static void kunit_sigchld_handler(int signal)
> +{
> + return;
--- ^^^
Why not removing this? checkpatch complains about return from void.

> +}
> +
> +static int kunit_kmsg_result_get(struct igt_list_head *results,
> +  struct modprobe_data *modprobe,
> +  int fd, struct igt_ktap_results *ktap)
> +{
> + struct sigaction sigchld = { .sa_handler = kunit_sigchld_handler, },
> +  *saved;
> + char record[BUF_LEN + 1], *buf;
> + unsigned long taints;
> + int ret;
> +
> + do {
> + int err;
> +
> + if (igt_debug_on(igt_kernel_tainted()))
> + return -ENOTRECOVERABLE;
> +
> + err = igt_debug_on(sigaction(SIGCHLD, , saved));
> + if (err == -1)
> + return -errno;
> + else if (unlikely(err))
> + return err;
> +
> + err = pthread_mutex_lock(>lock);
> + switch (err) {
> + case EOWNERDEAD:
> + /* leave the mutex unrecoverable */
> +  

Re: [Intel-gfx] [PATCH i-g-t v2 10/11] lib/kunit: Fetch a list of test cases in advance

2023-10-09 Thread Kamil Konieczny
k);
> +
> + while (igt_debug_on_f(strcmp(r->suite_name, 
> t->suite_name),
> +   "suite_name expected: %s, got: 
> %s\n",
> +   t->suite_name, r->suite_name) ||
> +igt_debug_on_f(strcmp(r->case_name, 
> t->case_name),
> +   "case_name expected: %s, got: 
> %s\n",
> +   t->case_name, r->case_name) ||
> +r->code == IGT_EXIT_INVALID) {
> +
> + int code = r->code;
> +
> + kunit_result_free(, _name, _name);
> + if (igt_list_empty()) {
> + igt_assert_eq(ret, -EINPROGRESS);
> + ret = kunit_kmsg_result_get(,
> + ,
> + tst->kmsg,
> + ktap);
> + igt_fail_on(igt_list_empty());
> + }
>  
>   r = igt_list_first_entry(, r, link);
>  
> + if (code != IGT_EXIT_INVALID)
> + continue;
> +
> + /* result from parametrized test case */
>   igt_fail_on_f(strcmp(r->suite_name, suite_name),
> "suite_name expected: %s, got: 
> %s\n",
> suite_name, r->suite_name);
> @@ -1009,7 +1081,9 @@ __igt_kunit(struct igt_ktest *tst, const char *name, 
> const char *opts)
>  
>   kunit_result_free(, _name, _name);
>  
> - } while (ret == -EINPROGRESS);
> + if (igt_debug_on(ret != -EINPROGRESS))
> + break;
> + }
>  
>   kunit_results_free(, _name, _name);
>  
> @@ -1035,7 +1109,8 @@ __igt_kunit(struct igt_ktest *tst, const char *name, 
> const char *opts)
>  
>   igt_skip_on(modprobe.err);
>   igt_skip_on(igt_kernel_tainted());
> - igt_skip_on_f(ret, "KTAP parser failed\n");
> + if (ret != -EINPROGRESS)
> + igt_skip_on_f(ret, "KTAP parser failed\n");
>  }
>  
>  /**
> @@ -1049,7 +1124,8 @@ __igt_kunit(struct igt_ktest *tst, const char *name, 
> const char *opts)
>  void igt_kunit(const char *module_name, const char *name, const char *opts)
>  {
>   struct igt_ktest tst = { .kmsg = -1, };
> -
> + const char *filter = name;
> + IGT_LIST_HEAD(tests);
>  
>   /*
>* If the caller (an IGT test) provides no subtest name then we
> @@ -1074,6 +1150,15 @@ void igt_kunit(const char *module_name, const char 
> *name, const char *opts)
>  
>   igt_skip_on(igt_ktest_init(, module_name));
>   igt_skip_on(igt_ktest_begin());
> +
> + /*
> +  * Since we need to load kunit base module with specific
> +  * options in order to get a list of test cases, make
> +  * sure that the module is not loaded.  However, since
- ^^
Same here.

Acked-by: Kamil Konieczny 

> +  * unload may fail if kunit base module is not loaded,
> +  * ignore any failures, we'll fail later if still loaded.
> +  */
> + igt_ignore_warn(igt_kmod_unload("kunit", KMOD_REMOVE_FORCE));
>   }
>  
>   /*
> @@ -1083,11 +1168,21 @@ void igt_kunit(const char *module_name, const char 
> *name, const char *opts)
>* proper namespace for dynamic subtests, with is required for CI
>* and for documentation.
>*/
> - igt_subtest_with_dynamic(name)
> - __igt_kunit(, name, opts);
> + igt_subtest_with_dynamic(name) {
> + kunit_get_tests(, , filter, opts);
> + igt_skip_on(igt_list_empty());
> +
> + __igt_kunit(, name, opts, );
> + }
> +
> + igt_fixture {
> + char *suite_name = NULL, *case_name = NULL;
> +
> + kunit_results_free(, _name, _name);
>  
> - igt_fixture
>   igt_ktest_end();
> + igt_debug_on(igt_kmod_unload("kunit", KMOD_REMOVE_FORCE));
> + }
>  
>   igt_ktest_fini();
>  }
> -- 
> 2.42.0
> 


Re: [Intel-gfx] [PATCH i-g-t v2 09/11] lib/kunit: Prepare for KTAP parsing after modprobe completed

2023-10-09 Thread Kamil Konieczny
Hi Janusz,
On 2023-10-09 at 14:28:00 +0200, Janusz Krzysztofik wrote:
> We are going to add support for reading a list of kunit test cases
> provided by a kunit test module prior to executing those test cases.  That
- ^^
Two spaces, use only one.

> will be done by first loading kunit modules in list only mode, then
> reading the list from /dev/kmsg with our KTAP parser.  Since that parsing
---^^
Same here.

> will be performed after the kunit test module is successfully loaded and
> there will be no concurrently running modprobe thread, we need to make
> synchronization of reads from /dev/kmsg with potential errors modprobe
> thread optional.
> 
> Signed-off-by: Janusz Krzysztofik 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_kmod.c | 50 ++
>  1 file changed, 26 insertions(+), 24 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index fed0855c84..ed41aa1235 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -802,34 +802,36 @@ static int kunit_kmsg_result_get(struct igt_list_head 
> *results,
>   if (igt_debug_on(igt_kernel_tainted()))
>   return -ENOTRECOVERABLE;
>  
> - err = igt_debug_on(sigaction(SIGCHLD, , saved));
> - if (err == -1)
> - return -errno;
> - else if (unlikely(err))
> - return err;
> -
> - err = pthread_mutex_lock(>lock);
> - switch (err) {
> - case EOWNERDEAD:
> - /* leave the mutex unrecoverable */
> - igt_debug_on(pthread_mutex_unlock(>lock));
> - __attribute__ ((fallthrough));
> - case ENOTRECOVERABLE:
> - igt_debug_on(sigaction(SIGCHLD, saved, NULL));
> - if (igt_debug_on(modprobe->err))
> - return modprobe->err;
> - break;
> - case 0:
> - break;
> - default:
> - igt_debug("pthread_mutex_lock() error: %d\n", err);
> - igt_debug_on(sigaction(SIGCHLD, saved, NULL));
> - return -err;
> + if (modprobe) {
> + err = igt_debug_on(sigaction(SIGCHLD, , saved));
> + if (err == -1)
> + return -errno;
> + else if (unlikely(err))
> + return err;
> +
> + err = pthread_mutex_lock(>lock);
> + switch (err) {
> + case EOWNERDEAD:
> + /* leave the mutex unrecoverable */
> + 
> igt_debug_on(pthread_mutex_unlock(>lock));
> + __attribute__ ((fallthrough));
> + case ENOTRECOVERABLE:
> + igt_debug_on(sigaction(SIGCHLD, saved, NULL));
> + if (igt_debug_on(modprobe->err))
> + return modprobe->err;
> + break;
> + case 0:
> + break;
> + default:
> + igt_debug("pthread_mutex_lock() error: %d\n", 
> err);
> + igt_debug_on(sigaction(SIGCHLD, saved, NULL));
> + return -err;
> + }
>   }
>  
>   ret = read(fd, record, BUF_LEN);
>  
> - if (!err) {
> + if (modprobe && !err) {
>   igt_debug_on(pthread_mutex_unlock(>lock));
>   igt_debug_on(sigaction(SIGCHLD, saved, NULL));
>   }
> -- 
> 2.42.0
> 


Re: [Intel-gfx] [PATCH i-g-t v2 08/11] lib/kunit: Provide all results cleanup helper

2023-10-09 Thread Kamil Konieczny
Hi Janusz,
On 2023-10-09 at 14:27:59 +0200, Janusz Krzysztofik wrote:
> Planned changes require a couple of loops around kunit_result_free().
> Since we already have such loop, move it into a helper in preparation for
> future uses.
> 
> Signed-off-by: Janusz Krzysztofik 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_kmod.c | 20 ++--
>  1 file changed, 14 insertions(+), 6 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index 387efbb59f..fed0855c84 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -885,13 +885,25 @@ static void kunit_result_free(struct igt_ktap_result 
> **r,
>   *r = NULL;
>  }
>  
> +static void kunit_results_free(struct igt_list_head *results,
> +char **suite_name, char **case_name)
> +{
> + struct igt_ktap_result *r, *rn;
> +
> + igt_list_for_each_entry_safe(r, rn, results, link)
> + kunit_result_free(, suite_name, case_name);
> +
> + free(*case_name);
> + free(*suite_name);
> +}
> +
>  static void
>  __igt_kunit(struct igt_ktest *tst, const char *name, const char *opts)
>  {
>   struct modprobe_data modprobe = { pthread_self(), tst->kmod, opts, 0, };
>   char *suite_name = NULL, *case_name = NULL;
> - struct igt_ktap_result *r, *rn;
>   struct igt_ktap_results *ktap;
> + struct igt_ktap_result *r;
>   pthread_mutexattr_t attr;
>   IGT_LIST_HEAD(results);
>   unsigned long taints;
> @@ -997,11 +1009,7 @@ __igt_kunit(struct igt_ktest *tst, const char *name, 
> const char *opts)
>  
>   } while (ret == -EINPROGRESS);
>  
> - igt_list_for_each_entry_safe(r, rn, , link)
> - kunit_result_free(, _name, _name);
> -
> - free(case_name);
> - free(suite_name);
> + kunit_results_free(, _name, _name);
>  
>   switch (pthread_mutex_lock()) {
>   case 0:
> -- 
> 2.42.0
> 


Re: [Intel-gfx] [PATCH i-g-t v2 11/11] lib/kunit: Execute kunit test cases only when needed

2023-10-09 Thread Kamil Konieczny
Hi Janusz,
On 2023-10-09 at 14:28:02 +0200, Janusz Krzysztofik wrote:
> IGT user interface allows to request execution of only those dynamic sub-
> subtests that match a user provided name pattern.  If the user pattern
> doesn't match any names of test cases provided by a kunit test module used
> with the subtest to be run then no results from any dynamic sub-subtests
> will be reported.  Since we already know the list of test cases provided
> by the kunit test module, there is no need to load that module to execute
> them unless the user pattern matches at least one of those test cases.
> 
> Don't load the kunit test module in execute mode before entering the loop
> of dynamic sub-subtests, and do that only from the first actually executed
> dynamic sub-subtest.
> 
> v2: Always pass last result to next dynamic sub-subtest, fetch first
> result right after loading the kunit test module for execution.
> 
> Signed-off-by: Janusz Krzysztofik 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_kmod.c | 66 ++
>  1 file changed, 35 insertions(+), 31 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index 150fe49803..69915adc40 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -981,33 +981,37 @@ static void __igt_kunit(struct igt_ktest *tst,
>  
>   igt_skip_on(lseek(tst->kmsg, 0, SEEK_END) < 0);
>  
> - igt_skip_on(pthread_mutexattr_init());
> - igt_skip_on(pthread_mutexattr_setrobust(, PTHREAD_MUTEX_ROBUST));
> - igt_skip_on(pthread_mutex_init(, ));
> -
>   ktap = igt_ktap_alloc();
>   igt_require(ktap);
>  
> - if (igt_debug_on(pthread_create(, NULL,
> - modprobe_task, ))) {
> - igt_ktap_free(ktap);
> - igt_skip("Failed to create a modprobe thread\n");
> - }
> -
>   igt_list_for_each_entry(t, tests, link) {
>   igt_dynamic_f("%s%s%s",
> strcmp(t->suite_name, name) ?  t->suite_name : "",
> strcmp(t->suite_name, name) ? "-" : "",
> t->case_name) {
>  
> - if (igt_list_empty()) {
> + if (!modprobe.thread) {
> + igt_assert_eq(pthread_mutexattr_init(), 0);
> + igt_assert_eq(pthread_mutexattr_setrobust(,
> +   PTHREAD_MUTEX_ROBUST),
> +   0);
> + igt_assert_eq(pthread_mutex_init(,
> +  ), 0);
> +
> + modprobe.err = pthread_create(,
> +   NULL,
> +   modprobe_task,
> +   );
> + igt_assert_eq(modprobe.err, 0);
> +
> + igt_assert(igt_list_empty());
>   igt_assert_eq(ret, -EINPROGRESS);
>   ret = kunit_kmsg_result_get(, ,
>   tst->kmsg, ktap);
>   igt_fail_on(igt_list_empty());
> - }
>  
> - r = igt_list_first_entry(, r, link);
> + r = igt_list_first_entry(, r, link);
> + }
>  
>   while (igt_debug_on_f(strcmp(r->suite_name, 
> t->suite_name),
> "suite_name expected: %s, got: 
> %s\n",
> @@ -1079,30 +1083,30 @@ static void __igt_kunit(struct igt_ktest *tst,
>   igt_assert_eq(igt_kernel_tainted(), 0);
>   }
>  
> - kunit_result_free(, _name, _name);
> -
>   if (igt_debug_on(ret != -EINPROGRESS))
>   break;
>   }
>  
>   kunit_results_free(, _name, _name);
>  
> - switch (pthread_mutex_lock()) {
> - case 0:
> - igt_debug_on(pthread_cancel(modprobe.thread));
> - igt_debug_on(pthread_mutex_unlock());
> - igt_debug_on(pthread_join(modprobe.thread, NULL));
> - break;
> - case EOWNERDEAD:
> - /* leave the mutex unrecoverable */
> - igt_debug_on(pthread_mutex_unlock());
> - break;
> - case ENOTRECOVERABLE:
> - break;
> - default:
> - igt_debug("pthread

Re: [Intel-gfx] [PATCH i-g-t v2 07/11] lib/ktap: Drop workaround for missing top level KTAP headers

2023-10-09 Thread Kamil Konieczny
Hi Janusz,
On 2023-10-09 at 14:27:58 +0200, Janusz Krzysztofik wrote:
> A workaround was implemented in IGT KTAP parser so it could accepted KTAP
> reports with missing top level KTAP version and test suite plan headers.
> Since kernel side commit c95e7c05c139 ("kunit: Report the count of test
> suites in a module"), included in the mainline kernel since v6.6-rc1, has
> fixed that issue, that workaround is no longer needed.  Drop it.
> 
> Signed-off-by: Janusz Krzysztofik 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_ktap.c  | 12 
>  lib/tests/igt_ktap_parser.c |  3 +--
>  2 files changed, 1 insertion(+), 14 deletions(-)
> 
> diff --git a/lib/igt_ktap.c b/lib/igt_ktap.c
> index 53a6c63288..7c52ba11ed 100644
> --- a/lib/igt_ktap.c
> +++ b/lib/igt_ktap.c
> @@ -84,18 +84,6 @@ int igt_ktap_parse(const char *buf, struct 
> igt_ktap_results *ktap)
>  igt_debug_on(sscanf(buf,
>  "%*1[ ]%*1[ ]%*1[ ]%*1[ ]KTAP%*[ 
> ]version%*[ ]%u %n",
>  , ) == 1 && len == strlen(buf))) {
> - /*
> -  * TODO: drop the following workaround as soon as
> -  * kernel side issue of missing lines with top level
> -  * KTAP version and test suite plan is fixed.
> -  */
> - if (ktap->expect == KTAP_START) {
> - ktap->suite_count = 1;
> - ktap->suite_last = 0;
> - ktap->suite_name = NULL;
> - ktap->expect = SUITE_START;
> - }
> -
>   if (igt_debug_on(ktap->expect != SUITE_START))
>   return -EPROTO;
>  
> diff --git a/lib/tests/igt_ktap_parser.c b/lib/tests/igt_ktap_parser.c
> index 6357bdf6a5..476e14092f 100644
> --- a/lib/tests/igt_ktap_parser.c
> +++ b/lib/tests/igt_ktap_parser.c
> @@ -190,8 +190,7 @@ static void ktap_top_version(void)
>  
>   ktap = igt_ktap_alloc();
>   igt_require(ktap);
> - /* TODO: change to -EPROTO as soon as related workaround is dropped */
> - igt_assert_eq(igt_ktap_parse("KTAP version 1\n", ktap), 
> -EINPROGRESS);
> + igt_assert_eq(igt_ktap_parse("KTAP version 1\n", ktap), -EPROTO);
>   igt_ktap_free(ktap);
>  
>   ktap = igt_ktap_alloc();
> -- 
> 2.42.0
> 


Re: [Intel-gfx] [PATCH i-g-t 8/9] lib/kunit: Fetch a list of test cases in advance

2023-10-05 Thread Kamil Konieczny
Hi Janusz,

On 2023-10-03 at 11:10:53 +0200, Janusz Krzysztofik wrote:
> Recent improvements to the kernel kunit framework allow us to obtain a
> list of test cases provided by a kunit test module without actually
> running them.  Use that feature to get a list of expected test cases
> before we enter a loop around igt_dynamic().  Once done, enter the
> igt_dynamic() section for each consecutive test case immediately, even
> before first line of a related KTAP report appears, then look for a result
> from that test case.  That should make our IGT results output still better
> synchronized with related kernel messages.
> 
> The list of test cases provided by a kunit test module can be obtained by
> loading the kunit base module with specific options, then loading the test
> module.  For that to be possible, take care of unloading the kunit base
> module before each kunit subtest (I was wrong when in one of my previous
> commit messages I suggested that on final unload of a kunit test module
> the kunit base module is unloaded automatically as its dependency,
> however, that didn't matter before, then no separate fix was required).
> Since that module can then be left loaded with non-default options if an
> error occurs, unload it explicitly before returning from igt_kunit().
> 
> There are two possible ways of getting a list of test cases: by loading
> the base kunit module with action=list module option, or by filtering
> out all test cases from being executed while asking for SKIP results from
> those filtered out.  Since the latter provides regular KTAP report that we
> can alredy parse perfectly, use it instead of trying to identify an
- ^^
s/alredy/already/

> unstructured list of test cases of unknown length submitted by the former.
> 
> If an IGT test that calls igt_kunit() provides a subtest name then use
> that name to filter out potential test cases that don't belong to the
> named test suite from the list.
> 
> To avoid loading any modules if no subtest is going to be executed (e.g.,
> if a nonexistent subtest has been requested), load the kunit modules in
> list mode from inside the igt_subtest_with_dynamic() section.  In order to
> be free to skip the whole subtest on unmet requirements that need to be
> verified after that list has been already populated, clean it up from a
> follow up igt_fixture section.
> 
> Since we start reading the list of test cases from /dev/kmsg only after
> the kunit test module is loaded successfully in list only mode, don't
> synchronize reads with potential modprobe breakage in that case, unlike we
> still do later when parsing KTAP results in parallel to loading the test
> module in normal (execute) mode.
> 
> Since we neither fetch KTAP results before entering igt_dynamic section
> nor even return an error from KTAP result fetch attempts immediately on
> modprobe error or kernel taint, break the loop of dynamic sub-subtests
> explicitly as soon as one of those conditions is detected.

Could you split this patch into two, one with reading names and rest
with modprobe error or kernel taint detection?

> Also, don't
> force IGT SKIP result from the subtest if KTAP parsing hasn't completed.
> That's perfectly legitimate since we no longer iterate over KTAP results,
> only over a list of test cases obtained in advance, then we stop parsing
> KTAP report as soon as we get a result from the last test case from the
> list.
> 
> Signed-off-by: Janusz Krzysztofik 
> ---
>  lib/igt_kmod.c | 217 +++--
>  1 file changed, 157 insertions(+), 60 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index 387efbb59f..4fba77ead4 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -802,34 +802,36 @@ static int kunit_kmsg_result_get(struct igt_list_head 
> *results,
>   if (igt_debug_on(igt_kernel_tainted()))
>   return -ENOTRECOVERABLE;
>  
> - err = igt_debug_on(sigaction(SIGCHLD, , saved));
> - if (err == -1)
> - return -errno;
> - else if (unlikely(err))
> - return err;
> -
> - err = pthread_mutex_lock(>lock);
> - switch (err) {
> - case EOWNERDEAD:
> - /* leave the mutex unrecoverable */
> - igt_debug_on(pthread_mutex_unlock(>lock));
> - __attribute__ ((fallthrough));
> - case ENOTRECOVERABLE:
> - igt_debug_on(sigaction(SIGCHLD, saved, NULL));
> - if (igt_debug_on(modprobe->err))
> - return modprobe->err;
> - break;
> - case 0:
> - break;
> - default:
> - igt_debug("pthread_mutex_lock() error: %d\n", err);
> - igt_debug_on(sigaction(SIGCHLD, saved, NULL));
> - return -err;
> + if (modprobe) {
> + 

Re: [Intel-gfx] [PATCH i-g-t 6/9] tests/kms_selftest: Let subtest names match suite names

2023-10-05 Thread Kamil Konieczny
Hi Janusz,
On 2023-10-03 at 11:10:51 +0200, Janusz Krzysztofik wrote:
> There is a rule specified in Kunit Test Style and Nomenclature guidelines
> [1] that states modules should be named after the test suite, followed by
> _test.  Of course, that rule applies only to modules that provide one test
> suite per module.
> 
> As long as that rule is obeyed by authors of Kunit test modules, there is
> no need to hardcode related IGT subtest names in IGT source code.  We are
> already able to derive subtest names from module names, with their _test
> or _kunit suffixes stripped.  We may expect those names will match Kunit
> suite names provided by the modules.
> 
> Drop custom subtest names from IGT Kunit tests that still use them.
> However, keep the mechanism that allows us to provide a name that differs
> from that derived from module name.  That will be required if we ever need
> to support a kunit test module that provides multiple test suites (think
> of i915 selftests code converted to kunit and the i915 module potentially
> providing three test suites: mock, live and perf).
> 
> [1] https://docs.kernel.org/dev-tools/kunit/style.html
> 
> Signed-off-by: Janusz Krzysztofik 

Reviewed-by: Kamil Konieczny 

> ---
>  tests/kms_selftest.c | 37 -
>  1 file changed, 16 insertions(+), 21 deletions(-)
> 
> diff --git a/tests/kms_selftest.c b/tests/kms_selftest.c
> index 080ffdf2c0..6618dbe50b 100644
> --- a/tests/kms_selftest.c
> +++ b/tests/kms_selftest.c
> @@ -37,35 +37,30 @@
>   *
>   * arg[1]:
>   *
> - * @drm_cmdline:drm cmdline
> - * @drm_damage: drm damage
> - * @drm_dp_mst: drm dp mst
> + * @drm_cmdline_parser: drm cmdline parser
> + * @drm_damage_helper:  drm damage helper
> + * @drm_dp_mst_helper:  drm dp mst helper
>   * @drm_format_helper:  drm format helper
>   * @drm_format: drm format
> - * @drm_plane:  drm plane
> - * @framebuffer:framebuffer
> + * @drm_plane_helper:   drm plane helper
> + * @drm_framebuffer:drm framebuffer
>   */
>  
>  IGT_TEST_DESCRIPTION("Basic sanity check of KMS selftests.");
>  
> -struct kms_kunittests {
> - const char *kunit;
> - const char *name;
> -};
> -
>  igt_main
>  {
> - static const struct kms_kunittests kunit_subtests[] = {
> - { "drm_cmdline_parser_test","drm_cmdline" },
> - { "drm_damage_helper_test", "drm_damage" },
> - { "drm_dp_mst_helper_test", "drm_dp_mst" },
> - { "drm_format_helper_test", "drm_format_helper" },
> - { "drm_format_test","drm_format" },
> - { "drm_framebuffer_test",   "framebuffer" },
> - { "drm_plane_helper_test",  "drm_plane" },
> - { NULL, NULL}
> + static const char *kunit_subtests[] = {
> + "drm_cmdline_parser_test",
> + "drm_damage_helper_test",
> + "drm_dp_mst_helper_test",
> + "drm_format_helper_test",
> + "drm_format_test",
> + "drm_framebuffer_test",
> + "drm_plane_helper_test",
> + NULL,
>   };
>  
> - for (int i = 0; kunit_subtests[i].kunit != NULL; i++)
> - igt_kunit(kunit_subtests[i].kunit, kunit_subtests[i].name, 
> NULL);
> + for (int i = 0; kunit_subtests[i] != NULL; i++)
> + igt_kunit(kunit_subtests[i], NULL, NULL);
>  }
> -- 
> 2.42.0
> 


Re: [Intel-gfx] [PATCH i-g-t 3/9] lib/kunit: Fix misplaced igt_kunit() doc

2023-10-05 Thread Kamil Konieczny
Hi Janusz,
On 2023-10-03 at 11:10:48 +0200, Janusz Krzysztofik wrote:
> When igt_kunit() was converted to a helper and wrapped with a new function
> promoted to take the name and role of the library API, related
> documentation was left unchanged and still placed in front the demoted
> function.  Update that documentation and move it to where it now belongs.
> 
> Signed-off-by: Janusz Krzysztofik 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_kmod.c | 17 -
>  1 file changed, 8 insertions(+), 9 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index df0e650d49..426ae5b26f 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -762,15 +762,6 @@ static void *modprobe_task(void *arg)
>   return NULL;
>  }
>  
> -/**
> - * igt_kunit:
> - * @module_name: the name of the module
> - * @opts: options to load the module
> - *
> - * Loads the test module, parses its (k)tap dmesg output, then unloads it
> - *
> - * Returns: IGT default codes
> - */
>  static void __igt_kunit(struct igt_ktest *tst, const char *opts)
>  {
>   struct modprobe_data modprobe = { tst->kmod, opts, 0, };
> @@ -849,6 +840,14 @@ static void __igt_kunit(struct igt_ktest *tst, const 
> char *opts)
>   igt_skip_on_f(ret, "KTAP parser failed\n");
>  }
>  
> +/**
> + * igt_kunit:
> + * @module_name: the name of the module
> + * @name: the name of subtest, if different from that derived from module 
> name
> + * @opts: options to load the module
> + *
> + * Loads the test module, parses its (k)tap dmesg output, then unloads it
> + */
>  void igt_kunit(const char *module_name, const char *name, const char *opts)
>  {
>   struct igt_ktest tst = { .kmsg = -1, };
> -- 
> 2.42.0
> 


Re: [Intel-gfx] [PATCH i-g-t 2/9] lib/kunit: Be more verbose on errors

2023-10-05 Thread Kamil Konieczny
Hi Janusz,
On 2023-10-03 at 11:10:47 +0200, Janusz Krzysztofik wrote:
> Use a more verbose variant of igt_fail() when failing a dynamic sub-
> subtest on kernel taint.  Also, print a debug message on string
> duplication failure.
> 
> Signed-off-by: Janusz Krzysztofik 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_kmod.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index 05ff178b27..df0e650d49 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -834,7 +834,7 @@ static void __igt_kunit(struct igt_ktest *tst, const char 
> *opts)
>   if (!pthread_tryjoin_np(modprobe_thread, NULL))
>   igt_assert_eq(modprobe.err, 0);
>  
> - igt_fail_on(igt_kernel_tainted());
> + igt_assert_eq(igt_kernel_tainted(), 0);
>   }
>  
>   free(result);
> @@ -861,7 +861,7 @@ void igt_kunit(const char *module_name, const char *name, 
> const char *opts)
>*/
>   if (!name) {
>   name = strdup(module_name);
> - if (name) {
> + if (!igt_debug_on(!name)) {
>   char *suffix = strstr(name, "_test");
>  
>   if (!suffix)
> -- 
> 2.42.0
> 


Re: [Intel-gfx] [PATCH i-g-t 1/9] lib/kunit: Fix handling of potential errors from F_GETFL

2023-10-05 Thread Kamil Konieczny
Hi Janusz,
On 2023-10-03 at 11:10:46 +0200, Janusz Krzysztofik wrote:
> Function fcntl(..., F_GETFL, ...) that returns file status flags may also
> return a negative error code.  Handle that error instead of blindly using
> the returned value as flags.
> 
> Signed-off-by: Janusz Krzysztofik 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_kmod.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index d98e6c5f9e..05ff178b27 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -783,8 +783,8 @@ static void __igt_kunit(struct igt_ktest *tst, const char 
> *opts)
>  
>   igt_skip_on_f(tst->kmsg < 0, "Could not open /dev/kmsg\n");
>  
> - flags = fcntl(tst->kmsg, F_GETFL, 0) & ~O_NONBLOCK;
> - igt_skip_on_f(fcntl(tst->kmsg, F_SETFL, flags) == -1,
> + igt_skip_on((flags = fcntl(tst->kmsg, F_GETFL, 0), flags < 0));
> + igt_skip_on_f(fcntl(tst->kmsg, F_SETFL, flags & ~O_NONBLOCK) == -1,
> "Could not set /dev/kmsg to blocking mode\n");
>  
>   igt_skip_on(lseek(tst->kmsg, 0, SEEK_END) < 0);
> -- 
> 2.42.0
> 


Re: [Intel-gfx] [PATCH i-g-t] tests/core_hotunplug: Wait for device nodes to re-appear

2023-08-22 Thread Kamil Konieczny
Hi Janusz,

On 2023-08-22 at 09:58:58 +0200, Janusz Krzysztofik wrote:
> Sometimes our health check is not able to find a device node (cardX or
> renderY) after driver rebind or device rediscover.  Since device nodes are
> recreated in detmpvfs asynchronously, give it a bit of time to do its job
> before we try to reopen the device for health check.
> 
> (core_hotunplug:3612) DEBUG: Test requirement passed: priv->fd.drm == -1
> (core_hotunplug:3612) DEBUG: reopening DRM device for health check
> (core_hotunplug:3612) drmtest-DEBUG: Looking for devices to open using filter 
> 0: 
> sys:/sys/devices/pci:4a/:4a:02.0/:4b:00.0/:4c:01.0/:4d:00.0
> (core_hotunplug:3612) drmtest-DEBUG: Filter matched /dev/dri/card1 | 
> /dev/dri/renderD128
> (core_hotunplug:3612) drmtest-DEBUG: Opened previously opened device: 
> /dev/dri/card1
> (core_hotunplug:3612) DEBUG: running device sysfs healthcheck
> (core_hotunplug:3612) DEBUG: closing health checked device instance
> (core_hotunplug:3612) DEBUG: reopening render device for health check
> (core_hotunplug:3612) drmtest-DEBUG: Looking for devices to open using filter 
> 0: 
> sys:/sys/devices/pci:4a/:4a:02.0/:4b:00.0/:4c:01.0/:4d:00.0
> (core_hotunplug:3612) drmtest-DEBUG: Filter matched /dev/dri/card1 | 
> /dev/dri/renderD128
> (core_hotunplug:3612) drmtest-INFO: Opened device: /dev/dri/renderD128
> (core_hotunplug:3612) DEBUG: running device sysfs healthcheck
> (core_hotunplug:3612) DEBUG: closing health checked device instance
> (core_hotunplug:3612) DEBUG: Test requirement passed: healthcheck(priv, false)
> (core_hotunplug:3612) DEBUG: Test requirement passed: priv->fd.drm_hc == -1
> (core_hotunplug:3612) igt_kmod-DEBUG: Module snd_hda_intel unloaded 
> immediately
> (core_hotunplug:3612) INFO: Unloaded audio driver snd_hda_intel
> (core_hotunplug:3612) DEBUG: unbinding the driver from the device
> (core_hotunplug:3612) DEBUG: rebinding the driver to the device
> (core_hotunplug:3612) INFO: Realoading snd_hda_intel
> (core_hotunplug:3612) DEBUG: reopening DRM device for health check
> (core_hotunplug:3612) drmtest-DEBUG: Looking for devices to open using filter 
> 0: 
> sys:/sys/devices/pci:4a/:4a:02.0/:4b:00.0/:4c:01.0/:4d:00.0
> (core_hotunplug:3612) drmtest-DEBUG: Filter matched /dev/dri/card1 |
> (core_hotunplug:3612) drmtest-DEBUG: Opened previously opened device: 
> /dev/dri/card1
> (core_hotunplug:3612) DEBUG: running device sysfs healthcheck
> (core_hotunplug:3612) DEBUG: closing health checked device instance
> (core_hotunplug:3612) DEBUG: reopening render device for health check
> (core_hotunplug:3612) drmtest-DEBUG: Looking for devices to open using filter 
> 0: 
> sys:/sys/devices/pci:4a/:4a:02.0/:4b:00.0/:4c:01.0/:4d:00.0
> (core_hotunplug:3612) drmtest-DEBUG: Filter matched /dev/dri/card1 |
> (core_hotunplug:3612) CRITICAL: Test assertion failure function 
> local_drm_open_driver, file 
> ../../../usr/src/igt-gpu-tools/tests/core_hotunplug.c:130:
> (core_hotunplug:3612) CRITICAL: Failed assertion: fd_drm >= 0
> (core_hotunplug:3612) CRITICAL: file descriptor fd_drm failed
> 
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8830
> Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/500
> Signed-off-by: Janusz Krzysztofik 
> Cc: Petri Latvala 

Reviewed-by: Kamil Konieczny 

> ---
>  tests/core_hotunplug.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/tests/core_hotunplug.c b/tests/core_hotunplug.c
> index 30d9a6a576..b254447c71 100644
> --- a/tests/core_hotunplug.c
> +++ b/tests/core_hotunplug.c
> @@ -501,6 +501,9 @@ static void node_healthcheck(struct hotunplug *priv, 
> unsigned flags)
>  
>  static bool healthcheck(struct hotunplug *priv, bool recover)
>  {
> + /* give udev some time to recreate device nodes before we continue */
> + sleep(1);
> +
>   /* device name may have changed, rebuild IGT device list */
>   igt_devices_scan(true);
>  
> -- 
> 2.41.0
> 


Re: [Intel-gfx] [PATCH i-g-t 2/3] lib/igt_drm_clients: Store memory info in the client

2023-08-07 Thread Kamil Konieczny
Hi Tvrtko,

On 2023-07-27 at 10:20:24 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Define the storage structure and copy over memory data as parsed by the
> fdinfo helpers.
> 
> v2:
>  * Fix empty region map entry skip condition. (Kamil, Chris)
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Rob Clark 
> Cc: Chris Healy 
> Cc: Kamil Konieczny 

Thx for v2 with fix and reply, LGTM,

Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_drm_clients.c | 32 
>  lib/igt_drm_clients.h | 11 +++
>  2 files changed, 43 insertions(+)
> 
> diff --git a/lib/igt_drm_clients.c b/lib/igt_drm_clients.c
> index fdea42752a81..47ad137d5f1f 100644
> --- a/lib/igt_drm_clients.c
> +++ b/lib/igt_drm_clients.c
> @@ -103,6 +103,8 @@ igt_drm_client_update(struct igt_drm_client *c, unsigned 
> int pid, char *name,
>   c->clients->max_name_len = len;
>   }
>  
> + /* Engines */
> +
>   c->last_runtime = 0;
>   c->total_runtime = 0;
>  
> @@ -118,6 +120,13 @@ igt_drm_client_update(struct igt_drm_client *c, unsigned 
> int pid, char *name,
>   c->last[i] = info->busy[i];
>   }
>  
> + /* Memory regions */
> + for (i = 0; i <= c->regions->max_region_id; i++) {
> + assert(i < ARRAY_SIZE(info->region_mem));
> +
> + c->memory[i] = info->region_mem[i];
> + }
> +
>   c->samples++;
>   c->status = IGT_DRM_CLIENT_ALIVE;
>  }
> @@ -154,6 +163,8 @@ igt_drm_client_add(struct igt_drm_clients *clients,
>   c->id = info->id;
>   c->drm_minor = drm_minor;
>   c->clients = clients;
> +
> + /* Engines */
>   c->engines = malloc(sizeof(*c->engines));
>   assert(c->engines);
>   memset(c->engines, 0, sizeof(*c->engines));
> @@ -178,6 +189,27 @@ igt_drm_client_add(struct igt_drm_clients *clients,
>   c->last = calloc(c->engines->max_engine_id + 1, sizeof(c->last));
>   assert(c->val && c->last);
>  
> + /* Memory regions */
> + c->regions = malloc(sizeof(*c->regions));
> + assert(c->regions);
> + memset(c->regions, 0, sizeof(*c->regions));
> + c->regions->names = calloc(info->last_region_index + 1,
> +sizeof(*c->regions->names));
> + assert(c->regions->names);
> +
> + for (i = 0; i <= info->last_region_index; i++) {
> + /* Region map is allowed to be sparse. */
> + if (!info->region_names[i][0])
> + continue;
> +
> + c->regions->names[i] = strdup(info->region_names[i]);
> + assert(c->regions->names[i]);
> + c->regions->num_regions++;
> + c->regions->max_region_id = i;
> + }
> + c->memory = calloc(c->regions->max_region_id + 1, sizeof(*c->memory));
> + assert(c->memory);
> +
>   igt_drm_client_update(c, pid, name, info);
>  }
>  
> diff --git a/lib/igt_drm_clients.h b/lib/igt_drm_clients.h
> index ed795c193986..07bd236d43bf 100644
> --- a/lib/igt_drm_clients.h
> +++ b/lib/igt_drm_clients.h
> @@ -8,6 +8,8 @@
>  
>  #include 
>  
> +#include "lib/igt_drm_fdinfo.h"
> +
>  /**
>   * SECTION:igt_drm_clients
>   * @short_description: Parsing driver exposed fdinfo to track DRM clients
> @@ -39,12 +41,20 @@ struct igt_drm_client_engines {
>   char **names; /* Array of engine names, either auto-detected or from 
> the passed in engine map. */
>  };
>  
> +struct igt_drm_client_regions {
> + unsigned int num_regions; /* Number of discovered memory_regions. */
> + unsigned int max_region_id; /* Largest memory region index discovered.
> +(Can differ from num_regions - 1 when 
> using the region map facility.) */
> + char **names; /* Array of region names, either auto-detected or from 
> the passed in region map. */
> +};
> +
>  struct igt_drm_clients;
>  
>  struct igt_drm_client {
>   struct igt_drm_clients *clients; /* Owning list. */
>  
>   enum igt_drm_client_status status;
> + struct igt_drm_client_regions *regions; /* Memory regions present in 
> this client, to map with memory usage. */
>   struct igt_drm_client_engines *engines; /* Engines used by this client, 
> to map with busynees data. */
>   unsigned int id; /* DRM client id from fdinfo. */
>   unsigned int drm_minor; /* DRM minor of this client. */
> @@ -57,6 +67,7 @@ struct igt_drm_client {
>   unsigned long last_runtime; /* Aggregate busyness on all engines since 
> previous scan. */
>   unsigned long *val; /* Array of engine busyness data, relative to 
> previous scan. */
>   uint64_t *last; /* Array of engine busyness data as parsed from fdinfo. 
> */
> + struct drm_client_meminfo *memory; /* Array of region memory 
> utilisation as parsed from fdinfo. */
>  };
>  
>  struct igt_drm_clients {
> -- 
> 2.39.2
> 


Re: [Intel-gfx] [PATCH i-g-t 1/3] lib/igt_drm_fdinfo: Parse memory usage

2023-07-27 Thread Kamil Konieczny
Hi Tvrtko,

On 2023-07-27 at 10:20:23 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Add parsing and memory storage for the memory usage related fdinfo stats.
> 
> Uses the same approach as the engine utilization code by either auto-
> discovering different memory regions, or allowing for the caller to pass
> in a map with predefined index to name relationship.
> 
> v2:
>  * Fix s-o-b and satisfy kernel checkpatch. (Kamil)
> 
> Co-developed-by: Rob Clark 
> Signed-off-by: Rob Clark 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Kamil Konieczny 

LGTM,
Reviewed-by: Kamil Konieczny 

> ---
>  lib/igt_drm_clients.c   |   3 +-
>  lib/igt_drm_fdinfo.c| 143 ++--
>  lib/igt_drm_fdinfo.h|  24 ++-
>  tests/i915/drm_fdinfo.c |   8 +--
>  tools/intel_gpu_top.c   |   2 +-
>  5 files changed, 166 insertions(+), 14 deletions(-)
> 
> diff --git a/lib/igt_drm_clients.c b/lib/igt_drm_clients.c
> index f0294ba81c42..fdea42752a81 100644
> --- a/lib/igt_drm_clients.c
> +++ b/lib/igt_drm_clients.c
> @@ -491,7 +491,8 @@ igt_drm_clients_scan(struct igt_drm_clients *clients,
>  
>   if (!__igt_parse_drm_fdinfo(dirfd(fdinfo_dir),
>   fdinfo_dent->d_name, ,
> - name_map, map_entries))
> + name_map, map_entries,
> + NULL, 0))
>   continue;
>  
>   if (filter_client && !filter_client(clients, ))
> diff --git a/lib/igt_drm_fdinfo.c b/lib/igt_drm_fdinfo.c
> index b5f8a8679a71..f5a5b8e19dc3 100644
> --- a/lib/igt_drm_fdinfo.c
> +++ b/lib/igt_drm_fdinfo.c
> @@ -124,13 +124,82 @@ static const char *find_kv(const char *buf, const char 
> *key, size_t keylen)
>   return *p ? p : NULL;
>  }
>  
> +static int parse_region(char *line, struct drm_client_fdinfo *info,
> + size_t prefix_len,
> + const char **region_map, unsigned int region_entries,
> + uint64_t *val)
> +{
> + char *name, *p, *unit = NULL;
> + ssize_t name_len;
> + int found = -1;
> + unsigned int i;
> +
> + p = index(line, ':');
> + if (!p || p == line)
> + return -1;
> +
> + name_len = p - line - prefix_len;
> + if (name_len < 1)
> + return -1;
> +
> + name = line + prefix_len;
> +
> + if (region_map) {
> + for (i = 0; i < region_entries; i++) {
> + if (!strncmp(name, region_map[i], name_len)) {
> + found = i;
> + break;
> + }
> + }
> + } else {
> + for (i = 0; i < info->num_regions; i++) {
> + if (!strncmp(name, info->region_names[i], name_len)) {
> + found = i;
> + break;
> + }
> + }
> +
> + if (found < 0) {
> + assert((info->num_regions + 1) < 
> ARRAY_SIZE(info->region_names));
> + assert((strlen(name) + 1) < 
> sizeof(info->region_names[0]));
> + strncpy(info->region_names[info->num_regions], name, 
> name_len);
> + found = info->num_regions;
> + }
> + }
> +
> + if (found < 0)
> + goto out;
> +
> + while (*++p && isspace(*p))
> + ;
> + *val = strtoull(p, NULL, 10);
> +
> + p = index(p, ' ');
> + if (!p)
> + goto out;
> +
> + unit = ++p;
> + if (!strcmp(unit, "KiB")) {
> + *val *= 1024;
> + } else if (!strcmp(unit, "MiB")) {
> + *val *= 1024 * 1024;
> + } else if (!strcmp(unit, "GiB")) {
> + *val *= 1024 * 1024 * 1024;
> + }
> +
> +out:
> + return found;
> +}
> +
>  unsigned int
>  __igt_parse_drm_fdinfo(int dir, const char *fd, struct drm_client_fdinfo 
> *info,
> -const char **name_map, unsigned int map_entries)
> +const char **name_map, unsigned int map_entries,
> +const char **region_map, unsigned int region_entries)
>  {
> + bool regions_found[DRM_CLIENT_FDINFO_MAX_REGIONS] = { };
> + unsigned int good = 0, num_capacity = 0;
>   char buf[4096], *_buf = buf;
>   char *l, *ctx = NULL;
> - unsigned int g

Re: [Intel-gfx] [PATCH i-g-t 2/3] lib/igt_drm_clients: Store memory info in the client

2023-07-27 Thread Kamil Konieczny
Hi Tvrtko,

On 2023-07-27 at 10:20:24 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Define the storage structure and copy over memory data as parsed by the
> fdinfo helpers.
> 
> v2:
>  * Fix empty region map entry skip condition. (Kamil, Chris)
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Rob Clark 
> Cc: Chris Healy 
> Cc: Kamil Konieczny 
> ---
>  lib/igt_drm_clients.c | 32 
>  lib/igt_drm_clients.h | 11 +++
>  2 files changed, 43 insertions(+)
> 
> diff --git a/lib/igt_drm_clients.c b/lib/igt_drm_clients.c
> index fdea42752a81..47ad137d5f1f 100644
> --- a/lib/igt_drm_clients.c
> +++ b/lib/igt_drm_clients.c
> @@ -103,6 +103,8 @@ igt_drm_client_update(struct igt_drm_client *c, unsigned 
> int pid, char *name,
>   c->clients->max_name_len = len;
>   }
>  
> + /* Engines */
> +
>   c->last_runtime = 0;
>   c->total_runtime = 0;
>  
> @@ -118,6 +120,13 @@ igt_drm_client_update(struct igt_drm_client *c, unsigned 
> int pid, char *name,
>   c->last[i] = info->busy[i];
>   }
>  
> + /* Memory regions */
> + for (i = 0; i <= c->regions->max_region_id; i++) {
> + assert(i < ARRAY_SIZE(info->region_mem));
> +
> + c->memory[i] = info->region_mem[i];
> + }
> +
>   c->samples++;
>   c->status = IGT_DRM_CLIENT_ALIVE;
>  }
> @@ -154,6 +163,8 @@ igt_drm_client_add(struct igt_drm_clients *clients,
>   c->id = info->id;
>   c->drm_minor = drm_minor;
>   c->clients = clients;
> +
> + /* Engines */
>   c->engines = malloc(sizeof(*c->engines));
>   assert(c->engines);
>   memset(c->engines, 0, sizeof(*c->engines));
> @@ -178,6 +189,27 @@ igt_drm_client_add(struct igt_drm_clients *clients,
>   c->last = calloc(c->engines->max_engine_id + 1, sizeof(c->last));
>   assert(c->val && c->last);
>  
> + /* Memory regions */
> + c->regions = malloc(sizeof(*c->regions));
> + assert(c->regions);
> + memset(c->regions, 0, sizeof(*c->regions));
> + c->regions->names = calloc(info->last_region_index + 1,
> +sizeof(*c->regions->names));
> + assert(c->regions->names);
> +
> + for (i = 0; i <= info->last_region_index; i++) {
> + /* Region map is allowed to be sparse. */
> + if (!info->region_names[i][0])
> + continue;
> +
> + c->regions->names[i] = strdup(info->region_names[i]);
- ^
Should this be c->regions->num_regions?

Regards,
Kamil

> + assert(c->regions->names[i]);
> + c->regions->num_regions++;
> + c->regions->max_region_id = i;
> + }
> + c->memory = calloc(c->regions->max_region_id + 1, sizeof(*c->memory));
> + assert(c->memory);
> +
>   igt_drm_client_update(c, pid, name, info);
>  }
>  
> diff --git a/lib/igt_drm_clients.h b/lib/igt_drm_clients.h
> index ed795c193986..07bd236d43bf 100644
> --- a/lib/igt_drm_clients.h
> +++ b/lib/igt_drm_clients.h
> @@ -8,6 +8,8 @@
>  
>  #include 
>  
> +#include "lib/igt_drm_fdinfo.h"
> +
>  /**
>   * SECTION:igt_drm_clients
>   * @short_description: Parsing driver exposed fdinfo to track DRM clients
> @@ -39,12 +41,20 @@ struct igt_drm_client_engines {
>   char **names; /* Array of engine names, either auto-detected or from 
> the passed in engine map. */
>  };
>  
> +struct igt_drm_client_regions {
> + unsigned int num_regions; /* Number of discovered memory_regions. */
> + unsigned int max_region_id; /* Largest memory region index discovered.
> +(Can differ from num_regions - 1 when 
> using the region map facility.) */
> + char **names; /* Array of region names, either auto-detected or from 
> the passed in region map. */
> +};
> +
>  struct igt_drm_clients;
>  
>  struct igt_drm_client {
>   struct igt_drm_clients *clients; /* Owning list. */
>  
>   enum igt_drm_client_status status;
> + struct igt_drm_client_regions *regions; /* Memory regions present in 
> this client, to map with memory usage. */
>   struct igt_drm_client_engines *engines; /* Engines used by this client, 
> to map with busynees data. */
>   unsigned int id; /* DRM client id from fdinfo. */
>   unsigned int drm_minor; /* DRM minor of this client. */
> @@ -57,6 +67,7 @@ struct igt_drm_client {
>   unsigned long last_runtime; /* Aggregate busyness on all engines since 
> previous scan. */
>   unsigned long *val; /* Array of engine busyness data, relative to 
> previous scan. */
>   uint64_t *last; /* Array of engine busyness data as parsed from fdinfo. 
> */
> + struct drm_client_meminfo *memory; /* Array of region memory 
> utilisation as parsed from fdinfo. */
>  };
>  
>  struct igt_drm_clients {
> -- 
> 2.39.2
> 


Re: [Intel-gfx] [PATCH i-g-t 3/3] gputop: Add memory information

2023-07-26 Thread Kamil Konieczny
Hi Tvrtko,

On 2023-07-05 at 17:31:05 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Show total and resident memory usage for clients which support it.
> 
> For simplicity all memory regions are summed up and shown under a single
> heading.
> 
> Co-developed-by: Rob Clark 
> Signed-off-by: Tvrtko Ursulin 
> ---
>  tools/gputop.c | 34 +-
>  1 file changed, 33 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/gputop.c b/tools/gputop.c
> index 681f0a6bb748..b5b360cbb063 100644
> --- a/tools/gputop.c
> +++ b/tools/gputop.c
> @@ -28,6 +28,7 @@
>  
>  #include "igt_drm_clients.h"
>  #include "igt_drm_fdinfo.h"
> +#include "drmtest.h"
>  
>  static const char *bars[] = { " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█" };
>  
> @@ -80,7 +81,11 @@ print_client_header(struct igt_drm_client *c, int lines, 
> int con_w, int con_h,
>   return lines;
>  
>   putchar('\n');
> - len = printf("%*s ", c->clients->max_pid_len, "PID");
> + if (c->regions->num_regions)
> + len = printf("%*s  MEM  RSS ",
> +  c->clients->max_pid_len, "PID");
> + else
> + len = printf("%*s ", c->clients->max_pid_len, "PID");
>  
>   if (c->engines->num_engines) {
>   unsigned int i;
> @@ -121,12 +126,28 @@ newheader(const struct igt_drm_client *c, const struct 
> igt_drm_client *pc)
>   return !pc || c->drm_minor != pc->drm_minor;
>  }
>  
> +static int
> +print_size(uint64_t sz)
> +{
> + char units[] = {'B', 'K', 'M', 'G'};
> + unsigned u;
--- ^
Better:
unsigned int u;

With that add my r-b tag,

Regards,
Kamil

> +
> + for (u = 0; u < ARRAY_SIZE(units) - 1; u++) {
> + if (sz < 1024)
> + break;
> + sz /= 1024;
> + }
> +
> + return printf("%7"PRIu64"%c ", sz, units[u]);
> +}
> +
>  static int
>  print_client(struct igt_drm_client *c, struct igt_drm_client **prevc,
>double t, int lines, int con_w, int con_h,
>unsigned int period_us, int *engine_w)
>  {
>   unsigned int i;
> + uint64_t sz;
>   int len;
>  
>   /* Filter out idle clients. */
> @@ -143,6 +164,17 @@ print_client(struct igt_drm_client *c, struct 
> igt_drm_client **prevc,
>   *prevc = c;
>  
>   len = printf("%*s ", c->clients->max_pid_len, c->pid_str);
> +
> + if (c->regions->num_regions) {
> + for (sz = 0, i = 0; i < c->regions->max_region_id; i++)
> + sz += c->memory[i].total;
> + len += print_size(sz);
> +
> + for (sz = 0, i = 0; i < c->regions->max_region_id; i++)
> + sz += c->memory[i].resident;
> + len += print_size(sz);
> + }
> +
>   lines++;
>  
>   for (i = 0; c->samples > 1 && i <= c->engines->max_engine_id; i++) {
> -- 
> 2.39.2
> 


Re: [Intel-gfx] [PATCH i-g-t 1/3] lib/igt_drm_fdinfo: Parse memory usage

2023-07-26 Thread Kamil Konieczny
Hi Tvrtko,

please check your patches with Linux kernel script checkpatch.pl
Some of it's warnings seems strange, like:

WARNING: Co-developed-by and Signed-off-by: name/email do not match
#12:
Co-developed-by: Rob Clark 
Signed-off-by: Tvrtko Ursulin 

On 2023-07-05 at 17:31:03 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Add parsing and memory storage for the memory usage related fdinfo stats.
> 
> Uses the same approach as the engine utilization code by either auto-
> discovering different memory regions, or allowing for the caller to pass
> in a map with predefined index to name relationship.
> 
> Co-developed-by: Rob Clark 
> Signed-off-by: Tvrtko Ursulin 
> ---
>  lib/igt_drm_clients.c   |   3 +-
>  lib/igt_drm_fdinfo.c| 142 ++--
>  lib/igt_drm_fdinfo.h|  24 ++-
>  tests/i915/drm_fdinfo.c |   8 +--
>  tools/intel_gpu_top.c   |   2 +-
>  5 files changed, 165 insertions(+), 14 deletions(-)
> 
> diff --git a/lib/igt_drm_clients.c b/lib/igt_drm_clients.c
> index f0294ba81c42..fdea42752a81 100644
> --- a/lib/igt_drm_clients.c
> +++ b/lib/igt_drm_clients.c
> @@ -491,7 +491,8 @@ igt_drm_clients_scan(struct igt_drm_clients *clients,
>  
>   if (!__igt_parse_drm_fdinfo(dirfd(fdinfo_dir),
>   fdinfo_dent->d_name, ,
> - name_map, map_entries))
> + name_map, map_entries,
> + NULL, 0))
>   continue;
>  
>   if (filter_client && !filter_client(clients, ))
> diff --git a/lib/igt_drm_fdinfo.c b/lib/igt_drm_fdinfo.c
> index b5f8a8679a71..d08632dfb690 100644
> --- a/lib/igt_drm_fdinfo.c
> +++ b/lib/igt_drm_fdinfo.c
> @@ -124,13 +124,81 @@ static const char *find_kv(const char *buf, const char 
> *key, size_t keylen)
>   return *p ? p : NULL;
>  }
>  
> +static int parse_region(char *line, struct drm_client_fdinfo *info,
> + size_t prefix_len,
> + const char **region_map, unsigned int region_entries,
> + uint64_t *val)
> +{
> + char *name, *p, *unit = NULL;
> + ssize_t name_len;
> + int found = -1;
> + unsigned int i;
> +
> + p = index(line, ':');
> + if (!p || p == line)
> + return -1;
> +
> + name_len = p - line - prefix_len;
> + if (name_len < 1)
> + return -1;
> +
> + name = line + prefix_len;
> +
> + if (region_map) {
> + for (i = 0; i < region_entries; i++) {
> + if (!strncmp(name, region_map[i], name_len)) {
> + found = i;
> + break;
> + }
> + }
> + } else {
> + for (i = 0; i < info->num_regions; i++) {
> + if (!strncmp(name, info->region_names[i], name_len)) {
> + found = i;
> + break;
> + }
> + }
> +
> + if (found < 0) {
> + assert((info->num_regions + 1) < 
> ARRAY_SIZE(info->region_names));
> + assert((strlen(name) + 1) < 
> sizeof(info->region_names[0]));
> + strncpy(info->region_names[info->num_regions], name, 
> name_len);
> + found = info->num_regions;
> + }
> + }
> +
> + if (found < 0)
> + goto out;
> +
> + while (*++p && isspace(*p));
-- ^
According to checkpatch:
while (*++p && isspace(*p))
;

> + *val = strtoull(p, NULL, 10);
> +
> + p = index(p, ' ');
> + if (!p)
> + goto out;
> +
> + unit = ++p;
> + if (!strcmp(unit, "KiB")) {
> + *val *= 1024;
> + } else if (!strcmp(unit, "MiB")) {
--- ^^
No need for separate 'else':
if (!strcmp(unit, "MiB")) {

> + *val *= 1024 * 1024;
> + } else if (!strcmp(unit, "GiB")) {
--- ^^
Same here.

Regards,
Kamil

> + *val *= 1024 * 1024 * 1024;
> + }
> +
> +out:
> + return found;
> +}
> +
>  unsigned int
>  __igt_parse_drm_fdinfo(int dir, const char *fd, struct drm_client_fdinfo 
> *info,
> -const char **name_map, unsigned int map_entries)
> +const char **name_map, unsigned int map_entries,
> +const char **region_map, unsigned int region_entries)
>  {
> + bool regions_found[DRM_CLIENT_FDINFO_MAX_REGIONS] = { };
> + unsigned int good = 0, num_capacity = 0;
>   char buf[4096], *_buf = buf;
>   char *l, *ctx = NULL;
> - unsigned int good = 0, num_capacity = 0;
>   size_t count;
>  
>   count = read_fdinfo(buf, sizeof(buf), dir, fd);
> @@ -173,18 +241,79 @@ __igt_parse_drm_fdinfo(int dir, const char *fd, struct 
> 

Re: [Intel-gfx] [PATCH i-g-t 2/3] lib/igt_drm_clients: Store memory info in the client

2023-07-26 Thread Kamil Konieczny
Hi Tvrtko,

On 2023-07-05 at 17:31:04 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Define the storage structure and copy over memory data as parsed by the
> fdinfo helpers.
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Rob Clark 
> ---
>  lib/igt_drm_clients.c | 31 +++
>  lib/igt_drm_clients.h | 11 +++
>  2 files changed, 42 insertions(+)
> 
> diff --git a/lib/igt_drm_clients.c b/lib/igt_drm_clients.c
> index fdea42752a81..0db5b64effea 100644
> --- a/lib/igt_drm_clients.c
> +++ b/lib/igt_drm_clients.c
> @@ -103,6 +103,8 @@ igt_drm_client_update(struct igt_drm_client *c, unsigned 
> int pid, char *name,
>   c->clients->max_name_len = len;
>   }
>  
> + /* Engines */
> +
>   c->last_runtime = 0;
>   c->total_runtime = 0;
>  
> @@ -118,6 +120,13 @@ igt_drm_client_update(struct igt_drm_client *c, unsigned 
> int pid, char *name,
>   c->last[i] = info->busy[i];
>   }
>  
> + /* Memory regions */
> + for (i = 0; i <= c->regions->max_region_id; i++) {
> + assert(i < ARRAY_SIZE(info->region_mem));
> +
> + c->memory[i] = info->region_mem[i];
> + }
> +
>   c->samples++;
>   c->status = IGT_DRM_CLIENT_ALIVE;
>  }
> @@ -154,6 +163,8 @@ igt_drm_client_add(struct igt_drm_clients *clients,
>   c->id = info->id;
>   c->drm_minor = drm_minor;
>   c->clients = clients;
> +
> + /* Engines */
>   c->engines = malloc(sizeof(*c->engines));
>   assert(c->engines);
>   memset(c->engines, 0, sizeof(*c->engines));
> @@ -178,6 +189,26 @@ igt_drm_client_add(struct igt_drm_clients *clients,
>   c->last = calloc(c->engines->max_engine_id + 1, sizeof(c->last));
>   assert(c->val && c->last);
>  
> + /* Memory regions */
> + c->regions = malloc(sizeof(*c->regions));
> + assert(c->regions);
> + memset(c->regions, 0, sizeof(*c->regions));
> + c->regions->names = calloc(info->last_region_index + 1,
> +sizeof(*c->regions->names));
> + assert(c->regions->names);
> +
> + for (i = 0; i <= info->last_region_index; i++) {
> + if (!info->region_names[i])

This do not compile:
../lib/igt_drm_clients.c:201:21: error: the comparison will always evaluate as 
‘true’ for the address of ‘region_names’ will never be NULL [-Werror=address]
  201 | if (!info->region_names[i])
  | ^
In file included from ../lib/igt_drm_clients.h:11,
 from ../lib/igt_drm_clients.c:20:
../lib/igt_drm_fdinfo.h:57:14: note: ‘region_names’ declared here
   57 | char region_names[DRM_CLIENT_FDINFO_MAX_REGIONS][256];
  |  ^~~~

did you mean:

if (!info->region_names[i][0])

Regards,
Kamil

> + continue;
> +
> + c->regions->names[i] = strdup(info->region_names[i]);
> + assert(c->regions->names[i]);
> + c->regions->num_regions++;
> + c->regions->max_region_id = i;
> + }
> + c->memory = calloc(c->regions->max_region_id + 1, sizeof(*c->memory));
> + assert(c->memory);
> +
>   igt_drm_client_update(c, pid, name, info);
>  }
>  
> diff --git a/lib/igt_drm_clients.h b/lib/igt_drm_clients.h
> index ed795c193986..07bd236d43bf 100644
> --- a/lib/igt_drm_clients.h
> +++ b/lib/igt_drm_clients.h
> @@ -8,6 +8,8 @@
>  
>  #include 
>  
> +#include "lib/igt_drm_fdinfo.h"
> +
>  /**
>   * SECTION:igt_drm_clients
>   * @short_description: Parsing driver exposed fdinfo to track DRM clients
> @@ -39,12 +41,20 @@ struct igt_drm_client_engines {
>   char **names; /* Array of engine names, either auto-detected or from 
> the passed in engine map. */
>  };
>  
> +struct igt_drm_client_regions {
> + unsigned int num_regions; /* Number of discovered memory_regions. */
> + unsigned int max_region_id; /* Largest memory region index discovered.
> +(Can differ from num_regions - 1 when 
> using the region map facility.) */
> + char **names; /* Array of region names, either auto-detected or from 
> the passed in region map. */
> +};
> +
>  struct igt_drm_clients;
>  
>  struct igt_drm_client {
>   struct igt_drm_clients *clients; /* Owning list. */
>  
>   enum igt_drm_client_status status;
> + struct igt_drm_client_regions *regions; /* Memory regions present in 
> this client, to map with memory usage. */
>   struct igt_drm_client_engines *engines; /* Engines used by this client, 
> to map with busynees data. */
>   unsigned int id; /* DRM client id from fdinfo. */
>   unsigned int drm_minor; /* DRM minor of this client. */
> @@ -57,6 +67,7 @@ struct igt_drm_client {
>   unsigned long last_runtime; /* Aggregate busyness on all engines since 
> previous scan. */
>   unsigned long *val; /* Array of engine busyness data, relative to 
> previous scan. */
>   uint64_t *last; /* Array of engine 

Re: [Intel-gfx] [PATCH v3 i-g-t] tests/i915_pm_freq_api: Add a suspend subtest

2023-06-23 Thread Kamil Konieczny
Hi Vinay,

small nit, see below.

On 2023-06-16 at 08:50:48 -0700, Vinay Belgaumkar wrote:
> Verify that SLPC API works as expected after a suspend. Added
> another subtest that does multiple GT resets and checks freq api
> works as expected after each one.
> 
> We now check requested frequency instead of soft min/max after a
> reset or suspend. That ensures the soft limits got applied
> correctly at init. Also, disable efficient freq before starting the
> test which allows current freq to be consistent with SLPC min freq.
> 
> v2: Restore freq in exit handler (Ashutosh)
> v3: Free the allocated stash arrays
> 
> Signed-off-by: Vinay Belgaumkar 
> ---
>  tests/i915/i915_pm_freq_api.c | 92 +++
>  1 file changed, 71 insertions(+), 21 deletions(-)
> 
> diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c
> index 9005cd220..522abee35 100644
> --- a/tests/i915/i915_pm_freq_api.c
> +++ b/tests/i915/i915_pm_freq_api.c
> @@ -18,6 +18,12 @@
>   *
>   * SUBTEST: freq-reset
>   * Description: Test basic freq API works after a reset
> + *
> + * SUBTEST: freq-reset-multiple
> + * Description: Test basic freq API works after multiple resets
> + *
> + * SUBTEST: freq-suspend
> + * Description: Test basic freq API works after a runtime suspend
>   */
>  
>  IGT_TEST_DESCRIPTION("Test SLPC freq API");
> @@ -49,7 +55,6 @@ static void test_freq_basic_api(int dirfd, int gt)
>   rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ);
>   rp0 = get_freq(dirfd, RPS_RP0_FREQ_MHZ);
>   rpe = get_freq(dirfd, RPS_RP1_FREQ_MHZ);
> - igt_info("System min freq: %dMHz; max freq: %dMHz\n", rpn, rp0);
>  
>   /*
>* Negative bound tests
> @@ -79,31 +84,66 @@ static void test_freq_basic_api(int dirfd, int gt)
>  
>  }
>  
> -static void test_reset(int i915, int dirfd, int gt)
> +static void test_reset(int i915, int dirfd, int gt, int count)
>  {
>   uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ);
>   int fd;
>  
> + for (int i = 0; i < count; i++) {
> + igt_assert_f(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0,
> +  "Failed after %d good cycles\n", i);
> + igt_assert_f(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0,
> +  "Failed after %d good cycles\n", i);
> + usleep(ACT_FREQ_LATENCY_US);
> + igt_assert_f(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn,
> +  "Failed after %d good cycles\n", i);
> +
> + /* Manually trigger a GT reset */
> + fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY);
> + igt_require(fd >= 0);

Move these open and require before for() loop.

Regards,
Kamil

> + igt_ignore_warn(write(fd, "1\n", 2));
> +
> + igt_assert_f(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn,
> +  "Failed after %d good cycles\n", i);
> + }
> + close(fd);
> +}
> +
> +static void test_suspend(int i915, int dirfd, int gt)
> +{
> + uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ);
> +
>   igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0);
>   igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0);
>   usleep(ACT_FREQ_LATENCY_US);
> - igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn);
> + igt_assert(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn);
>  
> - /* Manually trigger a GT reset */
> - fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY);
> - igt_require(fd >= 0);
> - igt_ignore_warn(write(fd, "1\n", 2));
> - close(fd);
> + /* Manually trigger a suspend */
> + igt_system_suspend_autoresume(SUSPEND_STATE_S3,
> +   SUSPEND_TEST_NONE);
>  
> - igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn);
> - igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn);
> + igt_assert(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn);
>  }
>  
> -igt_main
> +int i915 = -1;
> +uint32_t *stash_min, *stash_max;
> +
> +static void restore_sysfs_freq(int sig)
>  {
> - int i915 = -1;
> - uint32_t *stash_min, *stash_max;
> + int dirfd, gt;
> + /* Restore frequencies */
> + for_each_sysfs_gt_dirfd(i915, dirfd, gt) {
> + igt_pm_ignore_slpc_efficient_freq(i915, dirfd, false);
> + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, stash_max[gt]) > 
> 0);
> + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, stash_min[gt]) > 
> 0);
> + }
> + free(stash_min);
> + free(stash_max);
> + close(i915);
> +}
>  
> +igt_main
> +{
>   igt_fixture {
>   int num_gts, dirfd, gt;
>  
> @@ -122,7 +162,9 @@ igt_main
>   for_each_sysfs_gt_dirfd(i915, dirfd, gt) {
>   stash_min[gt] = get_freq(dirfd, RPS_MIN_FREQ_MHZ);
>   stash_max[gt] = get_freq(dirfd, RPS_MAX_FREQ_MHZ);
> + igt_pm_ignore_slpc_efficient_freq(i915, dirfd, true);
>   }
> + 

Re: [Intel-gfx] [PATCH i-g-t] tests/gem_ctx_persistence: Skip hang subtest with GuC

2023-06-07 Thread Kamil Konieczny
Hi Vinay,

On 2023-06-06 at 15:14:18 -0700, Vinay Belgaumkar wrote:
> Hang subtest is not supported with GuC submission enabled.

This is Guc which do not support some operations, so please
improve description, maybe use Andrzej suggestions ?

Regards,
Kamil

> 
> Cc: Kamil Konieczny 
> Signed-off-by: Vinay Belgaumkar 
> ---
>  tests/i915/gem_ctx_persistence.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/tests/i915/gem_ctx_persistence.c 
> b/tests/i915/gem_ctx_persistence.c
> index df9b1c491..d2558354e 100644
> --- a/tests/i915/gem_ctx_persistence.c
> +++ b/tests/i915/gem_ctx_persistence.c
> @@ -577,6 +577,8 @@ static void test_nohangcheck_hang(int i915, const 
> intel_ctx_cfg_t *cfg)
>   int testable_engines = 0;
>   int dir;
>  
> + igt_require(!gem_using_guc_submission(i915));
> +
>   cleanup(i915);
>  
>   /*
> -- 
> 2.38.1
> 


Re: [Intel-gfx] [PATCH i-g-t] tests/i915/gem_ctx_persistence: Skip some subtests

2023-05-25 Thread Kamil Konieczny
Hi Vinay,

On 2023-05-24 at 12:19:06 -0700, Vinay Belgaumkar wrote:
> Hang and heartbeat subtests are not supported with GuC submission
> enabled.
> 
> Signed-off-by: Vinay Belgaumkar 
> ---
>  tests/i915/gem_ctx_persistence.c | 32 +++-
>  1 file changed, 19 insertions(+), 13 deletions(-)
> 
> diff --git a/tests/i915/gem_ctx_persistence.c 
> b/tests/i915/gem_ctx_persistence.c
> index 42cf96329..1e122535e 100644
> --- a/tests/i915/gem_ctx_persistence.c
> +++ b/tests/i915/gem_ctx_persistence.c
> @@ -1366,19 +1366,25 @@ igt_main
>  
>   igt_subtest("hostile")
>   test_nohangcheck_hostile(i915, _cfg);
> - igt_subtest("hang")
> - test_nohangcheck_hang(i915, _cfg);
> -
> - igt_subtest("heartbeat-stop")
> - test_noheartbeat_many(i915, 1, 0);
> - igt_subtest("heartbeat-hang")
> - test_noheartbeat_many(i915, 1, IGT_SPIN_NO_PREEMPTION);
> - igt_subtest("heartbeat-many")
> - test_noheartbeat_many(i915, 16, 0);
> - igt_subtest("heartbeat-close")
> - test_noheartbeat_close(i915, 0);
> - igt_subtest("heartbeat-hostile")
> - test_noheartbeat_close(i915, IGT_SPIN_NO_PREEMPTION);
> +
> + igt_subtest_group {
> + igt_fixture
> + igt_skip_on(gem_using_guc_submission(i915));
--- ^^^
You cannot put this in fixture as there is no test defined in it.
Place skips at begin of test functions that need it.

Regards,
Kamil

> +
> + igt_subtest("hang")
> + test_nohangcheck_hang(i915, _cfg);
> +
> + igt_subtest("heartbeat-stop")
> + test_noheartbeat_many(i915, 1, 0);
> + igt_subtest("heartbeat-hang")
> + test_noheartbeat_many(i915, 1, IGT_SPIN_NO_PREEMPTION);
> + igt_subtest("heartbeat-many")
> + test_noheartbeat_many(i915, 16, 0);
> + igt_subtest("heartbeat-close")
> + test_noheartbeat_close(i915, 0);
> + igt_subtest("heartbeat-hostile")
> + test_noheartbeat_close(i915, IGT_SPIN_NO_PREEMPTION);
> + }
>  
>   igt_subtest_group {
>   igt_fixture
> -- 
> 2.38.1
> 


Re: [Intel-gfx] [PATCH i-g-t 2/2] intel_gpu_top: Move client name last

2023-05-23 Thread Kamil Konieczny
On 2023-05-15 at 14:36:30 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Move client name to be the right most field which visually aligns better
> with top(1) and prepares for inserting memory usage fields somewhere in
> the middle.
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Rob Clark 

Acked-by: Kamil Konieczny 

> ---
>  tools/intel_gpu_top.c | 19 +--
>  1 file changed, 9 insertions(+), 10 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index 453090c298bc..937280a7151a 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -1809,9 +1809,7 @@ print_clients_header(struct igt_drm_clients *clients, 
> int lines,
>   return lines;
>  
>   printf("\033[7m");
> - len = printf("%*s %*s ",
> -  clients->max_pid_len, "PID",
> -  clients->max_name_len, "NAME");
> + len = printf("%*s ", clients->max_pid_len, "PID");
>  
>   if (lines++ >= con_h || len >= con_w)
>   return lines;
> @@ -1825,7 +1823,9 @@ print_clients_header(struct igt_drm_clients *clients, 
> int lines,
>   num_active++;
>   }
>  
> - *class_w = width = (con_w - len) / num_active;
> + *class_w = width =
> + (con_w - len - clients->max_name_len - 1) /
> + num_active;
>  
>   for (i = 0; i <= iclients->classes.max_engine_id; i++) {
>   const char *name = iclients->classes.names[i];
> @@ -1846,8 +1846,7 @@ print_clients_header(struct igt_drm_clients *clients, 
> int lines,
>   }
>   }
>  
> - n_spaces(con_w - len);
> - printf("\033[0m\n");
> + printf(" %-*s\033[0m\n", con_w - len - 1, "NAME");
>   } else {
>   if (iclients->classes.num_engines)
>   pops->open_struct("clients");
> @@ -1866,6 +1865,7 @@ print_client(struct igt_drm_client *c, struct engines 
> *engines, double t, int li
>   struct igt_drm_clients *clients = c->clients;
>   struct intel_clients *iclients = clients->private_data;
>   unsigned int i;
> + int len;
>  
>   if (output_mode == INTERACTIVE) {
>   if (filter_idle && (!c->total_runtime || c->samples < 2))
> @@ -1873,9 +1873,7 @@ print_client(struct igt_drm_client *c, struct engines 
> *engines, double t, int li
>  
>   lines++;
>  
> - printf("%*s %*s ",
> -clients->max_pid_len, c->pid_str,
> -clients->max_name_len, c->print_name);
> + len = printf("%*s ", clients->max_pid_len, c->pid_str);
>  
>   for (i = 0;
>c->samples > 1 && i <= iclients->classes.max_engine_id;
> @@ -1898,9 +1896,10 @@ print_client(struct igt_drm_client *c, struct engines 
> *engines, double t, int li
>  
>   print_percentage_bar(pct, max, *class_w,
>numeric_clients);
> + len += *class_w;
>   }
>  
> - putchar('\n');
> + printf(" %-*s\n", con_w - len - 1, c->print_name);
>   } else if (output_mode == JSON) {
>   char buf[64];
>  
> -- 
> 2.37.2
> 


Re: [Intel-gfx] [PATCH i-g-t 1/2] gputop: Move client name last

2023-05-23 Thread Kamil Konieczny
On 2023-05-15 at 14:36:29 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Move client name to be the right most field which visually aligns better
> with top(1) and prepares for inserting memory usage fields somewhere in
> the middle.
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Rob Clark 

Acked-by: Kamil Konieczny 

> ---
>  tools/gputop.c | 19 +--
>  1 file changed, 9 insertions(+), 10 deletions(-)
> 
> diff --git a/tools/gputop.c b/tools/gputop.c
> index 4fb5ce63e07c..681f0a6bb748 100644
> --- a/tools/gputop.c
> +++ b/tools/gputop.c
> @@ -80,15 +80,15 @@ print_client_header(struct igt_drm_client *c, int lines, 
> int con_w, int con_h,
>   return lines;
>  
>   putchar('\n');
> - len = printf("%*s %*s ",
> -  c->clients->max_pid_len, "PID",
> -  c->clients->max_name_len, "NAME");
> + len = printf("%*s ", c->clients->max_pid_len, "PID");
>  
>   if (c->engines->num_engines) {
>   unsigned int i;
>   int width;
>  
> - *engine_w = width = (con_w - len) / c->engines->num_engines;
> + *engine_w = width =
> + (con_w - len - c->clients->max_name_len - 1) /
> + c->engines->num_engines;
>  
>   for (i = 0; i <= c->engines->max_engine_id; i++) {
>   const char *name = c->engines->names[i];
> @@ -109,8 +109,7 @@ print_client_header(struct igt_drm_client *c, int lines, 
> int con_w, int con_h,
>   }
>   }
>  
> - n_spaces(con_w - len);
> - printf("\033[0m\n");
> + printf(" %-*s\033[0m\n", con_w - len - 1, "NAME");
>  
>   return lines;
>  }
> @@ -128,6 +127,7 @@ print_client(struct igt_drm_client *c, struct 
> igt_drm_client **prevc,
>unsigned int period_us, int *engine_w)
>  {
>   unsigned int i;
> + int len;
>  
>   /* Filter out idle clients. */
>   if (!c->total_runtime || c->samples < 2)
> @@ -142,9 +142,7 @@ print_client(struct igt_drm_client *c, struct 
> igt_drm_client **prevc,
>  
>   *prevc = c;
>  
> - printf("%*s %*s ",
> -c->clients->max_pid_len, c->pid_str,
> -c->clients->max_name_len, c->print_name);
> + len = printf("%*s ", c->clients->max_pid_len, c->pid_str);
>   lines++;
>  
>   for (i = 0; c->samples > 1 && i <= c->engines->max_engine_id; i++) {
> @@ -164,9 +162,10 @@ print_client(struct igt_drm_client *c, struct 
> igt_drm_client **prevc,
>   pct = 100.0;
>  
>   print_percentage_bar(pct, *engine_w);
> + len += *engine_w;
>   }
>  
> - putchar('\n');
> + printf(" %-*s\n", con_w - len - 1, c->print_name);
>  
>   return lines;
>  }
> -- 
> 2.37.2
> 


Re: [Intel-gfx] [PATCH i-g-t] tests/i915: Exercise coherency of mmapped frame buffers

2023-05-15 Thread Kamil Konieczny
Hi Janusz,

On 2023-05-15 at 10:50:20 +0200, Janusz Krzysztofik wrote:
> Visible glitches have been observed when running graphics applications on
> Linux under Xen hypervisor.  Those observations have been confirmed with
> failures from kms_pwrite_crc IGT test that verifies data coherency of DRM
> frame buffer objects using hardware CRC checksums calculated by display
> controllers, exposed to userspace via debugfs.  Since not all applications
> exhibit the issue, we need to exercise more methods than just pwrite in
> order to identify all affected processing paths.
> 
> Create a new test focused on exercising coherency of future scanout
> buffers populated over mmap.  Cover all available mmap methods and caching
> modes expected to be device coherent.
> 

+cc kms dev Bhanuprakash Modem

> Link: https://gitlab.freedesktop.org/drm/intel/-/issues/7648
> Signed-off-by: Janusz Krzysztofik 
> ---
>  tests/i915/kms_fb_coherency.c | 354 ++
>  tests/meson.build |   1 +
>  2 files changed, 355 insertions(+)
>  create mode 100644 tests/i915/kms_fb_coherency.c
> 
> diff --git a/tests/i915/kms_fb_coherency.c b/tests/i915/kms_fb_coherency.c
> new file mode 100644
> index 00..9223f13b05
> --- /dev/null
> +++ b/tests/i915/kms_fb_coherency.c
> @@ -0,0 +1,354 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2023 Intel Corporation
> + *
> + * Derived from tests/i915/kms_pwrite_crc.c
> + * Copyright © 2014 Intel Corporation

imho you do not need above two lines, you already wrote this
in description.

> + */
> +
> +/**
> + * TEST: kms_fb_coherency
> + * Description: Exercise coherency of future scanout buffer objects
> + */
> +
> +#include "igt.h"

Put this after sys includes below.

> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +

Here put any igt include(s).

> +
> +typedef struct {
> + int drm_fd;
> + igt_display_t display;
> + struct igt_fb fb[2];
> + igt_output_t *output;
> + igt_plane_t *primary;
> + enum pipe pipe;
> + igt_crc_t ref_crc;
> + igt_pipe_crc_t *pipe_crc;
> + uint32_t devid;
> +} data_t;
> +
> +static void prepare_crtc(data_t *data)
> +{
> + igt_display_t *display = >display;
> + igt_output_t *output = data->output;
> + drmModeModeInfo *mode;
> +
> + igt_display_reset(display);
> + /* select the pipe we want to use */
> + igt_output_set_pipe(output, data->pipe);
> +
> + mode = igt_output_get_mode(output);
> +
> + /* create a white reference fb and flip to it */
> + igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay,
> + DRM_FORMAT_XRGB, DRM_FORMAT_MOD_LINEAR,
> + 1.0, 1.0, 1.0, >fb[0]);
> +
> + data->primary = igt_output_get_plane_type(output, 
> DRM_PLANE_TYPE_PRIMARY);
> +
> + igt_plane_set_fb(data->primary, >fb[0]);
> + igt_display_commit(display);
> +
> + if (data->pipe_crc)
> + igt_pipe_crc_free(data->pipe_crc);
> +
> + data->pipe_crc = igt_pipe_crc_new(data->drm_fd, data->pipe,
> +   IGT_PIPE_CRC_SOURCE_AUTO);
> +
> + /* get reference crc for the white fb */
> + igt_pipe_crc_collect_crc(data->pipe_crc, >ref_crc);
> +}
> +
> +static struct igt_fb *prepare_fb(data_t *data)
> +{
> + igt_output_t *output = data->output;
> + struct igt_fb *fb = >fb[1];
> + drmModeModeInfo *mode;
> +
> + prepare_crtc(data);
> +
> + mode = igt_output_get_mode(output);
> +
> + /* create a non-white fb we can overwrite later */
> + igt_create_pattern_fb(data->drm_fd, mode->hdisplay, mode->vdisplay,
> +   DRM_FORMAT_XRGB, DRM_FORMAT_MOD_LINEAR, fb);
> +
> + /* flip to it to make it UC/WC and fully flushed */
> + drmModeSetPlane(data->drm_fd,
> + data->primary->drm_plane->plane_id,
> + output->config.crtc->crtc_id,
> + fb->fb_id, 0,
> + 0, 0, fb->width, fb->height,
> + 0, 0, fb->width << 16, fb->height << 16);
> +
> + /* flip back the original white buffer */
> + drmModeSetPlane(data->drm_fd,
> + data->primary->drm_plane->plane_id,
> + output->config.crtc->crtc_id,
> + data->fb[0].fb_id, 0,
> + 0, 0, fb->width, fb->height,
> + 0, 0, fb->width << 16, fb->height << 16);
> +
> + if (!gem_has_lmem(data->drm_fd)) {
> + uint32_t caching;
> +
> + /* make sure caching mode has become UC/WT */
> + caching = gem_get_caching(data->drm_fd, fb->gem_handle);
> + igt_assert(caching == I915_CACHING_NONE ||
> +caching == I915_CACHING_DISPLAY);
> + }
> +
> + return fb;
> +}
> +
> +static igt_crc_t get_buf_crc(data_t *data, void *buf, igt_fb_t *fb)
> +{
> + igt_crc_t crc;
> +
> + /* use memset 

Re: [Intel-gfx] [igt-dev] [PATCH i-g-t 3/4] i915_pm_freq_api: Add some basic SLPC igt tests

2023-04-27 Thread Kamil Konieczny
Hi Ashutosh,

On 2023-04-26 at 13:40:28 -0700, Dixit, Ashutosh wrote:
> On Tue, 25 Apr 2023 09:24:04 -0700, Vinay Belgaumkar wrote:
> >
> > diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c
> > new file mode 100644
> > index ..17adacbc
> > --- /dev/null
> > +++ b/tests/i915/i915_pm_freq_api.c
> > @@ -0,0 +1,153 @@
> > +// SPDX-License-Identifier: MIT
> > +/*
> > + * Copyright © 2023 Intel Corporation
> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#include "drmtest.h"
> 
> The series is merged but before merging I removed all the #include's above,
> they are not needed.

Please do not do this, at least send it to trybot and look at
GitLab.Pipeline status. There are platforms where compilation 
failed due to missing fcntl.h, see
https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/issues/137

It is fixed now with
https://patchwork.freedesktop.org/series/117047/

Regards,
Kamil

> 
> > +#include "i915/gem.h"
> > +#include "igt_sysfs.h"
> > +#include "igt.h"
> 
> Thanks.
> --
> Ashutosh


Re: [Intel-gfx] [PATCH i-g-t 3/3] intel_gpu_top: Show non-normalized client usage in numeric mode

2023-04-14 Thread Kamil Konieczny
On 2023-03-28 at 13:54:29 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> When numeric display is selected in the interactive mode it is more
> descriptive to show client's non-normalized (by number of engines per
> class) usage. Rendering of the visual representation (bar) is kept the
> same.
> 
> Signed-off-by: Tvrtko Ursulin 

Reviewed-by: Kamil Konieczny 

> ---
>  tools/intel_gpu_top.c | 20 +++-
>  1 file changed, 11 insertions(+), 9 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index 36da016c3df0..b6827b3de9bd 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -1275,14 +1275,14 @@ static void n_spaces(const unsigned int n)
>  }
>  
>  static void
> -print_percentage_bar(double percent, int max_len, bool numeric)
> +print_percentage_bar(double percent, double max, int max_len, bool numeric)
>  {
>   int bar_len, i, len = max_len - 2;
>   const int w = 8;
>  
>   assert(max_len > 0);
>  
> - bar_len = ceil(w * percent * len / 100.0);
> + bar_len = ceil(w * percent * len / max);
>   if (bar_len > w * len)
>   bar_len = w * len;
>  
> @@ -2010,7 +2010,8 @@ print_engine(struct engines *engines, unsigned int i, 
> double t,
> engine->display_name, engine_items[0].buf);
>  
>   val = pmu_calc(>busy.val, 1e9, t, 100);
> - print_percentage_bar(val, con_w > len ? con_w - len : 0, false);
> + print_percentage_bar(val, 100.0, con_w > len ? con_w - len : 0,
> +  false);
>  
>   printf("%s\n", buf);
>  
> @@ -2292,23 +2293,24 @@ print_client(struct client *c, struct engines 
> *engines, double t, int lines,
>  clients->max_name_len, c->print_name);
>  
>   for (i = 0; c->samples > 1 && i < clients->num_classes; i++) {
> - double pct;
> + double pct, max;
>  
>   if (!clients->class[i].num_engines)
>   continue; /* Assert in the ideal world. */
>  
> - pct = (double)c->val[i] / period_us / 1e3 * 100 /
> -   clients->class[i].num_engines;
> + pct = (double)c->val[i] / period_us / 1e3 * 100;
>  
>   /*
>* Guard against possible time-drift between sampling
>* client data and time we obtained our time-delta from
>* PMU.
>*/
> - if (pct > 100.0)
> - pct = 100.0;
> + max = 100.0 * clients->class[i].num_engines;
> + if (pct > max)
> + pct = max;
>  
> - print_percentage_bar(pct, *class_w, numeric_clients);
> + print_percentage_bar(pct, max, *class_w,
> +  numeric_clients);
>   }
>  
>   putchar('\n');
> -- 
> 2.37.2
> 


Re: [Intel-gfx] [igt-dev] [PATCH i-g-t 2/3] intel_gpu_top: Use full console width for global metrics

2023-04-14 Thread Kamil Konieczny
On 2023-03-28 at 13:54:28 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> It appears we had an off by one of a kind where we were not using the full
> width of the terminal window for the global metrics section.
> 
> Signed-off-by: Tvrtko Ursulin 

Reviewed-by: Kamil Konieczny 

> ---
>  tools/intel_gpu_top.c | 6 ++
>  1 file changed, 2 insertions(+), 4 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index 39be916297e4..36da016c3df0 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -1960,8 +1960,7 @@ print_engines_header(struct engines *engines, double t,
>   a = "  ENGINE BUSY  ";
>  
>   printf("\033[7m%s%*s%s\033[0m\n",
> -a, (int)(con_w - 1 - strlen(a) - strlen(b)),
> -" ", b);
> +a, (int)(con_w - strlen(a) - strlen(b)), " ", b);
>  
>   lines++;
>   }
> @@ -2000,7 +1999,6 @@ print_engine(struct engines *engines, unsigned int i, 
> double t,
>   print_groups(groups);
>  
>   if (output_mode == INTERACTIVE) {
> - unsigned int max_w = con_w - 1;
>   unsigned int len;
>   char buf[128];
>   double val;
> @@ -2012,7 +2010,7 @@ print_engine(struct engines *engines, unsigned int i, 
> double t,
> engine->display_name, engine_items[0].buf);
>  
>   val = pmu_calc(>busy.val, 1e9, t, 100);
> - print_percentage_bar(val, max_w > len ? max_w - len : 0, false);
> + print_percentage_bar(val, con_w > len ? con_w - len : 0, false);
>  
>   printf("%s\n", buf);
>  
> -- 
> 2.37.2
> 


Re: [Intel-gfx] [PATCH i-g-t 1/3] intel_gpu_top: Display large pids nicely in interactive mode

2023-04-14 Thread Kamil Konieczny
Hi,

On 2023-03-28 at 13:54:27 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> So far the width of the PID column was hardcoded to six characters which
> is not enough on systems with high uptime, where PID numbers can grow
> large, and results in broken line formatting.
> 
> Fix it by tracking the largest width for both the pid and name fields and
> use them dynamically.
> 
> Signed-off-by: Tvrtko Ursulin 

Reviewed-by: Kamil Konieczny 

> ---
>  tools/intel_gpu_top.c | 66 +--
>  1 file changed, 58 insertions(+), 8 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index a4302aa389b4..39be916297e4 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright © 2007-2021 Intel Corporation
> + * Copyright © 2007-2023 Intel Corporation
>   *
>   * Permission is hereby granted, free of charge, to any person obtaining a
>   * copy of this software and associated documentation files (the "Software"),
> @@ -693,6 +693,7 @@ struct client {
>   enum client_status status;
>   unsigned int id;
>   unsigned int pid;
> + char pid_str[10];
>   char name[24];
>   char print_name[24];
>   unsigned int samples;
> @@ -709,6 +710,9 @@ struct clients {
>   unsigned int num_classes;
>   struct engine_class *class;
>  
> + int max_pid_len;
> + int max_name_len;
> +
>   char pci_slot[64];
>  
>   struct client *client;
> @@ -758,9 +762,14 @@ update_client(struct client *c, unsigned int pid, char 
> *name,
> const struct drm_client_fdinfo *info)
>  {
>   unsigned int i;
> + int len;
>  
> - if (c->pid != pid)
> + if (c->pid != pid) {
>   c->pid = pid;
> + len = snprintf(c->pid_str, sizeof(c->pid_str) - 1, "%u", pid);
> + if (len > c->clients->max_pid_len)
> + c->clients->max_pid_len = len;
> + }
>  
>   if (strcmp(c->name, name)) {
>   char *p;
> @@ -774,6 +783,10 @@ update_client(struct client *c, unsigned int pid, char 
> *name,
>   *p = '*';
>   p++;
>   }
> +
> + len = strlen(c->print_name);
> + if (len > c->clients->max_name_len)
> + c->clients->max_name_len = len;
>   }
>  
>   c->last_runtime = 0;
> @@ -990,6 +1003,7 @@ static struct clients *display_clients(struct clients 
> *clients)
>   ac->id = -c->pid;
>   ac->pid = c->pid;
>   strcpy(ac->name, c->name);
> + strcpy(ac->pid_str, c->pid_str);
>   strcpy(ac->print_name, c->print_name);
>   ac->val = calloc(clients->num_classes,
>sizeof(ac->val[0]));
> @@ -1013,6 +1027,9 @@ static struct clients *display_clients(struct clients 
> *clients)
>   aggregated->num_clients = num;
>   aggregated->active_clients = num;
>  
> + aggregated->max_pid_len = clients->max_pid_len;
> + aggregated->max_name_len = clients->max_name_len;
> +
>   clients = aggregated;
>  
>  out:
> @@ -1104,9 +1121,34 @@ static size_t readat2buf(int at, const char *name, 
> char *buf, const size_t sz)
>   }
>  }
>  
> +static void clients_update_max_lengths(struct clients *clients)
> +{
> + struct client *c;
> + int tmp;
> +
> + clients->max_name_len = 0;
> + clients->max_pid_len = 0;
> +
> + for_each_client(clients, c, tmp) {
> + int len;
> +
> + if (c->status != ALIVE)
> + continue; /* Array not yet sorted by the caller. */
> +
> + len = strlen(c->print_name);
> + if (len > clients->max_name_len)
> + clients->max_name_len = len;
> +
> + len = strlen(c->pid_str);
> + if (len > clients->max_pid_len)
> + clients->max_pid_len = len;
> + }
> +}
> +
>  static struct clients *scan_clients(struct clients *clients, bool display)
>  {
>   struct dirent *proc_dent;
> + bool freed = false;
>   struct client *c;
>   DIR *proc_dir;
>   int tmp;
> @@ -1208,12 +1250,17 @@ next:
>   closedir(proc_dir);
>  
>   for_each_client(clients, c, tmp) {
> - if (c->status == PROBE)
> + if (c-&

Re: [Intel-gfx] [PATCH i-g-t] tools: Add tool to dump GuC/HuC CSS header

2023-04-04 Thread Kamil Konieczny
On 2023-04-03 at 13:24:37 -0700, Lucas De Marchi wrote:
> Since we are now using unversioned GuC/HuC, it's useful to be able to
> dump the firmware blob and get that information from the CSS header.
> Add a tool that decodes that information and dumps the raw header.
> 
> Example output:
> 
>   $ tools/intel-gfx-fw-info /lib/firmware/i915/tgl_guc_70.bin
>   version: 70.5.1
>   date: 2022-09-09
>   raw dump:
>     06 00 00 00 a1 00 00 00  00 00 01 00 00 00 00 00   
> 
>   0010  86 80 00 00 09 09 22 20  71 17 01 00 40 00 00 00   .." 
> q...@...
>   0020  40 00 00 00 01 00 00 00  09 21 45 00 73 79 73 5f   
> @!E.sys_
>   0030  67 62 73 62 50 43 2d 31  2e 30 2e 33 31 35 30 00   
> gbsbPC-1.0.3150.
>   0040  01 05 46 00 00 00 00 00  00 00 00 00 00 00 00 00   
> ..F.
>   0050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   
> 
>   0060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   
> 
>   0070  00 00 00 00 00 00 00 00  00 10 80 00 00 01 40 00   
> ..@.
> 
>   struct uc_css_header:
>   - module_type: 0x6
>   - header_size_dw: 0xa1
>   - header_version: 0x1
>   - module_id: 0x0
>   - module_vendor: 0x8086
>   - date: 0x20220909
>   - size_dw: 0x11771
>   - key_size_dw: 0x40
>   - modulus_size_dw: 0x40
>   - exponent_size_dw: 0x1
>   - time: 0x452109
>   - username: b'sys_gbsb'
>   - buildnumber: b'PC-1.0.3150\x00'
>   - sw_version: 0x460501
>   - vf_version: 0x0
>   - reserved0: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>   - rsvd: 
>   - header_info: 0x400100
> 
> Signed-off-by: Lucas De Marchi 

Acked-by: Kamil Konieczny 

--
Kamil

> ---
>  tools/intel-gfx-fw-info | 120 
>  tools/meson.build   |   2 +-
>  2 files changed, 121 insertions(+), 1 deletion(-)
>  create mode 100755 tools/intel-gfx-fw-info
> 
> diff --git a/tools/intel-gfx-fw-info b/tools/intel-gfx-fw-info
> new file mode 100755
> index 0..fc1fafdf5
> --- /dev/null
> +++ b/tools/intel-gfx-fw-info
> @@ -0,0 +1,120 @@
> +#!/usr/bin/env python3
> +# pylint: disable=C0301
> +# SPDX-License-Identifier: (GPL-2.0 OR MIT)
> +#
> +# Copyright (C) 2023Intel Corporation
> +
> +import argparse
> +import logging
> +import pprint
> +import sys
> +import typing
> +
> +from dissect import cstruct
> +
> +# struct definition below should match the one from i915
> +# (drivers/gpu/drm/i915/gt/uc/intel_uc_fw_abi.h) and xe
> +# (drivers/gpu/drm/xe/xe_uc_fw_abi.h).
> +#
> +# For compatibility reasons with dissect.cstruct python module, the following
> +# things are changed from the original kernel definition:
> +#
> +#   1) Comments removed
> +#   2) No anonymous union - not compatible with the
> +#  dumpstruct(), give it a name
> +
> +CDEF = """
> +typedef uint32 u32;
> +
> +struct uc_css_header {
> +u32 module_type;
> +u32 header_size_dw;
> +u32 header_version;
> +u32 module_id;
> +u32 module_vendor;
> +u32 date;
> +u32 size_dw;
> +u32 key_size_dw;
> +u32 modulus_size_dw;
> +u32 exponent_size_dw;
> +u32 time;
> +char username[8];
> +char buildnumber[12];
> +u32 sw_version;
> +u32 vf_version;
> +u32 reserved0[12];
> +union {
> +u32 private_data_size;
> +u32 reserved1;
> +} rsvd;
> +u32 header_info;
> +};
> +"""
> +
> +logger = logging.getLogger(__name__)
> +
> +
> +def ffs(x: int) -> int:
> +"""Returns the index, counting from 0, of the
> +least significant set bit in `x`.
> +"""
> +return (x & -x).bit_length() - 1
> +
> +
> +def FIELD_GET(mask: int, value: int) -> int:
> +return (value & mask) >> ffs(mask)
> +
> +
> +def decode(fw) -> str:
> +data = []
> +
> +CSS_SW_VERSION_UC_MAJOR = 0xFF << 16
> +CSS_SW_VERSION_UC_MINOR = 0xFF << 8
> +CSS_SW_VERSION_UC_PATCH = 0xFF
> +major = FIELD_GET(CSS_SW_VERSION_UC_MAJOR, fw.sw_version)
> +minor = FIELD_GET(CSS_SW_VERSION_UC_MINOR, fw.sw_version)
> +patch = FIELD_GET(CSS_SW_VERSION_UC_PATCH, fw.sw_version)
> +data += [f"version: {major}.{minor}.{patch}"]
> +
> +CSS_DATE_DAY = 0xFF
> +CSS_DATE_MONTH = 0xFF << 8
> +CSS_DATE_YEAR = 0x &l

Re: [Intel-gfx] [PATCH i-g-t v2] tests/i915_suspend: Refresh device list after *-without-i915 subtests

2023-02-24 Thread Kamil Konieczny
On 2023-02-13 at 15:34:45 +0100, Janusz Krzysztofik wrote:
> If any of *-without-i915 subtests fails or skips for any reason, it may
> leave the i915 module unloaded while keeping our device list populated
> with initially collected data.  In a follow up igt_fixture section we then
> try to reopen the device.  If the test has been executed with a device
> filter specified, an attempt to open the device finds a matching entry
> that belongs to the no longer existing device in that initially collected
> device list, fails to stat() it, concludes that's because of the device
> having been already open, and returns an error.  While that error,
> triggered after subtests completion, doesn't affect results of the
> subtest, reported by CI togethger with those results it is confusing to
> users reviewing those reports.
> 
> Fix this issue by refreshing the potentially outdated device list before
> continuing with drm_open_driver() if we've been called with a device
> filter specified.
> 
> While being at it, add a comment that explains why we call
> igt_devices_scan() from __igt_device_card_match() but don't force device
> rescan, and emit a debug message if we fail in _is_already_opened() on
> unsuccessful device stat().
> 
> v2: don't free the device list -- we can't tell if it has been populated,
> and igt_devices_free() fails if it hasn't,
>   - commit message updated, description improved.
> 
> Subtest basic-s3-without-i915: FAIL (9.572s)
> (i915_suspend:9050) drmtest-WARNING: card maching filter 0 is already opened
> (i915_suspend:9050) drmtest-CRITICAL: Test abort in function drm_open_driver, 
> file ../lib/drmtest.c:639:
> (i915_suspend:9050) drmtest-CRITICAL: abort condition: fd < 0
> (i915_suspend:9050) drmtest-CRITICAL: Last errno: 2, No such file or directory
> (i915_suspend:9050) drmtest-CRITICAL: No known gpu found for chipset flags 
> 0x1 (intel)
> Test i915_suspend failed.
>  DEBUG 
> (i915_suspend:9050) drmtest-DEBUG: Looking for devices to open using filter 
> 0: pci:vendor=intel,device=dg2
> (i915_suspend:9050) drmtest-DEBUG: Filter matched /dev/dri/card0 | 
> /dev/dri/renderD128
> (i915_suspend:9050) drmtest-WARNING: card maching filter 0 is already opened
> (i915_suspend:9050) drmtest-CRITICAL: Test abort in function drm_open_driver, 
> file ../lib/drmtest.c:639:
> (i915_suspend:9050) drmtest-CRITICAL: abort condition: fd < 0
> (i915_suspend:9050) drmtest-CRITICAL: Last errno: 2, No such file or directory
> (i915_suspend:9050) drmtest-CRITICAL: No known gpu found for chipset flags 
> 0x1 (intel)
> (i915_suspend:9050) igt_core-INFO: Stack trace:
> (i915_suspend:9050) igt_core-INFO:   #0 ../lib/igt_core.c:2066 __igt_abort()
> (i915_suspend:9050) igt_core-INFO:   #1 ../lib/drmtest.c:573 drm_open_driver()
> (i915_suspend:9050) igt_core-INFO:   #2 ../tests/i915/i915_suspend.c:258 
> __igt_uniquereal_main245()
> (i915_suspend:9050) igt_core-INFO:   #3 ../tests/i915/i915_suspend.c:245 
> main()
> (i915_suspend:9050) igt_core-INFO:   #4 
> ../sysdeps/nptl/libc_start_call_main.h:58 __libc_start_call_main()
> (i915_suspend:9050) igt_core-INFO:   #5 ../csu/libc-start.c:128 
> __libc_start_main@@GLIBC_2.34()
> (i915_suspend:9050) igt_core-INFO:   #6 [_start+0x2a]
>   END  ****
> 
> Fixes: f7aff600ab16 ("tests/i915/i915_suspend: Disable d3cold_allowed for 
> basic-s2idle-without-i915")
> Signed-off-by: Janusz Krzysztofik 
> Cc: Riana Tauro 

Reviewed-by: Kamil Konieczny 

> ---
>  lib/drmtest.c |  2 +-
>  lib/igt_device_scan.c |  4 
>  tests/i915/i915_suspend.c | 12 +++-
>  3 files changed, 16 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/drmtest.c b/lib/drmtest.c
> index 16e80bdfcf..8e2d1ac50b 100644
> --- a/lib/drmtest.c
> +++ b/lib/drmtest.c
> @@ -260,7 +260,7 @@ static bool _is_already_opened(const char *path, int 
> as_idx)
>* we cannot even stat the device, so it's of no use - let's claim it's
>* already opened
>*/
> - if (stat(path, ) != 0)
> + if (igt_debug_on(stat(path, ) != 0))
>   return true;
>  
>   for (int i = 0; i < as_idx; ++i) {
> diff --git a/lib/igt_device_scan.c b/lib/igt_device_scan.c
> index 8b767eed20..ae69ed09f1 100644
> --- a/lib/igt_device_scan.c
> +++ b/lib/igt_device_scan.c
> @@ -1918,6 +1918,10 @@ static bool __igt_device_card_match(const char *filter,
>   return false;
>   memset(card, 0, sizeof(*card));
>  
> + /*
> +  * Scan devices in case the user hasn't yet,
> +  * but leave a decision on forced rescan on the user side.
> +  */
>   igt_devices_scan(false);
>  
>   if (igt_device_filter_apply(filter) == f

Re: [Intel-gfx] [PATCH i-g-t] tests/gem_barrier_race: Extend support over compute engines

2023-02-20 Thread Kamil Konieczny
On 2023-02-20 at 14:24:45 +0100, Janusz Krzysztofik wrote:
> This test can work not only on render engines, as its current code
> suggests, but also on compute class engines.  Add them to the set of
> engine classes supported by the test, in case a future platform has only
> those and no RCS available.

Lgtm,
Reviewed-by: Kamil Konieczny 

--
Kamil

> 
> Suggested-by: Chris Wilson 
> Signed-off-by: Janusz Krzysztofik 
> ---
>  tests/i915/gem_barrier_race.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/tests/i915/gem_barrier_race.c b/tests/i915/gem_barrier_race.c
> index 484fef85ac..053fa2069e 100644
> --- a/tests/i915/gem_barrier_race.c
> +++ b/tests/i915/gem_barrier_race.c
> @@ -142,7 +142,8 @@ igt_main
>   struct intel_execution_engine2 *e;
>  
>   for_each_physical_engine(fd, e) {
> - if (e->class != I915_ENGINE_CLASS_RENDER)
> + if (e->class != I915_ENGINE_CLASS_RENDER &&
> + e->class != I915_ENGINE_CLASS_COMPUTE)
>   continue;
>  
>   igt_dynamic(e->name)
> -- 
> 2.25.1
> 


Re: [Intel-gfx] [PATCH i-g-t v4] tests: Exercise remote request vs barrier handling race

2023-02-16 Thread Kamil Konieczny
Hi Janusz,

On 2023-02-15 at 10:19:52 +0100, Janusz Krzysztofik wrote:
> Users reported oopses on list corruptions when using i915 perf with a
> number of concurrently running graphics applications.  That indicates we
> are currently missing some important tests for such scenarios.  Cover
> that gap.
> 
> Root cause analysis pointed out to an issue in barrier processing code and
> its interaction with perf replacing kernel contexts' active barriers with
> its own requests.
> 
> Add a new test intended for exercising intentionally racy barrier tasks
> list processing and its interaction with other i915 subsystems.  As a
> first subtest, add one that exercises the interaction of remote requests
> with barrier tasks list handling, especially barrier preallocate / acquire
> operations performed during context first pin / last unpin.
> 
> The code is partially inspired by Chris Wilson's igt@perf@open-race
> subtest, which I was not able to get an Ack for from upstream.
> 
> v4: fix typo in test description and make it generic so it will not need
> to be changed soon (Kamil),
>   - rename workload functions instead of providing name wrappers (Kamil),
>   - no need for all physical engines to be tested (Kamil).
> v3: don't add the new subtest to gem_ctx_exec which occurred blocklisted,
> create a new test hosting the new subtest, update commit descripion,
>   - prepare parameters for perf open still in the main thread to avoid
> test failures on platforms with no perf support (will skip now),
>   - call perf open with OA buffer reports disabled, this will make sure
> that the perf API doesn't unnecessarily enable the OA unit, while the
> test still runs the targeted code (Umesh),
>   - replace additional code for OA exponent calculations with a reasonable
> hardcoded value (Umesh).
> v2: convert to a separate subtest, not a variant of another one (that has
> been dropped from the series),
>   - move the subtest out of tests/i915/perf.c (Ashutosh), add it to
> tests/i915/gem_ctx_exec.c,
>   - don't touch lib/i915/perf.c (Umesh, Ashutosh), duplicate reused code
> from tests/i915/perf.c in tests/i915/gem_ctx_exec.c.
> 
> References: https://gitlab.freedesktop.org/drm/intel/-/issues/6333
> Signed-off-by: Janusz Krzysztofik 
> Cc: Chris Wilson 
> Cc: Kamil Konieczny 
> Cc: Ashutosh Dixit 
> Cc: Umesh Nerlige Ramappa 
> ---
>  tests/i915/gem_barrier_race.c | 153 ++
>  tests/meson.build |   8 ++
>  2 files changed, 161 insertions(+)
>  create mode 100644 tests/i915/gem_barrier_race.c
> 
> diff --git a/tests/i915/gem_barrier_race.c b/tests/i915/gem_barrier_race.c
> new file mode 100644
> index 00..594a043c16
> --- /dev/null
> +++ b/tests/i915/gem_barrier_race.c
> @@ -0,0 +1,153 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright(c) 2023 Intel Corporation. All rights reserved.
> + */
> +
> +#include 
> +
> +#include "drmtest.h"
> +#include "igt_aux.h"
> +#include "igt_core.h"
> +#include "igt_gt.h"
> +#include "intel_chipset.h"
> +#include "intel_reg.h"
> +#include "ioctl_wrappers.h"
> +
> +#include "i915/gem.h"
> +#include "i915/gem_create.h"
> +#include "i915/gem_engine_topology.h"
> +#include "i915/perf.h"
> +
> +IGT_TEST_DESCRIPTION("Exercise engine barriers and their interaction with 
> other subsystems");
> +
> +static void remote_request_workload(int fd, int *done)
> +{
> + /*
> +  * Use DRM_IOCTL_I915_PERF_OPEN / close as
> +  * intel_context_prepare_remote_request() workload
> +  *
> +  * Based on code patterns found in tests/i915/perf.c
> +  */
> + struct intel_perf_metric_set *metric_set = NULL, *metric_set_iter;
> + struct intel_perf *intel_perf = intel_perf_for_fd(fd);
> + uint64_t properties[] = {
> + DRM_I915_PERF_PROP_SAMPLE_OA, true,
> + DRM_I915_PERF_PROP_OA_METRICS_SET, 0,
> + DRM_I915_PERF_PROP_OA_FORMAT, 0,
> + DRM_I915_PERF_PROP_OA_EXPONENT, 5,
> + };
> + struct drm_i915_perf_open_param param = {
> + .flags = I915_PERF_FLAG_FD_CLOEXEC | I915_PERF_FLAG_DISABLED,
> + .num_properties = sizeof(properties) / 16,
> + .properties_ptr = to_user_pointer(properties),
> + };
> + uint32_t devid = intel_get_drm_devid(fd);
> +
> + igt_require(intel_perf);
> + intel_perf_load_perf_configs(intel_perf, fd);
> +
> + igt_require(devid);
> + igt_list_for_each_entry(metric_set_iter, _perf->metric_sets, 
> link) {
> + if (!

Re: [Intel-gfx] [PATCH i-g-t v3 1/1] tests: Exercise remote request vs barrier handling race

2023-02-14 Thread Kamil Konieczny
Hi Janusz,

On 2023-02-13 at 10:31:32 +0100, Janusz Krzysztofik wrote:
> Users reported oopses on list corruptions when using i915 perf with a
> number of concurrently running graphics applications.  That indicates we
> are currently missing some important tests for such scenarios.  Cover
> that gap.
> 
> Root cause analysis pointed out to an issue in barrier processing code and
> its interaction with perf replacing kernel contexts' active barriers with
> its own requests.
> 
> Add a new test intended for exercising intentionally racy barrier tasks
> list processing and its interaction with other i915 subsystems.  As a
> first subtest, add one that exercises the interaction of remote requests
> with barrier tasks list handling, especially barrier preallocate / acquire
> operations performed during context first pin / last unpin.
> 
> The code is partially inspired by Chris Wilson's igt@perf@open-race
> subtest, which I was not able to get an Ack for from upstream.
> 
> v3: don't add the new subtest to gem_ctx_exec which occurred blocklisted,
> create a new test hosting the new subtest, update commit descripion,
>   - prepare parameters for perf open still in the main thread to avoid
> test failures on platforms with no perf support (will skip now),
>   - call perf open with OA buffer reports disabled, this will make sure
> that the perf API doesn't unnecessarily enable the OA unit, while the
> test still runs the targeted code (Umesh),
>   - replace additional code for OA exponent calculations with a reasonable
> hardcoded value (Umesh).
> v2: convert to a separate subtest, not a variant of another one (that has
> been dropped from the series),
>   - move the subtest out of tests/i915/perf.c (Ashutosh), add it to
> tests/i915/gem_ctx_exec.c,
>   - don't touch lib/i915/perf.c (Umesh, Ashutosh), duplicate reused code
> from tests/i915/perf.c in tests/i915/gem_ctx_exec.c.
> 
> References: https://gitlab.freedesktop.org/drm/intel/-/issues/6333
> Signed-off-by: Janusz Krzysztofik 
> Cc: Chris Wilson 
> Cc: Kamil Konieczny 
> Cc: Ashutosh Dixit 
> Cc: Umesh Nerlige Ramappa 
> ---
>  tests/i915/gem_barrier_race.c | 159 ++
>  tests/meson.build |   8 ++
>  2 files changed, 167 insertions(+)
>  create mode 100644 tests/i915/gem_barrier_race.c
> 
> diff --git a/tests/i915/gem_barrier_race.c b/tests/i915/gem_barrier_race.c
> new file mode 100644
> index 00..fd0c7bdf1c
> --- /dev/null
> +++ b/tests/i915/gem_barrier_race.c
> @@ -0,0 +1,159 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright(c) 2023 Intel Corporation. All rights reserved.
> + */
> +
> +#include 
> +
> +#include "drmtest.h"
> +#include "igt_aux.h"
> +#include "igt_core.h"
> +#include "igt_gt.h"
> +#include "intel_chipset.h"
> +#include "intel_reg.h"
> +#include "ioctl_wrappers.h"
> +
> +#include "i915/gem.h"
> +#include "i915/gem_create.h"
> +#include "i915/gem_engine_topology.h"
> +#include "i915/perf.h"
> +
> +IGT_TEST_DESCRIPTION("Exercise barrier tasks list handling and its 
> interation with other i915 subsystems");
--- ^ 
--^-- ^
s/interation/interaction/

Please make it generic so it will not need to be changed soon,
for example:
IGT_TEST_DESCRIPTION("Exercise barrier tasks and its interaction with other 
subsystems");

> +
> +/* Based on code patterns found in tests/i915/perf.c */
> +static void perf_open_close_workload(int fd, int *done)
> +{
> + struct intel_perf_metric_set *metric_set = NULL, *metric_set_iter;
> + struct intel_perf *intel_perf = intel_perf_for_fd(fd);
> + uint64_t properties[] = {
> + DRM_I915_PERF_PROP_SAMPLE_OA, true,
> + DRM_I915_PERF_PROP_OA_METRICS_SET, 0,
> + DRM_I915_PERF_PROP_OA_FORMAT, 0,
> + DRM_I915_PERF_PROP_OA_EXPONENT, 5,
> + };
> + struct drm_i915_perf_open_param param = {
> + .flags = I915_PERF_FLAG_FD_CLOEXEC | I915_PERF_FLAG_DISABLED,
> + .num_properties = sizeof(properties) / 16,
> + .properties_ptr = to_user_pointer(properties),
> + };
> + uint32_t devid = intel_get_drm_devid(fd);
> +
> + igt_require(intel_perf);
> + intel_perf_load_perf_configs(intel_perf, fd);
> +
> + igt_require(devid);
> + igt_list_for_each_entry(metric_set_iter, _perf->metric_sets, 
> link) {
> + if (!strcmp(metric_set_iter->symbol_name,
> + IS_HASWELL(

Re: [Intel-gfx] [PATCH i-g-t] tests/i915_suspend: Free device list after *-without-i915 subtests

2023-02-10 Thread Kamil Konieczny
Hi Janusz,

On 2023-02-10 at 15:21:20 +0100, Janusz Krzysztofik wrote:
> On Friday, 10 February 2023 15:02:59 CET Kamil Konieczny wrote:
> > Hi Janusz,
> > 
> > I have one nit, see below.
> > 
> > On 2023-02-09 at 20:32:31 +0100, Janusz Krzysztofik wrote:
> > > If any of *-without-i915 subtests fails or skips for any reason, it may
> > > leave the i915 module unloaded while keeping our device list populated
> > > with initially collected data.  In a follow up igt_fixture section we then
> > > try to reopen the device.  If the test has been executed with a device
> > > filter specified, an attempt to open the device finds a matching entry
> > > that belongs to the no longer existing device in that initially collected
> > > device list, fails to stat() it, concludes that's because of the device
> > > having been already open, and returns an error.
> > > 
> > > Fix this potentially confusing test result by freeing the potentially
> > > outdated device list before continuing with drm_open_driver().
> > > 
> > > While being at it, add a comment that explains why we call
> > > igt_device_scan() from __igt_device_card_match() but don't force device
> > > rescan, and emit a debug message if we fail in _is_already_opened() on
> > > unsuccessful device stat().
> > > 
> > > Subtest basic-s3-without-i915: FAIL (9.572s)
> > > (i915_suspend:9050) drmtest-WARNING: card maching filter 0 is already 
> > > opened
> > > (i915_suspend:9050) drmtest-CRITICAL: Test abort in function 
> > > drm_open_driver, file ../lib/drmtest.c:639:
> > > (i915_suspend:9050) drmtest-CRITICAL: abort condition: fd < 0
> > > (i915_suspend:9050) drmtest-CRITICAL: Last errno: 2, No such file or 
> > > directory
> > > (i915_suspend:9050) drmtest-CRITICAL: No known gpu found for chipset 
> > > flags 0x1 (intel)
> > > Test i915_suspend failed.
> > >  DEBUG 
> > > (i915_suspend:9050) drmtest-DEBUG: Looking for devices to open using 
> > > filter 0: pci:vendor=intel,device=dg2
> > > (i915_suspend:9050) drmtest-DEBUG: Filter matched /dev/dri/card0 | 
> > > /dev/dri/renderD128
> > > (i915_suspend:9050) drmtest-WARNING: card maching filter 0 is already 
> > > opened
> > > (i915_suspend:9050) drmtest-CRITICAL: Test abort in function 
> > > drm_open_driver, file ../lib/drmtest.c:639:
> > > (i915_suspend:9050) drmtest-CRITICAL: abort condition: fd < 0
> > > (i915_suspend:9050) drmtest-CRITICAL: Last errno: 2, No such file or 
> > > directory
> > > (i915_suspend:9050) drmtest-CRITICAL: No known gpu found for chipset 
> > > flags 0x1 (intel)
> > > (i915_suspend:9050) igt_core-INFO: Stack trace:
> > > (i915_suspend:9050) igt_core-INFO:   #0 ../lib/igt_core.c:2066 
> > > __igt_abort()
> > > (i915_suspend:9050) igt_core-INFO:   #1 ../lib/drmtest.c:573 
> > > drm_open_driver()
> > > (i915_suspend:9050) igt_core-INFO:   #2 ../tests/i915/i915_suspend.c:258 
> > > __igt_uniquereal_main245()
> > > (i915_suspend:9050) igt_core-INFO:   #3 ../tests/i915/i915_suspend.c:245 
> > > main()
> > > (i915_suspend:9050) igt_core-INFO:   #4 
> > > ../sysdeps/nptl/libc_start_call_main.h:58 __libc_start_call_main()
> > > (i915_suspend:9050) igt_core-INFO:   #5 ../csu/libc-start.c:128 
> > > __libc_start_main@@GLIBC_2.34()
> > > (i915_suspend:9050) igt_core-INFO:   #6 [_start+0x2a]
> > >   END  
> > > 
> > > Fixes: f7aff600ab16 ("tests/i915/i915_suspend: Disable d3cold_allowed for 
> > > basic-s2idle-without-i915")
> > > Signed-off-by: Janusz Krzysztofik 
> > > Cc: Riana Tauro 
> > > ---
> > >  lib/drmtest.c |  2 +-
> > >  lib/igt_device_scan.c |  4 
> > >  tests/i915/i915_suspend.c | 10 +-
> > >  3 files changed, 14 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/lib/drmtest.c b/lib/drmtest.c
> > > index 16e80bdfcf..8e2d1ac50b 100644
> > > --- a/lib/drmtest.c
> > > +++ b/lib/drmtest.c
> > > @@ -260,7 +260,7 @@ static bool _is_already_opened(const char *path, int 
> > > as_idx)
> > >* we cannot even stat the device, so it's of no use - let's claim it's
> > >* already opened
> > >*/
> > > - if (stat(path, ) != 0)
> > > + if (igt_debug_on(stat(path, ) != 0))
> > 
> > This one looks a little too much, for example it can return -ENOENT
> 
> I'm not sure what

Re: [Intel-gfx] [PATCH i-g-t] intel_gpu_top: Add compute class names

2023-02-10 Thread Kamil Konieczny
Hi Tvrtko,

On 2023-02-10 at 15:22:07 +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> No one remembered to add names for the new compute engines.

Actually there was patch:
https://patchwork.freedesktop.org/series/112674/
intel_gpu_top: Add display name for compute engine class
Submitted by Christopher Snowhill on Jan. 11, 2023, 1:22 p.m. 

What prevented me from merge was From: != s-o-b

Christopher Snowhill  != Christopher Snowhill 


warning from checkpatch.pl but if you think it is minor warn
you are free to give r-b and to merge that.

+cc Christopher

Regards,
Kamil

> 
> Signed-off-by: Tvrtko Ursulin 
> ---
>  tools/intel_gpu_top.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index c043c8960dd0..e13e35b71f4b 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -281,6 +281,8 @@ static const char *class_display_name(unsigned int class)
>   return "Video";
>   case I915_ENGINE_CLASS_VIDEO_ENHANCE:
>   return "VideoEnhance";
> + case I915_ENGINE_CLASS_COMPUTE:
> + return "Compute";
>   default:
>   return "[unknown]";
>   }
> @@ -297,6 +299,8 @@ static const char *class_short_name(unsigned int class)
>   return "VCS";
>   case I915_ENGINE_CLASS_VIDEO_ENHANCE:
>   return "VECS";
> + case I915_ENGINE_CLASS_COMPUTE:
> + return "CCS";
>   default:
>   return "UNKN";
>   }
> -- 
> 2.34.1
> 


Re: [Intel-gfx] [PATCH i-g-t] tests/i915_suspend: Free device list after *-without-i915 subtests

2023-02-10 Thread Kamil Konieczny
Hi Janusz,

I have one nit, see below.

On 2023-02-09 at 20:32:31 +0100, Janusz Krzysztofik wrote:
> If any of *-without-i915 subtests fails or skips for any reason, it may
> leave the i915 module unloaded while keeping our device list populated
> with initially collected data.  In a follow up igt_fixture section we then
> try to reopen the device.  If the test has been executed with a device
> filter specified, an attempt to open the device finds a matching entry
> that belongs to the no longer existing device in that initially collected
> device list, fails to stat() it, concludes that's because of the device
> having been already open, and returns an error.
> 
> Fix this potentially confusing test result by freeing the potentially
> outdated device list before continuing with drm_open_driver().
> 
> While being at it, add a comment that explains why we call
> igt_device_scan() from __igt_device_card_match() but don't force device
> rescan, and emit a debug message if we fail in _is_already_opened() on
> unsuccessful device stat().
> 
> Subtest basic-s3-without-i915: FAIL (9.572s)
> (i915_suspend:9050) drmtest-WARNING: card maching filter 0 is already opened
> (i915_suspend:9050) drmtest-CRITICAL: Test abort in function drm_open_driver, 
> file ../lib/drmtest.c:639:
> (i915_suspend:9050) drmtest-CRITICAL: abort condition: fd < 0
> (i915_suspend:9050) drmtest-CRITICAL: Last errno: 2, No such file or directory
> (i915_suspend:9050) drmtest-CRITICAL: No known gpu found for chipset flags 
> 0x1 (intel)
> Test i915_suspend failed.
>  DEBUG 
> (i915_suspend:9050) drmtest-DEBUG: Looking for devices to open using filter 
> 0: pci:vendor=intel,device=dg2
> (i915_suspend:9050) drmtest-DEBUG: Filter matched /dev/dri/card0 | 
> /dev/dri/renderD128
> (i915_suspend:9050) drmtest-WARNING: card maching filter 0 is already opened
> (i915_suspend:9050) drmtest-CRITICAL: Test abort in function drm_open_driver, 
> file ../lib/drmtest.c:639:
> (i915_suspend:9050) drmtest-CRITICAL: abort condition: fd < 0
> (i915_suspend:9050) drmtest-CRITICAL: Last errno: 2, No such file or directory
> (i915_suspend:9050) drmtest-CRITICAL: No known gpu found for chipset flags 
> 0x1 (intel)
> (i915_suspend:9050) igt_core-INFO: Stack trace:
> (i915_suspend:9050) igt_core-INFO:   #0 ../lib/igt_core.c:2066 __igt_abort()
> (i915_suspend:9050) igt_core-INFO:   #1 ../lib/drmtest.c:573 drm_open_driver()
> (i915_suspend:9050) igt_core-INFO:   #2 ../tests/i915/i915_suspend.c:258 
> __igt_uniquereal_main245()
> (i915_suspend:9050) igt_core-INFO:   #3 ../tests/i915/i915_suspend.c:245 
> main()
> (i915_suspend:9050) igt_core-INFO:   #4 
> ../sysdeps/nptl/libc_start_call_main.h:58 __libc_start_call_main()
> (i915_suspend:9050) igt_core-INFO:   #5 ../csu/libc-start.c:128 
> __libc_start_main@@GLIBC_2.34()
> (i915_suspend:9050) igt_core-INFO:   #6 [_start+0x2a]
>   END  
> 
> Fixes: f7aff600ab16 ("tests/i915/i915_suspend: Disable d3cold_allowed for 
> basic-s2idle-without-i915")
> Signed-off-by: Janusz Krzysztofik 
> Cc: Riana Tauro 
> ---
>  lib/drmtest.c |  2 +-
>  lib/igt_device_scan.c |  4 
>  tests/i915/i915_suspend.c | 10 +-
>  3 files changed, 14 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/drmtest.c b/lib/drmtest.c
> index 16e80bdfcf..8e2d1ac50b 100644
> --- a/lib/drmtest.c
> +++ b/lib/drmtest.c
> @@ -260,7 +260,7 @@ static bool _is_already_opened(const char *path, int 
> as_idx)
>* we cannot even stat the device, so it's of no use - let's claim it's
>* already opened
>*/
> - if (stat(path, ) != 0)
> + if (igt_debug_on(stat(path, ) != 0))

This one looks a little too much, for example it can return -ENOENT

Rest looks ok.

Regards,
Kamil

>   return true;
>  
>   for (int i = 0; i < as_idx; ++i) {
> diff --git a/lib/igt_device_scan.c b/lib/igt_device_scan.c
> index 8b767eed20..ae69ed09f1 100644
> --- a/lib/igt_device_scan.c
> +++ b/lib/igt_device_scan.c
> @@ -1918,6 +1918,10 @@ static bool __igt_device_card_match(const char *filter,
>   return false;
>   memset(card, 0, sizeof(*card));
>  
> + /*
> +  * Scan devices in case the user hasn't yet,
> +  * but leave a decision on forced rescan on the user side.
> +  */
>   igt_devices_scan(false);
>  
>   if (igt_device_filter_apply(filter) == false)
> diff --git a/tests/i915/i915_suspend.c b/tests/i915/i915_suspend.c
> index 815f1c8a2c..c68110476e 100644
> --- a/tests/i915/i915_suspend.c
> +++ b/tests/i915/i915_suspend.c
> @@ -253,8 +253,16 @@ igt_main
>   igt_subtest("basic-s3-without-i915")
>   test_suspend_without_i915(SUSPEND_STATE_S3);
>  
> - igt_fixture
> + igt_fixture {
> + /*
> +  * Since above tests may fail leaving the i915 module unloaded,
> +  * force refresh of device list before opening an i915 device
> +  * by cleaning up the current device list, otherwise we can fail
> +

Re: [Intel-gfx] [PATCH i-g-t v2 0/1] tests/i915/perf: Add stress / race exercises

2023-02-10 Thread Kamil Konieczny
Hi,

On 2023-02-10 at 08:53:12 +0100, Janusz Krzysztofik wrote:
> Hi,
> 
> On Thursday, 9 February 2023 12:50:38 CET Janusz Krzysztofik wrote:
> > Users reported oopses on list corruptions when using i915 perf with a
> > number of concurrently running graphics applications.  That indicates we
> > are currently missing some important tests for such scenarios.  Cover
> > that gap.
> > 
> > v2: drop open-race subtest for now, not capable of triggering the user
> > reported bug, but triggering other bugs which I can't see any fixes
> > for queued yet,
> >   - move the other new subtest out of tests/i915/perf.c (Ashutosh).
> > 
> > Janusz Krzysztofik (1):
> >   tests/gem_ctx_exec: Exercise barrier race
> 
> While still waiting for CI results (BAT results don't cover the new subtest) 
> I've collected results from a forced execution of the subtest in BAT scope on 
> trybot: https://patchwork.freedesktop.org/series/113608/#rev2
> 
> While working as expected on most platforms, the test failed on some ancient 
> ones instead of skipping.  I've fixed this issue and tested the fix 
> successfully on trybot: https://patchwork.freedesktop.org/series/113608/#rev3
> 
> I'm still waiting for your comments, if any, before I submit the fixed 
> version.

Patch looks good but as you already noticed it is blacklisted
and do not cause noticeable fail. Proposed solution is to move
it to other test or to create new one, imho one you proposed

igt@gem_barrier_race@remote-request

looks good.

Regards,
Kamil

> 
> Thanks,
> Janusz
> 
> > 
> >  tests/i915/gem_ctx_exec.c | 123 ++
> >  tests/meson.build |   9 ++-
> >  2 files changed, 131 insertions(+), 1 deletion(-)
> > 
> > 
> 
> 
> 
> 


Re: [Intel-gfx] [PATCH i-g-t 1/3] intel_gpu_top: Do not repeat header lines in non-interactive output

2023-02-08 Thread Kamil Konieczny
Hi Tvrtko,

one small nit, see below.

On 2023-02-03 at 11:16:34 +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> If output is redirected to a file, or a pipe, lets not repeat the headers
> because that can usually mean user is trying to parse the data later and
> so repeated headers are a hindrance.
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Caleb Callaway 
> ---
>  tools/intel_gpu_top.c | 19 ++-
>  1 file changed, 14 insertions(+), 5 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index 0a1de41b3374..e2a7f4753099 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -1391,6 +1391,7 @@ static unsigned int stdout_level;
>  
>  #define STDOUT_HEADER_REPEAT 20
>  static unsigned int stdout_lines = STDOUT_HEADER_REPEAT;
> +static bool stdout_header_repeat;
>  
>  static void
>  stdout_open_struct(const char *name)
> @@ -1580,16 +1581,22 @@ static const struct print_operations term_pops = {
>  
>  static bool print_groups(struct cnt_group **groups)
>  {
> - unsigned int headers = stdout_lines % STDOUT_HEADER_REPEAT + 1;
> + static bool headers_printed = false;
--- ^
Remove this initialization (use checkpatch from Linux kernel).

Please correct and resend (you can keep my r-b).

Regards,
Kamil

>   bool print_data = true;
>  
> - if (output_mode == STDOUT && (headers == 1 || headers == 2)) {
> - for (struct cnt_group **grp = groups; *grp; grp++)
> - print_data = pops->print_group(*grp, headers);
> + if (output_mode == STDOUT &&
> + (stdout_header_repeat || !headers_printed)) {
> + unsigned int headers = stdout_lines % STDOUT_HEADER_REPEAT + 1;
> +
> + if (headers == 1 || headers == 2)
> + for (struct cnt_group **grp = groups; *grp; grp++)
> + print_data = pops->print_group(*grp, headers);
> +
> + headers_printed = print_data;
>   }
>  
>   for (struct cnt_group **grp = groups; print_data && *grp; grp++)
> - pops->print_group(*grp, false);
> + pops->print_group(*grp, 0);
>  
>   return print_data;
>  }
> @@ -2512,6 +2519,8 @@ int main(int argc, char **argv)
>   out = stdout;
>   }
>  
> + stdout_header_repeat = output_mode == STDOUT && isatty(fileno(out));
> +
>   if (signal(SIGINT, sigint_handler) == SIG_ERR)
>   fprintf(stderr, "Failed to install signal handler!\n");
>  
> -- 
> 2.34.1
> 


Re: [Intel-gfx] [PATCH i-g-t 3/3] intel_gpu_top: Add CSV output format

2023-02-07 Thread Kamil Konieczny
On 2023-02-03 at 11:31:19 +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Add CSV output mode.
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Caleb Callaway 

Reviewed-by: Kamil Konieczny 

> ---
>  man/intel_gpu_top.rst |  3 ++
>  tools/intel_gpu_top.c | 78 +--
>  2 files changed, 78 insertions(+), 3 deletions(-)
> 
> diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
> index 69834756b81e..2d041457a95e 100644
> --- a/man/intel_gpu_top.rst
> +++ b/man/intel_gpu_top.rst
> @@ -31,6 +31,9 @@ OPTIONS
>  -h
>  Show help text.
>  
> +-c
> +Output CSV formatted data.
> +
>  -J
>  Output JSON formatted data.
>  
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index a980cc7043dc..2e1365959d8b 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -1268,6 +1268,7 @@ usage(const char *appname)
>   "\n"
>   "\tThe following parameters are optional:\n\n"
>   "\t[-h]Show this help text.\n"
> + "\t[-c]Output CSV formatted data.\n"
>   "\t[-J]Output JSON formatted data.\n"
>   "\t[-l]List plain text data.\n"
>   "\t[-o ]   Output to specified file or '-' for standard 
> out.\n"
> @@ -1283,6 +1284,7 @@ usage(const char *appname)
>  static enum {
>   INTERACTIVE,
>   TEXT,
> + CSV,
>   JSON
>  } output_mode;
>  
> @@ -1457,6 +1459,22 @@ text_add_member(const struct cnt_group *parent, struct 
> cnt_item *item,
>   return len > 0 ? len : 0;
>  }
>  
> +static unsigned int
> +csv_add_member(const struct cnt_group *parent, struct cnt_item *item,
> +unsigned int headers)
> +{
> + int len = 0;
> +
> + if (headers)
> + fprintf(out, "%s %s", parent->display_name, item->unit);
> + else
> + len = fprintf(out, "%f",
> +   pmu_calc(>pmu->val, item->d, item->t,
> +item->s));
> +
> + return len > 0 ? len : 0;
> +}
> +
>  static void
>  term_open_struct(const char *name)
>  {
> @@ -1540,6 +1558,46 @@ print_group(struct cnt_group *grp, unsigned int 
> headers)
>   return consumed;
>  }
>  
> +static unsigned int csv_count, prev_csv_count;
> +
> +static void csv_close_struct(void)
> +{
> + assert(text_level > 0);
> + if (--text_level == 0) {
> + csv_count = prev_csv_count = 0;
> + text_lines++;
> + fputs("\n", out);
> + fflush(out);
> + }
> +}
> +
> +static bool
> +csv_print_group(struct cnt_group *grp, unsigned int headers)
> +{
> + unsigned int consumed = 0;
> + struct cnt_item *item;
> +
> + if (!present_in_group(grp))
> + return false;
> +
> + text_open_struct(grp->name);
> +
> + for (item = grp->items; item->name; item++) {
> + if (!item->pmu || !item->pmu->present)
> + continue;
> +
> + if (csv_count != prev_csv_count)
> + fprintf(out, ",");
> + prev_csv_count = csv_count++;
> +
> + consumed += csv_add_member(grp, item, headers);
> + }
> +
> + csv_close_struct();
> +
> + return consumed;
> +}
> +
>  static bool
>  term_print_group(struct cnt_group *grp, unsigned int headers)
>  {
> @@ -1570,6 +1628,13 @@ static const struct print_operations text_pops = {
>   .print_group = print_group,
>  };
>  
> +static const struct print_operations csv_pops = {
> + .open_struct = text_open_struct,
> + .close_struct = csv_close_struct,
> + .add_member = csv_add_member,
> + .print_group = csv_print_group,
> +};
> +
>  static const struct print_operations term_pops = {
>   .open_struct = term_open_struct,
>   .close_struct = term_close_struct,
> @@ -1582,11 +1647,12 @@ static bool print_groups(struct cnt_group **groups)
>   static bool headers_printed = false;
>   bool print_data = true;
>  
> - if (output_mode == TEXT &&
> + if ((output_mode == TEXT || output_mode == CSV) &&
>   (text_header_repeat || !headers_printed)) {
> + const unsigned int header_lines = output_mode == TEXT ? 2 : 1;
>   unsigned int headers = text_lines % TEXT_HEADER_REPEAT + 1;
>  
> - if (headers == 1 || headers == 2)
> + if

Re: [Intel-gfx] [PATCH i-g-t 1/3] intel_gpu_top: Do not repeat header lines in non-interactive output

2023-02-07 Thread Kamil Konieczny
On 2023-02-03 at 11:16:34 +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> If output is redirected to a file, or a pipe, lets not repeat the headers
> because that can usually mean user is trying to parse the data later and
> so repeated headers are a hindrance.
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Caleb Callaway 

Reviewed-by: Kamil Konieczny 

> ---
>  tools/intel_gpu_top.c | 19 ++-
>  1 file changed, 14 insertions(+), 5 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index 0a1de41b3374..e2a7f4753099 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -1391,6 +1391,7 @@ static unsigned int stdout_level;
>  
>  #define STDOUT_HEADER_REPEAT 20
>  static unsigned int stdout_lines = STDOUT_HEADER_REPEAT;
> +static bool stdout_header_repeat;
>  
>  static void
>  stdout_open_struct(const char *name)
> @@ -1580,16 +1581,22 @@ static const struct print_operations term_pops = {
>  
>  static bool print_groups(struct cnt_group **groups)
>  {
> - unsigned int headers = stdout_lines % STDOUT_HEADER_REPEAT + 1;
> + static bool headers_printed = false;
>   bool print_data = true;
>  
> - if (output_mode == STDOUT && (headers == 1 || headers == 2)) {
> - for (struct cnt_group **grp = groups; *grp; grp++)
> - print_data = pops->print_group(*grp, headers);
> + if (output_mode == STDOUT &&
> + (stdout_header_repeat || !headers_printed)) {
> + unsigned int headers = stdout_lines % STDOUT_HEADER_REPEAT + 1;
> +
> + if (headers == 1 || headers == 2)
> + for (struct cnt_group **grp = groups; *grp; grp++)
> + print_data = pops->print_group(*grp, headers);
> +
> + headers_printed = print_data;
>   }
>  
>   for (struct cnt_group **grp = groups; print_data && *grp; grp++)
> - pops->print_group(*grp, false);
> + pops->print_group(*grp, 0);
>  
>   return print_data;
>  }
> @@ -2512,6 +2519,8 @@ int main(int argc, char **argv)
>   out = stdout;
>   }
>  
> + stdout_header_repeat = output_mode == STDOUT && isatty(fileno(out));
> +
>   if (signal(SIGINT, sigint_handler) == SIG_ERR)
>   fprintf(stderr, "Failed to install signal handler!\n");
>  
> -- 
> 2.34.1
> 


Re: [Intel-gfx] [igt-dev] [PATCH i-g-t 2/3] intel_gpu_top: Rename STDOUT to TEXT

2023-02-07 Thread Kamil Konieczny
On 2023-02-03 at 11:16:35 +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Internal cleanup only - the name text is more accurate given the output
> can also go to a file.
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Caleb Callaway 

Lgtm,
Reviewed-by: Kamil Konieczny 

> ---
>  tools/intel_gpu_top.c | 54 +--
>  1 file changed, 26 insertions(+), 28 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index e2a7f4753099..a980cc7043dc 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -1282,7 +1282,7 @@ usage(const char *appname)
>  
>  static enum {
>   INTERACTIVE,
> - STDOUT,
> + TEXT,
>   JSON
>  } output_mode;
>  
> @@ -1387,33 +1387,31 @@ json_add_member(const struct cnt_group *parent, 
> struct cnt_item *item,
>   return 1;
>  }
>  
> -static unsigned int stdout_level;
> +static unsigned int text_level;
>  
> -#define STDOUT_HEADER_REPEAT 20
> -static unsigned int stdout_lines = STDOUT_HEADER_REPEAT;
> -static bool stdout_header_repeat;
> +#define TEXT_HEADER_REPEAT 20
> +static unsigned int text_lines = TEXT_HEADER_REPEAT;
> +static bool text_header_repeat;
>  
> -static void
> -stdout_open_struct(const char *name)
> +static void text_open_struct(const char *name)
>  {
> - stdout_level++;
> - assert(stdout_level > 0);
> + text_level++;
> + assert(text_level > 0);
>  }
>  
> -static void
> -stdout_close_struct(void)
> +static void text_close_struct(void)
>  {
> - assert(stdout_level > 0);
> - if (--stdout_level == 0) {
> - stdout_lines++;
> + assert(text_level > 0);
> + if (--text_level == 0) {
> + text_lines++;
>   fputs("\n", out);
>   fflush(out);
>   }
>  }
>  
>  static unsigned int
> -stdout_add_member(const struct cnt_group *parent, struct cnt_item *item,
> -   unsigned int headers)
> +text_add_member(const struct cnt_group *parent, struct cnt_item *item,
> + unsigned int headers)
>  {
>   unsigned int fmt_tot = item->fmt_width + (item->fmt_precision ? 1 : 0);
>   char buf[fmt_tot + 1];
> @@ -1565,10 +1563,10 @@ static const struct print_operations json_pops = {
>   .print_group = print_group,
>  };
>  
> -static const struct print_operations stdout_pops = {
> - .open_struct = stdout_open_struct,
> - .close_struct = stdout_close_struct,
> - .add_member = stdout_add_member,
> +static const struct print_operations text_pops = {
> + .open_struct = text_open_struct,
> + .close_struct = text_close_struct,
> + .add_member = text_add_member,
>   .print_group = print_group,
>  };
>  
> @@ -1584,9 +1582,9 @@ static bool print_groups(struct cnt_group **groups)
>   static bool headers_printed = false;
>   bool print_data = true;
>  
> - if (output_mode == STDOUT &&
> - (stdout_header_repeat || !headers_printed)) {
> - unsigned int headers = stdout_lines % STDOUT_HEADER_REPEAT + 1;
> + if (output_mode == TEXT &&
> + (text_header_repeat || !headers_printed)) {
> + unsigned int headers = text_lines % TEXT_HEADER_REPEAT + 1;
>  
>   if (headers == 1 || headers == 2)
>   for (struct cnt_group **grp = groups; *grp; grp++)
> @@ -2492,7 +2490,7 @@ int main(int argc, char **argv)
>   list_device = true;
>   break;
>   case 'l':
> - output_mode = STDOUT;
> + output_mode = TEXT;
>   break;
>   case 'h':
>   usage(argv[0]);
> @@ -2505,7 +2503,7 @@ int main(int argc, char **argv)
>   }
>  
>   if (output_mode == INTERACTIVE && (output_path || isatty(1) != 1))
> - output_mode = STDOUT;
> + output_mode = TEXT;
>  
>   if (output_path && strcmp(output_path, "-")) {
>   out = fopen(output_path, "w");
> @@ -2519,7 +2517,7 @@ int main(int argc, char **argv)
>   out = stdout;
>   }
>  
> - stdout_header_repeat = output_mode == STDOUT && isatty(fileno(out));
> + text_header_repeat = output_mode == TEXT && isatty(fileno(out));
>  
>   if (signal(SIGINT, sigint_handler) == SIG_ERR)
>   fprintf(stderr, "Failed to install signal handler!\n");
> @@ -2531,8 +2529,8 @@ int main(int argc, char **argv)
>   pops = _pops;
>   interactive_stdin();
>   break;
> - case STDOUT:
> - pops = _pops;
> + case TEXT:
> + pops = _pops;
>   break;
>   case JSON:
>   pops = _pops;
> -- 
> 2.34.1
> 


Re: [Intel-gfx] [igt-dev] [PATCH i-g-t 8/8] gputop: Basic vendor agnostic GPU top tool

2023-02-06 Thread Kamil Konieczny
Hi Tvrtko,

On 2023-02-06 at 09:19:02 +, Tvrtko Ursulin wrote:
> 
> On 03/02/2023 16:42, Kamil Konieczny wrote:
> > Hi Tvrtko,
> > 
> > On 2023-01-31 at 11:32:37 +, Tvrtko Ursulin wrote:
> > > From: Tvrtko Ursulin 
> > > 
> > > Rudimentary vendor agnostic example of how lib_igt_drm_clients can be used
> > > to display a sorted by card and usage list of processes using GPUs.
> > > 
> > > Borrows a bit of code from intel_gpu_top but for now omits the fancy
> > > features like interactive functionality, card selection, client
> > > aggregation, sort modes, JSON output  and pretty engine names. Also no
> > > support for global GPU or system metrics.
> > > 
> > > On the other hand it shows clients from all DRM cards which
> > > intel_gpu_top does not do.
> > > 
> > > Signed-off-by: Tvrtko Ursulin 
> > > Cc: Rob Clark 
> > > Cc: Christian König 
> > > Acked-by: Christian König 
> > 
> > I run it with:
> > # ./gputop
> > 
> > but it do not work on my Skylake card, I see no output,
> > kernel 5.19.0-29-generic, ubuntu 22.10
> 
> Odd, 5.19 should have the support. Intel_gpu_top works - it is showing the
> individual clients?

There is no display nor any gpu app running, when I run some igt tests
then it does sometimes prints some activity. Intel_gpu_top works and
shows headers and zero activity so it mislead me.

> 
> > 
> > # ./lsgpu
> > card0Intel Skylake (Gen9)  
> > drm:/dev/dri/card0
> > └─renderD128   
> > drm:/dev/dri/renderD128
> > 
> > Please add some options like debug, version, debug with high
> > verbose level, help. It seems like q or Q do not exit.
> 
> As the cover letter hints I was only set out to demonstrate an extremely
> rudimentary vendor agnostic tool. To quote the cover letter more - "..It
> also makes no effort to provide sorting modes, well any interactivity, or
> any pretty names for GPUs or engines..". I have no scope presently to make
> it better or nicer.
> 
> The tool however can serve as a starting point and people had reported it
> working as-is with a few other drivers, AMD, msm and most recently I believe
> etnaviv. So perhaps a pool of people to further improve it will be found
> there in the future.
> 
> In summary I think it's worth reviewing so that the common code gets
> extracted from intel_gpu_top into respective libraries. After that I was
> hoping other people start contributing further improvements.
> 
> Regards,
> 
> Tvrtko

I agree it is good starting point, it may have something like overall
gpu activity, imho something which shows gpu % usage (mem % and power %)
for all GPUs present.

Regards,
Kamil



Re: [Intel-gfx] [igt-dev] [PATCH i-g-t 8/8] gputop: Basic vendor agnostic GPU top tool

2023-02-03 Thread Kamil Konieczny
Hi Tvrtko,

On 2023-01-31 at 11:32:37 +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Rudimentary vendor agnostic example of how lib_igt_drm_clients can be used
> to display a sorted by card and usage list of processes using GPUs.
> 
> Borrows a bit of code from intel_gpu_top but for now omits the fancy
> features like interactive functionality, card selection, client
> aggregation, sort modes, JSON output  and pretty engine names. Also no
> support for global GPU or system metrics.
> 
> On the other hand it shows clients from all DRM cards which
> intel_gpu_top does not do.
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Rob Clark 
> Cc: Christian König 
> Acked-by: Christian König 

I run it with:
# ./gputop

but it do not work on my Skylake card, I see no output,
kernel 5.19.0-29-generic, ubuntu 22.10

# ./lsgpu
card0Intel Skylake (Gen9)  drm:/dev/dri/card0
└─renderD128   
drm:/dev/dri/renderD128

Please add some options like debug, version, debug with high
verbose level, help. It seems like q or Q do not exit.

Regards,
Kamil

> ---
>  tools/gputop.c| 260 ++
>  tools/meson.build |   5 +
>  2 files changed, 265 insertions(+)
>  create mode 100644 tools/gputop.c
> 
> diff --git a/tools/gputop.c b/tools/gputop.c
> new file mode 100644
> index ..d259cac1ab17
> --- /dev/null
> +++ b/tools/gputop.c
> @@ -0,0 +1,260 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2022 Intel Corporation
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "igt_drm_clients.h"
> +#include "igt_drm_fdinfo.h"
> +
> +static const char *bars[] = { " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█" };
> +
> +static void n_spaces(const unsigned int n)
> +{
> + unsigned int i;
> +
> + for (i = 0; i < n; i++)
> + putchar(' ');
> +}
> +
> +static void print_percentage_bar(double percent, int max_len)
> +{
> + int bar_len, i, len = max_len - 2;
> + const int w = 8;
> +
> + assert(max_len > 0);
> +
> + bar_len = ceil(w * percent * len / 100.0);
> + if (bar_len > w * len)
> + bar_len = w * len;
> +
> + putchar('|');
> +
> + for (i = bar_len; i >= w; i -= w)
> + printf("%s", bars[w]);
> + if (i)
> + printf("%s", bars[i]);
> +
> + len -= (bar_len + (w - 1)) / w;
> + n_spaces(len);
> +
> + putchar('|');
> +}
> +
> +static int
> +print_client_header(struct igt_drm_client *c, int lines, int con_w, int 
> con_h,
> + int *engine_w)
> +{
> + const char *pidname = "PID   NAME ";
> + int ret, len = strlen(pidname);
> +
> + if (lines++ >= con_h || len >= con_w)
> + return lines;
> + printf("\033[7m");
> + ret = printf("DRM minor %u", c->drm_minor);
> + n_spaces(con_w - ret);
> +
> + if (lines++ >= con_h)
> + return lines;
> + printf("\n%s", pidname);
> +
> + if (c->engines->num_engines) {
> + unsigned int i;
> + int width;
> +
> + *engine_w = width = (con_w - len) / c->engines->num_engines;
> +
> + for (i = 0; i <= c->engines->max_engine_id; i++) {
> + const char *name = c->engines->names[i];
> + int name_len = strlen(name);
> + int pad = (width - name_len) / 2;
> + int spaces = width - pad - name_len;
> +
> + if (!name)
> + continue;
> +
> + if (pad < 0 || spaces < 0)
> + continue;
> +
> + n_spaces(pad);
> + printf("%s", name);
> + n_spaces(spaces);
> + len += pad + name_len + spaces;
> + }
> + }
> +
> + n_spaces(con_w - len);
> + printf("\033[0m\n");
> +
> + return lines;
> +}
> +
> +
> +static bool
> +newheader(const struct igt_drm_client *c, const struct igt_drm_client *pc)
> +{
> + return !pc || c->drm_minor != pc->drm_minor;
> +}
> +
> +static int
> +print_client(struct igt_drm_client *c, struct igt_drm_client **prevc,
> +  double t, int lines, int con_w, int con_h,
> +  unsigned int period_us, int *engine_w)
> +{
> + unsigned int i;
> +
> + /* Filter out idle clients. */
> + if (!c->total_runtime || c->samples < 2)
> + return lines;
> +
> + /* Print header when moving to a different DRM card. */
> + if (newheader(c, *prevc)) {
> + lines = print_client_header(c, lines, con_w, con_h, engine_w);
> + if (lines >= con_h)
> + return lines;
> 

Re: [Intel-gfx] [PATCH i-g-t 2/2] tests/i915/perf: Exercise barrier race

2023-02-02 Thread Kamil Konieczny
Hi Janusz,

On 2023-02-01 at 20:16:11 +0100, Janusz Krzysztofik wrote:
> Hi Kamil,
> 
> On Wednesday, 1 February 2023 19:21:57 CET Kamil Konieczny wrote:
> > Hi Janusz,
> > 
> > please send patches to igt ML and add other addresses to cc:
> > I have one nit, see below.
> > 
> > On 2023-01-31 at 10:17:31 +0100, Janusz Krzysztofik wrote:
> > > Add a new subtest focused on exercising interaction between perf open /
> > > close operations, which replace active barriers with perf requests, and
> > > concurrent barrier preallocate / acquire operations performed during
> > > context first pin / last unpin.
> > > 
> > > References: https://gitlab.freedesktop.org/drm/intel/-/issues/6333
> > > Signed-off-by: Janusz Krzysztofik 
> > > Cc: Chris Wilson 
> > > ---
> > >  tests/i915/perf.c | 41 +++--
> > >  1 file changed, 39 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/tests/i915/perf.c b/tests/i915/perf.c
> > > index e33cacc443..11a3ec21ab 100644
> > > --- a/tests/i915/perf.c
> > > +++ b/tests/i915/perf.c
> > > @@ -39,6 +39,7 @@
> > >  #include 
> > >  
> > >  #include "i915/gem.h"
> > > +#include "i915/gem_create.h"
> > >  #include "i915/perf.h"
> > >  #include "igt.h"
> > >  #include "igt_perf.h"
> > > @@ -4885,7 +4886,27 @@ test_whitelisted_registers_userspace_config(void)
> > >   i915_perf_remove_config(drm_fd, config_id);
> > >  }
> > >  
> > > -static void test_open_race(const struct intel_execution_engine2 *e, int 
> > > timeout)
> > > +static void gem_exec_nop(int i915, const struct intel_execution_engine2 
> > > *e)
> > > +{
> > > + const uint32_t bbe = MI_BATCH_BUFFER_END;
> > > + struct drm_i915_gem_exec_object2 obj = { };
> > > + struct drm_i915_gem_execbuffer2 execbuf = {
> > > + .buffers_ptr = to_user_pointer(),
> > > + .buffer_count = 1,
> > > + };
> > > +
> > > + obj.handle = gem_create(i915, 4096);
> > > + gem_write(i915, obj.handle, 0, , sizeof(bbe));
> > > +
> > > + execbuf.flags = e->flags;
> > > + gem_execbuf(i915, );
> > > +
> > > + gem_sync(i915, obj.handle);
> > > + gem_close(i915, obj.handle);
> > > +}
> > > +
> > > +static void test_open_race(const struct intel_execution_engine2 *e, int 
> > > timeout,
> > > +bool use_spin)
> > -- ^
> > This is not the best way to develop new code, it may be good
> > for fast development but imho it is better to refactor existing
> > code and avoiding to add bool logic into function.
> 
> I'm not sure what you mean.  By refactoring, do you mean moving the code 
> common to both processing paths out to a separate helper, then call it from 
> two distinct functions, each implementing only one scenario?  What's wrong 
> with passing flags that select one of alternative processing paths within one 
> function?  Or are you just not happy with bool type?

It is not wrong unless there is only one such var but even then
readability of code is reduced.

> 
> > It can be done later as this is revealing the bug.
> > 
> > >  {
> > >   int *done;
> > >  
> > > @@ -4926,6 +4947,12 @@ static void test_open_race(const struct 
> > > intel_execution_engine2 *e, int timeout)
> > >   ctx = gem_context_create_for_engine(i915, 
> > > e->class, e->instance);
> > >   gem_context_set_persistence(i915, ctx, 
> > > persistence);
> > >  
> > > + if (!use_spin) {
> > > + gem_exec_nop(i915, e);
> > > + gem_context_destroy(i915, ctx);
> > > + continue;
> > > + }
> > > +
> > >   spin = __igt_spin_new(i915, ctx, .ahnd = ahnd);
> > >   for (int i = random() % 7; i--; ) {
> > >   if (random() & 1) {
> > > @@ -5330,7 +5357,17 @@ igt_main
> > >   for_each_physical_engine(drm_fd, e)
> > >   if (e->class == I915_ENGINE_CLASS_RENDER)
> > >   igt_dynamic_f("%s", e->name)
> > > - test_open_

Re: [Intel-gfx] [PATCH i-g-t 2/2] tests/i915/perf: Exercise barrier race

2023-02-01 Thread Kamil Konieczny
Hi Janusz,

please send patches to igt ML and add other addresses to cc:
I have one nit, see below.

On 2023-01-31 at 10:17:31 +0100, Janusz Krzysztofik wrote:
> Add a new subtest focused on exercising interaction between perf open /
> close operations, which replace active barriers with perf requests, and
> concurrent barrier preallocate / acquire operations performed during
> context first pin / last unpin.
> 
> References: https://gitlab.freedesktop.org/drm/intel/-/issues/6333
> Signed-off-by: Janusz Krzysztofik 
> Cc: Chris Wilson 
> ---
>  tests/i915/perf.c | 41 +++--
>  1 file changed, 39 insertions(+), 2 deletions(-)
> 
> diff --git a/tests/i915/perf.c b/tests/i915/perf.c
> index e33cacc443..11a3ec21ab 100644
> --- a/tests/i915/perf.c
> +++ b/tests/i915/perf.c
> @@ -39,6 +39,7 @@
>  #include 
>  
>  #include "i915/gem.h"
> +#include "i915/gem_create.h"
>  #include "i915/perf.h"
>  #include "igt.h"
>  #include "igt_perf.h"
> @@ -4885,7 +4886,27 @@ test_whitelisted_registers_userspace_config(void)
>   i915_perf_remove_config(drm_fd, config_id);
>  }
>  
> -static void test_open_race(const struct intel_execution_engine2 *e, int 
> timeout)
> +static void gem_exec_nop(int i915, const struct intel_execution_engine2 *e)
> +{
> + const uint32_t bbe = MI_BATCH_BUFFER_END;
> + struct drm_i915_gem_exec_object2 obj = { };
> + struct drm_i915_gem_execbuffer2 execbuf = {
> + .buffers_ptr = to_user_pointer(),
> + .buffer_count = 1,
> + };
> +
> + obj.handle = gem_create(i915, 4096);
> + gem_write(i915, obj.handle, 0, , sizeof(bbe));
> +
> + execbuf.flags = e->flags;
> + gem_execbuf(i915, );
> +
> + gem_sync(i915, obj.handle);
> + gem_close(i915, obj.handle);
> +}
> +
> +static void test_open_race(const struct intel_execution_engine2 *e, int 
> timeout,
> +bool use_spin)
-- ^
This is not the best way to develop new code, it may be good
for fast development but imho it is better to refactor existing
code and avoiding to add bool logic into function.
It can be done later as this is revealing the bug.

>  {
>   int *done;
>  
> @@ -4926,6 +4947,12 @@ static void test_open_race(const struct 
> intel_execution_engine2 *e, int timeout)
>   ctx = gem_context_create_for_engine(i915, 
> e->class, e->instance);
>   gem_context_set_persistence(i915, ctx, 
> persistence);
>  
> + if (!use_spin) {
> + gem_exec_nop(i915, e);
> + gem_context_destroy(i915, ctx);
> + continue;
> + }
> +
>   spin = __igt_spin_new(i915, ctx, .ahnd = ahnd);
>   for (int i = random() % 7; i--; ) {
>   if (random() & 1) {
> @@ -5330,7 +5357,17 @@ igt_main
>   for_each_physical_engine(drm_fd, e)
>   if (e->class == I915_ENGINE_CLASS_RENDER)
>   igt_dynamic_f("%s", e->name)
> - test_open_race(e, 5);
> + test_open_race(e, 5, true);
> + }
> +

Please add here some TODO comments from discussions and a note
which will help bug filling team to classify that.

Regards,
Kamil

> + igt_describe("Exercise perf open/close against intensive barrier 
> preallocate/acquire");
> + igt_subtest_with_dynamic("barrier-race") {
> + const struct intel_execution_engine2 *e;
> +
> + for_each_physical_engine(drm_fd, e)
> + if (e->class == I915_ENGINE_CLASS_RENDER)
> + igt_dynamic_f("%s", e->name)
> + test_open_race(e, 5, false);
>   }
>  
>   igt_fixture {
> -- 
> 2.25.1
> 


Re: [Intel-gfx] [PATCH i-g-t 1/2] i915/perf: Stress opening of new perf streams against existing contexts

2023-01-31 Thread Kamil Konieczny
Hi,

On 2023-01-31 at 10:17:30 +0100, Janusz Krzysztofik wrote:
> From: Chris Wilson 
> 
> Try opening the perf stream while there is a flurry of activity on the
> system, both new and old contexts. This will exercise the ability of the
> driver to modify those contexts to work with perf.
> 
> References: https://gitlab.freedesktop.org/drm/intel/-/issues/6333
> Signed-off-by: Chris Wilson 
> Signed-off-by: Janusz Krzysztofik 
> Cc: Andi Shyti 
> ---
>  tests/i915/perf.c | 74 +++
>  1 file changed, 74 insertions(+)
> 
> diff --git a/tests/i915/perf.c b/tests/i915/perf.c
> index dd1f1ac399..e33cacc443 100644
> --- a/tests/i915/perf.c
> +++ b/tests/i915/perf.c
> @@ -4885,6 +4885,71 @@ test_whitelisted_registers_userspace_config(void)
>   i915_perf_remove_config(drm_fd, config_id);
>  }
>  
> +static void test_open_race(const struct intel_execution_engine2 *e, int 
> timeout)
> +{
> + int *done;
> +
> + done = mmap(0, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
> + igt_assert(done != MAP_FAILED);
> +
> + igt_fork(child, 1) {
> + uint64_t properties[] = {
> + DRM_I915_PERF_PROP_SAMPLE_OA, true,
> + DRM_I915_PERF_PROP_OA_METRICS_SET, 
> test_set->perf_oa_metrics_set,
> + DRM_I915_PERF_PROP_OA_FORMAT, test_set->perf_oa_format,
> + DRM_I915_PERF_PROP_OA_EXPONENT, oa_exp_1_millisec,
> + };
> + struct drm_i915_perf_open_param param = {
> + .flags = I915_PERF_FLAG_FD_CLOEXEC,
> + .num_properties = sizeof(properties) / 16,
> + .properties_ptr = to_user_pointer(properties),
> + };
> + unsigned long count = 0;
> +
> + do {
> + __perf_close(__perf_open(drm_fd, , false));
> + count++;
> + } while (!READ_ONCE(*done));
> +
> + igt_info("Completed %lu cycles\n", count);
> + }
> +
> + for (int persistence = 0; persistence <= 1; persistence++) {
> + igt_fork(child, sysconf(_SC_NPROCESSORS_ONLN)) {
> + int i915 = gem_reopen_driver(drm_fd);
> +
> + do {
> + igt_spin_t *spin;
> + uint64_t ahnd;
> + uint32_t ctx;
> +
> + ctx = gem_context_create_for_engine(i915, 
> e->class, e->instance);
> + gem_context_set_persistence(i915, ctx, 
> persistence);
> +
> + spin = __igt_spin_new(i915, ctx, .ahnd = ahnd);
> + for (int i = random() % 7; i--; ) {
> + if (random() & 1) {
> + igt_spin_end(spin);
> + gem_sync(i915, spin->handle);
> + igt_spin_reset(spin);
> + }
> + gem_execbuf(i915, >execbuf);
> + }
> +
> + gem_context_destroy(i915, ctx);
> + igt_spin_free(i915, spin);
> + put_ahnd(ahnd);
> + } while (!READ_ONCE(*done));
> + }
> + }
> +
> + sleep(timeout);
> + *done = 1;
> + igt_waitchildren();
> +
> + munmap(done, 4096);
> +}
> +
>  static unsigned
>  read_i915_module_ref(void)
>  {
> @@ -5259,6 +5324,15 @@ igt_main
>   igt_subtest("whitelisted-registers-userspace-config")
>   test_whitelisted_registers_userspace_config();
>  

Please add description to new test.

Regards,
Kamil

> + igt_subtest_with_dynamic("open-race") {
> + const struct intel_execution_engine2 *e;
> +
> + for_each_physical_engine(drm_fd, e)
> + if (e->class == I915_ENGINE_CLASS_RENDER)
> + igt_dynamic_f("%s", e->name)
> + test_open_race(e, 5);
> + }
> +
>   igt_fixture {
>   /* leave sysctl options in their default state... */
>   write_u64_file("/proc/sys/dev/i915/oa_max_sample_rate", 10);
> -- 
> 2.25.1
> 


Re: [Intel-gfx] [igt-dev] [PATCH i-g-t 5/6] intel_gpu_top: Fix cleanup on old kernels / unsupported GPU

2023-01-30 Thread Kamil Konieczny
Hi,

On 2023-01-30 at 10:55:42 +, Tvrtko Ursulin wrote:
> 
> On 27/01/2023 16:10, Kamil Konieczny wrote:
> > Hi Tvrtko,
> > 
> > On 2023-01-27 at 11:12:40 +, Tvrtko Ursulin wrote:
> > > From: Tvrtko Ursulin 
> > > 
> > > Avoid trying to dereference null engines on exit when there are either
> > > none which are supported, or kernel does not have i915 PMU support.
> > > 
> > > Also fix a memory leak on the same failure path just so Valgrind runs are
> > > quite.
> > > 
> > > v2:
> > >   * Fix a memory leak in the same failure mode too.
> > 
> > Please rebase, patch do not apply.
> 
> Hm how, CI applied it fine. Maybe you mean as standalone? There is the same
> patch here:
> https://patchwork.freedesktop.org/patch/519751/?series=113096=2
> 
> > > Signed-off-by: Tvrtko Ursulin 
> > > Acked-by: Nirmoy Das  # v1
> >  ^
> > Delete this.
> 
> I can do that only if Nirmoy agrees. ;)
> 
> Regards,
> 
> Tvrtko

It is already too late, that was merged some time ago and got
into git history so nothing can be done now.

Regards,
Kamil

> 
> > Rest looks good,
> > 
> > Regards,
> > Kamil
> > 
> > > ---
> > >   tools/intel_gpu_top.c | 21 ++---
> > >   1 file changed, 14 insertions(+), 7 deletions(-)
> > > 
> > > diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> > > index 7aa233570463..0a1de41b3374 100644
> > > --- a/tools/intel_gpu_top.c
> > > +++ b/tools/intel_gpu_top.c
> > > @@ -340,7 +340,7 @@ static struct engines *discover_engines(char *device)
> > >   d = opendir(sysfs_root);
> > >   if (!d)
> > > - return NULL;
> > > + goto err;
> > >   while ((dent = readdir(d)) != NULL) {
> > >   const char *endswith = "-busy";
> > > @@ -423,10 +423,8 @@ static struct engines *discover_engines(char *device)
> > >   }
> > >   if (ret) {
> > > - free(engines);
> > >   errno = ret;
> > > -
> > > - return NULL;
> > > + goto err;
> > >   }
> > >   qsort(engine_ptr(engines, 0), engines->num_engines,
> > > @@ -435,6 +433,11 @@ static struct engines *discover_engines(char *device)
> > >   engines->root = d;
> > >   return engines;
> > > +
> > > +err:
> > > + free(engines);
> > > +
> > > + return NULL;
> > >   }
> > >   static void free_engines(struct engines *engines)
> > > @@ -448,6 +451,9 @@ static void free_engines(struct engines *engines)
> > >   };
> > >   unsigned int i;
> > > + if (!engines)
> > > + return;
> > > +
> > >   for (pmu = _list[0]; *pmu; pmu++) {
> > >   if ((*pmu)->present)
> > >   free((char *)(*pmu)->units);
> > > @@ -2568,7 +2574,7 @@ int main(int argc, char **argv)
> > >   "Failed to detect engines! (%s)\n(Kernel 4.16 
> > > or newer is required for i915 PMU support.)\n",
> > >   strerror(errno));
> > >   ret = EXIT_FAILURE;
> > > - goto err;
> > > + goto err_engines;
> > >   }
> > >   ret = pmu_init(engines);
> > > @@ -2585,7 +2591,7 @@ int main(int argc, char **argv)
> > >   "More information can be found at 'Perf events and tool security' 
> > > document:\n"
> > >   
> > > "https://www.kernel.org/doc/html/latest/admin-guide/perf-security.html\n;);
> > >   ret = EXIT_FAILURE;
> > > - goto err;
> > > + goto err_pmu;
> > >   }
> > >   ret = EXIT_SUCCESS;
> > > @@ -2699,8 +2705,9 @@ int main(int argc, char **argv)
> > >   free_clients(clients);
> > >   free(codename);
> > > -err:
> > > +err_pmu:
> > >   free_engines(engines);
> > > +err_engines:
> > >   free(pmu_device);
> > >   exit:
> > >   igt_devices_free();
> > > -- 
> > > 2.34.1
> > > 


Re: [Intel-gfx] [igt-dev] [PATCH i-g-t 6/6] lib/igt_device_scan: Improve Intel discrete GPU selection

2023-01-30 Thread Kamil Konieczny
Hi,

On 2023-01-30 at 11:04:07 +, Tvrtko Ursulin wrote:
> 
> On 27/01/2023 16:17, Kamil Konieczny wrote:
> > Hi Tvrtko,
> > 
> > On 2023-01-27 at 11:12:41 +, Tvrtko Ursulin wrote:
> > > From: Tvrtko Ursulin 
> > > 
> > > Now that DRM subsystem can contain PCI cards with the vendor set to Intel
> > > but they are not Intel GPUs, we need a better selection logic than looking
> > > at the vendor. Use the driver name instead.
> > > 
> > > Caveat that the driver key was on a blacklist so far, and although I can't
> > > imagine it can be slow to probe, this is something to double check.
> > > 
> > > Signed-off-by: Tvrtko Ursulin 
> > > Cc: Kamil Konieczny 
> > > Cc: Zbigniew Kempczyński 
> > 
> > Please send this as separate patch, not in this series.
> 
> Yeah I was lazy and wanting to save time so okay.
> 

Well maybe next time, I already merged your series without 5/6,
that one were merged some time ago.

Regards,
Kamil

> > > ---
> > >   lib/igt_device_scan.c | 7 +--
> > >   1 file changed, 5 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/lib/igt_device_scan.c b/lib/igt_device_scan.c
> > > index ed128d24dd10..8b767eed202d 100644
> > > --- a/lib/igt_device_scan.c
> > > +++ b/lib/igt_device_scan.c
> > > @@ -237,6 +237,7 @@ struct igt_device {
> > >   char *vendor;
> > >   char *device;
> > >   char *pci_slot_name;
> > > + char *driver;
> > >   int gpu_index; /* For more than one GPU with same vendor and 
> > > device. */
> > >   char *codename; /* For grouping by codename */
> > > @@ -440,7 +441,6 @@ static bool is_on_blacklist(const char *what)
> > > "resource3", "resource4", 
> > > "resource5",
> > > "resource0_wc", "resource1_wc", 
> > > "resource2_wc",
> > > "resource3_wc", "resource4_wc", 
> > > "resource5_wc",
> > > -   "driver",
> > > "uevent", NULL};
> > >   const char *key;
> > >   int i = 0;
> > > @@ -662,6 +662,8 @@ static struct igt_device 
> > > *igt_device_new_from_udev(struct udev_device *dev)
> > >   get_pci_vendor_device(idev, , );
> > >   idev->codename = __pci_codename(vendor, device);
> > >   idev->dev_type = __pci_devtype(vendor, device, 
> > > idev->pci_slot_name);
> > > + idev->driver = strdup_nullsafe(get_attr(idev, "driver"));
> > > + igt_assert(idev->driver);
> > >   }
> > >   return idev;
> > > @@ -776,7 +778,7 @@ static bool __find_first_i915_card(struct 
> > > igt_device_card *card, bool discrete)
> > >   igt_list_for_each_entry(dev, _devs.all, link) {
> > > - if (!is_pci_subsystem(dev) || !is_vendor_matched(dev, "intel"))
> > > + if (!is_pci_subsystem(dev) || strcmp(dev->driver, "i915"))
> > 
> > Put the comment here why it can be problematic to relay on driver name.
> 
> Function name being __find_first_*i915*_card is IMO enough so it feels any
> comment to the same effect would be redundant.
> 
> Hm if anything igt_device_find_integrated_card should be renamed..
> 
> Regards,
> 
> Tvrtko
> 
> > 
> > Regards,
> > Kamil
> > 
> > >   continue;
> > >   cmp = strncmp(dev->pci_slot_name, 
> > > INTEGRATED_I915_GPU_PCI_ID,
> > > @@ -1023,6 +1025,7 @@ static void igt_device_free(struct igt_device *dev)
> > >   free(dev->drm_render);
> > >   free(dev->vendor);
> > >   free(dev->device);
> > > + free(dev->driver);
> > >   free(dev->pci_slot_name);
> > >   g_hash_table_destroy(dev->attrs_ht);
> > >   g_hash_table_destroy(dev->props_ht);
> > > -- 
> > > 2.34.1
> > > 


Re: [Intel-gfx] [PATCH i-g-t 1/6] intel_gpu_top: Fix man page formatting

2023-01-27 Thread Kamil Konieczny
Hi Tvrtko,

On 2023-01-27 at 11:12:36 +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> New lines are not respected when rst2man generates the page so try to work
> around that by followin advice from the Internet.
> 
> v2:
>  * Improve some wording.
>  * Tidy -o option description.
>  * Update dates.
>  * Convert the filter list to table.
> 
> Signed-off-by: Tvrtko Ursulin 
> Reviewed-by: Kamil Konieczny  # v1
--- ^
Remove this addition at end,
s/ # v1//

Man page looks much better so you can keep my r-b,
thank you for your effort,

Regards,
Kamil

> ---
>  man/intel_gpu_top.rst | 55 ---
>  1 file changed, 25 insertions(+), 30 deletions(-)
> 
> diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
> index 748c7740c800..4417bcff0d5b 100644
> --- a/man/intel_gpu_top.rst
> +++ b/man/intel_gpu_top.rst
> @@ -7,9 +7,9 @@ Display a top-like summary of Intel GPU usage
>  -
>  .. include:: defs.rst
>  :Author: IGT Developers 
> -:Date: 2020-03-18
> +:Date: 2023-01-27
>  :Version: |PACKAGE_STRING|
> -:Copyright: 2009,2011,2012,2016,2018,2019,2020 Intel Corporation
> +:Copyright: 2009,2011,2012,2016,2018,2019,2020,2023 Intel Corporation
>  :Manual section: |MANUAL_SECTION|
>  :Manual group: |MANUAL_GROUP|
>  
> @@ -23,7 +23,7 @@ DESCRIPTION
>  
>  **intel_gpu_top** is a tool to display usage information on Intel GPU's.
>  
> -The tool gathers data using perf performance counters (PMU) exposed by i915 
> and other platform drivers like RAPL (power) and Uncore IMC (memory 
> bandwidth).
> +The tool presents data collected from performance counters (PMU), exposed by 
> i915 and other platform drivers like RAPL (power) and Uncore IMC (memory 
> bandwidth).
>  
>  OPTIONS
>  ===
> @@ -37,49 +37,44 @@ OPTIONS
>  -l
>  List plain text data.
>  
> --o 
> -Output to the specified file instead of standard output.
> -'-' can also be specified to explicitly select standard output.
> +-o , or -o -
> +Output to the specified file instead of standard output. '-' can also be 
> specified to explicitly select standard output.
>  
>  -s 
>  Refresh period in milliseconds.
> +
>  -L
> -List available GPUs on the platform.
> +List available GPUs on the system.
> +
>  -d
> -Select a specific GPU using supported filter.
> +Select a specific GPU using one of the supported filters.
>  
>  RUNTIME CONTROL
>  ===
>  
>  Supported keys:
>  
> -'q'Exit from the tool.
> -'h'Show interactive help.
> -'1'Toggle between aggregated engine class and physical engine mode.
> -'n'Toggle display of numeric client busyness overlay.
> -'s'Toggle between sort modes (runtime, total runtime, pid, client 
> id).
> -'i'Toggle display of clients which used no GPU time.
> -'H'Toggle between per PID aggregation and individual clients.
> +|
> +|'q'Exit from the tool.
> +|'h'Show interactive help.
> +|'1'Toggle between aggregated by engine class and physical engine 
> mode.
> +|'n'Toggle display of numeric client busyness overlay.
> +|'s'Toggle between sort modes (runtime, total runtime, pid, client 
> id).
> +|'i'Toggle display of clients which used no GPU time.
> +|'H'Toggle between per PID aggregation and individual clients.
>  
>  DEVICE SELECTION
>  
>  
> -User can select specific GPU for performance monitoring on platform where 
> multiple GPUs are available.
> -A GPU can be selected by sysfs path, drm node or using various PCI sub 
> filters.
> -
> -Filter types: ::
> -
> ----
> -filter   syntax
> ----
> -sys  sys:/sys/devices/pci:00/:00:02.0
> - find device by its sysfs path
> -
> -drm  drm:/dev/dri/* path
> - find drm device by /dev/dri/* node
> +On systems where multiple GPUs are present it is possible to select a 
> specific GPU to be monitored. A GPU can be selected by sysfs path, drm device 
> node or using various PCI sub filters.
>  
> -pci  pci:[vendor=%04x/name][,device=%04x][,card=%d]
> - vendor is hex number or vendor name
> +==  == 
> ==
> +**Filter**  **Syntax** **GPU 
> selection criteria**
> +==  == 
> ===

Re: [Intel-gfx] [PATCH i-g-t 6/6] lib/igt_device_scan: Improve Intel discrete GPU selection

2023-01-27 Thread Kamil Konieczny
Hi Tvrtko,

On 2023-01-27 at 11:12:41 +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Now that DRM subsystem can contain PCI cards with the vendor set to Intel
> but they are not Intel GPUs, we need a better selection logic than looking
> at the vendor. Use the driver name instead.
> 
> Caveat that the driver key was on a blacklist so far, and although I can't
> imagine it can be slow to probe, this is something to double check.
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Kamil Konieczny 
> Cc: Zbigniew Kempczyński 

Please send this as separate patch, not in this series.

> ---
>  lib/igt_device_scan.c | 7 +--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/igt_device_scan.c b/lib/igt_device_scan.c
> index ed128d24dd10..8b767eed202d 100644
> --- a/lib/igt_device_scan.c
> +++ b/lib/igt_device_scan.c
> @@ -237,6 +237,7 @@ struct igt_device {
>   char *vendor;
>   char *device;
>   char *pci_slot_name;
> + char *driver;
>   int gpu_index; /* For more than one GPU with same vendor and device. */
>  
>   char *codename; /* For grouping by codename */
> @@ -440,7 +441,6 @@ static bool is_on_blacklist(const char *what)
> "resource3", "resource4", "resource5",
> "resource0_wc", "resource1_wc", 
> "resource2_wc",
> "resource3_wc", "resource4_wc", 
> "resource5_wc",
> -   "driver",
> "uevent", NULL};
>   const char *key;
>   int i = 0;
> @@ -662,6 +662,8 @@ static struct igt_device *igt_device_new_from_udev(struct 
> udev_device *dev)
>   get_pci_vendor_device(idev, , );
>   idev->codename = __pci_codename(vendor, device);
>   idev->dev_type = __pci_devtype(vendor, device, 
> idev->pci_slot_name);
> + idev->driver = strdup_nullsafe(get_attr(idev, "driver"));
> + igt_assert(idev->driver);
>   }
>  
>   return idev;
> @@ -776,7 +778,7 @@ static bool __find_first_i915_card(struct igt_device_card 
> *card, bool discrete)
>  
>   igt_list_for_each_entry(dev, _devs.all, link) {
>  
> - if (!is_pci_subsystem(dev) || !is_vendor_matched(dev, "intel"))
> + if (!is_pci_subsystem(dev) || strcmp(dev->driver, "i915"))

Put the comment here why it can be problematic to relay on driver name.

Regards,
Kamil

>   continue;
>  
>   cmp = strncmp(dev->pci_slot_name, INTEGRATED_I915_GPU_PCI_ID,
> @@ -1023,6 +1025,7 @@ static void igt_device_free(struct igt_device *dev)
>   free(dev->drm_render);
>   free(dev->vendor);
>   free(dev->device);
> + free(dev->driver);
>   free(dev->pci_slot_name);
>   g_hash_table_destroy(dev->attrs_ht);
>   g_hash_table_destroy(dev->props_ht);
> -- 
> 2.34.1
> 


Re: [Intel-gfx] [PATCH i-g-t 5/6] intel_gpu_top: Fix cleanup on old kernels / unsupported GPU

2023-01-27 Thread Kamil Konieczny
Hi Tvrtko,

On 2023-01-27 at 11:12:40 +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Avoid trying to dereference null engines on exit when there are either
> none which are supported, or kernel does not have i915 PMU support.
> 
> Also fix a memory leak on the same failure path just so Valgrind runs are
> quite.
> 
> v2:
>  * Fix a memory leak in the same failure mode too.

Please rebase, patch do not apply.

> 
> Signed-off-by: Tvrtko Ursulin 
> Acked-by: Nirmoy Das  # v1
 ^
Delete this.

Rest looks good,

Regards,
Kamil

> ---
>  tools/intel_gpu_top.c | 21 ++---
>  1 file changed, 14 insertions(+), 7 deletions(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index 7aa233570463..0a1de41b3374 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -340,7 +340,7 @@ static struct engines *discover_engines(char *device)
>  
>   d = opendir(sysfs_root);
>   if (!d)
> - return NULL;
> + goto err;
>  
>   while ((dent = readdir(d)) != NULL) {
>   const char *endswith = "-busy";
> @@ -423,10 +423,8 @@ static struct engines *discover_engines(char *device)
>   }
>  
>   if (ret) {
> - free(engines);
>   errno = ret;
> -
> - return NULL;
> + goto err;
>   }
>  
>   qsort(engine_ptr(engines, 0), engines->num_engines,
> @@ -435,6 +433,11 @@ static struct engines *discover_engines(char *device)
>   engines->root = d;
>  
>   return engines;
> +
> +err:
> + free(engines);
> +
> + return NULL;
>  }
>  
>  static void free_engines(struct engines *engines)
> @@ -448,6 +451,9 @@ static void free_engines(struct engines *engines)
>   };
>   unsigned int i;
>  
> + if (!engines)
> + return;
> +
>   for (pmu = _list[0]; *pmu; pmu++) {
>   if ((*pmu)->present)
>   free((char *)(*pmu)->units);
> @@ -2568,7 +2574,7 @@ int main(int argc, char **argv)
>   "Failed to detect engines! (%s)\n(Kernel 4.16 or newer 
> is required for i915 PMU support.)\n",
>   strerror(errno));
>   ret = EXIT_FAILURE;
> - goto err;
> + goto err_engines;
>   }
>  
>   ret = pmu_init(engines);
> @@ -2585,7 +2591,7 @@ int main(int argc, char **argv)
>  "More information can be found at 'Perf events and tool security' 
> document:\n"
>  "https://www.kernel.org/doc/html/latest/admin-guide/perf-security.html\n;);
>   ret = EXIT_FAILURE;
> - goto err;
> + goto err_pmu;
>   }
>  
>   ret = EXIT_SUCCESS;
> @@ -2699,8 +2705,9 @@ int main(int argc, char **argv)
>   free_clients(clients);
>  
>   free(codename);
> -err:
> +err_pmu:
>   free_engines(engines);
> +err_engines:
>   free(pmu_device);
>  exit:
>   igt_devices_free();
> -- 
> 2.34.1
> 


Re: [Intel-gfx] [igt-dev] [PATCH i-g-t 1/4] intel_gpu_top: Fix man page formatting

2023-01-26 Thread Kamil Konieczny
Hi,

On 2023-01-26 at 16:09:29 +, Tvrtko Ursulin wrote:
> 
> On 26/01/2023 15:39, Kamil Konieczny wrote:
> > On 2023-01-12 at 17:47:27 +, Tvrtko Ursulin wrote:
> > > From: Tvrtko Ursulin 
> > > 
> > > New lines are not respected when rst2man generates the page so try to work
> > > around that by followin advice from the Internet.
> > > 
> > > Signed-off-by: Tvrtko Ursulin 
> > 
> > Reviewed-by: Kamil Konieczny 
> 
> Thanks! Later I noticed there is one more thing which currently renders
> badly, this line:
> 
>   -o 
> 
> Are you okay with re-review if I can fix that one too and respin?

Yes, no problem, I can review respin.

Regards,
Kamil

> 
> Regards,
> 
> Tvrtko
> 
> > > ---
> > >   man/intel_gpu_top.rst | 15 ---
> > >   1 file changed, 8 insertions(+), 7 deletions(-)
> > > 
> > > diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
> > > index 748c7740c800..b0c95446a011 100644
> > > --- a/man/intel_gpu_top.rst
> > > +++ b/man/intel_gpu_top.rst
> > > @@ -53,13 +53,14 @@ RUNTIME CONTROL
> > >   Supported keys:
> > > -'q'Exit from the tool.
> > > -'h'Show interactive help.
> > > -'1'Toggle between aggregated engine class and physical engine 
> > > mode.
> > > -'n'Toggle display of numeric client busyness overlay.
> > > -'s'Toggle between sort modes (runtime, total runtime, pid, 
> > > client id).
> > > -'i'Toggle display of clients which used no GPU time.
> > > -'H'Toggle between per PID aggregation and individual clients.
> > > +|
> > > +|'q'Exit from the tool.
> > > +|'h'Show interactive help.
> > > +|'1'Toggle between aggregated engine class and physical engine 
> > > mode.
> > > +|'n'Toggle display of numeric client busyness overlay.
> > > +|'s'Toggle between sort modes (runtime, total runtime, pid, 
> > > client id).
> > > +|'i'Toggle display of clients which used no GPU time.
> > > +|'H'Toggle between per PID aggregation and individual clients.
> > >   DEVICE SELECTION
> > >   
> > > -- 
> > > 2.34.1
> > > 


Re: [Intel-gfx] [PATCH i-g-t 0/8] Vendor agnostic gputop

2023-01-26 Thread Kamil Konieczny
Hi,

please rebase and resend, also please change commit subject to start
with lib: or lib/[name of lib changed]: rest od commit description

For example, in 3/8 instead of
libdrmclients: Record client drm minor
write:
lib/igt_drm_clients: Record client drm minor

If there are more lib changes, use "lib: " alone, for example
in your 2/8 patch,
libdrmfdinfo: Allow specifying custom engine map
write:
lib: Allow specifying custom engine map

+Cc Petri and Zbyszek

Regards,
Kamil

On 2022-11-11 at 15:58:36 +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> This is a pile of patches which implements a rudimentary vendor agnostic 
> gputop
> tool based of the new DRM spec as documented in
> Documentation/gpu/drm-usage-stats.rst.
> 
> First part of the series is code refactoring which should be reasonably 
> stable.
> I've tested it all while working on it both against intel_gpu_top and gputop.
> 
> Last patch is the actual tool itself. It works but it is rather rudimentary
> which is hopefully good enough for a start.
> 
> Fundamental difference between intel_gpu_top and gputop is that the former is
> centered around a single card and only shows processes belonging to it. Gputop
> on the other hand has an idea to show all processes with DRM file descriptors
> open and sort them into groups per card. It also makes no effort to provide
> sorting modes, well any interactivity, or any pretty names for GPUs or 
> engines.
> 
> It looks like this:
> 
> DRM minor 0
> PID   NAMErender   copy   video
> 3816  kwin_x11 |███▎  ||  ||  ||  |
> 3523  Xorg |▊ ||  ||  ||  |
>  1120449   mpv |  ||  ||▋ ||  |
>  1120529  glxgears |▋ ||  ||  ||  |
>  1120449   mpv |▍ ||  ||  ||  |
> 3860   plasmashell |▏ ||  ||  ||  |
> 4764   krunner |  ||  ||  ||  |
>   575206chrome |  ||  ||  ||  |
>   833481   firefox |  ||  ||  ||  |
>   892924   thunderbird |  ||  ||  ||  |
> 
> 
> I did test it as well with two cards and confirmed that too works.
> 
> Rob Clark also tested it with a patch which exports the respective data from 
> the
> msm driver and confirmed it works fine. Christian König tested it with in
> progress patches for amdgpu and that worked as well.
> 
> v2:
>  * Fixed SPDX headers and added a bunch of code comments/docs throughout.
> 
> Tvrtko Ursulin (8):
>   lib: Extract igt_drm_clients from intel_gpu_top
>   libdrmfdinfo: Allow specifying custom engine map
>   libdrmclients: Record client drm minor
>   libdrmclient: Support multiple DRM cards
>   libdrmfdinfo: Track largest engine index
>   libdrmclient/intel_gpu_top: Decouple hardcoded engine assumptions
>   libdrmclient: Enforce client status sort order in the library
>   gputop: Basic vendor agnostic GPU top tool
> 
>  lib/igt_drm_clients.c   | 503 +
>  lib/igt_drm_clients.h   |  87 ++
>  lib/igt_drm_fdinfo.c|  50 ++-
>  lib/igt_drm_fdinfo.h|  16 +-
>  lib/meson.build |   8 +
>  tests/i915/drm_fdinfo.c |  19 +-
>  tools/gputop.c  | 260 +++
>  tools/intel_gpu_top.c   | 677 +++-
>  tools/meson.build   |   7 +-
>  9 files changed, 1113 insertions(+), 514 deletions(-)
>  create mode 100644 lib/igt_drm_clients.c
>  create mode 100644 lib/igt_drm_clients.h
>  create mode 100644 tools/gputop.c
> 
> -- 
> 2.34.1
> 


Re: [Intel-gfx] [PATCH i-g-t 0/4] Some intel_gpu_top tweaks

2023-01-26 Thread Kamil Konieczny
On 2023-01-12 at 17:47:26 +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Mostly by popular demand from
> https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/issues/109, although for
> some of these changes I'd like some second opinions. For instance is it user
> friendly to change the default aggregation mode for stdout and JSON output?

I do not see any response so imho we can merge this.

Regrads,
Kamil

> 
> Tvrtko Ursulin (4):
>   intel_gpu_top: Fix man page formatting
>   intel_gpu_top: Automatically enclose JSON output into brackets
>   intel_gpu_top: Add command line switch to start in physical engine
> mode
>   intel_gpu_top: Aggregate engine classes in all output modes
> 
>  man/intel_gpu_top.rst | 20 
>  tools/intel_gpu_top.c | 16 ++--
>  2 files changed, 26 insertions(+), 10 deletions(-)
> 
> -- 
> 2.34.1
> 


Re: [Intel-gfx] [PATCH i-g-t 4/4] intel_gpu_top: Aggregate engine classes in all output modes

2023-01-26 Thread Kamil Konieczny
On 2023-01-12 at 17:47:30 +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Use the same default for stdout and JSON output modes as it is for
> interactive.
> 
> Previously added command line switch can be used to go back to showing all
> physical engines.
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Dmitry Rogozhkin 

Reviewed-by: Kamil Konieczny 

> ---
>  tools/intel_gpu_top.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index e91b47baf72b..7aa233570463 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -2509,11 +2509,12 @@ int main(int argc, char **argv)
>   if (signal(SIGINT, sigint_handler) == SIG_ERR)
>   fprintf(stderr, "Failed to install signal handler!\n");
>  
> + class_view = !physical_engines;
> +
>   switch (output_mode) {
>   case INTERACTIVE:
>   pops = _pops;
>   interactive_stdin();
> - class_view = !physical_engines;
>   break;
>   case STDOUT:
>   pops = _pops;
> -- 
> 2.34.1
> 


Re: [Intel-gfx] [PATCH i-g-t 3/4] intel_gpu_top: Add command line switch to start in physical engine mode

2023-01-26 Thread Kamil Konieczny
On 2023-01-12 at 17:47:29 +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Default mode is to aggreate engines per class but some users would prefer
> to be able to start in physical engine mode too.
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Dmitry Rogozhkin 

Reviewed-by: Kamil Konieczny 

> ---
>  man/intel_gpu_top.rst | 3 +++
>  tools/intel_gpu_top.c | 9 +++--
>  2 files changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
> index 3317e04816b4..b24216c0ae91 100644
> --- a/man/intel_gpu_top.rst
> +++ b/man/intel_gpu_top.rst
> @@ -48,6 +48,9 @@ OPTIONS
>  -d
>  Select a specific GPU using supported filter.
>  
> +-p
> +   Default to showing physical engines instead of classes.
> +
>  RUNTIME CONTROL
>  ===
>  
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index c4d98de4fe31..e91b47baf72b 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -1268,6 +1268,7 @@ usage(const char *appname)
>   "\t[-s ]   Refresh period in milliseconds (default 
> %ums).\n"
>   "\t[-L]List all cards.\n"
>   "\t[-d ]   Device filter, please check manual page for 
> more details.\n"
> + "\t[-p]Default to showing physical engines instead 
> of classes.\n"
>   "\n",
>   appname, DEFAULT_PERIOD_MS);
>   igt_device_print_filter_types();
> @@ -2446,6 +2447,7 @@ int main(int argc, char **argv)
>  {
>   unsigned int period_us = DEFAULT_PERIOD_MS * 1000;
>   struct clients *clients = NULL;
> + bool physical_engines = false;
>   int con_w = -1, con_h = -1;
>   char *output_path = NULL;
>   struct engines *engines;
> @@ -2456,7 +2458,7 @@ int main(int argc, char **argv)
>   char *codename = NULL;
>  
>   /* Parse options */
> - while ((ch = getopt(argc, argv, "o:s:d:JLlh")) != -1) {
> + while ((ch = getopt(argc, argv, "o:s:d:pJLlh")) != -1) {
>   switch (ch) {
>   case 'o':
>   output_path = optarg;
> @@ -2467,6 +2469,9 @@ int main(int argc, char **argv)
>   case 'd':
>   opt_device = strdup(optarg);
>   break;
> + case 'p':
> + physical_engines = true;
> + break;
>   case 'J':
>   output_mode = JSON;
>   break;
> @@ -2508,7 +2513,7 @@ int main(int argc, char **argv)
>   case INTERACTIVE:
>   pops = _pops;
>   interactive_stdin();
> - class_view = true;
> + class_view = !physical_engines;
>   break;
>   case STDOUT:
>   pops = _pops;
> -- 
> 2.34.1
> 


Re: [Intel-gfx] [PATCH i-g-t 2/4] intel_gpu_top: Automatically enclose JSON output into brackets

2023-01-26 Thread Kamil Konieczny
On 2023-01-12 at 17:47:28 +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> Parsers need the whole output enclosed into square brackets so every
> period sample becomes an array element.
> 
> So far we have been suggesting this in the man page but we can trivially
> make the tool output that itself.
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Eero Tamminen 

Reviewed-by: Kamil Konieczny 

> ---
>  man/intel_gpu_top.rst | 2 +-
>  tools/intel_gpu_top.c | 6 ++
>  2 files changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
> index b0c95446a011..3317e04816b4 100644
> --- a/man/intel_gpu_top.rst
> +++ b/man/intel_gpu_top.rst
> @@ -85,7 +85,7 @@ Filter types: ::
>  JSON OUTPUT
>  ===
>  
> -To parse the JSON as output by the tool the consumer should wrap its 
> entirety into square brackets ([ ]). This will make each sample point a JSON 
> array element and will avoid "Multiple root elements" JSON validation error.
> +JSON output will be correctly terminated when the tool cleanly exits, 
> otherwise one square bracket needs to be added before parsing.
>  
>  LIMITATIONS
>  ===
> diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
> index 6de8a164fcff..c4d98de4fe31 100644
> --- a/tools/intel_gpu_top.c
> +++ b/tools/intel_gpu_top.c
> @@ -2597,6 +2597,9 @@ int main(int argc, char **argv)
>   scan_clients(clients, false);
>   codename = igt_device_get_pretty_name(, false);
>  
> + if (output_mode == JSON)
> + printf("[\n");
> +
>   while (!stop_top) {
>   struct clients *disp_clients;
>   bool consumed = false;
> @@ -2683,6 +2686,9 @@ int main(int argc, char **argv)
>   usleep(period_us);
>   }
>  
> + if (output_mode == JSON)
> + printf("]\n");
> +
>   if (clients)
>   free_clients(clients);
>  
> -- 
> 2.34.1
> 


Re: [Intel-gfx] [igt-dev] [PATCH i-g-t 1/4] intel_gpu_top: Fix man page formatting

2023-01-26 Thread Kamil Konieczny
On 2023-01-12 at 17:47:27 +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> New lines are not respected when rst2man generates the page so try to work
> around that by followin advice from the Internet.
> 
> Signed-off-by: Tvrtko Ursulin 

Reviewed-by: Kamil Konieczny 

> ---
>  man/intel_gpu_top.rst | 15 ---
>  1 file changed, 8 insertions(+), 7 deletions(-)
> 
> diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
> index 748c7740c800..b0c95446a011 100644
> --- a/man/intel_gpu_top.rst
> +++ b/man/intel_gpu_top.rst
> @@ -53,13 +53,14 @@ RUNTIME CONTROL
>  
>  Supported keys:
>  
> -'q'Exit from the tool.
> -'h'Show interactive help.
> -'1'Toggle between aggregated engine class and physical engine mode.
> -'n'Toggle display of numeric client busyness overlay.
> -'s'Toggle between sort modes (runtime, total runtime, pid, client 
> id).
> -'i'Toggle display of clients which used no GPU time.
> -'H'Toggle between per PID aggregation and individual clients.
> +|
> +|'q'Exit from the tool.
> +|'h'Show interactive help.
> +|'1'Toggle between aggregated engine class and physical engine mode.
> +|'n'Toggle display of numeric client busyness overlay.
> +|'s'Toggle between sort modes (runtime, total runtime, pid, client 
> id).
> +|'i'Toggle display of clients which used no GPU time.
> +|'H'Toggle between per PID aggregation and individual clients.
>  
>  DEVICE SELECTION
>  
> -- 
> 2.34.1
> 


Re: [Intel-gfx] [PATCH i-g-t v2 1/2] lib/dmabuf_sync_file: move common stuff into lib

2022-12-07 Thread Kamil Konieczny
Hi Matt,

On 2022-12-05 at 17:11:44 +, Matthew Auld wrote:
> On 05/12/2022 16:31, Kamil Konieczny wrote:
> > Hi Matt,
> > 
> > after re-reading I have few more nits.
> > 
> > On 2022-12-02 at 12:02:41 +, Matthew Auld wrote:
> > > So we can use this across different tests.
> > > 
> > > v2
> > >- Add docs for everything (Petri)
> > >- Add missing copyright and fix headers slightly (Kamil)
> > > 
> > > Signed-off-by: Matthew Auld 
> > > Cc: Kamil Konieczny 
> > > Cc: Petri Latvala 
> > > Cc: Andrzej Hajda 
> > > Cc: Nirmoy Das 
> > > ---
> > >   .../igt-gpu-tools/igt-gpu-tools-docs.xml  |   1 +
> > >   lib/dmabuf_sync_file.c| 211 ++
> > >   lib/dmabuf_sync_file.h|  26 +++
> > >   lib/meson.build   |   1 +
> > >   tests/dmabuf_sync_file.c  | 133 +--
> > >   5 files changed, 243 insertions(+), 129 deletions(-)
> > >   create mode 100644 lib/dmabuf_sync_file.c
> > >   create mode 100644 lib/dmabuf_sync_file.h
> > > 
> > > diff --git a/docs/reference/igt-gpu-tools/igt-gpu-tools-docs.xml 
> > > b/docs/reference/igt-gpu-tools/igt-gpu-tools-docs.xml
> > > index 1ce842f4..102c8a89 100644
> > > --- a/docs/reference/igt-gpu-tools/igt-gpu-tools-docs.xml
> > > +++ b/docs/reference/igt-gpu-tools/igt-gpu-tools-docs.xml
> > > @@ -15,6 +15,7 @@
> > > 
> > >   API Reference
> > > +
> > >   
> > >   
> > >   
> > > diff --git a/lib/dmabuf_sync_file.c b/lib/dmabuf_sync_file.c
> > > new file mode 100644
> > > index ..bcce2486
> > > --- /dev/null
> > > +++ b/lib/dmabuf_sync_file.c
> > > @@ -0,0 +1,211 @@
> > > +// SPDX-License-Identifier: MIT
> > > +/*
> > > + * Copyright © 2022 Intel Corporation
> > > + */
> > > +
> > > +#include "igt.h"
> > > +#include "igt_vgem.h"
> > > +#include "sw_sync.h"
> > > +
> > > +#include "dmabuf_sync_file.h"
> > > +
> > > +/**
> > > + * SECTION: dmabuf_sync_file
> > > + * @short_description: DMABUF importing/exporting fencing support library
> > > + * @title: DMABUF Sync File
> > > + * @include: dmabuf_sync_file.h
> > > + */
> > > +
> > > +struct igt_dma_buf_sync_file {
> > > + __u32 flags;
> > > + __s32 fd;
> > > +};
> > > +
> > > +#define IGT_DMA_BUF_IOCTL_EXPORT_SYNC_FILE _IOWR(DMA_BUF_BASE, 2, struct 
> > > igt_dma_buf_sync_file)
> > > +#define IGT_DMA_BUF_IOCTL_IMPORT_SYNC_FILE _IOW(DMA_BUF_BASE, 3, struct 
> > > igt_dma_buf_sync_file)
> > > +
> > > +/**
> > > + * has_dmabuf_export_sync_file:
> > > + * @fd: The open drm fd
> > > + *
> > > + * Check if the kernel supports exporting a sync file from dmabuf.
> > > + */
> > > +bool has_dmabuf_export_sync_file(int fd)
> > > +{
> > > + struct vgem_bo bo;
> > > + int dmabuf, ret;
> > > + struct igt_dma_buf_sync_file arg;
> > > +
> > > + bo.width = 1;
> > > + bo.height = 1;
> > > + bo.bpp = 32;
> > > + vgem_create(fd, );
> > > +
> > > + dmabuf = prime_handle_to_fd(fd, bo.handle);
> > > + gem_close(fd, bo.handle);
> > > +
> > > + arg.flags = DMA_BUF_SYNC_WRITE;
> > > + arg.fd = -1;
> > > +
> > > + ret = igt_ioctl(dmabuf, IGT_DMA_BUF_IOCTL_EXPORT_SYNC_FILE, );
> > > + close(dmabuf);
> > > + igt_assert(ret == 0 || errno == ENOTTY);
> > 
> > imho we should not explode here, it was ok in test but in lib
> > we should just return false in case of unexpected error, you can
> > add igt_debug if you think it will help.
> > This may lead to change in place where you use it, like
> > igt_require(has_dmabuf_export_sync_file(fd));
> 
> Yup, makes sense. Will fix.
> 
> > 
> > > +
> > > + return ret == 0;
> > > +}
> > > +
> > > +/**
> > > + * dmabuf_export_sync_file:
> > > + * @dmabuf: The dmabuf fd
> > > + * @flags: The flags to control the behaviour
> > > + *
> > > + * Take a snapshot of the current dma-resv fences in the dmabuf, and 
> > > export as a
> > > + * syncfile. The @flags should at least specify either 
> > > DMA_BUF_SYN

Re: [Intel-gfx] [PATCH i-g-t v2 1/2] lib/dmabuf_sync_file: move common stuff into lib

2022-12-05 Thread Kamil Konieczny
Hi Matt,

after re-reading I have few more nits.

On 2022-12-02 at 12:02:41 +, Matthew Auld wrote:
> So we can use this across different tests.
> 
> v2
>   - Add docs for everything (Petri)
>   - Add missing copyright and fix headers slightly (Kamil)
> 
> Signed-off-by: Matthew Auld 
> Cc: Kamil Konieczny 
> Cc: Petri Latvala 
> Cc: Andrzej Hajda 
> Cc: Nirmoy Das 
> ---
>  .../igt-gpu-tools/igt-gpu-tools-docs.xml  |   1 +
>  lib/dmabuf_sync_file.c| 211 ++
>  lib/dmabuf_sync_file.h|  26 +++
>  lib/meson.build   |   1 +
>  tests/dmabuf_sync_file.c  | 133 +--
>  5 files changed, 243 insertions(+), 129 deletions(-)
>  create mode 100644 lib/dmabuf_sync_file.c
>  create mode 100644 lib/dmabuf_sync_file.h
> 
> diff --git a/docs/reference/igt-gpu-tools/igt-gpu-tools-docs.xml 
> b/docs/reference/igt-gpu-tools/igt-gpu-tools-docs.xml
> index 1ce842f4..102c8a89 100644
> --- a/docs/reference/igt-gpu-tools/igt-gpu-tools-docs.xml
> +++ b/docs/reference/igt-gpu-tools/igt-gpu-tools-docs.xml
> @@ -15,6 +15,7 @@
>  
>
>  API Reference
> +
>  
>  
>  
> diff --git a/lib/dmabuf_sync_file.c b/lib/dmabuf_sync_file.c
> new file mode 100644
> index ..bcce2486
> --- /dev/null
> +++ b/lib/dmabuf_sync_file.c
> @@ -0,0 +1,211 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2022 Intel Corporation
> + */
> +
> +#include "igt.h"
> +#include "igt_vgem.h"
> +#include "sw_sync.h"
> +
> +#include "dmabuf_sync_file.h"
> +
> +/**
> + * SECTION: dmabuf_sync_file
> + * @short_description: DMABUF importing/exporting fencing support library
> + * @title: DMABUF Sync File
> + * @include: dmabuf_sync_file.h
> + */
> +
> +struct igt_dma_buf_sync_file {
> + __u32 flags;
> + __s32 fd;
> +};
> +
> +#define IGT_DMA_BUF_IOCTL_EXPORT_SYNC_FILE _IOWR(DMA_BUF_BASE, 2, struct 
> igt_dma_buf_sync_file)
> +#define IGT_DMA_BUF_IOCTL_IMPORT_SYNC_FILE _IOW(DMA_BUF_BASE, 3, struct 
> igt_dma_buf_sync_file)
> +
> +/**
> + * has_dmabuf_export_sync_file:
> + * @fd: The open drm fd
> + *
> + * Check if the kernel supports exporting a sync file from dmabuf.
> + */
> +bool has_dmabuf_export_sync_file(int fd)
> +{
> + struct vgem_bo bo;
> + int dmabuf, ret;
> + struct igt_dma_buf_sync_file arg;
> +
> + bo.width = 1;
> + bo.height = 1;
> + bo.bpp = 32;
> + vgem_create(fd, );
> +
> + dmabuf = prime_handle_to_fd(fd, bo.handle);
> + gem_close(fd, bo.handle);
> +
> + arg.flags = DMA_BUF_SYNC_WRITE;
> + arg.fd = -1;
> +
> + ret = igt_ioctl(dmabuf, IGT_DMA_BUF_IOCTL_EXPORT_SYNC_FILE, );
> + close(dmabuf);
> + igt_assert(ret == 0 || errno == ENOTTY);

imho we should not explode here, it was ok in test but in lib
we should just return false in case of unexpected error, you can
add igt_debug if you think it will help.
This may lead to change in place where you use it, like
igt_require(has_dmabuf_export_sync_file(fd));

> +
> + return ret == 0;
> +}
> +
> +/**
> + * dmabuf_export_sync_file:
> + * @dmabuf: The dmabuf fd
> + * @flags: The flags to control the behaviour
> + *
> + * Take a snapshot of the current dma-resv fences in the dmabuf, and export 
> as a
> + * syncfile. The @flags should at least specify either DMA_BUF_SYNC_WRITE or
> + * DMA_BUF_SYNC_READ, depending on if we care about the read or write fences.
> + */
> +int dmabuf_export_sync_file(int dmabuf, uint32_t flags)

As you do not check for errors so this should be 
int __dmabuf_export_sync_file(int dmabuf, uint32_t flags)

> +{
> + struct igt_dma_buf_sync_file arg;
> +
> + arg.flags = flags;
> + arg.fd = -1;
> + do_ioctl(dmabuf, IGT_DMA_BUF_IOCTL_EXPORT_SYNC_FILE, );
> +
> + return arg.fd;
> +}
> +
> +/**
> + * has_dmabuf_import_sync_file:
> + * @fd: The open drm fd
> + *
> + * Check if the kernel supports importing a sync file into a dmabuf.
> + */
> +bool has_dmabuf_import_sync_file(int fd)
> +{
> + struct vgem_bo bo;
> + int dmabuf, timeline, fence, ret;
> + struct igt_dma_buf_sync_file arg;
> +
> + bo.width = 1;
> + bo.height = 1;
> + bo.bpp = 32;
> + vgem_create(fd, );
> +
> + dmabuf = prime_handle_to_fd(fd, bo.handle);
> + gem_close(fd, bo.handle);
> +
> + timeline = sw_sync_timeline_create();
> + fence = sw_sync_timeline_create_fence(timeline, 1);
> + sw_sync_timeline_inc(timeline, 1);
> +
> + arg.flags = DMA_BUF_SYNC_RW;
>

Re: [Intel-gfx] [PATCH i-g-t 1/2] lib/dmabuf_sync_file: move common stuff into lib

2022-12-02 Thread Kamil Konieczny
Hi Matthew,

On 2022-12-01 at 16:49:43 +, Matthew Auld wrote:
> So we can use this across different tests.
> 
> Signed-off-by: Matthew Auld 
> Cc: Kamil Konieczny 
> Cc: Andrzej Hajda 
> Cc: Nirmoy Das 
> ---
>  lib/dmabuf_sync_file.c   | 138 +++
>  lib/dmabuf_sync_file.h   |  19 ++
>  lib/meson.build  |   1 +
>  tests/dmabuf_sync_file.c | 135 ++
>  4 files changed, 164 insertions(+), 129 deletions(-)
>  create mode 100644 lib/dmabuf_sync_file.c
>  create mode 100644 lib/dmabuf_sync_file.h
> 
> diff --git a/lib/dmabuf_sync_file.c b/lib/dmabuf_sync_file.c
> new file mode 100644
> index ..24e0f96d
> --- /dev/null
> +++ b/lib/dmabuf_sync_file.c
> @@ -0,0 +1,138 @@
> +// SPDX-License-Identifier: MIT

Add also copyright here, like in lib/intel_allocator.c
(I changed year):
/*
 * Copyright © 2022 Intel Corporation
 */

> +
> +#ifdef __linux__
> +#include 
> +#endif
> +#include 
> +
> +#include "igt.h"
> +#include "igt_vgem.h"
> +#include "sw_sync.h"
> +
> +#include "dmabuf_sync_file.h"
> +
> +struct igt_dma_buf_sync_file {
> + __u32 flags;
> + __s32 fd;
> +};
> +
> +#define IGT_DMA_BUF_IOCTL_EXPORT_SYNC_FILE _IOWR(DMA_BUF_BASE, 2, struct 
> igt_dma_buf_sync_file)
> +#define IGT_DMA_BUF_IOCTL_IMPORT_SYNC_FILE _IOW(DMA_BUF_BASE, 3, struct 
> igt_dma_buf_sync_file)
> +
> +bool has_dmabuf_export_sync_file(int fd)
> +{
> + struct vgem_bo bo;
> + int dmabuf, ret;
> + struct igt_dma_buf_sync_file arg;
> +
> + bo.width = 1;
> + bo.height = 1;
> + bo.bpp = 32;
> + vgem_create(fd, );
> +
> + dmabuf = prime_handle_to_fd(fd, bo.handle);
> + gem_close(fd, bo.handle);
> +
> + arg.flags = DMA_BUF_SYNC_WRITE;
> + arg.fd = -1;
> +
> + ret = igt_ioctl(dmabuf, IGT_DMA_BUF_IOCTL_EXPORT_SYNC_FILE, );
> + close(dmabuf);
> + igt_assert(ret == 0 || errno == ENOTTY);
> +
> + return ret == 0;
> +}
> +
> +int dmabuf_export_sync_file(int dmabuf, uint32_t flags)
> +{
> + struct igt_dma_buf_sync_file arg;
> +
> + arg.flags = flags;
> + arg.fd = -1;
> + do_ioctl(dmabuf, IGT_DMA_BUF_IOCTL_EXPORT_SYNC_FILE, );
> +
> + return arg.fd;
> +}
> +
> +bool has_dmabuf_import_sync_file(int fd)
> +{
> + struct vgem_bo bo;
> + int dmabuf, timeline, fence, ret;
> + struct igt_dma_buf_sync_file arg;
> +
> + bo.width = 1;
> + bo.height = 1;
> + bo.bpp = 32;
> + vgem_create(fd, );
> +
> + dmabuf = prime_handle_to_fd(fd, bo.handle);
> + gem_close(fd, bo.handle);
> +
> + timeline = sw_sync_timeline_create();
> + fence = sw_sync_timeline_create_fence(timeline, 1);
> + sw_sync_timeline_inc(timeline, 1);
> +
> + arg.flags = DMA_BUF_SYNC_RW;
> + arg.fd = fence;
> +
> + ret = igt_ioctl(dmabuf, IGT_DMA_BUF_IOCTL_IMPORT_SYNC_FILE, );
> + close(dmabuf);
> + close(fence);
> + igt_assert(ret == 0 || errno == ENOTTY);
> +
> + return ret == 0;
> +}
> +
> +void dmabuf_import_sync_file(int dmabuf, uint32_t flags, int sync_fd)
> +{
> + struct igt_dma_buf_sync_file arg;
> +
> + arg.flags = flags;
> + arg.fd = sync_fd;
> + do_ioctl(dmabuf, IGT_DMA_BUF_IOCTL_IMPORT_SYNC_FILE, );
> +}
> +
> +void
> +dmabuf_import_timeline_fence(int dmabuf, uint32_t flags,
> +  int timeline, uint32_t seqno)
> +{
> + int fence;
> +
> + fence = sw_sync_timeline_create_fence(timeline, seqno);
> + dmabuf_import_sync_file(dmabuf, flags, fence);
> + close(fence);
> +}
> +
> +bool dmabuf_busy(int dmabuf, uint32_t flags)
> +{
> + struct pollfd pfd = { .fd = dmabuf };
> +
> + /* If DMA_BUF_SYNC_WRITE is set, we don't want to set POLLIN or
> +  * else poll() may return a non-zero value if there are only read
> +  * fences because POLLIN is ready even if POLLOUT isn't.
> +  */
> + if (flags & DMA_BUF_SYNC_WRITE)
> + pfd.events |= POLLOUT;
> + else if (flags & DMA_BUF_SYNC_READ)
> + pfd.events |= POLLIN;
> +
> + return poll(, 1, 0) == 0;
> +}
> +
> +bool sync_file_busy(int sync_file)
> +{
> + struct pollfd pfd = { .fd = sync_file, .events = POLLIN };
> + return poll(, 1, 0) == 0;
> +}
> +
> +bool dmabuf_sync_file_busy(int dmabuf, uint32_t flags)
> +{
> + int sync_file;
> + bool busy;
> +
> + sync_file = dmabuf_export_sync_file(dmabuf, flags);
> + busy = sync_file_busy(sync_file);
> + close(sync_file)

Re: [Intel-gfx] [PATCH i-g-t] tests/i915/gem_exec_balancer: exercise dmabuf import

2022-11-25 Thread Kamil Konieczny
Hi Matthew,

one more nit, see below.

On 2022-11-18 at 15:53:35 +, Matthew Auld wrote:
> With parallel submission it should be easy to get a fence array as the
> output fence. Try importing this into dma-buf reservation object, to see
> if anything explodes.
> 
> References: https://gitlab.freedesktop.org/drm/intel/-/issues/7532
> Signed-off-by: Matthew Auld 
> Cc: Andrzej Hajda 
> Cc: Nirmoy Das 
> ---
>  tests/i915/gem_exec_balancer.c | 39 ++
>  1 file changed, 39 insertions(+)
> 
> diff --git a/tests/i915/gem_exec_balancer.c b/tests/i915/gem_exec_balancer.c
> index 4300dbd1..fdae8de5 100644
> --- a/tests/i915/gem_exec_balancer.c
> +++ b/tests/i915/gem_exec_balancer.c
> @@ -37,6 +37,7 @@
>  #include "igt_sysfs.h"
>  #include "igt_types.h"
>  #include "sw_sync.h"
> +#include 
- ^^
This should be above with other . Also it is linux
specific, so please put it with

#ifdef __linux__
#include 
#endif

Regards,
Kamil

>  
>  IGT_TEST_DESCRIPTION("Exercise in-kernel load-balancing");
>  
> @@ -2856,6 +2857,24 @@ static void logical_sort_siblings(int i915,
>  #define PARALLEL_SUBMIT_FENCE(0x1 << 3)
>  #define PARALLEL_CONTEXTS(0x1 << 4)
>  #define PARALLEL_VIRTUAL (0x1 << 5)
> +#define PARALLEL_OUT_FENCE_DMABUF(0x1 << 6)
> +
> +struct igt_dma_buf_sync_file {
> +__u32 flags;
> +__s32 fd;
> +};
> +
> +#define IGT_DMA_BUF_IOCTL_EXPORT_SYNC_FILE _IOWR(DMA_BUF_BASE, 2, struct 
> igt_dma_buf_sync_file)
> +#define IGT_DMA_BUF_IOCTL_IMPORT_SYNC_FILE _IOW(DMA_BUF_BASE, 3, struct 
> igt_dma_buf_sync_file)
> +
> +static void dmabuf_import_sync_file(int dmabuf, uint32_t flags, int sync_fd)
> +{
> +struct igt_dma_buf_sync_file arg;
> +
> +arg.flags = flags;
> +arg.fd = sync_fd;
> +do_ioctl(dmabuf, IGT_DMA_BUF_IOCTL_IMPORT_SYNC_FILE, );
> +}
>  
>  static void parallel_thread(int i915, unsigned int flags,
>   struct i915_engine_class_instance *siblings,
> @@ -2871,6 +2890,8 @@ static void parallel_thread(int i915, unsigned int 
> flags,
>   uint32_t target_bo_idx = 0;
>   uint32_t first_bb_idx = 1;
>   intel_ctx_cfg_t cfg;
> + uint32_t dmabuf_handle;
> + int dmabuf;
>  
>   igt_assert(bb_per_execbuf < 32);
>  
> @@ -2924,11 +2945,20 @@ static void parallel_thread(int i915, unsigned int 
> flags,
>   execbuf.buffers_ptr = to_user_pointer(obj);
>   execbuf.rsvd1 = ctx->id;
>  
> + if (flags & PARALLEL_OUT_FENCE_DMABUF) {
> + dmabuf_handle = gem_create(i915, 4096);
> + dmabuf = prime_handle_to_fd(i915, dmabuf_handle);
> + }
> +
>   for (n = 0; n < PARALLEL_BB_LOOP_COUNT; ++n) {
>   execbuf.flags &= ~0x3full;
>   gem_execbuf_wr(i915, );
>  
>   if (flags & PARALLEL_OUT_FENCE) {
> + if (flags & PARALLEL_OUT_FENCE_DMABUF)
> + dmabuf_import_sync_file(dmabuf, 
> DMA_BUF_SYNC_WRITE,
> + execbuf.rsvd2 >> 32);
> +
>   igt_assert_eq(sync_fence_wait(execbuf.rsvd2 >> 32,
> 1000), 0);
>   igt_assert_eq(sync_fence_status(execbuf.rsvd2 >> 32), 
> 1);
> @@ -2959,6 +2989,11 @@ static void parallel_thread(int i915, unsigned int 
> flags,
>   if (fence)
>   close(fence);
>  
> + if (flags & PARALLEL_OUT_FENCE_DMABUF) {
> + gem_close(i915, dmabuf_handle);
> + close(dmabuf);
> + }
> +
>   check_bo(i915, obj[target_bo_idx].handle,
>bb_per_execbuf * PARALLEL_BB_LOOP_COUNT, true);
>  
> @@ -3420,6 +3455,10 @@ igt_main
>   igt_subtest("parallel-out-fence")
>   parallel(i915, PARALLEL_OUT_FENCE);
>  
> + igt_subtest("parallel-out-fence-import-dmabuf")
> + parallel(i915, PARALLEL_OUT_FENCE |
> +  PARALLEL_OUT_FENCE_DMABUF);
> +
>   igt_subtest("parallel-keep-in-fence")
>   parallel(i915, PARALLEL_OUT_FENCE | PARALLEL_IN_FENCE);
>  
> -- 
> 2.38.1
> 


Re: [Intel-gfx] [PATCH i-g-t] tests/i915/gem_exec_balancer: exercise dmabuf import

2022-11-25 Thread Kamil Konieczny
Hi Matthew,

few nits, see below.

On 2022-11-18 at 15:53:35 +, Matthew Auld wrote:
> With parallel submission it should be easy to get a fence array as the
> output fence. Try importing this into dma-buf reservation object, to see
> if anything explodes.
> 
> References: https://gitlab.freedesktop.org/drm/intel/-/issues/7532
> Signed-off-by: Matthew Auld 
> Cc: Andrzej Hajda 
> Cc: Nirmoy Das 
> ---
>  tests/i915/gem_exec_balancer.c | 39 ++
>  1 file changed, 39 insertions(+)
> 
> diff --git a/tests/i915/gem_exec_balancer.c b/tests/i915/gem_exec_balancer.c
> index 4300dbd1..fdae8de5 100644
> --- a/tests/i915/gem_exec_balancer.c
> +++ b/tests/i915/gem_exec_balancer.c
> @@ -37,6 +37,7 @@
>  #include "igt_sysfs.h"
>  #include "igt_types.h"
>  #include "sw_sync.h"
> +#include 
>  
>  IGT_TEST_DESCRIPTION("Exercise in-kernel load-balancing");
>  
> @@ -2856,6 +2857,24 @@ static void logical_sort_siblings(int i915,
>  #define PARALLEL_SUBMIT_FENCE(0x1 << 3)
>  #define PARALLEL_CONTEXTS(0x1 << 4)
>  #define PARALLEL_VIRTUAL (0x1 << 5)
> +#define PARALLEL_OUT_FENCE_DMABUF(0x1 << 6)
> +
> +struct igt_dma_buf_sync_file {
> +__u32 flags;
> +__s32 fd;
> +};
> +
> +#define IGT_DMA_BUF_IOCTL_EXPORT_SYNC_FILE _IOWR(DMA_BUF_BASE, 2, struct 
> igt_dma_buf_sync_file)
> +#define IGT_DMA_BUF_IOCTL_IMPORT_SYNC_FILE _IOW(DMA_BUF_BASE, 3, struct 
> igt_dma_buf_sync_file)
> +
> +static void dmabuf_import_sync_file(int dmabuf, uint32_t flags, int sync_fd)
> +{
> +struct igt_dma_buf_sync_file arg;
> +
> +arg.flags = flags;
> +arg.fd = sync_fd;
> +do_ioctl(dmabuf, IGT_DMA_BUF_IOCTL_IMPORT_SYNC_FILE, );
> +}

You did not check for error here, so either add assert
do_ioctl ... == 0 or change function name, add __ before like:
static int __dmabuf_import_sync_file(int dmabuf, uint32_t flags, int sync_fd)

>  
>  static void parallel_thread(int i915, unsigned int flags,
>   struct i915_engine_class_instance *siblings,
> @@ -2871,6 +2890,8 @@ static void parallel_thread(int i915, unsigned int 
> flags,
>   uint32_t target_bo_idx = 0;
>   uint32_t first_bb_idx = 1;
>   intel_ctx_cfg_t cfg;
> + uint32_t dmabuf_handle;
> + int dmabuf;
>  
>   igt_assert(bb_per_execbuf < 32);
>  
> @@ -2924,11 +2945,20 @@ static void parallel_thread(int i915, unsigned int 
> flags,
>   execbuf.buffers_ptr = to_user_pointer(obj);
>   execbuf.rsvd1 = ctx->id;
>  
> + if (flags & PARALLEL_OUT_FENCE_DMABUF) {
> + dmabuf_handle = gem_create(i915, 4096);
> + dmabuf = prime_handle_to_fd(i915, dmabuf_handle);
> + }
> +
>   for (n = 0; n < PARALLEL_BB_LOOP_COUNT; ++n) {
>   execbuf.flags &= ~0x3full;
>   gem_execbuf_wr(i915, );
>  
>   if (flags & PARALLEL_OUT_FENCE) {
> + if (flags & PARALLEL_OUT_FENCE_DMABUF)
> + dmabuf_import_sync_file(dmabuf, 
> DMA_BUF_SYNC_WRITE,
> + execbuf.rsvd2 >> 32);
> +
>   igt_assert_eq(sync_fence_wait(execbuf.rsvd2 >> 32,
> 1000), 0);
>   igt_assert_eq(sync_fence_status(execbuf.rsvd2 >> 32), 
> 1);
> @@ -2959,6 +2989,11 @@ static void parallel_thread(int i915, unsigned int 
> flags,
>   if (fence)
>   close(fence);
>  
> + if (flags & PARALLEL_OUT_FENCE_DMABUF) {
> + gem_close(i915, dmabuf_handle);
> + close(dmabuf);
> + }
> +
>   check_bo(i915, obj[target_bo_idx].handle,
>bb_per_execbuf * PARALLEL_BB_LOOP_COUNT, true);
>  
> @@ -3420,6 +3455,10 @@ igt_main
>   igt_subtest("parallel-out-fence")
>   parallel(i915, PARALLEL_OUT_FENCE);
>  

Please put description here.

Regards,
Kamil

> + igt_subtest("parallel-out-fence-import-dmabuf")
> + parallel(i915, PARALLEL_OUT_FENCE |
> +  PARALLEL_OUT_FENCE_DMABUF);
> +
>   igt_subtest("parallel-keep-in-fence")
>   parallel(i915, PARALLEL_OUT_FENCE | PARALLEL_IN_FENCE);
>  
> -- 
> 2.38.1
> 


Re: [Intel-gfx] [i-g-t] tests/kms_plane: skip memory demanding modes in test_plane_panning

2022-11-22 Thread Kamil Konieczny
Hi Andrzej,

On 2022-11-15 at 08:28:34 +0100, Andrzej Hajda wrote:
> test_plane_panning requires about 10 times bigger amount of memory than
> memory required by framebuffer in default display mode. In case of some
> configurations it can exceed available memory (4k modes on small-bar
> systems), causing test aborts.
> 
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6824
> Signed-off-by: Andrzej Hajda 
> ---
>  tests/kms_plane.c | 28 +---
>  1 file changed, 25 insertions(+), 3 deletions(-)
> 
> diff --git a/tests/kms_plane.c b/tests/kms_plane.c
> index 8a54ba6645c..fc530d2cfd3 100644
> --- a/tests/kms_plane.c
> +++ b/tests/kms_plane.c
> @@ -342,14 +342,14 @@ test_plane_panning_with_output(data_t *data,
>   drmModeModeInfo *mode;
>   igt_crc_t crc;
>  
> - igt_info("Testing connector %s using pipe %s\n",
> -  igt_output_name(output), kmstest_pipe_name(pipe));
> -
>   igt_output_set_pipe(output, pipe);
>  
>   mode = igt_output_get_mode(output);
>   primary = igt_output_get_plane(output, 0);
>  
> + igt_info("Testing connector %s using pipe %s, mode %s\n",
> +  igt_output_name(output), kmstest_pipe_name(pipe), mode->name);
> +
>   create_fb_for_mode_panning(data, mode, _fb);
>   igt_plane_set_fb(primary, _fb);
>  
> @@ -381,6 +381,8 @@ test_plane_panning_with_output(data_t *data,
>  static void
>  test_plane_panning(data_t *data, enum pipe pipe)
>  {
> + bool mode_found = false;
> + uint64_t mem_size = 0;
>   igt_output_t *output;
>   igt_crc_t ref_crc;
>  
> @@ -389,6 +391,26 @@ test_plane_panning(data_t *data, enum pipe pipe)
>  
>   test_init(data, pipe);
>  
> + for_each_memory_region(r, data->drm_fd)
> + if (r->ci.memory_class == I915_MEMORY_CLASS_DEVICE)
> + mem_size = r->cpu_size;

imho either max(mem_size, r->cpu_size) or just break after
assign but maybe I overcomplicate this, so

Reviewed-by: Kamil Konieczny 

> +
> + for_each_connector_mode(output) {
> + drmModeModeInfo *m = >config.connector->modes[j__];
> + uint32_t fb_size = m->hdisplay * m->vdisplay * 4;
> +
> + /* test allocates 2 double-dim fbs, add one more, to be safe */
> + if (mem_size && 3 * 4 * fb_size > mem_size) {
> + igt_debug("Skipping mode %s due to low memory\n", 
> m->name);
> + continue;
> + }
> +
> + igt_output_override_mode(output, m);
> + mode_found = true;
> + break;
> + }
> + igt_require(mode_found);
> +
>   if (data->flags & TEST_PANNING_TOP_LEFT)
>   test_grab_crc(data, output, pipe, , data->flags, _crc);
>   else
> -- 
> 2.34.1
> 


Re: [Intel-gfx] [PATCH i-g-t] gem_ctx_persistence: adjust reset timeout

2022-10-04 Thread Kamil Konieczny
On 2022-09-23 at 18:01:37 +0200, Andrzej Hajda wrote:
> Tests on DG2 show that context cancel can take even 350ms,
> due to error state capturing in guc_handle_context_reset.
> Since it happens only in debug mode and tests runs in debug mode
> it should be fine to adjust the timeout.
> Let's double this value, to be on safe side.
> It should fix multiple test timeout failures.
> 
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/1551
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5891
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/3952
> Signed-off-by: Andrzej Hajda 

Reviewed-by: Kamil Konieczny 

> ---
>  tests/i915/gem_ctx_persistence.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/tests/i915/gem_ctx_persistence.c 
> b/tests/i915/gem_ctx_persistence.c
> index 50196edb19f..a844439de19 100644
> --- a/tests/i915/gem_ctx_persistence.c
> +++ b/tests/i915/gem_ctx_persistence.c
> @@ -1214,7 +1214,7 @@ static void do_test(void (*test)(int i915, const 
> intel_ctx_cfg_t *cfg,
>   if (timeout != -1) {
>   igt_require(gem_engine_property_printf(i915, name,
>  ATTR, "%d", 50) > 0);
> - reset_timeout_ms = 200;
> + reset_timeout_ms = 700;
>   }
>  
>   test(i915, cfg, engine);
> -- 
> 2.34.1
> 


Re: [Intel-gfx] [CI] tests/drm_fdinfo: Test virtual engines

2022-06-20 Thread Kamil Konieczny
Hi Tvrtko,

On 2022-06-17 at 10:08:28 +0100, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> We need some coverage of the virtual engines.
> 
> v2:
>  * Mark contexts as "allow hang". (Umesh)
>  * Fix destruction order in virtual_all.
> 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Umesh Nerlige Ramappa 
> Reviewed-by: Umesh Nerlige Ramappa 
> ---
>  tests/i915/drm_fdinfo.c | 293 +++-
>  1 file changed, 291 insertions(+), 2 deletions(-)
> 
> diff --git a/tests/i915/drm_fdinfo.c b/tests/i915/drm_fdinfo.c
> index 3475d35b23b9..65b8b8307c66 100644
> --- a/tests/i915/drm_fdinfo.c
> +++ b/tests/i915/drm_fdinfo.c
> @@ -27,6 +27,7 @@
>  #include "igt_device.h"
>  #include "igt_drm_fdinfo.h"
>  #include "i915/gem.h"
> +#include "i915/gem_vm.h"
>  #include "intel_ctx.h"
>  
>  IGT_TEST_DESCRIPTION("Test the i915 drm fdinfo data");
> @@ -90,10 +91,10 @@ static igt_spin_t *__spin_poll(int fd, uint64_t ahnd, 
> const intel_ctx_t *ctx,
>   struct igt_spin_factory opts = {
>   .ahnd = ahnd,
>   .ctx = ctx,
> - .engine = e->flags,
> + .engine = e ? e->flags : 0,
>   };
>  
> - if (gem_class_can_store_dword(fd, e->class))
> + if (!e || gem_class_can_store_dword(fd, e->class))
>   opts.flags |= IGT_SPIN_POLL_RUN;
>  
>   return __igt_spin_factory(fd, );
> @@ -440,6 +441,274 @@ all_busy_check_all(int gem_fd, const intel_ctx_t *ctx,
>   gem_quiescent_gpu(gem_fd);
>  }
>  
> +static struct i915_engine_class_instance *
> +list_engines(const intel_ctx_cfg_t *cfg,
> +  unsigned int class, unsigned int *out)
> +{
> + struct i915_engine_class_instance *ci;
> + unsigned int count = 0, i;
> +
> + ci = malloc(cfg->num_engines * sizeof(*ci));
> + igt_assert(ci);
> +
> + for (i = 0; i < cfg->num_engines; i++) {
> + if (class == cfg->engines[i].engine_class)
> + ci[count++] = cfg->engines[i];
> + }
> +
> + if (!count) {
> + free(ci);
> + ci = NULL;
> + }
> +
> + *out = count;
> + return ci;
> +}
> +
> +static size_t sizeof_load_balance(int count)
> +{
> + return offsetof(struct i915_context_engines_load_balance,
> + engines[count]);
> +}
> +
> +static size_t sizeof_param_engines(int count)
> +{
> + return offsetof(struct i915_context_param_engines,
> + engines[count]);
> +}
> +
> +#define alloca0(sz) ({ size_t sz__ = (sz); memset(alloca(sz__), 0, sz__); })
> +
> +static int __set_load_balancer(int i915, uint32_t ctx,
> +const struct i915_engine_class_instance *ci,
> +unsigned int count,
> +void *ext)
> +{
> + struct i915_context_engines_load_balance *balancer =
> + alloca0(sizeof_load_balance(count));
> + struct i915_context_param_engines *engines =
> + alloca0(sizeof_param_engines(count + 1));
> + struct drm_i915_gem_context_param p = {
> + .ctx_id = ctx,
> + .param = I915_CONTEXT_PARAM_ENGINES,
> + .size = sizeof_param_engines(count + 1),
> + .value = to_user_pointer(engines)
> + };
> +
> + balancer->base.name = I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE;
> + balancer->base.next_extension = to_user_pointer(ext);
> +
> + igt_assert(count);
> + balancer->num_siblings = count;
> + memcpy(balancer->engines, ci, count * sizeof(*ci));
> +
> + engines->extensions = to_user_pointer(balancer);
> + engines->engines[0].engine_class =
> + I915_ENGINE_CLASS_INVALID;
> + engines->engines[0].engine_instance =
> + I915_ENGINE_CLASS_INVALID_NONE;
> + memcpy(engines->engines + 1, ci, count * sizeof(*ci));
> +
> + return __gem_context_set_param(i915, );
> +}
> +
> +static void set_load_balancer(int i915, uint32_t ctx,
> +   const struct i915_engine_class_instance *ci,
> +   unsigned int count,
> +   void *ext)
> +{
> + igt_assert_eq(__set_load_balancer(i915, ctx, ci, count, ext), 0);
> +}
> +
> +static void
> +virtual(int i915, const intel_ctx_cfg_t *base_cfg, unsigned int flags)
> +{
> + intel_ctx_cfg_t cfg = {};
> +
> + cfg.vm = gem_vm_create(i915);
> +
> + for (int class = 0; class < 32; class++) {
> + struct i915_engine_class_instance *ci;
> + unsigned int count;
> +
> + if (!gem_class_can_store_dword(i915, class))
> + continue;
> +
> + ci = list_engines(base_cfg, class, );
> + if (!ci)
> + continue;
> +
> + for (unsigned int pass = 0; pass < count; pass++) {
> + const intel_ctx_t *ctx;
> + unsigned long slept;
> + uint64_t ahnd, val;
> + igt_spin_t *spin;
> + 

Re: [Intel-gfx] [igt-dev] [PATCH v5 i-g-t 2/3] tests/i915/query: Add descriptions to existing tests

2022-06-06 Thread Kamil Konieczny
On 2022-06-03 at 09:25:51 -0700, john.c.harri...@intel.com wrote:
> From: John Harrison 
> 
> None of the query tests had a description. So make some up.
> 
> Signed-off-by: John Harrison 
> ---

Reviewed-by: Kamil Konieczny 

>  tests/i915/i915_query.c | 12 
>  1 file changed, 12 insertions(+)
> 
> diff --git a/tests/i915/i915_query.c b/tests/i915/i915_query.c
> index 246a979af72a..35a91d245ec1 100644
> --- a/tests/i915/i915_query.c
> +++ b/tests/i915/i915_query.c
> @@ -923,34 +923,41 @@ igt_main
>   devid = intel_get_drm_devid(fd);
>   }
>  
> + igt_describe("Test reponse to an invalid query call");
>   igt_subtest("query-garbage")
>   test_query_garbage(fd);
>  
> + igt_describe("Test response to invalid DRM_I915_QUERY_TOPOLOGY_INFO 
> query");
>   igt_subtest("query-topology-garbage-items") {
>   igt_require(query_topology_supported(fd));
>   test_query_topology_garbage_items(fd);
>   }
>  
> + igt_describe("Guardband test for DRM_I915_QUERY_TOPOLOGY_INFO query");
>   igt_subtest("query-topology-kernel-writes") {
>   igt_require(query_topology_supported(fd));
>   test_query_topology_kernel_writes(fd);
>   }
>  
> + igt_describe("Verify DRM_I915_QUERY_TOPOLOGY_INFO query fails when it 
> is not supported");
>   igt_subtest("query-topology-unsupported") {
>   igt_require(!query_topology_supported(fd));
>   test_query_topology_unsupported(fd);
>   }
>  
> + igt_describe("Compare new DRM_I915_QUERY_TOPOLOGY_INFO query with 
> legacy (sub)slice getparams");
>   igt_subtest("query-topology-coherent-slice-mask") {
>   igt_require(query_topology_supported(fd));
>   test_query_topology_coherent_slice_mask(fd);
>   }
>  
> + igt_describe("More compare new DRM_I915_QUERY_TOPOLOGY_INFO query with 
> legacy (sub)slice getparams");
>   igt_subtest("query-topology-matches-eu-total") {
>   igt_require(query_topology_supported(fd));
>   test_query_topology_matches_eu_total(fd);
>   }
>  
> + igt_describe("Verify DRM_I915_QUERY_TOPOLOGY_INFO query against 
> hardcoded known values for certain platforms");
>   igt_subtest("query-topology-known-pci-ids") {
>   igt_require(query_topology_supported(fd));
>   igt_require(IS_HASWELL(devid) || IS_BROADWELL(devid) ||
> @@ -959,16 +966,19 @@ igt_main
>   test_query_topology_known_pci_ids(fd, devid);
>   }
>  
> + igt_describe("Test DRM_I915_QUERY_GEOMETRY_SUBSLICES query");
>   igt_subtest("test-query-geometry-subslices") {
>   igt_require(query_geometry_subslices_supported(fd));
>   test_query_geometry_subslices(fd);
>   }
>  
> + igt_describe("Dodgy returned data tests for 
> DRM_I915_QUERY_MEMORY_REGIONS");
>   igt_subtest("query-regions-garbage-items") {
>   igt_require(query_regions_supported(fd));
>   test_query_regions_garbage_items(fd);
>   }
>  
> + igt_describe("Basic tests for DRM_I915_QUERY_MEMORY_REGIONS");
>   igt_subtest("query-regions-sanity-check") {
>   igt_require(query_regions_supported(fd));
>   test_query_regions_sanity_check(fd);
> @@ -979,9 +989,11 @@ igt_main
>   igt_require(query_engine_info_supported(fd));
>   }
>  
> + igt_describe("Negative tests for DRM_I915_QUERY_ENGINE_INFO");
>   igt_subtest("engine-info-invalid")
>   engines_invalid(fd);
>  
> + igt_describe("Positive tests for DRM_I915_QUERY_ENGINE_INFO");
>   igt_subtest("engine-info")
>   engines(fd);
>   }
> -- 
> 2.36.0
> 


  1   2   >