All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/7] drm/selftests: Move i915 buddy selftests into drm
@ 2022-02-03 13:32 ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

- move i915 buddy selftests into drm selftests folder
- add Makefile and Kconfig support
- add sanitycheck testcase

Prerequisites
- These series of selftests patches are created on top of
  drm buddy series
- Enable kselftests for DRM as a module in .config

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 drivers/gpu/drm/Kconfig                       |  1 +
 drivers/gpu/drm/selftests/Makefile            |  3 +-
 .../gpu/drm/selftests/drm_buddy_selftests.h   |  9 ++++
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 49 +++++++++++++++++++
 4 files changed, 61 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/selftests/drm_buddy_selftests.h
 create mode 100644 drivers/gpu/drm/selftests/test-drm_buddy.c

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index eb5a57ae3c5c..ff856df3f97f 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -71,6 +71,7 @@ config DRM_DEBUG_SELFTEST
 	select DRM_DP_HELPER
 	select DRM_LIB_RANDOM
 	select DRM_KMS_HELPER
+	select DRM_BUDDY
 	select DRM_EXPORT_FOR_TESTS if m
 	default n
 	help
diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile
index 0856e4b12f70..5ba5f9138c95 100644
--- a/drivers/gpu/drm/selftests/Makefile
+++ b/drivers/gpu/drm/selftests/Makefile
@@ -4,4 +4,5 @@ test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
 		      test-drm_damage_helper.o test-drm_dp_mst_helper.o \
 		      test-drm_rect.o
 
-obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o
+obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o \
+				    test-drm_buddy.o
diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
new file mode 100644
index 000000000000..a4bcf3a6dfe3
--- /dev/null
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* List each unit test as selftest(name, function)
+ *
+ * The name is used as both an enum and expanded as igt__name to create
+ * a module parameter. It must be unique and legal for a C identifier.
+ *
+ * Tests are executed in order by igt/drm_buddy
+ */
+selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
new file mode 100644
index 000000000000..51e4d393d22c
--- /dev/null
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2019 Intel Corporation
+ */
+
+#define pr_fmt(fmt) "drm_buddy: " fmt
+
+#include <linux/module.h>
+
+#include <drm/drm_buddy.h>
+
+#include "../lib/drm_random.h"
+
+#define TESTS "drm_buddy_selftests.h"
+#include "drm_selftest.h"
+
+static unsigned int random_seed;
+
+static int igt_sanitycheck(void *ignored)
+{
+	pr_info("%s - ok!\n", __func__);
+	return 0;
+}
+
+#include "drm_selftest.c"
+
+static int __init test_drm_buddy_init(void)
+{
+	int err;
+
+	while (!random_seed)
+		random_seed = get_random_int();
+
+	pr_info("Testing DRM buddy manager (struct drm_buddy), with random_seed=0x%x\n",
+		random_seed);
+	err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
+
+	return err > 0 ? 0 : err;
+}
+
+static void __exit test_drm_buddy_exit(void)
+{
+}
+
+module_init(test_drm_buddy_init);
+module_exit(test_drm_buddy_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL");
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Intel-gfx] [PATCH 1/7] drm/selftests: Move i915 buddy selftests into drm
@ 2022-02-03 13:32 ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

- move i915 buddy selftests into drm selftests folder
- add Makefile and Kconfig support
- add sanitycheck testcase

Prerequisites
- These series of selftests patches are created on top of
  drm buddy series
- Enable kselftests for DRM as a module in .config

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 drivers/gpu/drm/Kconfig                       |  1 +
 drivers/gpu/drm/selftests/Makefile            |  3 +-
 .../gpu/drm/selftests/drm_buddy_selftests.h   |  9 ++++
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 49 +++++++++++++++++++
 4 files changed, 61 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/selftests/drm_buddy_selftests.h
 create mode 100644 drivers/gpu/drm/selftests/test-drm_buddy.c

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index eb5a57ae3c5c..ff856df3f97f 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -71,6 +71,7 @@ config DRM_DEBUG_SELFTEST
 	select DRM_DP_HELPER
 	select DRM_LIB_RANDOM
 	select DRM_KMS_HELPER
+	select DRM_BUDDY
 	select DRM_EXPORT_FOR_TESTS if m
 	default n
 	help
diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile
index 0856e4b12f70..5ba5f9138c95 100644
--- a/drivers/gpu/drm/selftests/Makefile
+++ b/drivers/gpu/drm/selftests/Makefile
@@ -4,4 +4,5 @@ test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
 		      test-drm_damage_helper.o test-drm_dp_mst_helper.o \
 		      test-drm_rect.o
 
-obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o
+obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o \
+				    test-drm_buddy.o
diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
new file mode 100644
index 000000000000..a4bcf3a6dfe3
--- /dev/null
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* List each unit test as selftest(name, function)
+ *
+ * The name is used as both an enum and expanded as igt__name to create
+ * a module parameter. It must be unique and legal for a C identifier.
+ *
+ * Tests are executed in order by igt/drm_buddy
+ */
+selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
new file mode 100644
index 000000000000..51e4d393d22c
--- /dev/null
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2019 Intel Corporation
+ */
+
+#define pr_fmt(fmt) "drm_buddy: " fmt
+
+#include <linux/module.h>
+
+#include <drm/drm_buddy.h>
+
+#include "../lib/drm_random.h"
+
+#define TESTS "drm_buddy_selftests.h"
+#include "drm_selftest.h"
+
+static unsigned int random_seed;
+
+static int igt_sanitycheck(void *ignored)
+{
+	pr_info("%s - ok!\n", __func__);
+	return 0;
+}
+
+#include "drm_selftest.c"
+
+static int __init test_drm_buddy_init(void)
+{
+	int err;
+
+	while (!random_seed)
+		random_seed = get_random_int();
+
+	pr_info("Testing DRM buddy manager (struct drm_buddy), with random_seed=0x%x\n",
+		random_seed);
+	err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
+
+	return err > 0 ? 0 : err;
+}
+
+static void __exit test_drm_buddy_exit(void)
+{
+}
+
+module_init(test_drm_buddy_init);
+module_exit(test_drm_buddy_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL");
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 1/7] drm/selftests: Move i915 buddy selftests into drm
@ 2022-02-03 13:32 ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: daniel, Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

- move i915 buddy selftests into drm selftests folder
- add Makefile and Kconfig support
- add sanitycheck testcase

Prerequisites
- These series of selftests patches are created on top of
  drm buddy series
- Enable kselftests for DRM as a module in .config

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 drivers/gpu/drm/Kconfig                       |  1 +
 drivers/gpu/drm/selftests/Makefile            |  3 +-
 .../gpu/drm/selftests/drm_buddy_selftests.h   |  9 ++++
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 49 +++++++++++++++++++
 4 files changed, 61 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/selftests/drm_buddy_selftests.h
 create mode 100644 drivers/gpu/drm/selftests/test-drm_buddy.c

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index eb5a57ae3c5c..ff856df3f97f 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -71,6 +71,7 @@ config DRM_DEBUG_SELFTEST
 	select DRM_DP_HELPER
 	select DRM_LIB_RANDOM
 	select DRM_KMS_HELPER
+	select DRM_BUDDY
 	select DRM_EXPORT_FOR_TESTS if m
 	default n
 	help
diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile
index 0856e4b12f70..5ba5f9138c95 100644
--- a/drivers/gpu/drm/selftests/Makefile
+++ b/drivers/gpu/drm/selftests/Makefile
@@ -4,4 +4,5 @@ test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
 		      test-drm_damage_helper.o test-drm_dp_mst_helper.o \
 		      test-drm_rect.o
 
-obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o
+obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o \
+				    test-drm_buddy.o
diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
new file mode 100644
index 000000000000..a4bcf3a6dfe3
--- /dev/null
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* List each unit test as selftest(name, function)
+ *
+ * The name is used as both an enum and expanded as igt__name to create
+ * a module parameter. It must be unique and legal for a C identifier.
+ *
+ * Tests are executed in order by igt/drm_buddy
+ */
+selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
new file mode 100644
index 000000000000..51e4d393d22c
--- /dev/null
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2019 Intel Corporation
+ */
+
+#define pr_fmt(fmt) "drm_buddy: " fmt
+
+#include <linux/module.h>
+
+#include <drm/drm_buddy.h>
+
+#include "../lib/drm_random.h"
+
+#define TESTS "drm_buddy_selftests.h"
+#include "drm_selftest.h"
+
+static unsigned int random_seed;
+
+static int igt_sanitycheck(void *ignored)
+{
+	pr_info("%s - ok!\n", __func__);
+	return 0;
+}
+
+#include "drm_selftest.c"
+
+static int __init test_drm_buddy_init(void)
+{
+	int err;
+
+	while (!random_seed)
+		random_seed = get_random_int();
+
+	pr_info("Testing DRM buddy manager (struct drm_buddy), with random_seed=0x%x\n",
+		random_seed);
+	err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
+
+	return err > 0 ? 0 : err;
+}
+
+static void __exit test_drm_buddy_exit(void)
+{
+}
+
+module_init(test_drm_buddy_init);
+module_exit(test_drm_buddy_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL");
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 2/7] drm/selftests: add drm buddy alloc limit testcase
  2022-02-03 13:32 ` [Intel-gfx] " Arunpravin
  (?)
@ 2022-02-03 13:32   ` Arunpravin
  -1 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

add a test to check the maximum allocation limit

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 .../gpu/drm/selftests/drm_buddy_selftests.h   |  1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 60 +++++++++++++++++++
 2 files changed, 61 insertions(+)

diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index a4bcf3a6dfe3..ebe16162762f 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -7,3 +7,4 @@
  * Tests are executed in order by igt/drm_buddy
  */
 selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
+selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index 51e4d393d22c..fd7d1a112458 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -16,6 +16,66 @@
 
 static unsigned int random_seed;
 
+static int igt_buddy_alloc_limit(void *arg)
+{
+	u64 end, size = U64_MAX, start = 0;
+	struct drm_buddy_block *block;
+	unsigned long flags = 0;
+	LIST_HEAD(allocated);
+	struct drm_buddy mm;
+	int err;
+
+	size = end = round_down(size, 4096);
+	err = drm_buddy_init(&mm, size, PAGE_SIZE);
+	if (err)
+		return err;
+
+	if (mm.max_order != DRM_BUDDY_MAX_ORDER) {
+		pr_err("mm.max_order(%d) != %d\n",
+		       mm.max_order, DRM_BUDDY_MAX_ORDER);
+		err = -EINVAL;
+		goto out_fini;
+	}
+
+	err = drm_buddy_alloc_blocks(&mm, start, end, size,
+				     PAGE_SIZE, &allocated, flags);
+
+	if (unlikely(err))
+		goto out_free;
+
+	block = list_first_entry_or_null(&allocated,
+					 struct drm_buddy_block,
+					 link);
+
+	if (!block)
+		goto out_fini;
+
+	if (drm_buddy_block_order(block) != mm.max_order) {
+		pr_err("block order(%d) != %d\n",
+		       drm_buddy_block_order(block), mm.max_order);
+		err = -EINVAL;
+		goto out_free;
+	}
+
+	if (drm_buddy_block_size(&mm, block) !=
+	    BIT_ULL(mm.max_order) * PAGE_SIZE) {
+		pr_err("block size(%llu) != %llu\n",
+		       drm_buddy_block_size(&mm, block),
+		       BIT_ULL(mm.max_order) * PAGE_SIZE);
+		err = -EINVAL;
+		goto out_free;
+	}
+
+	if (!err)
+		pr_info("%s - succeeded\n", __func__);
+
+out_free:
+	drm_buddy_free_list(&mm, &allocated);
+out_fini:
+	drm_buddy_fini(&mm);
+	return err;
+}
+
 static int igt_sanitycheck(void *ignored)
 {
 	pr_info("%s - ok!\n", __func__);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Intel-gfx] [PATCH 2/7] drm/selftests: add drm buddy alloc limit testcase
@ 2022-02-03 13:32   ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

add a test to check the maximum allocation limit

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 .../gpu/drm/selftests/drm_buddy_selftests.h   |  1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 60 +++++++++++++++++++
 2 files changed, 61 insertions(+)

diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index a4bcf3a6dfe3..ebe16162762f 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -7,3 +7,4 @@
  * Tests are executed in order by igt/drm_buddy
  */
 selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
+selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index 51e4d393d22c..fd7d1a112458 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -16,6 +16,66 @@
 
 static unsigned int random_seed;
 
+static int igt_buddy_alloc_limit(void *arg)
+{
+	u64 end, size = U64_MAX, start = 0;
+	struct drm_buddy_block *block;
+	unsigned long flags = 0;
+	LIST_HEAD(allocated);
+	struct drm_buddy mm;
+	int err;
+
+	size = end = round_down(size, 4096);
+	err = drm_buddy_init(&mm, size, PAGE_SIZE);
+	if (err)
+		return err;
+
+	if (mm.max_order != DRM_BUDDY_MAX_ORDER) {
+		pr_err("mm.max_order(%d) != %d\n",
+		       mm.max_order, DRM_BUDDY_MAX_ORDER);
+		err = -EINVAL;
+		goto out_fini;
+	}
+
+	err = drm_buddy_alloc_blocks(&mm, start, end, size,
+				     PAGE_SIZE, &allocated, flags);
+
+	if (unlikely(err))
+		goto out_free;
+
+	block = list_first_entry_or_null(&allocated,
+					 struct drm_buddy_block,
+					 link);
+
+	if (!block)
+		goto out_fini;
+
+	if (drm_buddy_block_order(block) != mm.max_order) {
+		pr_err("block order(%d) != %d\n",
+		       drm_buddy_block_order(block), mm.max_order);
+		err = -EINVAL;
+		goto out_free;
+	}
+
+	if (drm_buddy_block_size(&mm, block) !=
+	    BIT_ULL(mm.max_order) * PAGE_SIZE) {
+		pr_err("block size(%llu) != %llu\n",
+		       drm_buddy_block_size(&mm, block),
+		       BIT_ULL(mm.max_order) * PAGE_SIZE);
+		err = -EINVAL;
+		goto out_free;
+	}
+
+	if (!err)
+		pr_info("%s - succeeded\n", __func__);
+
+out_free:
+	drm_buddy_free_list(&mm, &allocated);
+out_fini:
+	drm_buddy_fini(&mm);
+	return err;
+}
+
 static int igt_sanitycheck(void *ignored)
 {
 	pr_info("%s - ok!\n", __func__);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 2/7] drm/selftests: add drm buddy alloc limit testcase
@ 2022-02-03 13:32   ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: daniel, Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

add a test to check the maximum allocation limit

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 .../gpu/drm/selftests/drm_buddy_selftests.h   |  1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 60 +++++++++++++++++++
 2 files changed, 61 insertions(+)

diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index a4bcf3a6dfe3..ebe16162762f 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -7,3 +7,4 @@
  * Tests are executed in order by igt/drm_buddy
  */
 selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
+selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index 51e4d393d22c..fd7d1a112458 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -16,6 +16,66 @@
 
 static unsigned int random_seed;
 
+static int igt_buddy_alloc_limit(void *arg)
+{
+	u64 end, size = U64_MAX, start = 0;
+	struct drm_buddy_block *block;
+	unsigned long flags = 0;
+	LIST_HEAD(allocated);
+	struct drm_buddy mm;
+	int err;
+
+	size = end = round_down(size, 4096);
+	err = drm_buddy_init(&mm, size, PAGE_SIZE);
+	if (err)
+		return err;
+
+	if (mm.max_order != DRM_BUDDY_MAX_ORDER) {
+		pr_err("mm.max_order(%d) != %d\n",
+		       mm.max_order, DRM_BUDDY_MAX_ORDER);
+		err = -EINVAL;
+		goto out_fini;
+	}
+
+	err = drm_buddy_alloc_blocks(&mm, start, end, size,
+				     PAGE_SIZE, &allocated, flags);
+
+	if (unlikely(err))
+		goto out_free;
+
+	block = list_first_entry_or_null(&allocated,
+					 struct drm_buddy_block,
+					 link);
+
+	if (!block)
+		goto out_fini;
+
+	if (drm_buddy_block_order(block) != mm.max_order) {
+		pr_err("block order(%d) != %d\n",
+		       drm_buddy_block_order(block), mm.max_order);
+		err = -EINVAL;
+		goto out_free;
+	}
+
+	if (drm_buddy_block_size(&mm, block) !=
+	    BIT_ULL(mm.max_order) * PAGE_SIZE) {
+		pr_err("block size(%llu) != %llu\n",
+		       drm_buddy_block_size(&mm, block),
+		       BIT_ULL(mm.max_order) * PAGE_SIZE);
+		err = -EINVAL;
+		goto out_free;
+	}
+
+	if (!err)
+		pr_info("%s - succeeded\n", __func__);
+
+out_free:
+	drm_buddy_free_list(&mm, &allocated);
+out_fini:
+	drm_buddy_fini(&mm);
+	return err;
+}
+
 static int igt_sanitycheck(void *ignored)
 {
 	pr_info("%s - ok!\n", __func__);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 3/7] drm/selftests: add drm buddy alloc range testcase
  2022-02-03 13:32 ` [Intel-gfx] " Arunpravin
  (?)
@ 2022-02-03 13:32   ` Arunpravin
  -1 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

- add a test to check the range allocation
- export get_buddy() function in drm_buddy.c
- export drm_prandom_u32_max_state() in lib/drm_random.c
- include helper functions
- include prime number header file

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 drivers/gpu/drm/drm_buddy.c                   |  20 +-
 drivers/gpu/drm/lib/drm_random.c              |   3 +-
 drivers/gpu/drm/lib/drm_random.h              |   2 +
 .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 390 ++++++++++++++++++
 include/drm/drm_buddy.h                       |   3 +
 6 files changed, 414 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
index 4845ef784b5e..501229d843c4 100644
--- a/drivers/gpu/drm/drm_buddy.c
+++ b/drivers/gpu/drm/drm_buddy.c
@@ -211,7 +211,7 @@ static int split_block(struct drm_buddy *mm,
 }
 
 static struct drm_buddy_block *
-get_buddy(struct drm_buddy_block *block)
+__get_buddy(struct drm_buddy_block *block)
 {
 	struct drm_buddy_block *parent;
 
@@ -225,6 +225,18 @@ get_buddy(struct drm_buddy_block *block)
 	return parent->left;
 }
 
+/**
+ * drm_get_buddy - get buddy address
+ *
+ * @block: DRM buddy block
+ */
+struct drm_buddy_block *
+drm_get_buddy(struct drm_buddy_block *block)
+{
+	return __get_buddy(block);
+}
+EXPORT_SYMBOL(drm_get_buddy);
+
 static void __drm_buddy_free(struct drm_buddy *mm,
 			     struct drm_buddy_block *block)
 {
@@ -233,7 +245,7 @@ static void __drm_buddy_free(struct drm_buddy *mm,
 	while ((parent = block->parent)) {
 		struct drm_buddy_block *buddy;
 
-		buddy = get_buddy(block);
+		buddy = __get_buddy(block);
 
 		if (!drm_buddy_block_is_free(buddy))
 			break;
@@ -361,7 +373,7 @@ alloc_range_bias(struct drm_buddy *mm,
 	 * bigger is better, so make sure we merge everything back before we
 	 * free the allocated blocks.
 	 */
-	buddy = get_buddy(block);
+	buddy = __get_buddy(block);
 	if (buddy &&
 	    (drm_buddy_block_is_free(block) &&
 	     drm_buddy_block_is_free(buddy)))
@@ -500,7 +512,7 @@ static int __alloc_range(struct drm_buddy *mm,
 	 * bigger is better, so make sure we merge everything back before we
 	 * free the allocated blocks.
 	 */
-	buddy = get_buddy(block);
+	buddy = __get_buddy(block);
 	if (buddy &&
 	    (drm_buddy_block_is_free(block) &&
 	     drm_buddy_block_is_free(buddy)))
diff --git a/drivers/gpu/drm/lib/drm_random.c b/drivers/gpu/drm/lib/drm_random.c
index eeb155826d27..31b5a3e21911 100644
--- a/drivers/gpu/drm/lib/drm_random.c
+++ b/drivers/gpu/drm/lib/drm_random.c
@@ -7,10 +7,11 @@
 
 #include "drm_random.h"
 
-static inline u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
+u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
 {
 	return upper_32_bits((u64)prandom_u32_state(state) * ep_ro);
 }
+EXPORT_SYMBOL(drm_prandom_u32_max_state);
 
 void drm_random_reorder(unsigned int *order, unsigned int count,
 			struct rnd_state *state)
diff --git a/drivers/gpu/drm/lib/drm_random.h b/drivers/gpu/drm/lib/drm_random.h
index 4a3e94dfa0c0..5543bf0474bc 100644
--- a/drivers/gpu/drm/lib/drm_random.h
+++ b/drivers/gpu/drm/lib/drm_random.h
@@ -22,5 +22,7 @@ unsigned int *drm_random_order(unsigned int count,
 void drm_random_reorder(unsigned int *order,
 			unsigned int count,
 			struct rnd_state *state);
+u32 drm_prandom_u32_max_state(u32 ep_ro,
+			      struct rnd_state *state);
 
 #endif /* !__DRM_RANDOM_H__ */
diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index ebe16162762f..3230bfd2770b 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -8,3 +8,4 @@
  */
 selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
 selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
+selftest(buddy_alloc_range, igt_buddy_alloc_range)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index fd7d1a112458..e347060c05a2 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -6,6 +6,7 @@
 #define pr_fmt(fmt) "drm_buddy: " fmt
 
 #include <linux/module.h>
+#include <linux/prime_numbers.h>
 
 #include <drm/drm_buddy.h>
 
@@ -16,6 +17,395 @@
 
 static unsigned int random_seed;
 
+static inline const char *yesno(bool v)
+{
+	return v ? "yes" : "no";
+}
+
+static void __igt_dump_block(struct drm_buddy *mm,
+			     struct drm_buddy_block *block,
+			     bool buddy)
+{
+	pr_err("block info: header=%llx, state=%u, order=%d, offset=%llx size=%llx root=%s buddy=%s\n",
+	       block->header,
+	       drm_buddy_block_state(block),
+	       drm_buddy_block_order(block),
+	       drm_buddy_block_offset(block),
+	       drm_buddy_block_size(mm, block),
+	       yesno(!block->parent),
+	       yesno(buddy));
+}
+
+static void igt_dump_block(struct drm_buddy *mm,
+			   struct drm_buddy_block *block)
+{
+	struct drm_buddy_block *buddy;
+
+	__igt_dump_block(mm, block, false);
+
+	buddy = drm_get_buddy(block);
+	if (buddy)
+		__igt_dump_block(mm, buddy, true);
+}
+
+static int igt_check_block(struct drm_buddy *mm,
+			   struct drm_buddy_block *block)
+{
+	struct drm_buddy_block *buddy;
+	unsigned int block_state;
+	u64 block_size;
+	u64 offset;
+	int err = 0;
+
+	block_state = drm_buddy_block_state(block);
+
+	if (block_state != DRM_BUDDY_ALLOCATED &&
+	    block_state != DRM_BUDDY_FREE &&
+	    block_state != DRM_BUDDY_SPLIT) {
+		pr_err("block state mismatch\n");
+		err = -EINVAL;
+	}
+
+	block_size = drm_buddy_block_size(mm, block);
+	offset = drm_buddy_block_offset(block);
+
+	if (block_size < mm->chunk_size) {
+		pr_err("block size smaller than min size\n");
+		err = -EINVAL;
+	}
+
+	if (!is_power_of_2(block_size)) {
+		pr_err("block size not power of two\n");
+		err = -EINVAL;
+	}
+
+	if (!IS_ALIGNED(block_size, mm->chunk_size)) {
+		pr_err("block size not aligned to min size\n");
+		err = -EINVAL;
+	}
+
+	if (!IS_ALIGNED(offset, mm->chunk_size)) {
+		pr_err("block offset not aligned to min size\n");
+		err = -EINVAL;
+	}
+
+	if (!IS_ALIGNED(offset, block_size)) {
+		pr_err("block offset not aligned to block size\n");
+		err = -EINVAL;
+	}
+
+	buddy = drm_get_buddy(block);
+
+	if (!buddy && block->parent) {
+		pr_err("buddy has gone fishing\n");
+		err = -EINVAL;
+	}
+
+	if (buddy) {
+		if (drm_buddy_block_offset(buddy) != (offset ^ block_size)) {
+			pr_err("buddy has wrong offset\n");
+			err = -EINVAL;
+		}
+
+		if (drm_buddy_block_size(mm, buddy) != block_size) {
+			pr_err("buddy size mismatch\n");
+			err = -EINVAL;
+		}
+
+		if (drm_buddy_block_state(buddy) == block_state &&
+		    block_state == DRM_BUDDY_FREE) {
+			pr_err("block and its buddy are free\n");
+			err = -EINVAL;
+		}
+	}
+
+	return err;
+}
+
+static int igt_check_blocks(struct drm_buddy *mm,
+			    struct list_head *blocks,
+			    u64 expected_size,
+			    bool is_contiguous)
+{
+	struct drm_buddy_block *block;
+	struct drm_buddy_block *prev;
+	u64 total;
+	int err = 0;
+
+	block = NULL;
+	prev = NULL;
+	total = 0;
+
+	list_for_each_entry(block, blocks, link) {
+		err = igt_check_block(mm, block);
+
+		if (!drm_buddy_block_is_allocated(block)) {
+			pr_err("block not allocated\n"),
+			       err = -EINVAL;
+		}
+
+		if (is_contiguous && prev) {
+			u64 prev_block_size;
+			u64 prev_offset;
+			u64 offset;
+
+			prev_offset = drm_buddy_block_offset(prev);
+			prev_block_size = drm_buddy_block_size(mm, prev);
+			offset = drm_buddy_block_offset(block);
+
+			if (offset != (prev_offset + prev_block_size)) {
+				pr_err("block offset mismatch\n");
+				err = -EINVAL;
+			}
+		}
+
+		if (err)
+			break;
+
+		total += drm_buddy_block_size(mm, block);
+		prev = block;
+	}
+
+	if (!err) {
+		if (total != expected_size) {
+			pr_err("size mismatch, expected=%llx, found=%llx\n",
+			       expected_size, total);
+			err = -EINVAL;
+		}
+		return err;
+	}
+
+	if (prev) {
+		pr_err("prev block, dump:\n");
+		igt_dump_block(mm, prev);
+	}
+
+	pr_err("bad block, dump:\n");
+	igt_dump_block(mm, block);
+
+	return err;
+}
+
+static int igt_check_mm(struct drm_buddy *mm)
+{
+	struct drm_buddy_block *root;
+	struct drm_buddy_block *prev;
+	unsigned int i;
+	u64 total;
+	int err = 0;
+
+	if (!mm->n_roots) {
+		pr_err("n_roots is zero\n");
+		return -EINVAL;
+	}
+
+	if (mm->n_roots != hweight64(mm->size)) {
+		pr_err("n_roots mismatch, n_roots=%u, expected=%lu\n",
+		       mm->n_roots, hweight64(mm->size));
+		return -EINVAL;
+	}
+
+	root = NULL;
+	prev = NULL;
+	total = 0;
+
+	for (i = 0; i < mm->n_roots; ++i) {
+		struct drm_buddy_block *block;
+		unsigned int order;
+
+		root = mm->roots[i];
+		if (!root) {
+			pr_err("root(%u) is NULL\n", i);
+			err = -EINVAL;
+			break;
+		}
+
+		err = igt_check_block(mm, root);
+
+		if (!drm_buddy_block_is_free(root)) {
+			pr_err("root not free\n");
+			err = -EINVAL;
+		}
+
+		order = drm_buddy_block_order(root);
+
+		if (!i) {
+			if (order != mm->max_order) {
+				pr_err("max order root missing\n");
+				err = -EINVAL;
+			}
+		}
+
+		if (prev) {
+			u64 prev_block_size;
+			u64 prev_offset;
+			u64 offset;
+
+			prev_offset = drm_buddy_block_offset(prev);
+			prev_block_size = drm_buddy_block_size(mm, prev);
+			offset = drm_buddy_block_offset(root);
+
+			if (offset != (prev_offset + prev_block_size)) {
+				pr_err("root offset mismatch\n");
+				err = -EINVAL;
+			}
+		}
+
+		block = list_first_entry_or_null(&mm->free_list[order],
+						 struct drm_buddy_block,
+						 link);
+		if (block != root) {
+			pr_err("root mismatch at order=%u\n", order);
+			err = -EINVAL;
+		}
+
+		if (err)
+			break;
+
+		prev = root;
+		total += drm_buddy_block_size(mm, root);
+	}
+
+	if (!err) {
+		if (total != mm->size) {
+			pr_err("expected mm size=%llx, found=%llx\n", mm->size,
+			       total);
+			err = -EINVAL;
+		}
+		return err;
+	}
+
+	if (prev) {
+		pr_err("prev root(%u), dump:\n", i - 1);
+		igt_dump_block(mm, prev);
+	}
+
+	if (root) {
+		pr_err("bad root(%u), dump:\n", i);
+		igt_dump_block(mm, root);
+	}
+
+	return err;
+}
+
+static void igt_mm_config(u64 *size, u64 *chunk_size)
+{
+	DRM_RND_STATE(prng, random_seed);
+	u32 s, ms;
+
+	/* Nothing fancy, just try to get an interesting bit pattern */
+
+	prandom_seed_state(&prng, random_seed);
+
+	/* Let size be a random number of pages up to 8 GB (2M pages) */
+	s = 1 + drm_prandom_u32_max_state((BIT(33 - 12)) - 1, &prng);
+	/* Let the chunk size be a random power of 2 less than size */
+	ms = BIT(drm_prandom_u32_max_state(ilog2(s), &prng));
+	/* Round size down to the chunk size */
+	s &= -ms;
+
+	/* Convert from pages to bytes */
+	*chunk_size = (u64)ms << 12;
+	*size = (u64)s << 12;
+}
+
+static int igt_buddy_alloc_range(void *arg)
+{
+	unsigned long flags = DRM_BUDDY_RANGE_ALLOCATION;
+	u64 offset, size, rem, chunk_size, end;
+	unsigned long page_num;
+	struct drm_buddy mm;
+	LIST_HEAD(blocks);
+	int err;
+
+	igt_mm_config(&size, &chunk_size);
+
+	err = drm_buddy_init(&mm, size, chunk_size);
+	if (err) {
+		pr_err("buddy_init failed(%d)\n", err);
+		return err;
+	}
+
+	err = igt_check_mm(&mm);
+	if (err) {
+		pr_err("pre-mm check failed, abort, abort, abort!\n");
+		goto err_fini;
+	}
+
+	rem = mm.size;
+	offset = 0;
+
+	for_each_prime_number_from(page_num, 1, ULONG_MAX - 1) {
+		struct drm_buddy_block *block;
+		LIST_HEAD(tmp);
+
+		size = min(page_num * mm.chunk_size, rem);
+		end = offset + size;
+
+		err = drm_buddy_alloc_blocks(&mm, offset, end, size, mm.chunk_size, &tmp, flags);
+		if (err) {
+			if (err == -ENOMEM) {
+				pr_info("alloc_range hit -ENOMEM with size=%llx\n",
+					size);
+			} else {
+				pr_err("alloc_range with offset=%llx, size=%llx failed(%d)\n",
+				       offset, size, err);
+			}
+
+			break;
+		}
+
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_range has no blocks\n");
+			err = -EINVAL;
+			break;
+		}
+
+		if (drm_buddy_block_offset(block) != offset) {
+			pr_err("alloc_range start offset mismatch, found=%llx, expected=%llx\n",
+			       drm_buddy_block_offset(block), offset);
+			err = -EINVAL;
+		}
+
+		if (!err)
+			err = igt_check_blocks(&mm, &tmp, size, true);
+
+		list_splice_tail(&tmp, &blocks);
+
+		if (err)
+			break;
+
+		offset += size;
+
+		rem -= size;
+		if (!rem)
+			break;
+
+		cond_resched();
+	}
+
+	if (err == -ENOMEM)
+		err = 0;
+
+	drm_buddy_free_list(&mm, &blocks);
+
+	if (!err) {
+		err = igt_check_mm(&mm);
+		if (err)
+			pr_err("post-mm check failed\n");
+		else
+			pr_info("%s - succeeded\n", __func__);
+	}
+
+err_fini:
+	drm_buddy_fini(&mm);
+
+	return err;
+}
+
 static int igt_buddy_alloc_limit(void *arg)
 {
 	u64 end, size = U64_MAX, start = 0;
diff --git a/include/drm/drm_buddy.h b/include/drm/drm_buddy.h
index bd21f9dfd15e..572077ff8ae7 100644
--- a/include/drm/drm_buddy.h
+++ b/include/drm/drm_buddy.h
@@ -134,6 +134,9 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size);
 
 void drm_buddy_fini(struct drm_buddy *mm);
 
+struct drm_buddy_block *
+drm_get_buddy(struct drm_buddy_block *block);
+
 int drm_buddy_alloc_blocks(struct drm_buddy *mm,
 			   u64 start, u64 end, u64 size,
 			   u64 min_page_size,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Intel-gfx] [PATCH 3/7] drm/selftests: add drm buddy alloc range testcase
@ 2022-02-03 13:32   ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

- add a test to check the range allocation
- export get_buddy() function in drm_buddy.c
- export drm_prandom_u32_max_state() in lib/drm_random.c
- include helper functions
- include prime number header file

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 drivers/gpu/drm/drm_buddy.c                   |  20 +-
 drivers/gpu/drm/lib/drm_random.c              |   3 +-
 drivers/gpu/drm/lib/drm_random.h              |   2 +
 .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 390 ++++++++++++++++++
 include/drm/drm_buddy.h                       |   3 +
 6 files changed, 414 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
index 4845ef784b5e..501229d843c4 100644
--- a/drivers/gpu/drm/drm_buddy.c
+++ b/drivers/gpu/drm/drm_buddy.c
@@ -211,7 +211,7 @@ static int split_block(struct drm_buddy *mm,
 }
 
 static struct drm_buddy_block *
-get_buddy(struct drm_buddy_block *block)
+__get_buddy(struct drm_buddy_block *block)
 {
 	struct drm_buddy_block *parent;
 
@@ -225,6 +225,18 @@ get_buddy(struct drm_buddy_block *block)
 	return parent->left;
 }
 
+/**
+ * drm_get_buddy - get buddy address
+ *
+ * @block: DRM buddy block
+ */
+struct drm_buddy_block *
+drm_get_buddy(struct drm_buddy_block *block)
+{
+	return __get_buddy(block);
+}
+EXPORT_SYMBOL(drm_get_buddy);
+
 static void __drm_buddy_free(struct drm_buddy *mm,
 			     struct drm_buddy_block *block)
 {
@@ -233,7 +245,7 @@ static void __drm_buddy_free(struct drm_buddy *mm,
 	while ((parent = block->parent)) {
 		struct drm_buddy_block *buddy;
 
-		buddy = get_buddy(block);
+		buddy = __get_buddy(block);
 
 		if (!drm_buddy_block_is_free(buddy))
 			break;
@@ -361,7 +373,7 @@ alloc_range_bias(struct drm_buddy *mm,
 	 * bigger is better, so make sure we merge everything back before we
 	 * free the allocated blocks.
 	 */
-	buddy = get_buddy(block);
+	buddy = __get_buddy(block);
 	if (buddy &&
 	    (drm_buddy_block_is_free(block) &&
 	     drm_buddy_block_is_free(buddy)))
@@ -500,7 +512,7 @@ static int __alloc_range(struct drm_buddy *mm,
 	 * bigger is better, so make sure we merge everything back before we
 	 * free the allocated blocks.
 	 */
-	buddy = get_buddy(block);
+	buddy = __get_buddy(block);
 	if (buddy &&
 	    (drm_buddy_block_is_free(block) &&
 	     drm_buddy_block_is_free(buddy)))
diff --git a/drivers/gpu/drm/lib/drm_random.c b/drivers/gpu/drm/lib/drm_random.c
index eeb155826d27..31b5a3e21911 100644
--- a/drivers/gpu/drm/lib/drm_random.c
+++ b/drivers/gpu/drm/lib/drm_random.c
@@ -7,10 +7,11 @@
 
 #include "drm_random.h"
 
-static inline u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
+u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
 {
 	return upper_32_bits((u64)prandom_u32_state(state) * ep_ro);
 }
+EXPORT_SYMBOL(drm_prandom_u32_max_state);
 
 void drm_random_reorder(unsigned int *order, unsigned int count,
 			struct rnd_state *state)
diff --git a/drivers/gpu/drm/lib/drm_random.h b/drivers/gpu/drm/lib/drm_random.h
index 4a3e94dfa0c0..5543bf0474bc 100644
--- a/drivers/gpu/drm/lib/drm_random.h
+++ b/drivers/gpu/drm/lib/drm_random.h
@@ -22,5 +22,7 @@ unsigned int *drm_random_order(unsigned int count,
 void drm_random_reorder(unsigned int *order,
 			unsigned int count,
 			struct rnd_state *state);
+u32 drm_prandom_u32_max_state(u32 ep_ro,
+			      struct rnd_state *state);
 
 #endif /* !__DRM_RANDOM_H__ */
diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index ebe16162762f..3230bfd2770b 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -8,3 +8,4 @@
  */
 selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
 selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
+selftest(buddy_alloc_range, igt_buddy_alloc_range)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index fd7d1a112458..e347060c05a2 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -6,6 +6,7 @@
 #define pr_fmt(fmt) "drm_buddy: " fmt
 
 #include <linux/module.h>
+#include <linux/prime_numbers.h>
 
 #include <drm/drm_buddy.h>
 
@@ -16,6 +17,395 @@
 
 static unsigned int random_seed;
 
+static inline const char *yesno(bool v)
+{
+	return v ? "yes" : "no";
+}
+
+static void __igt_dump_block(struct drm_buddy *mm,
+			     struct drm_buddy_block *block,
+			     bool buddy)
+{
+	pr_err("block info: header=%llx, state=%u, order=%d, offset=%llx size=%llx root=%s buddy=%s\n",
+	       block->header,
+	       drm_buddy_block_state(block),
+	       drm_buddy_block_order(block),
+	       drm_buddy_block_offset(block),
+	       drm_buddy_block_size(mm, block),
+	       yesno(!block->parent),
+	       yesno(buddy));
+}
+
+static void igt_dump_block(struct drm_buddy *mm,
+			   struct drm_buddy_block *block)
+{
+	struct drm_buddy_block *buddy;
+
+	__igt_dump_block(mm, block, false);
+
+	buddy = drm_get_buddy(block);
+	if (buddy)
+		__igt_dump_block(mm, buddy, true);
+}
+
+static int igt_check_block(struct drm_buddy *mm,
+			   struct drm_buddy_block *block)
+{
+	struct drm_buddy_block *buddy;
+	unsigned int block_state;
+	u64 block_size;
+	u64 offset;
+	int err = 0;
+
+	block_state = drm_buddy_block_state(block);
+
+	if (block_state != DRM_BUDDY_ALLOCATED &&
+	    block_state != DRM_BUDDY_FREE &&
+	    block_state != DRM_BUDDY_SPLIT) {
+		pr_err("block state mismatch\n");
+		err = -EINVAL;
+	}
+
+	block_size = drm_buddy_block_size(mm, block);
+	offset = drm_buddy_block_offset(block);
+
+	if (block_size < mm->chunk_size) {
+		pr_err("block size smaller than min size\n");
+		err = -EINVAL;
+	}
+
+	if (!is_power_of_2(block_size)) {
+		pr_err("block size not power of two\n");
+		err = -EINVAL;
+	}
+
+	if (!IS_ALIGNED(block_size, mm->chunk_size)) {
+		pr_err("block size not aligned to min size\n");
+		err = -EINVAL;
+	}
+
+	if (!IS_ALIGNED(offset, mm->chunk_size)) {
+		pr_err("block offset not aligned to min size\n");
+		err = -EINVAL;
+	}
+
+	if (!IS_ALIGNED(offset, block_size)) {
+		pr_err("block offset not aligned to block size\n");
+		err = -EINVAL;
+	}
+
+	buddy = drm_get_buddy(block);
+
+	if (!buddy && block->parent) {
+		pr_err("buddy has gone fishing\n");
+		err = -EINVAL;
+	}
+
+	if (buddy) {
+		if (drm_buddy_block_offset(buddy) != (offset ^ block_size)) {
+			pr_err("buddy has wrong offset\n");
+			err = -EINVAL;
+		}
+
+		if (drm_buddy_block_size(mm, buddy) != block_size) {
+			pr_err("buddy size mismatch\n");
+			err = -EINVAL;
+		}
+
+		if (drm_buddy_block_state(buddy) == block_state &&
+		    block_state == DRM_BUDDY_FREE) {
+			pr_err("block and its buddy are free\n");
+			err = -EINVAL;
+		}
+	}
+
+	return err;
+}
+
+static int igt_check_blocks(struct drm_buddy *mm,
+			    struct list_head *blocks,
+			    u64 expected_size,
+			    bool is_contiguous)
+{
+	struct drm_buddy_block *block;
+	struct drm_buddy_block *prev;
+	u64 total;
+	int err = 0;
+
+	block = NULL;
+	prev = NULL;
+	total = 0;
+
+	list_for_each_entry(block, blocks, link) {
+		err = igt_check_block(mm, block);
+
+		if (!drm_buddy_block_is_allocated(block)) {
+			pr_err("block not allocated\n"),
+			       err = -EINVAL;
+		}
+
+		if (is_contiguous && prev) {
+			u64 prev_block_size;
+			u64 prev_offset;
+			u64 offset;
+
+			prev_offset = drm_buddy_block_offset(prev);
+			prev_block_size = drm_buddy_block_size(mm, prev);
+			offset = drm_buddy_block_offset(block);
+
+			if (offset != (prev_offset + prev_block_size)) {
+				pr_err("block offset mismatch\n");
+				err = -EINVAL;
+			}
+		}
+
+		if (err)
+			break;
+
+		total += drm_buddy_block_size(mm, block);
+		prev = block;
+	}
+
+	if (!err) {
+		if (total != expected_size) {
+			pr_err("size mismatch, expected=%llx, found=%llx\n",
+			       expected_size, total);
+			err = -EINVAL;
+		}
+		return err;
+	}
+
+	if (prev) {
+		pr_err("prev block, dump:\n");
+		igt_dump_block(mm, prev);
+	}
+
+	pr_err("bad block, dump:\n");
+	igt_dump_block(mm, block);
+
+	return err;
+}
+
+static int igt_check_mm(struct drm_buddy *mm)
+{
+	struct drm_buddy_block *root;
+	struct drm_buddy_block *prev;
+	unsigned int i;
+	u64 total;
+	int err = 0;
+
+	if (!mm->n_roots) {
+		pr_err("n_roots is zero\n");
+		return -EINVAL;
+	}
+
+	if (mm->n_roots != hweight64(mm->size)) {
+		pr_err("n_roots mismatch, n_roots=%u, expected=%lu\n",
+		       mm->n_roots, hweight64(mm->size));
+		return -EINVAL;
+	}
+
+	root = NULL;
+	prev = NULL;
+	total = 0;
+
+	for (i = 0; i < mm->n_roots; ++i) {
+		struct drm_buddy_block *block;
+		unsigned int order;
+
+		root = mm->roots[i];
+		if (!root) {
+			pr_err("root(%u) is NULL\n", i);
+			err = -EINVAL;
+			break;
+		}
+
+		err = igt_check_block(mm, root);
+
+		if (!drm_buddy_block_is_free(root)) {
+			pr_err("root not free\n");
+			err = -EINVAL;
+		}
+
+		order = drm_buddy_block_order(root);
+
+		if (!i) {
+			if (order != mm->max_order) {
+				pr_err("max order root missing\n");
+				err = -EINVAL;
+			}
+		}
+
+		if (prev) {
+			u64 prev_block_size;
+			u64 prev_offset;
+			u64 offset;
+
+			prev_offset = drm_buddy_block_offset(prev);
+			prev_block_size = drm_buddy_block_size(mm, prev);
+			offset = drm_buddy_block_offset(root);
+
+			if (offset != (prev_offset + prev_block_size)) {
+				pr_err("root offset mismatch\n");
+				err = -EINVAL;
+			}
+		}
+
+		block = list_first_entry_or_null(&mm->free_list[order],
+						 struct drm_buddy_block,
+						 link);
+		if (block != root) {
+			pr_err("root mismatch at order=%u\n", order);
+			err = -EINVAL;
+		}
+
+		if (err)
+			break;
+
+		prev = root;
+		total += drm_buddy_block_size(mm, root);
+	}
+
+	if (!err) {
+		if (total != mm->size) {
+			pr_err("expected mm size=%llx, found=%llx\n", mm->size,
+			       total);
+			err = -EINVAL;
+		}
+		return err;
+	}
+
+	if (prev) {
+		pr_err("prev root(%u), dump:\n", i - 1);
+		igt_dump_block(mm, prev);
+	}
+
+	if (root) {
+		pr_err("bad root(%u), dump:\n", i);
+		igt_dump_block(mm, root);
+	}
+
+	return err;
+}
+
+static void igt_mm_config(u64 *size, u64 *chunk_size)
+{
+	DRM_RND_STATE(prng, random_seed);
+	u32 s, ms;
+
+	/* Nothing fancy, just try to get an interesting bit pattern */
+
+	prandom_seed_state(&prng, random_seed);
+
+	/* Let size be a random number of pages up to 8 GB (2M pages) */
+	s = 1 + drm_prandom_u32_max_state((BIT(33 - 12)) - 1, &prng);
+	/* Let the chunk size be a random power of 2 less than size */
+	ms = BIT(drm_prandom_u32_max_state(ilog2(s), &prng));
+	/* Round size down to the chunk size */
+	s &= -ms;
+
+	/* Convert from pages to bytes */
+	*chunk_size = (u64)ms << 12;
+	*size = (u64)s << 12;
+}
+
+static int igt_buddy_alloc_range(void *arg)
+{
+	unsigned long flags = DRM_BUDDY_RANGE_ALLOCATION;
+	u64 offset, size, rem, chunk_size, end;
+	unsigned long page_num;
+	struct drm_buddy mm;
+	LIST_HEAD(blocks);
+	int err;
+
+	igt_mm_config(&size, &chunk_size);
+
+	err = drm_buddy_init(&mm, size, chunk_size);
+	if (err) {
+		pr_err("buddy_init failed(%d)\n", err);
+		return err;
+	}
+
+	err = igt_check_mm(&mm);
+	if (err) {
+		pr_err("pre-mm check failed, abort, abort, abort!\n");
+		goto err_fini;
+	}
+
+	rem = mm.size;
+	offset = 0;
+
+	for_each_prime_number_from(page_num, 1, ULONG_MAX - 1) {
+		struct drm_buddy_block *block;
+		LIST_HEAD(tmp);
+
+		size = min(page_num * mm.chunk_size, rem);
+		end = offset + size;
+
+		err = drm_buddy_alloc_blocks(&mm, offset, end, size, mm.chunk_size, &tmp, flags);
+		if (err) {
+			if (err == -ENOMEM) {
+				pr_info("alloc_range hit -ENOMEM with size=%llx\n",
+					size);
+			} else {
+				pr_err("alloc_range with offset=%llx, size=%llx failed(%d)\n",
+				       offset, size, err);
+			}
+
+			break;
+		}
+
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_range has no blocks\n");
+			err = -EINVAL;
+			break;
+		}
+
+		if (drm_buddy_block_offset(block) != offset) {
+			pr_err("alloc_range start offset mismatch, found=%llx, expected=%llx\n",
+			       drm_buddy_block_offset(block), offset);
+			err = -EINVAL;
+		}
+
+		if (!err)
+			err = igt_check_blocks(&mm, &tmp, size, true);
+
+		list_splice_tail(&tmp, &blocks);
+
+		if (err)
+			break;
+
+		offset += size;
+
+		rem -= size;
+		if (!rem)
+			break;
+
+		cond_resched();
+	}
+
+	if (err == -ENOMEM)
+		err = 0;
+
+	drm_buddy_free_list(&mm, &blocks);
+
+	if (!err) {
+		err = igt_check_mm(&mm);
+		if (err)
+			pr_err("post-mm check failed\n");
+		else
+			pr_info("%s - succeeded\n", __func__);
+	}
+
+err_fini:
+	drm_buddy_fini(&mm);
+
+	return err;
+}
+
 static int igt_buddy_alloc_limit(void *arg)
 {
 	u64 end, size = U64_MAX, start = 0;
diff --git a/include/drm/drm_buddy.h b/include/drm/drm_buddy.h
index bd21f9dfd15e..572077ff8ae7 100644
--- a/include/drm/drm_buddy.h
+++ b/include/drm/drm_buddy.h
@@ -134,6 +134,9 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size);
 
 void drm_buddy_fini(struct drm_buddy *mm);
 
+struct drm_buddy_block *
+drm_get_buddy(struct drm_buddy_block *block);
+
 int drm_buddy_alloc_blocks(struct drm_buddy *mm,
 			   u64 start, u64 end, u64 size,
 			   u64 min_page_size,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 3/7] drm/selftests: add drm buddy alloc range testcase
@ 2022-02-03 13:32   ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: daniel, Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

- add a test to check the range allocation
- export get_buddy() function in drm_buddy.c
- export drm_prandom_u32_max_state() in lib/drm_random.c
- include helper functions
- include prime number header file

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 drivers/gpu/drm/drm_buddy.c                   |  20 +-
 drivers/gpu/drm/lib/drm_random.c              |   3 +-
 drivers/gpu/drm/lib/drm_random.h              |   2 +
 .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 390 ++++++++++++++++++
 include/drm/drm_buddy.h                       |   3 +
 6 files changed, 414 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
index 4845ef784b5e..501229d843c4 100644
--- a/drivers/gpu/drm/drm_buddy.c
+++ b/drivers/gpu/drm/drm_buddy.c
@@ -211,7 +211,7 @@ static int split_block(struct drm_buddy *mm,
 }
 
 static struct drm_buddy_block *
-get_buddy(struct drm_buddy_block *block)
+__get_buddy(struct drm_buddy_block *block)
 {
 	struct drm_buddy_block *parent;
 
@@ -225,6 +225,18 @@ get_buddy(struct drm_buddy_block *block)
 	return parent->left;
 }
 
+/**
+ * drm_get_buddy - get buddy address
+ *
+ * @block: DRM buddy block
+ */
+struct drm_buddy_block *
+drm_get_buddy(struct drm_buddy_block *block)
+{
+	return __get_buddy(block);
+}
+EXPORT_SYMBOL(drm_get_buddy);
+
 static void __drm_buddy_free(struct drm_buddy *mm,
 			     struct drm_buddy_block *block)
 {
@@ -233,7 +245,7 @@ static void __drm_buddy_free(struct drm_buddy *mm,
 	while ((parent = block->parent)) {
 		struct drm_buddy_block *buddy;
 
-		buddy = get_buddy(block);
+		buddy = __get_buddy(block);
 
 		if (!drm_buddy_block_is_free(buddy))
 			break;
@@ -361,7 +373,7 @@ alloc_range_bias(struct drm_buddy *mm,
 	 * bigger is better, so make sure we merge everything back before we
 	 * free the allocated blocks.
 	 */
-	buddy = get_buddy(block);
+	buddy = __get_buddy(block);
 	if (buddy &&
 	    (drm_buddy_block_is_free(block) &&
 	     drm_buddy_block_is_free(buddy)))
@@ -500,7 +512,7 @@ static int __alloc_range(struct drm_buddy *mm,
 	 * bigger is better, so make sure we merge everything back before we
 	 * free the allocated blocks.
 	 */
-	buddy = get_buddy(block);
+	buddy = __get_buddy(block);
 	if (buddy &&
 	    (drm_buddy_block_is_free(block) &&
 	     drm_buddy_block_is_free(buddy)))
diff --git a/drivers/gpu/drm/lib/drm_random.c b/drivers/gpu/drm/lib/drm_random.c
index eeb155826d27..31b5a3e21911 100644
--- a/drivers/gpu/drm/lib/drm_random.c
+++ b/drivers/gpu/drm/lib/drm_random.c
@@ -7,10 +7,11 @@
 
 #include "drm_random.h"
 
-static inline u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
+u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
 {
 	return upper_32_bits((u64)prandom_u32_state(state) * ep_ro);
 }
+EXPORT_SYMBOL(drm_prandom_u32_max_state);
 
 void drm_random_reorder(unsigned int *order, unsigned int count,
 			struct rnd_state *state)
diff --git a/drivers/gpu/drm/lib/drm_random.h b/drivers/gpu/drm/lib/drm_random.h
index 4a3e94dfa0c0..5543bf0474bc 100644
--- a/drivers/gpu/drm/lib/drm_random.h
+++ b/drivers/gpu/drm/lib/drm_random.h
@@ -22,5 +22,7 @@ unsigned int *drm_random_order(unsigned int count,
 void drm_random_reorder(unsigned int *order,
 			unsigned int count,
 			struct rnd_state *state);
+u32 drm_prandom_u32_max_state(u32 ep_ro,
+			      struct rnd_state *state);
 
 #endif /* !__DRM_RANDOM_H__ */
diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index ebe16162762f..3230bfd2770b 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -8,3 +8,4 @@
  */
 selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
 selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
+selftest(buddy_alloc_range, igt_buddy_alloc_range)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index fd7d1a112458..e347060c05a2 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -6,6 +6,7 @@
 #define pr_fmt(fmt) "drm_buddy: " fmt
 
 #include <linux/module.h>
+#include <linux/prime_numbers.h>
 
 #include <drm/drm_buddy.h>
 
@@ -16,6 +17,395 @@
 
 static unsigned int random_seed;
 
+static inline const char *yesno(bool v)
+{
+	return v ? "yes" : "no";
+}
+
+static void __igt_dump_block(struct drm_buddy *mm,
+			     struct drm_buddy_block *block,
+			     bool buddy)
+{
+	pr_err("block info: header=%llx, state=%u, order=%d, offset=%llx size=%llx root=%s buddy=%s\n",
+	       block->header,
+	       drm_buddy_block_state(block),
+	       drm_buddy_block_order(block),
+	       drm_buddy_block_offset(block),
+	       drm_buddy_block_size(mm, block),
+	       yesno(!block->parent),
+	       yesno(buddy));
+}
+
+static void igt_dump_block(struct drm_buddy *mm,
+			   struct drm_buddy_block *block)
+{
+	struct drm_buddy_block *buddy;
+
+	__igt_dump_block(mm, block, false);
+
+	buddy = drm_get_buddy(block);
+	if (buddy)
+		__igt_dump_block(mm, buddy, true);
+}
+
+static int igt_check_block(struct drm_buddy *mm,
+			   struct drm_buddy_block *block)
+{
+	struct drm_buddy_block *buddy;
+	unsigned int block_state;
+	u64 block_size;
+	u64 offset;
+	int err = 0;
+
+	block_state = drm_buddy_block_state(block);
+
+	if (block_state != DRM_BUDDY_ALLOCATED &&
+	    block_state != DRM_BUDDY_FREE &&
+	    block_state != DRM_BUDDY_SPLIT) {
+		pr_err("block state mismatch\n");
+		err = -EINVAL;
+	}
+
+	block_size = drm_buddy_block_size(mm, block);
+	offset = drm_buddy_block_offset(block);
+
+	if (block_size < mm->chunk_size) {
+		pr_err("block size smaller than min size\n");
+		err = -EINVAL;
+	}
+
+	if (!is_power_of_2(block_size)) {
+		pr_err("block size not power of two\n");
+		err = -EINVAL;
+	}
+
+	if (!IS_ALIGNED(block_size, mm->chunk_size)) {
+		pr_err("block size not aligned to min size\n");
+		err = -EINVAL;
+	}
+
+	if (!IS_ALIGNED(offset, mm->chunk_size)) {
+		pr_err("block offset not aligned to min size\n");
+		err = -EINVAL;
+	}
+
+	if (!IS_ALIGNED(offset, block_size)) {
+		pr_err("block offset not aligned to block size\n");
+		err = -EINVAL;
+	}
+
+	buddy = drm_get_buddy(block);
+
+	if (!buddy && block->parent) {
+		pr_err("buddy has gone fishing\n");
+		err = -EINVAL;
+	}
+
+	if (buddy) {
+		if (drm_buddy_block_offset(buddy) != (offset ^ block_size)) {
+			pr_err("buddy has wrong offset\n");
+			err = -EINVAL;
+		}
+
+		if (drm_buddy_block_size(mm, buddy) != block_size) {
+			pr_err("buddy size mismatch\n");
+			err = -EINVAL;
+		}
+
+		if (drm_buddy_block_state(buddy) == block_state &&
+		    block_state == DRM_BUDDY_FREE) {
+			pr_err("block and its buddy are free\n");
+			err = -EINVAL;
+		}
+	}
+
+	return err;
+}
+
+static int igt_check_blocks(struct drm_buddy *mm,
+			    struct list_head *blocks,
+			    u64 expected_size,
+			    bool is_contiguous)
+{
+	struct drm_buddy_block *block;
+	struct drm_buddy_block *prev;
+	u64 total;
+	int err = 0;
+
+	block = NULL;
+	prev = NULL;
+	total = 0;
+
+	list_for_each_entry(block, blocks, link) {
+		err = igt_check_block(mm, block);
+
+		if (!drm_buddy_block_is_allocated(block)) {
+			pr_err("block not allocated\n"),
+			       err = -EINVAL;
+		}
+
+		if (is_contiguous && prev) {
+			u64 prev_block_size;
+			u64 prev_offset;
+			u64 offset;
+
+			prev_offset = drm_buddy_block_offset(prev);
+			prev_block_size = drm_buddy_block_size(mm, prev);
+			offset = drm_buddy_block_offset(block);
+
+			if (offset != (prev_offset + prev_block_size)) {
+				pr_err("block offset mismatch\n");
+				err = -EINVAL;
+			}
+		}
+
+		if (err)
+			break;
+
+		total += drm_buddy_block_size(mm, block);
+		prev = block;
+	}
+
+	if (!err) {
+		if (total != expected_size) {
+			pr_err("size mismatch, expected=%llx, found=%llx\n",
+			       expected_size, total);
+			err = -EINVAL;
+		}
+		return err;
+	}
+
+	if (prev) {
+		pr_err("prev block, dump:\n");
+		igt_dump_block(mm, prev);
+	}
+
+	pr_err("bad block, dump:\n");
+	igt_dump_block(mm, block);
+
+	return err;
+}
+
+static int igt_check_mm(struct drm_buddy *mm)
+{
+	struct drm_buddy_block *root;
+	struct drm_buddy_block *prev;
+	unsigned int i;
+	u64 total;
+	int err = 0;
+
+	if (!mm->n_roots) {
+		pr_err("n_roots is zero\n");
+		return -EINVAL;
+	}
+
+	if (mm->n_roots != hweight64(mm->size)) {
+		pr_err("n_roots mismatch, n_roots=%u, expected=%lu\n",
+		       mm->n_roots, hweight64(mm->size));
+		return -EINVAL;
+	}
+
+	root = NULL;
+	prev = NULL;
+	total = 0;
+
+	for (i = 0; i < mm->n_roots; ++i) {
+		struct drm_buddy_block *block;
+		unsigned int order;
+
+		root = mm->roots[i];
+		if (!root) {
+			pr_err("root(%u) is NULL\n", i);
+			err = -EINVAL;
+			break;
+		}
+
+		err = igt_check_block(mm, root);
+
+		if (!drm_buddy_block_is_free(root)) {
+			pr_err("root not free\n");
+			err = -EINVAL;
+		}
+
+		order = drm_buddy_block_order(root);
+
+		if (!i) {
+			if (order != mm->max_order) {
+				pr_err("max order root missing\n");
+				err = -EINVAL;
+			}
+		}
+
+		if (prev) {
+			u64 prev_block_size;
+			u64 prev_offset;
+			u64 offset;
+
+			prev_offset = drm_buddy_block_offset(prev);
+			prev_block_size = drm_buddy_block_size(mm, prev);
+			offset = drm_buddy_block_offset(root);
+
+			if (offset != (prev_offset + prev_block_size)) {
+				pr_err("root offset mismatch\n");
+				err = -EINVAL;
+			}
+		}
+
+		block = list_first_entry_or_null(&mm->free_list[order],
+						 struct drm_buddy_block,
+						 link);
+		if (block != root) {
+			pr_err("root mismatch at order=%u\n", order);
+			err = -EINVAL;
+		}
+
+		if (err)
+			break;
+
+		prev = root;
+		total += drm_buddy_block_size(mm, root);
+	}
+
+	if (!err) {
+		if (total != mm->size) {
+			pr_err("expected mm size=%llx, found=%llx\n", mm->size,
+			       total);
+			err = -EINVAL;
+		}
+		return err;
+	}
+
+	if (prev) {
+		pr_err("prev root(%u), dump:\n", i - 1);
+		igt_dump_block(mm, prev);
+	}
+
+	if (root) {
+		pr_err("bad root(%u), dump:\n", i);
+		igt_dump_block(mm, root);
+	}
+
+	return err;
+}
+
+static void igt_mm_config(u64 *size, u64 *chunk_size)
+{
+	DRM_RND_STATE(prng, random_seed);
+	u32 s, ms;
+
+	/* Nothing fancy, just try to get an interesting bit pattern */
+
+	prandom_seed_state(&prng, random_seed);
+
+	/* Let size be a random number of pages up to 8 GB (2M pages) */
+	s = 1 + drm_prandom_u32_max_state((BIT(33 - 12)) - 1, &prng);
+	/* Let the chunk size be a random power of 2 less than size */
+	ms = BIT(drm_prandom_u32_max_state(ilog2(s), &prng));
+	/* Round size down to the chunk size */
+	s &= -ms;
+
+	/* Convert from pages to bytes */
+	*chunk_size = (u64)ms << 12;
+	*size = (u64)s << 12;
+}
+
+static int igt_buddy_alloc_range(void *arg)
+{
+	unsigned long flags = DRM_BUDDY_RANGE_ALLOCATION;
+	u64 offset, size, rem, chunk_size, end;
+	unsigned long page_num;
+	struct drm_buddy mm;
+	LIST_HEAD(blocks);
+	int err;
+
+	igt_mm_config(&size, &chunk_size);
+
+	err = drm_buddy_init(&mm, size, chunk_size);
+	if (err) {
+		pr_err("buddy_init failed(%d)\n", err);
+		return err;
+	}
+
+	err = igt_check_mm(&mm);
+	if (err) {
+		pr_err("pre-mm check failed, abort, abort, abort!\n");
+		goto err_fini;
+	}
+
+	rem = mm.size;
+	offset = 0;
+
+	for_each_prime_number_from(page_num, 1, ULONG_MAX - 1) {
+		struct drm_buddy_block *block;
+		LIST_HEAD(tmp);
+
+		size = min(page_num * mm.chunk_size, rem);
+		end = offset + size;
+
+		err = drm_buddy_alloc_blocks(&mm, offset, end, size, mm.chunk_size, &tmp, flags);
+		if (err) {
+			if (err == -ENOMEM) {
+				pr_info("alloc_range hit -ENOMEM with size=%llx\n",
+					size);
+			} else {
+				pr_err("alloc_range with offset=%llx, size=%llx failed(%d)\n",
+				       offset, size, err);
+			}
+
+			break;
+		}
+
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_range has no blocks\n");
+			err = -EINVAL;
+			break;
+		}
+
+		if (drm_buddy_block_offset(block) != offset) {
+			pr_err("alloc_range start offset mismatch, found=%llx, expected=%llx\n",
+			       drm_buddy_block_offset(block), offset);
+			err = -EINVAL;
+		}
+
+		if (!err)
+			err = igt_check_blocks(&mm, &tmp, size, true);
+
+		list_splice_tail(&tmp, &blocks);
+
+		if (err)
+			break;
+
+		offset += size;
+
+		rem -= size;
+		if (!rem)
+			break;
+
+		cond_resched();
+	}
+
+	if (err == -ENOMEM)
+		err = 0;
+
+	drm_buddy_free_list(&mm, &blocks);
+
+	if (!err) {
+		err = igt_check_mm(&mm);
+		if (err)
+			pr_err("post-mm check failed\n");
+		else
+			pr_info("%s - succeeded\n", __func__);
+	}
+
+err_fini:
+	drm_buddy_fini(&mm);
+
+	return err;
+}
+
 static int igt_buddy_alloc_limit(void *arg)
 {
 	u64 end, size = U64_MAX, start = 0;
diff --git a/include/drm/drm_buddy.h b/include/drm/drm_buddy.h
index bd21f9dfd15e..572077ff8ae7 100644
--- a/include/drm/drm_buddy.h
+++ b/include/drm/drm_buddy.h
@@ -134,6 +134,9 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size);
 
 void drm_buddy_fini(struct drm_buddy *mm);
 
+struct drm_buddy_block *
+drm_get_buddy(struct drm_buddy_block *block);
+
 int drm_buddy_alloc_blocks(struct drm_buddy *mm,
 			   u64 start, u64 end, u64 size,
 			   u64 min_page_size,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 4/7] drm/selftests: add drm buddy optimistic testcase
  2022-02-03 13:32 ` [Intel-gfx] " Arunpravin
  (?)
@ 2022-02-03 13:32   ` Arunpravin
  -1 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

create a mm with one block of each order available, and
try to allocate them all.

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 .../gpu/drm/selftests/drm_buddy_selftests.h   |  1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 82 +++++++++++++++++++
 2 files changed, 83 insertions(+)

diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index 3230bfd2770b..21a6bd38864f 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -9,3 +9,4 @@
 selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
 selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
 selftest(buddy_alloc_range, igt_buddy_alloc_range)
+selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index e347060c05a2..b193d9556fb4 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -17,6 +17,11 @@
 
 static unsigned int random_seed;
 
+static inline u64 get_size(int order, u64 chunk_size)
+{
+	return (1 << order) * chunk_size;
+}
+
 static inline const char *yesno(bool v)
 {
 	return v ? "yes" : "no";
@@ -309,6 +314,83 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
 	*size = (u64)s << 12;
 }
 
+static int igt_buddy_alloc_optimistic(void *arg)
+{
+	u64 mm_size, size, min_page_size, start = 0;
+	struct drm_buddy_block *block;
+	unsigned long flags = 0;
+	const int max_order = 16;
+	struct drm_buddy mm;
+	LIST_HEAD(blocks);
+	LIST_HEAD(tmp);
+	int order, err;
+
+	/*
+	 * Create a mm with one block of each order available, and
+	 * try to allocate them all.
+	 */
+
+	mm_size = PAGE_SIZE * ((1 << (max_order + 1)) - 1);
+	err = drm_buddy_init(&mm,
+			     mm_size,
+			     PAGE_SIZE);
+	if (err) {
+		pr_err("buddy_init failed(%d)\n", err);
+		return err;
+	}
+
+	BUG_ON(mm.max_order != max_order);
+
+	for (order = 0; order <= max_order; order++) {
+		size = min_page_size = get_size(order, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (err) {
+			pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
+				order);
+			goto err;
+		}
+
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_blocks has no blocks\n");
+			err = -EINVAL;
+			goto err;
+		}
+
+		list_del(&block->link);
+		list_add_tail(&block->link, &blocks);
+	}
+
+	/* Should be completely full! */
+	size = min_page_size = get_size(0, PAGE_SIZE);
+	err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+	if (!err) {
+		pr_info("buddy_alloc unexpectedly succeeded, it should be full!");
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_blocks has no blocks\n");
+			err = -EINVAL;
+			goto err;
+		}
+
+		list_del(&block->link);
+		list_add_tail(&block->link, &blocks);
+		goto err;
+	} else {
+		pr_info("%s - succeeded\n", __func__);
+		err = 0;
+	}
+
+err:
+	drm_buddy_free_list(&mm, &blocks);
+	drm_buddy_fini(&mm);
+	return err;
+}
+
 static int igt_buddy_alloc_range(void *arg)
 {
 	unsigned long flags = DRM_BUDDY_RANGE_ALLOCATION;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Intel-gfx] [PATCH 4/7] drm/selftests: add drm buddy optimistic testcase
@ 2022-02-03 13:32   ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

create a mm with one block of each order available, and
try to allocate them all.

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 .../gpu/drm/selftests/drm_buddy_selftests.h   |  1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 82 +++++++++++++++++++
 2 files changed, 83 insertions(+)

diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index 3230bfd2770b..21a6bd38864f 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -9,3 +9,4 @@
 selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
 selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
 selftest(buddy_alloc_range, igt_buddy_alloc_range)
+selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index e347060c05a2..b193d9556fb4 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -17,6 +17,11 @@
 
 static unsigned int random_seed;
 
+static inline u64 get_size(int order, u64 chunk_size)
+{
+	return (1 << order) * chunk_size;
+}
+
 static inline const char *yesno(bool v)
 {
 	return v ? "yes" : "no";
@@ -309,6 +314,83 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
 	*size = (u64)s << 12;
 }
 
+static int igt_buddy_alloc_optimistic(void *arg)
+{
+	u64 mm_size, size, min_page_size, start = 0;
+	struct drm_buddy_block *block;
+	unsigned long flags = 0;
+	const int max_order = 16;
+	struct drm_buddy mm;
+	LIST_HEAD(blocks);
+	LIST_HEAD(tmp);
+	int order, err;
+
+	/*
+	 * Create a mm with one block of each order available, and
+	 * try to allocate them all.
+	 */
+
+	mm_size = PAGE_SIZE * ((1 << (max_order + 1)) - 1);
+	err = drm_buddy_init(&mm,
+			     mm_size,
+			     PAGE_SIZE);
+	if (err) {
+		pr_err("buddy_init failed(%d)\n", err);
+		return err;
+	}
+
+	BUG_ON(mm.max_order != max_order);
+
+	for (order = 0; order <= max_order; order++) {
+		size = min_page_size = get_size(order, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (err) {
+			pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
+				order);
+			goto err;
+		}
+
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_blocks has no blocks\n");
+			err = -EINVAL;
+			goto err;
+		}
+
+		list_del(&block->link);
+		list_add_tail(&block->link, &blocks);
+	}
+
+	/* Should be completely full! */
+	size = min_page_size = get_size(0, PAGE_SIZE);
+	err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+	if (!err) {
+		pr_info("buddy_alloc unexpectedly succeeded, it should be full!");
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_blocks has no blocks\n");
+			err = -EINVAL;
+			goto err;
+		}
+
+		list_del(&block->link);
+		list_add_tail(&block->link, &blocks);
+		goto err;
+	} else {
+		pr_info("%s - succeeded\n", __func__);
+		err = 0;
+	}
+
+err:
+	drm_buddy_free_list(&mm, &blocks);
+	drm_buddy_fini(&mm);
+	return err;
+}
+
 static int igt_buddy_alloc_range(void *arg)
 {
 	unsigned long flags = DRM_BUDDY_RANGE_ALLOCATION;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 4/7] drm/selftests: add drm buddy optimistic testcase
@ 2022-02-03 13:32   ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: daniel, Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

create a mm with one block of each order available, and
try to allocate them all.

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 .../gpu/drm/selftests/drm_buddy_selftests.h   |  1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 82 +++++++++++++++++++
 2 files changed, 83 insertions(+)

diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index 3230bfd2770b..21a6bd38864f 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -9,3 +9,4 @@
 selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
 selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
 selftest(buddy_alloc_range, igt_buddy_alloc_range)
+selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index e347060c05a2..b193d9556fb4 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -17,6 +17,11 @@
 
 static unsigned int random_seed;
 
+static inline u64 get_size(int order, u64 chunk_size)
+{
+	return (1 << order) * chunk_size;
+}
+
 static inline const char *yesno(bool v)
 {
 	return v ? "yes" : "no";
@@ -309,6 +314,83 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
 	*size = (u64)s << 12;
 }
 
+static int igt_buddy_alloc_optimistic(void *arg)
+{
+	u64 mm_size, size, min_page_size, start = 0;
+	struct drm_buddy_block *block;
+	unsigned long flags = 0;
+	const int max_order = 16;
+	struct drm_buddy mm;
+	LIST_HEAD(blocks);
+	LIST_HEAD(tmp);
+	int order, err;
+
+	/*
+	 * Create a mm with one block of each order available, and
+	 * try to allocate them all.
+	 */
+
+	mm_size = PAGE_SIZE * ((1 << (max_order + 1)) - 1);
+	err = drm_buddy_init(&mm,
+			     mm_size,
+			     PAGE_SIZE);
+	if (err) {
+		pr_err("buddy_init failed(%d)\n", err);
+		return err;
+	}
+
+	BUG_ON(mm.max_order != max_order);
+
+	for (order = 0; order <= max_order; order++) {
+		size = min_page_size = get_size(order, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (err) {
+			pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
+				order);
+			goto err;
+		}
+
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_blocks has no blocks\n");
+			err = -EINVAL;
+			goto err;
+		}
+
+		list_del(&block->link);
+		list_add_tail(&block->link, &blocks);
+	}
+
+	/* Should be completely full! */
+	size = min_page_size = get_size(0, PAGE_SIZE);
+	err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+	if (!err) {
+		pr_info("buddy_alloc unexpectedly succeeded, it should be full!");
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_blocks has no blocks\n");
+			err = -EINVAL;
+			goto err;
+		}
+
+		list_del(&block->link);
+		list_add_tail(&block->link, &blocks);
+		goto err;
+	} else {
+		pr_info("%s - succeeded\n", __func__);
+		err = 0;
+	}
+
+err:
+	drm_buddy_free_list(&mm, &blocks);
+	drm_buddy_fini(&mm);
+	return err;
+}
+
 static int igt_buddy_alloc_range(void *arg)
 {
 	unsigned long flags = DRM_BUDDY_RANGE_ALLOCATION;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 5/7] drm/selftests: add drm buddy pessimistic testcase
  2022-02-03 13:32 ` [Intel-gfx] " Arunpravin
  (?)
@ 2022-02-03 13:32   ` Arunpravin
  -1 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

create a pot-sized mm, then allocate one of each possible
order within. This should leave the mm with exactly one
page left.

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 153 ++++++++++++++++++
 2 files changed, 154 insertions(+)

diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index 21a6bd38864f..b14f04a1de19 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -10,3 +10,4 @@ selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
 selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
 selftest(buddy_alloc_range, igt_buddy_alloc_range)
 selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
+selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index b193d9556fb4..e97f583ed0cd 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -314,6 +314,159 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
 	*size = (u64)s << 12;
 }
 
+static int igt_buddy_alloc_pessimistic(void *arg)
+{
+	u64 mm_size, size, min_page_size, start = 0;
+	struct drm_buddy_block *block, *bn;
+	const unsigned int max_order = 16;
+	unsigned long flags = 0;
+	struct drm_buddy mm;
+	unsigned int order;
+	LIST_HEAD(blocks);
+	LIST_HEAD(tmp);
+	int err;
+
+	/*
+	 * Create a pot-sized mm, then allocate one of each possible
+	 * order within. This should leave the mm with exactly one
+	 * page left.
+	 */
+
+	mm_size = PAGE_SIZE << max_order;
+	err = drm_buddy_init(&mm, mm_size, PAGE_SIZE);
+	if (err) {
+		pr_err("buddy_init failed(%d)\n", err);
+		return err;
+	}
+	BUG_ON(mm.max_order != max_order);
+
+	for (order = 0; order < max_order; order++) {
+		size = min_page_size = get_size(order, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (err) {
+			pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
+				order);
+			goto err;
+		}
+
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_blocks has no blocks\n");
+			err = -EINVAL;
+			goto err;
+		}
+
+		list_del(&block->link);
+		list_add_tail(&block->link, &blocks);
+	}
+
+	/* And now the last remaining block available */
+	size = min_page_size = get_size(0, PAGE_SIZE);
+	err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+	if (err) {
+		pr_info("buddy_alloc hit -ENOMEM on final alloc\n");
+		goto err;
+	}
+
+	block = list_first_entry_or_null(&tmp,
+					 struct drm_buddy_block,
+					 link);
+	if (!block) {
+		pr_err("alloc_blocks has no blocks\n");
+		err = -EINVAL;
+		goto err;
+	}
+
+	list_del(&block->link);
+	list_add_tail(&block->link, &blocks);
+
+	/* Should be completely full! */
+	for (order = max_order; order--; ) {
+		size = min_page_size = get_size(order, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (!err) {
+			pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
+				order);
+			block = list_first_entry_or_null(&tmp,
+							 struct drm_buddy_block,
+							 link);
+			if (!block) {
+				pr_err("alloc_blocks has no blocks\n");
+				err = -EINVAL;
+				goto err;
+			}
+
+			list_del(&block->link);
+			list_add_tail(&block->link, &blocks);
+			err = -EINVAL;
+			goto err;
+		}
+	}
+
+	block = list_last_entry(&blocks, typeof(*block), link);
+	list_del(&block->link);
+	drm_buddy_free_block(&mm, block);
+
+	/* As we free in increasing size, we make available larger blocks */
+	order = 1;
+	list_for_each_entry_safe(block, bn, &blocks, link) {
+		list_del(&block->link);
+		drm_buddy_free_block(&mm, block);
+
+		size = min_page_size = get_size(order, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (err) {
+			pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
+				order);
+			goto err;
+		}
+
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_blocks has no blocks\n");
+			err = -EINVAL;
+			goto err;
+		}
+
+		list_del(&block->link);
+		drm_buddy_free_block(&mm, block);
+		order++;
+	}
+
+	/* To confirm, now the whole mm should be available */
+	size = min_page_size = get_size(max_order, PAGE_SIZE);
+	err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+	if (err) {
+		pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
+			max_order);
+		goto err;
+	}
+
+	block = list_first_entry_or_null(&tmp,
+					 struct drm_buddy_block,
+					 link);
+	if (!block) {
+		pr_err("alloc_blocks has no blocks\n");
+		err = -EINVAL;
+		goto err;
+	}
+
+	list_del(&block->link);
+	drm_buddy_free_block(&mm, block);
+
+	if (!err)
+		pr_info("%s - succeeded\n", __func__);
+
+err:
+	drm_buddy_free_list(&mm, &blocks);
+	drm_buddy_fini(&mm);
+	return err;
+}
+
 static int igt_buddy_alloc_optimistic(void *arg)
 {
 	u64 mm_size, size, min_page_size, start = 0;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Intel-gfx] [PATCH 5/7] drm/selftests: add drm buddy pessimistic testcase
@ 2022-02-03 13:32   ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

create a pot-sized mm, then allocate one of each possible
order within. This should leave the mm with exactly one
page left.

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 153 ++++++++++++++++++
 2 files changed, 154 insertions(+)

diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index 21a6bd38864f..b14f04a1de19 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -10,3 +10,4 @@ selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
 selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
 selftest(buddy_alloc_range, igt_buddy_alloc_range)
 selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
+selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index b193d9556fb4..e97f583ed0cd 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -314,6 +314,159 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
 	*size = (u64)s << 12;
 }
 
+static int igt_buddy_alloc_pessimistic(void *arg)
+{
+	u64 mm_size, size, min_page_size, start = 0;
+	struct drm_buddy_block *block, *bn;
+	const unsigned int max_order = 16;
+	unsigned long flags = 0;
+	struct drm_buddy mm;
+	unsigned int order;
+	LIST_HEAD(blocks);
+	LIST_HEAD(tmp);
+	int err;
+
+	/*
+	 * Create a pot-sized mm, then allocate one of each possible
+	 * order within. This should leave the mm with exactly one
+	 * page left.
+	 */
+
+	mm_size = PAGE_SIZE << max_order;
+	err = drm_buddy_init(&mm, mm_size, PAGE_SIZE);
+	if (err) {
+		pr_err("buddy_init failed(%d)\n", err);
+		return err;
+	}
+	BUG_ON(mm.max_order != max_order);
+
+	for (order = 0; order < max_order; order++) {
+		size = min_page_size = get_size(order, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (err) {
+			pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
+				order);
+			goto err;
+		}
+
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_blocks has no blocks\n");
+			err = -EINVAL;
+			goto err;
+		}
+
+		list_del(&block->link);
+		list_add_tail(&block->link, &blocks);
+	}
+
+	/* And now the last remaining block available */
+	size = min_page_size = get_size(0, PAGE_SIZE);
+	err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+	if (err) {
+		pr_info("buddy_alloc hit -ENOMEM on final alloc\n");
+		goto err;
+	}
+
+	block = list_first_entry_or_null(&tmp,
+					 struct drm_buddy_block,
+					 link);
+	if (!block) {
+		pr_err("alloc_blocks has no blocks\n");
+		err = -EINVAL;
+		goto err;
+	}
+
+	list_del(&block->link);
+	list_add_tail(&block->link, &blocks);
+
+	/* Should be completely full! */
+	for (order = max_order; order--; ) {
+		size = min_page_size = get_size(order, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (!err) {
+			pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
+				order);
+			block = list_first_entry_or_null(&tmp,
+							 struct drm_buddy_block,
+							 link);
+			if (!block) {
+				pr_err("alloc_blocks has no blocks\n");
+				err = -EINVAL;
+				goto err;
+			}
+
+			list_del(&block->link);
+			list_add_tail(&block->link, &blocks);
+			err = -EINVAL;
+			goto err;
+		}
+	}
+
+	block = list_last_entry(&blocks, typeof(*block), link);
+	list_del(&block->link);
+	drm_buddy_free_block(&mm, block);
+
+	/* As we free in increasing size, we make available larger blocks */
+	order = 1;
+	list_for_each_entry_safe(block, bn, &blocks, link) {
+		list_del(&block->link);
+		drm_buddy_free_block(&mm, block);
+
+		size = min_page_size = get_size(order, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (err) {
+			pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
+				order);
+			goto err;
+		}
+
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_blocks has no blocks\n");
+			err = -EINVAL;
+			goto err;
+		}
+
+		list_del(&block->link);
+		drm_buddy_free_block(&mm, block);
+		order++;
+	}
+
+	/* To confirm, now the whole mm should be available */
+	size = min_page_size = get_size(max_order, PAGE_SIZE);
+	err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+	if (err) {
+		pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
+			max_order);
+		goto err;
+	}
+
+	block = list_first_entry_or_null(&tmp,
+					 struct drm_buddy_block,
+					 link);
+	if (!block) {
+		pr_err("alloc_blocks has no blocks\n");
+		err = -EINVAL;
+		goto err;
+	}
+
+	list_del(&block->link);
+	drm_buddy_free_block(&mm, block);
+
+	if (!err)
+		pr_info("%s - succeeded\n", __func__);
+
+err:
+	drm_buddy_free_list(&mm, &blocks);
+	drm_buddy_fini(&mm);
+	return err;
+}
+
 static int igt_buddy_alloc_optimistic(void *arg)
 {
 	u64 mm_size, size, min_page_size, start = 0;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 5/7] drm/selftests: add drm buddy pessimistic testcase
@ 2022-02-03 13:32   ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: daniel, Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

create a pot-sized mm, then allocate one of each possible
order within. This should leave the mm with exactly one
page left.

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 153 ++++++++++++++++++
 2 files changed, 154 insertions(+)

diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index 21a6bd38864f..b14f04a1de19 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -10,3 +10,4 @@ selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
 selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
 selftest(buddy_alloc_range, igt_buddy_alloc_range)
 selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
+selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index b193d9556fb4..e97f583ed0cd 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -314,6 +314,159 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
 	*size = (u64)s << 12;
 }
 
+static int igt_buddy_alloc_pessimistic(void *arg)
+{
+	u64 mm_size, size, min_page_size, start = 0;
+	struct drm_buddy_block *block, *bn;
+	const unsigned int max_order = 16;
+	unsigned long flags = 0;
+	struct drm_buddy mm;
+	unsigned int order;
+	LIST_HEAD(blocks);
+	LIST_HEAD(tmp);
+	int err;
+
+	/*
+	 * Create a pot-sized mm, then allocate one of each possible
+	 * order within. This should leave the mm with exactly one
+	 * page left.
+	 */
+
+	mm_size = PAGE_SIZE << max_order;
+	err = drm_buddy_init(&mm, mm_size, PAGE_SIZE);
+	if (err) {
+		pr_err("buddy_init failed(%d)\n", err);
+		return err;
+	}
+	BUG_ON(mm.max_order != max_order);
+
+	for (order = 0; order < max_order; order++) {
+		size = min_page_size = get_size(order, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (err) {
+			pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
+				order);
+			goto err;
+		}
+
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_blocks has no blocks\n");
+			err = -EINVAL;
+			goto err;
+		}
+
+		list_del(&block->link);
+		list_add_tail(&block->link, &blocks);
+	}
+
+	/* And now the last remaining block available */
+	size = min_page_size = get_size(0, PAGE_SIZE);
+	err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+	if (err) {
+		pr_info("buddy_alloc hit -ENOMEM on final alloc\n");
+		goto err;
+	}
+
+	block = list_first_entry_or_null(&tmp,
+					 struct drm_buddy_block,
+					 link);
+	if (!block) {
+		pr_err("alloc_blocks has no blocks\n");
+		err = -EINVAL;
+		goto err;
+	}
+
+	list_del(&block->link);
+	list_add_tail(&block->link, &blocks);
+
+	/* Should be completely full! */
+	for (order = max_order; order--; ) {
+		size = min_page_size = get_size(order, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (!err) {
+			pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
+				order);
+			block = list_first_entry_or_null(&tmp,
+							 struct drm_buddy_block,
+							 link);
+			if (!block) {
+				pr_err("alloc_blocks has no blocks\n");
+				err = -EINVAL;
+				goto err;
+			}
+
+			list_del(&block->link);
+			list_add_tail(&block->link, &blocks);
+			err = -EINVAL;
+			goto err;
+		}
+	}
+
+	block = list_last_entry(&blocks, typeof(*block), link);
+	list_del(&block->link);
+	drm_buddy_free_block(&mm, block);
+
+	/* As we free in increasing size, we make available larger blocks */
+	order = 1;
+	list_for_each_entry_safe(block, bn, &blocks, link) {
+		list_del(&block->link);
+		drm_buddy_free_block(&mm, block);
+
+		size = min_page_size = get_size(order, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (err) {
+			pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
+				order);
+			goto err;
+		}
+
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_blocks has no blocks\n");
+			err = -EINVAL;
+			goto err;
+		}
+
+		list_del(&block->link);
+		drm_buddy_free_block(&mm, block);
+		order++;
+	}
+
+	/* To confirm, now the whole mm should be available */
+	size = min_page_size = get_size(max_order, PAGE_SIZE);
+	err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+	if (err) {
+		pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
+			max_order);
+		goto err;
+	}
+
+	block = list_first_entry_or_null(&tmp,
+					 struct drm_buddy_block,
+					 link);
+	if (!block) {
+		pr_err("alloc_blocks has no blocks\n");
+		err = -EINVAL;
+		goto err;
+	}
+
+	list_del(&block->link);
+	drm_buddy_free_block(&mm, block);
+
+	if (!err)
+		pr_info("%s - succeeded\n", __func__);
+
+err:
+	drm_buddy_free_list(&mm, &blocks);
+	drm_buddy_fini(&mm);
+	return err;
+}
+
 static int igt_buddy_alloc_optimistic(void *arg)
 {
 	u64 mm_size, size, min_page_size, start = 0;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 6/7] drm/selftests: add drm buddy smoke testcase
  2022-02-03 13:32 ` [Intel-gfx] " Arunpravin
  (?)
@ 2022-02-03 13:32   ` Arunpravin
  -1 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

- add a test to ascertain that the critical functionalities
  of the program is working fine
- add a timeout helper function

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 143 ++++++++++++++++++
 2 files changed, 144 insertions(+)

diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index b14f04a1de19..411d072cbfc5 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -11,3 +11,4 @@ selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
 selftest(buddy_alloc_range, igt_buddy_alloc_range)
 selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
 selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
+selftest(buddy_alloc_smoke, igt_buddy_alloc_smoke)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index e97f583ed0cd..2074e8c050a4 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -7,6 +7,7 @@
 
 #include <linux/module.h>
 #include <linux/prime_numbers.h>
+#include <linux/sched/signal.h>
 
 #include <drm/drm_buddy.h>
 
@@ -15,6 +16,9 @@
 #define TESTS "drm_buddy_selftests.h"
 #include "drm_selftest.h"
 
+#define IGT_TIMEOUT(name__) \
+	unsigned long name__ = jiffies + MAX_SCHEDULE_TIMEOUT
+
 static unsigned int random_seed;
 
 static inline u64 get_size(int order, u64 chunk_size)
@@ -22,6 +26,26 @@ static inline u64 get_size(int order, u64 chunk_size)
 	return (1 << order) * chunk_size;
 }
 
+__printf(2, 3)
+static bool __igt_timeout(unsigned long timeout, const char *fmt, ...)
+{
+	va_list va;
+
+	if (!signal_pending(current)) {
+		cond_resched();
+		if (time_before(jiffies, timeout))
+			return false;
+	}
+
+	if (fmt) {
+		va_start(va, fmt);
+		vprintk(fmt, va);
+		va_end(va);
+	}
+
+	return true;
+}
+
 static inline const char *yesno(bool v)
 {
 	return v ? "yes" : "no";
@@ -314,6 +338,125 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
 	*size = (u64)s << 12;
 }
 
+static int igt_buddy_alloc_smoke(void *arg)
+{
+	u64 mm_size, min_page_size, chunk_size, start = 0;
+	unsigned long flags = 0;
+	struct drm_buddy mm;
+	int *order;
+	int err, i;
+
+	DRM_RND_STATE(prng, random_seed);
+	IGT_TIMEOUT(end_time);
+
+	igt_mm_config(&mm_size, &chunk_size);
+
+	err = drm_buddy_init(&mm, mm_size, chunk_size);
+	if (err) {
+		pr_err("buddy_init failed(%d)\n", err);
+		return err;
+	}
+
+	order = drm_random_order(mm.max_order + 1, &prng);
+	if (!order)
+		goto out_fini;
+
+	for (i = 0; i <= mm.max_order; ++i) {
+		struct drm_buddy_block *block;
+		int max_order = order[i];
+		bool timeout = false;
+		LIST_HEAD(blocks);
+		u64 total, size;
+		LIST_HEAD(tmp);
+		int order;
+
+		err = igt_check_mm(&mm);
+		if (err) {
+			pr_err("pre-mm check failed, abort\n");
+			break;
+		}
+
+		order = max_order;
+		total = 0;
+
+		do {
+retry:
+			size = min_page_size = get_size(order, chunk_size);
+			err = drm_buddy_alloc_blocks(&mm, start, mm_size, size,
+						     min_page_size, &tmp, flags);
+			if (err) {
+				if (err == -ENOMEM) {
+					pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
+						order);
+				} else {
+					if (order--) {
+						err = 0;
+						goto retry;
+					}
+
+					pr_err("buddy_alloc with order=%d failed(%d)\n",
+					       order, err);
+				}
+
+				break;
+			}
+
+			block = list_first_entry_or_null(&tmp,
+							 struct drm_buddy_block,
+							 link);
+			if (!block) {
+				pr_err("alloc_blocks has no blocks\n");
+				err = -EINVAL;
+				break;
+			}
+
+			list_del(&block->link);
+			list_add_tail(&block->link, &blocks);
+
+			if (drm_buddy_block_order(block) != order) {
+				pr_err("buddy_alloc order mismatch\n");
+				err = -EINVAL;
+				break;
+			}
+
+			total += drm_buddy_block_size(&mm, block);
+
+			if (__igt_timeout(end_time, NULL)) {
+				timeout = true;
+				break;
+			}
+		} while (total < mm.size);
+
+		if (!err)
+			err = igt_check_blocks(&mm, &blocks, total, false);
+
+		drm_buddy_free_list(&mm, &blocks);
+
+		if (!err) {
+			err = igt_check_mm(&mm);
+			if (err)
+				pr_err("post-mm check failed\n");
+		}
+
+		if (err || timeout)
+			break;
+
+		cond_resched();
+	}
+
+	if (err == -ENOMEM)
+		err = 0;
+
+	if (!err)
+		pr_info("%s - succeeded\n", __func__);
+
+	kfree(order);
+out_fini:
+	drm_buddy_fini(&mm);
+
+	return err;
+}
+
 static int igt_buddy_alloc_pessimistic(void *arg)
 {
 	u64 mm_size, size, min_page_size, start = 0;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Intel-gfx] [PATCH 6/7] drm/selftests: add drm buddy smoke testcase
@ 2022-02-03 13:32   ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

- add a test to ascertain that the critical functionalities
  of the program is working fine
- add a timeout helper function

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 143 ++++++++++++++++++
 2 files changed, 144 insertions(+)

diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index b14f04a1de19..411d072cbfc5 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -11,3 +11,4 @@ selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
 selftest(buddy_alloc_range, igt_buddy_alloc_range)
 selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
 selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
+selftest(buddy_alloc_smoke, igt_buddy_alloc_smoke)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index e97f583ed0cd..2074e8c050a4 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -7,6 +7,7 @@
 
 #include <linux/module.h>
 #include <linux/prime_numbers.h>
+#include <linux/sched/signal.h>
 
 #include <drm/drm_buddy.h>
 
@@ -15,6 +16,9 @@
 #define TESTS "drm_buddy_selftests.h"
 #include "drm_selftest.h"
 
+#define IGT_TIMEOUT(name__) \
+	unsigned long name__ = jiffies + MAX_SCHEDULE_TIMEOUT
+
 static unsigned int random_seed;
 
 static inline u64 get_size(int order, u64 chunk_size)
@@ -22,6 +26,26 @@ static inline u64 get_size(int order, u64 chunk_size)
 	return (1 << order) * chunk_size;
 }
 
+__printf(2, 3)
+static bool __igt_timeout(unsigned long timeout, const char *fmt, ...)
+{
+	va_list va;
+
+	if (!signal_pending(current)) {
+		cond_resched();
+		if (time_before(jiffies, timeout))
+			return false;
+	}
+
+	if (fmt) {
+		va_start(va, fmt);
+		vprintk(fmt, va);
+		va_end(va);
+	}
+
+	return true;
+}
+
 static inline const char *yesno(bool v)
 {
 	return v ? "yes" : "no";
@@ -314,6 +338,125 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
 	*size = (u64)s << 12;
 }
 
+static int igt_buddy_alloc_smoke(void *arg)
+{
+	u64 mm_size, min_page_size, chunk_size, start = 0;
+	unsigned long flags = 0;
+	struct drm_buddy mm;
+	int *order;
+	int err, i;
+
+	DRM_RND_STATE(prng, random_seed);
+	IGT_TIMEOUT(end_time);
+
+	igt_mm_config(&mm_size, &chunk_size);
+
+	err = drm_buddy_init(&mm, mm_size, chunk_size);
+	if (err) {
+		pr_err("buddy_init failed(%d)\n", err);
+		return err;
+	}
+
+	order = drm_random_order(mm.max_order + 1, &prng);
+	if (!order)
+		goto out_fini;
+
+	for (i = 0; i <= mm.max_order; ++i) {
+		struct drm_buddy_block *block;
+		int max_order = order[i];
+		bool timeout = false;
+		LIST_HEAD(blocks);
+		u64 total, size;
+		LIST_HEAD(tmp);
+		int order;
+
+		err = igt_check_mm(&mm);
+		if (err) {
+			pr_err("pre-mm check failed, abort\n");
+			break;
+		}
+
+		order = max_order;
+		total = 0;
+
+		do {
+retry:
+			size = min_page_size = get_size(order, chunk_size);
+			err = drm_buddy_alloc_blocks(&mm, start, mm_size, size,
+						     min_page_size, &tmp, flags);
+			if (err) {
+				if (err == -ENOMEM) {
+					pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
+						order);
+				} else {
+					if (order--) {
+						err = 0;
+						goto retry;
+					}
+
+					pr_err("buddy_alloc with order=%d failed(%d)\n",
+					       order, err);
+				}
+
+				break;
+			}
+
+			block = list_first_entry_or_null(&tmp,
+							 struct drm_buddy_block,
+							 link);
+			if (!block) {
+				pr_err("alloc_blocks has no blocks\n");
+				err = -EINVAL;
+				break;
+			}
+
+			list_del(&block->link);
+			list_add_tail(&block->link, &blocks);
+
+			if (drm_buddy_block_order(block) != order) {
+				pr_err("buddy_alloc order mismatch\n");
+				err = -EINVAL;
+				break;
+			}
+
+			total += drm_buddy_block_size(&mm, block);
+
+			if (__igt_timeout(end_time, NULL)) {
+				timeout = true;
+				break;
+			}
+		} while (total < mm.size);
+
+		if (!err)
+			err = igt_check_blocks(&mm, &blocks, total, false);
+
+		drm_buddy_free_list(&mm, &blocks);
+
+		if (!err) {
+			err = igt_check_mm(&mm);
+			if (err)
+				pr_err("post-mm check failed\n");
+		}
+
+		if (err || timeout)
+			break;
+
+		cond_resched();
+	}
+
+	if (err == -ENOMEM)
+		err = 0;
+
+	if (!err)
+		pr_info("%s - succeeded\n", __func__);
+
+	kfree(order);
+out_fini:
+	drm_buddy_fini(&mm);
+
+	return err;
+}
+
 static int igt_buddy_alloc_pessimistic(void *arg)
 {
 	u64 mm_size, size, min_page_size, start = 0;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 6/7] drm/selftests: add drm buddy smoke testcase
@ 2022-02-03 13:32   ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: daniel, Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

- add a test to ascertain that the critical functionalities
  of the program is working fine
- add a timeout helper function

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 143 ++++++++++++++++++
 2 files changed, 144 insertions(+)

diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index b14f04a1de19..411d072cbfc5 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -11,3 +11,4 @@ selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
 selftest(buddy_alloc_range, igt_buddy_alloc_range)
 selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
 selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
+selftest(buddy_alloc_smoke, igt_buddy_alloc_smoke)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index e97f583ed0cd..2074e8c050a4 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -7,6 +7,7 @@
 
 #include <linux/module.h>
 #include <linux/prime_numbers.h>
+#include <linux/sched/signal.h>
 
 #include <drm/drm_buddy.h>
 
@@ -15,6 +16,9 @@
 #define TESTS "drm_buddy_selftests.h"
 #include "drm_selftest.h"
 
+#define IGT_TIMEOUT(name__) \
+	unsigned long name__ = jiffies + MAX_SCHEDULE_TIMEOUT
+
 static unsigned int random_seed;
 
 static inline u64 get_size(int order, u64 chunk_size)
@@ -22,6 +26,26 @@ static inline u64 get_size(int order, u64 chunk_size)
 	return (1 << order) * chunk_size;
 }
 
+__printf(2, 3)
+static bool __igt_timeout(unsigned long timeout, const char *fmt, ...)
+{
+	va_list va;
+
+	if (!signal_pending(current)) {
+		cond_resched();
+		if (time_before(jiffies, timeout))
+			return false;
+	}
+
+	if (fmt) {
+		va_start(va, fmt);
+		vprintk(fmt, va);
+		va_end(va);
+	}
+
+	return true;
+}
+
 static inline const char *yesno(bool v)
 {
 	return v ? "yes" : "no";
@@ -314,6 +338,125 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
 	*size = (u64)s << 12;
 }
 
+static int igt_buddy_alloc_smoke(void *arg)
+{
+	u64 mm_size, min_page_size, chunk_size, start = 0;
+	unsigned long flags = 0;
+	struct drm_buddy mm;
+	int *order;
+	int err, i;
+
+	DRM_RND_STATE(prng, random_seed);
+	IGT_TIMEOUT(end_time);
+
+	igt_mm_config(&mm_size, &chunk_size);
+
+	err = drm_buddy_init(&mm, mm_size, chunk_size);
+	if (err) {
+		pr_err("buddy_init failed(%d)\n", err);
+		return err;
+	}
+
+	order = drm_random_order(mm.max_order + 1, &prng);
+	if (!order)
+		goto out_fini;
+
+	for (i = 0; i <= mm.max_order; ++i) {
+		struct drm_buddy_block *block;
+		int max_order = order[i];
+		bool timeout = false;
+		LIST_HEAD(blocks);
+		u64 total, size;
+		LIST_HEAD(tmp);
+		int order;
+
+		err = igt_check_mm(&mm);
+		if (err) {
+			pr_err("pre-mm check failed, abort\n");
+			break;
+		}
+
+		order = max_order;
+		total = 0;
+
+		do {
+retry:
+			size = min_page_size = get_size(order, chunk_size);
+			err = drm_buddy_alloc_blocks(&mm, start, mm_size, size,
+						     min_page_size, &tmp, flags);
+			if (err) {
+				if (err == -ENOMEM) {
+					pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
+						order);
+				} else {
+					if (order--) {
+						err = 0;
+						goto retry;
+					}
+
+					pr_err("buddy_alloc with order=%d failed(%d)\n",
+					       order, err);
+				}
+
+				break;
+			}
+
+			block = list_first_entry_or_null(&tmp,
+							 struct drm_buddy_block,
+							 link);
+			if (!block) {
+				pr_err("alloc_blocks has no blocks\n");
+				err = -EINVAL;
+				break;
+			}
+
+			list_del(&block->link);
+			list_add_tail(&block->link, &blocks);
+
+			if (drm_buddy_block_order(block) != order) {
+				pr_err("buddy_alloc order mismatch\n");
+				err = -EINVAL;
+				break;
+			}
+
+			total += drm_buddy_block_size(&mm, block);
+
+			if (__igt_timeout(end_time, NULL)) {
+				timeout = true;
+				break;
+			}
+		} while (total < mm.size);
+
+		if (!err)
+			err = igt_check_blocks(&mm, &blocks, total, false);
+
+		drm_buddy_free_list(&mm, &blocks);
+
+		if (!err) {
+			err = igt_check_mm(&mm);
+			if (err)
+				pr_err("post-mm check failed\n");
+		}
+
+		if (err || timeout)
+			break;
+
+		cond_resched();
+	}
+
+	if (err == -ENOMEM)
+		err = 0;
+
+	if (!err)
+		pr_info("%s - succeeded\n", __func__);
+
+	kfree(order);
+out_fini:
+	drm_buddy_fini(&mm);
+
+	return err;
+}
+
 static int igt_buddy_alloc_pessimistic(void *arg)
 {
 	u64 mm_size, size, min_page_size, start = 0;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 7/7] drm/selftests: add drm buddy pathological testcase
  2022-02-03 13:32 ` [Intel-gfx] " Arunpravin
  (?)
@ 2022-02-03 13:32   ` Arunpravin
  -1 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

create a pot-sized mm, then allocate one of each possible
order within. This should leave the mm with exactly one
page left. Free the largest block, then whittle down again.
Eventually we will have a fully 50% fragmented mm.

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 136 ++++++++++++++++++
 2 files changed, 137 insertions(+)

diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index 411d072cbfc5..455b756c4ae5 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -12,3 +12,4 @@ selftest(buddy_alloc_range, igt_buddy_alloc_range)
 selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
 selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
 selftest(buddy_alloc_smoke, igt_buddy_alloc_smoke)
+selftest(buddy_alloc_pathological, igt_buddy_alloc_pathological)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index 2074e8c050a4..b2d0313a4bc5 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -338,6 +338,142 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
 	*size = (u64)s << 12;
 }
 
+static int igt_buddy_alloc_pathological(void *arg)
+{
+	u64 mm_size, size, min_page_size, start = 0;
+	struct drm_buddy_block *block;
+	const int max_order = 3;
+	unsigned long flags = 0;
+	int order, top, err;
+	struct drm_buddy mm;
+	LIST_HEAD(blocks);
+	LIST_HEAD(holes);
+	LIST_HEAD(tmp);
+
+	/*
+	 * Create a pot-sized mm, then allocate one of each possible
+	 * order within. This should leave the mm with exactly one
+	 * page left. Free the largest block, then whittle down again.
+	 * Eventually we will have a fully 50% fragmented mm.
+	 */
+
+	mm_size = PAGE_SIZE << max_order;
+	err = drm_buddy_init(&mm, mm_size, PAGE_SIZE);
+	if (err) {
+		pr_err("buddy_init failed(%d)\n", err);
+		return err;
+	}
+	BUG_ON(mm.max_order != max_order);
+
+	for (top = max_order; top; top--) {
+		/* Make room by freeing the largest allocated block */
+		block = list_first_entry_or_null(&blocks, typeof(*block), link);
+		if (block) {
+			list_del(&block->link);
+			drm_buddy_free_block(&mm, block);
+		}
+
+		for (order = top; order--; ) {
+			size = min_page_size = get_size(order, PAGE_SIZE);
+			err = drm_buddy_alloc_blocks(&mm, start, mm_size, size,
+						     min_page_size, &tmp, flags);
+			if (err) {
+				pr_info("buddy_alloc hit -ENOMEM with order=%d, top=%d\n",
+					order, top);
+				goto err;
+			}
+
+			block = list_first_entry_or_null(&tmp,
+							 struct drm_buddy_block,
+							 link);
+			if (!block) {
+				pr_err("alloc_blocks has no blocks\n");
+				err = -EINVAL;
+				goto err;
+			}
+
+			list_del(&block->link);
+			list_add_tail(&block->link, &blocks);
+		}
+
+		/* There should be one final page for this sub-allocation */
+		size = min_page_size = get_size(0, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (err) {
+			pr_info("buddy_alloc hit -ENOME for hole\n");
+			goto err;
+		}
+
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_blocks has no blocks\n");
+			err = -EINVAL;
+			goto err;
+		}
+
+		list_del(&block->link);
+		list_add_tail(&block->link, &holes);
+
+		size = min_page_size = get_size(top, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (!err) {
+			pr_info("buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!",
+				top, max_order);
+			block = list_first_entry_or_null(&tmp,
+							 struct drm_buddy_block,
+							 link);
+			if (!block) {
+				pr_err("alloc_blocks has no blocks\n");
+				err = -EINVAL;
+				goto err;
+			}
+
+			list_del(&block->link);
+			list_add_tail(&block->link, &blocks);
+			err = -EINVAL;
+			goto err;
+		}
+	}
+
+	drm_buddy_free_list(&mm, &holes);
+
+	/* Nothing larger than blocks of chunk_size now available */
+	for (order = 1; order <= max_order; order++) {
+		size = min_page_size = get_size(order, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (!err) {
+			pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
+				order);
+			block = list_first_entry_or_null(&tmp,
+							 struct drm_buddy_block,
+							 link);
+			if (!block) {
+				pr_err("alloc_blocks has no blocks\n");
+				err = -EINVAL;
+				goto err;
+			}
+
+			list_del(&block->link);
+			list_add_tail(&block->link, &blocks);
+			err = -EINVAL;
+			goto err;
+		}
+	}
+
+	if (err) {
+		pr_info("%s - succeeded\n", __func__);
+		err = 0;
+	}
+
+err:
+	list_splice_tail(&holes, &blocks);
+	drm_buddy_free_list(&mm, &blocks);
+	drm_buddy_fini(&mm);
+	return err;
+}
+
 static int igt_buddy_alloc_smoke(void *arg)
 {
 	u64 mm_size, min_page_size, chunk_size, start = 0;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Intel-gfx] [PATCH 7/7] drm/selftests: add drm buddy pathological testcase
@ 2022-02-03 13:32   ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

create a pot-sized mm, then allocate one of each possible
order within. This should leave the mm with exactly one
page left. Free the largest block, then whittle down again.
Eventually we will have a fully 50% fragmented mm.

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 136 ++++++++++++++++++
 2 files changed, 137 insertions(+)

diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index 411d072cbfc5..455b756c4ae5 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -12,3 +12,4 @@ selftest(buddy_alloc_range, igt_buddy_alloc_range)
 selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
 selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
 selftest(buddy_alloc_smoke, igt_buddy_alloc_smoke)
+selftest(buddy_alloc_pathological, igt_buddy_alloc_pathological)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index 2074e8c050a4..b2d0313a4bc5 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -338,6 +338,142 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
 	*size = (u64)s << 12;
 }
 
+static int igt_buddy_alloc_pathological(void *arg)
+{
+	u64 mm_size, size, min_page_size, start = 0;
+	struct drm_buddy_block *block;
+	const int max_order = 3;
+	unsigned long flags = 0;
+	int order, top, err;
+	struct drm_buddy mm;
+	LIST_HEAD(blocks);
+	LIST_HEAD(holes);
+	LIST_HEAD(tmp);
+
+	/*
+	 * Create a pot-sized mm, then allocate one of each possible
+	 * order within. This should leave the mm with exactly one
+	 * page left. Free the largest block, then whittle down again.
+	 * Eventually we will have a fully 50% fragmented mm.
+	 */
+
+	mm_size = PAGE_SIZE << max_order;
+	err = drm_buddy_init(&mm, mm_size, PAGE_SIZE);
+	if (err) {
+		pr_err("buddy_init failed(%d)\n", err);
+		return err;
+	}
+	BUG_ON(mm.max_order != max_order);
+
+	for (top = max_order; top; top--) {
+		/* Make room by freeing the largest allocated block */
+		block = list_first_entry_or_null(&blocks, typeof(*block), link);
+		if (block) {
+			list_del(&block->link);
+			drm_buddy_free_block(&mm, block);
+		}
+
+		for (order = top; order--; ) {
+			size = min_page_size = get_size(order, PAGE_SIZE);
+			err = drm_buddy_alloc_blocks(&mm, start, mm_size, size,
+						     min_page_size, &tmp, flags);
+			if (err) {
+				pr_info("buddy_alloc hit -ENOMEM with order=%d, top=%d\n",
+					order, top);
+				goto err;
+			}
+
+			block = list_first_entry_or_null(&tmp,
+							 struct drm_buddy_block,
+							 link);
+			if (!block) {
+				pr_err("alloc_blocks has no blocks\n");
+				err = -EINVAL;
+				goto err;
+			}
+
+			list_del(&block->link);
+			list_add_tail(&block->link, &blocks);
+		}
+
+		/* There should be one final page for this sub-allocation */
+		size = min_page_size = get_size(0, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (err) {
+			pr_info("buddy_alloc hit -ENOME for hole\n");
+			goto err;
+		}
+
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_blocks has no blocks\n");
+			err = -EINVAL;
+			goto err;
+		}
+
+		list_del(&block->link);
+		list_add_tail(&block->link, &holes);
+
+		size = min_page_size = get_size(top, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (!err) {
+			pr_info("buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!",
+				top, max_order);
+			block = list_first_entry_or_null(&tmp,
+							 struct drm_buddy_block,
+							 link);
+			if (!block) {
+				pr_err("alloc_blocks has no blocks\n");
+				err = -EINVAL;
+				goto err;
+			}
+
+			list_del(&block->link);
+			list_add_tail(&block->link, &blocks);
+			err = -EINVAL;
+			goto err;
+		}
+	}
+
+	drm_buddy_free_list(&mm, &holes);
+
+	/* Nothing larger than blocks of chunk_size now available */
+	for (order = 1; order <= max_order; order++) {
+		size = min_page_size = get_size(order, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (!err) {
+			pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
+				order);
+			block = list_first_entry_or_null(&tmp,
+							 struct drm_buddy_block,
+							 link);
+			if (!block) {
+				pr_err("alloc_blocks has no blocks\n");
+				err = -EINVAL;
+				goto err;
+			}
+
+			list_del(&block->link);
+			list_add_tail(&block->link, &blocks);
+			err = -EINVAL;
+			goto err;
+		}
+	}
+
+	if (err) {
+		pr_info("%s - succeeded\n", __func__);
+		err = 0;
+	}
+
+err:
+	list_splice_tail(&holes, &blocks);
+	drm_buddy_free_list(&mm, &blocks);
+	drm_buddy_fini(&mm);
+	return err;
+}
+
 static int igt_buddy_alloc_smoke(void *arg)
 {
 	u64 mm_size, min_page_size, chunk_size, start = 0;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 7/7] drm/selftests: add drm buddy pathological testcase
@ 2022-02-03 13:32   ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-03 13:32 UTC (permalink / raw)
  To: dri-devel, intel-gfx, amd-gfx
  Cc: daniel, Arunpravin, matthew.auld, tzimmermann, alexander.deucher,
	christian.koenig

create a pot-sized mm, then allocate one of each possible
order within. This should leave the mm with exactly one
page left. Free the largest block, then whittle down again.
Eventually we will have a fully 50% fragmented mm.

Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
---
 .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
 drivers/gpu/drm/selftests/test-drm_buddy.c    | 136 ++++++++++++++++++
 2 files changed, 137 insertions(+)

diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
index 411d072cbfc5..455b756c4ae5 100644
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
@@ -12,3 +12,4 @@ selftest(buddy_alloc_range, igt_buddy_alloc_range)
 selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
 selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
 selftest(buddy_alloc_smoke, igt_buddy_alloc_smoke)
+selftest(buddy_alloc_pathological, igt_buddy_alloc_pathological)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
index 2074e8c050a4..b2d0313a4bc5 100644
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
@@ -338,6 +338,142 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
 	*size = (u64)s << 12;
 }
 
+static int igt_buddy_alloc_pathological(void *arg)
+{
+	u64 mm_size, size, min_page_size, start = 0;
+	struct drm_buddy_block *block;
+	const int max_order = 3;
+	unsigned long flags = 0;
+	int order, top, err;
+	struct drm_buddy mm;
+	LIST_HEAD(blocks);
+	LIST_HEAD(holes);
+	LIST_HEAD(tmp);
+
+	/*
+	 * Create a pot-sized mm, then allocate one of each possible
+	 * order within. This should leave the mm with exactly one
+	 * page left. Free the largest block, then whittle down again.
+	 * Eventually we will have a fully 50% fragmented mm.
+	 */
+
+	mm_size = PAGE_SIZE << max_order;
+	err = drm_buddy_init(&mm, mm_size, PAGE_SIZE);
+	if (err) {
+		pr_err("buddy_init failed(%d)\n", err);
+		return err;
+	}
+	BUG_ON(mm.max_order != max_order);
+
+	for (top = max_order; top; top--) {
+		/* Make room by freeing the largest allocated block */
+		block = list_first_entry_or_null(&blocks, typeof(*block), link);
+		if (block) {
+			list_del(&block->link);
+			drm_buddy_free_block(&mm, block);
+		}
+
+		for (order = top; order--; ) {
+			size = min_page_size = get_size(order, PAGE_SIZE);
+			err = drm_buddy_alloc_blocks(&mm, start, mm_size, size,
+						     min_page_size, &tmp, flags);
+			if (err) {
+				pr_info("buddy_alloc hit -ENOMEM with order=%d, top=%d\n",
+					order, top);
+				goto err;
+			}
+
+			block = list_first_entry_or_null(&tmp,
+							 struct drm_buddy_block,
+							 link);
+			if (!block) {
+				pr_err("alloc_blocks has no blocks\n");
+				err = -EINVAL;
+				goto err;
+			}
+
+			list_del(&block->link);
+			list_add_tail(&block->link, &blocks);
+		}
+
+		/* There should be one final page for this sub-allocation */
+		size = min_page_size = get_size(0, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (err) {
+			pr_info("buddy_alloc hit -ENOME for hole\n");
+			goto err;
+		}
+
+		block = list_first_entry_or_null(&tmp,
+						 struct drm_buddy_block,
+						 link);
+		if (!block) {
+			pr_err("alloc_blocks has no blocks\n");
+			err = -EINVAL;
+			goto err;
+		}
+
+		list_del(&block->link);
+		list_add_tail(&block->link, &holes);
+
+		size = min_page_size = get_size(top, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (!err) {
+			pr_info("buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!",
+				top, max_order);
+			block = list_first_entry_or_null(&tmp,
+							 struct drm_buddy_block,
+							 link);
+			if (!block) {
+				pr_err("alloc_blocks has no blocks\n");
+				err = -EINVAL;
+				goto err;
+			}
+
+			list_del(&block->link);
+			list_add_tail(&block->link, &blocks);
+			err = -EINVAL;
+			goto err;
+		}
+	}
+
+	drm_buddy_free_list(&mm, &holes);
+
+	/* Nothing larger than blocks of chunk_size now available */
+	for (order = 1; order <= max_order; order++) {
+		size = min_page_size = get_size(order, PAGE_SIZE);
+		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
+		if (!err) {
+			pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
+				order);
+			block = list_first_entry_or_null(&tmp,
+							 struct drm_buddy_block,
+							 link);
+			if (!block) {
+				pr_err("alloc_blocks has no blocks\n");
+				err = -EINVAL;
+				goto err;
+			}
+
+			list_del(&block->link);
+			list_add_tail(&block->link, &blocks);
+			err = -EINVAL;
+			goto err;
+		}
+	}
+
+	if (err) {
+		pr_info("%s - succeeded\n", __func__);
+		err = 0;
+	}
+
+err:
+	list_splice_tail(&holes, &blocks);
+	drm_buddy_free_list(&mm, &blocks);
+	drm_buddy_fini(&mm);
+	return err;
+}
+
 static int igt_buddy_alloc_smoke(void *arg)
 {
 	u64 mm_size, min_page_size, chunk_size, start = 0;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [Intel-gfx] ✗ Fi.CI.BUILD: failure for series starting with [1/7] drm/selftests: Move i915 buddy selftests into drm
  2022-02-03 13:32 ` [Intel-gfx] " Arunpravin
                   ` (7 preceding siblings ...)
  (?)
@ 2022-02-03 14:12 ` Patchwork
  -1 siblings, 0 replies; 52+ messages in thread
From: Patchwork @ 2022-02-03 14:12 UTC (permalink / raw)
  To: Arunpravin; +Cc: intel-gfx

== Series Details ==

Series: series starting with [1/7] drm/selftests: Move i915 buddy selftests into drm
URL   : https://patchwork.freedesktop.org/series/99663/
State : failure

== Summary ==

Applying: drm/selftests: Move i915 buddy selftests into drm
Applying: drm/selftests: add drm buddy alloc limit testcase
Applying: drm/selftests: add drm buddy alloc range testcase
Using index info to reconstruct a base tree...
M	drivers/gpu/drm/drm_buddy.c
M	include/drm/drm_buddy.h
Falling back to patching base and 3-way merge...
Auto-merging include/drm/drm_buddy.h
CONFLICT (content): Merge conflict in include/drm/drm_buddy.h
Auto-merging drivers/gpu/drm/drm_buddy.c
CONFLICT (content): Merge conflict in drivers/gpu/drm/drm_buddy.c
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0003 drm/selftests: add drm buddy alloc range testcase
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".



^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 1/7] drm/selftests: Move i915 buddy selftests into drm
  2022-02-03 13:32 ` [Intel-gfx] " Arunpravin
  (?)
@ 2022-02-03 14:33   ` Christian König
  -1 siblings, 0 replies; 52+ messages in thread
From: Christian König @ 2022-02-03 14:33 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, matthew.auld

Am 03.02.22 um 14:32 schrieb Arunpravin:
> - move i915 buddy selftests into drm selftests folder
> - add Makefile and Kconfig support
> - add sanitycheck testcase
>
> Prerequisites
> - These series of selftests patches are created on top of
>    drm buddy series
> - Enable kselftests for DRM as a module in .config
>
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>

Only skimmed over this, but of hand I haven't seen anything obviously bad.

Feel free to add an Acked-by: Christian König <christian.koenig@amd.com> 
to the series.

Regards,
Christian.

> ---
>   drivers/gpu/drm/Kconfig                       |  1 +
>   drivers/gpu/drm/selftests/Makefile            |  3 +-
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |  9 ++++
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 49 +++++++++++++++++++
>   4 files changed, 61 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/gpu/drm/selftests/drm_buddy_selftests.h
>   create mode 100644 drivers/gpu/drm/selftests/test-drm_buddy.c
>
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index eb5a57ae3c5c..ff856df3f97f 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -71,6 +71,7 @@ config DRM_DEBUG_SELFTEST
>   	select DRM_DP_HELPER
>   	select DRM_LIB_RANDOM
>   	select DRM_KMS_HELPER
> +	select DRM_BUDDY
>   	select DRM_EXPORT_FOR_TESTS if m
>   	default n
>   	help
> diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile
> index 0856e4b12f70..5ba5f9138c95 100644
> --- a/drivers/gpu/drm/selftests/Makefile
> +++ b/drivers/gpu/drm/selftests/Makefile
> @@ -4,4 +4,5 @@ test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
>   		      test-drm_damage_helper.o test-drm_dp_mst_helper.o \
>   		      test-drm_rect.o
>   
> -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o
> +obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o \
> +				    test-drm_buddy.o
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> new file mode 100644
> index 000000000000..a4bcf3a6dfe3
> --- /dev/null
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -0,0 +1,9 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* List each unit test as selftest(name, function)
> + *
> + * The name is used as both an enum and expanded as igt__name to create
> + * a module parameter. It must be unique and legal for a C identifier.
> + *
> + * Tests are executed in order by igt/drm_buddy
> + */
> +selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> new file mode 100644
> index 000000000000..51e4d393d22c
> --- /dev/null
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -0,0 +1,49 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2019 Intel Corporation
> + */
> +
> +#define pr_fmt(fmt) "drm_buddy: " fmt
> +
> +#include <linux/module.h>
> +
> +#include <drm/drm_buddy.h>
> +
> +#include "../lib/drm_random.h"
> +
> +#define TESTS "drm_buddy_selftests.h"
> +#include "drm_selftest.h"
> +
> +static unsigned int random_seed;
> +
> +static int igt_sanitycheck(void *ignored)
> +{
> +	pr_info("%s - ok!\n", __func__);
> +	return 0;
> +}
> +
> +#include "drm_selftest.c"
> +
> +static int __init test_drm_buddy_init(void)
> +{
> +	int err;
> +
> +	while (!random_seed)
> +		random_seed = get_random_int();
> +
> +	pr_info("Testing DRM buddy manager (struct drm_buddy), with random_seed=0x%x\n",
> +		random_seed);
> +	err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
> +
> +	return err > 0 ? 0 : err;
> +}
> +
> +static void __exit test_drm_buddy_exit(void)
> +{
> +}
> +
> +module_init(test_drm_buddy_init);
> +module_exit(test_drm_buddy_exit);
> +
> +MODULE_AUTHOR("Intel Corporation");
> +MODULE_LICENSE("GPL");


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Intel-gfx] [PATCH 1/7] drm/selftests: Move i915 buddy selftests into drm
@ 2022-02-03 14:33   ` Christian König
  0 siblings, 0 replies; 52+ messages in thread
From: Christian König @ 2022-02-03 14:33 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, matthew.auld

Am 03.02.22 um 14:32 schrieb Arunpravin:
> - move i915 buddy selftests into drm selftests folder
> - add Makefile and Kconfig support
> - add sanitycheck testcase
>
> Prerequisites
> - These series of selftests patches are created on top of
>    drm buddy series
> - Enable kselftests for DRM as a module in .config
>
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>

Only skimmed over this, but of hand I haven't seen anything obviously bad.

Feel free to add an Acked-by: Christian König <christian.koenig@amd.com> 
to the series.

Regards,
Christian.

> ---
>   drivers/gpu/drm/Kconfig                       |  1 +
>   drivers/gpu/drm/selftests/Makefile            |  3 +-
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |  9 ++++
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 49 +++++++++++++++++++
>   4 files changed, 61 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/gpu/drm/selftests/drm_buddy_selftests.h
>   create mode 100644 drivers/gpu/drm/selftests/test-drm_buddy.c
>
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index eb5a57ae3c5c..ff856df3f97f 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -71,6 +71,7 @@ config DRM_DEBUG_SELFTEST
>   	select DRM_DP_HELPER
>   	select DRM_LIB_RANDOM
>   	select DRM_KMS_HELPER
> +	select DRM_BUDDY
>   	select DRM_EXPORT_FOR_TESTS if m
>   	default n
>   	help
> diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile
> index 0856e4b12f70..5ba5f9138c95 100644
> --- a/drivers/gpu/drm/selftests/Makefile
> +++ b/drivers/gpu/drm/selftests/Makefile
> @@ -4,4 +4,5 @@ test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
>   		      test-drm_damage_helper.o test-drm_dp_mst_helper.o \
>   		      test-drm_rect.o
>   
> -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o
> +obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o \
> +				    test-drm_buddy.o
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> new file mode 100644
> index 000000000000..a4bcf3a6dfe3
> --- /dev/null
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -0,0 +1,9 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* List each unit test as selftest(name, function)
> + *
> + * The name is used as both an enum and expanded as igt__name to create
> + * a module parameter. It must be unique and legal for a C identifier.
> + *
> + * Tests are executed in order by igt/drm_buddy
> + */
> +selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> new file mode 100644
> index 000000000000..51e4d393d22c
> --- /dev/null
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -0,0 +1,49 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2019 Intel Corporation
> + */
> +
> +#define pr_fmt(fmt) "drm_buddy: " fmt
> +
> +#include <linux/module.h>
> +
> +#include <drm/drm_buddy.h>
> +
> +#include "../lib/drm_random.h"
> +
> +#define TESTS "drm_buddy_selftests.h"
> +#include "drm_selftest.h"
> +
> +static unsigned int random_seed;
> +
> +static int igt_sanitycheck(void *ignored)
> +{
> +	pr_info("%s - ok!\n", __func__);
> +	return 0;
> +}
> +
> +#include "drm_selftest.c"
> +
> +static int __init test_drm_buddy_init(void)
> +{
> +	int err;
> +
> +	while (!random_seed)
> +		random_seed = get_random_int();
> +
> +	pr_info("Testing DRM buddy manager (struct drm_buddy), with random_seed=0x%x\n",
> +		random_seed);
> +	err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
> +
> +	return err > 0 ? 0 : err;
> +}
> +
> +static void __exit test_drm_buddy_exit(void)
> +{
> +}
> +
> +module_init(test_drm_buddy_init);
> +module_exit(test_drm_buddy_exit);
> +
> +MODULE_AUTHOR("Intel Corporation");
> +MODULE_LICENSE("GPL");


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 1/7] drm/selftests: Move i915 buddy selftests into drm
@ 2022-02-03 14:33   ` Christian König
  0 siblings, 0 replies; 52+ messages in thread
From: Christian König @ 2022-02-03 14:33 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, matthew.auld, daniel

Am 03.02.22 um 14:32 schrieb Arunpravin:
> - move i915 buddy selftests into drm selftests folder
> - add Makefile and Kconfig support
> - add sanitycheck testcase
>
> Prerequisites
> - These series of selftests patches are created on top of
>    drm buddy series
> - Enable kselftests for DRM as a module in .config
>
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>

Only skimmed over this, but of hand I haven't seen anything obviously bad.

Feel free to add an Acked-by: Christian König <christian.koenig@amd.com> 
to the series.

Regards,
Christian.

> ---
>   drivers/gpu/drm/Kconfig                       |  1 +
>   drivers/gpu/drm/selftests/Makefile            |  3 +-
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |  9 ++++
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 49 +++++++++++++++++++
>   4 files changed, 61 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/gpu/drm/selftests/drm_buddy_selftests.h
>   create mode 100644 drivers/gpu/drm/selftests/test-drm_buddy.c
>
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index eb5a57ae3c5c..ff856df3f97f 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -71,6 +71,7 @@ config DRM_DEBUG_SELFTEST
>   	select DRM_DP_HELPER
>   	select DRM_LIB_RANDOM
>   	select DRM_KMS_HELPER
> +	select DRM_BUDDY
>   	select DRM_EXPORT_FOR_TESTS if m
>   	default n
>   	help
> diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile
> index 0856e4b12f70..5ba5f9138c95 100644
> --- a/drivers/gpu/drm/selftests/Makefile
> +++ b/drivers/gpu/drm/selftests/Makefile
> @@ -4,4 +4,5 @@ test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
>   		      test-drm_damage_helper.o test-drm_dp_mst_helper.o \
>   		      test-drm_rect.o
>   
> -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o
> +obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o \
> +				    test-drm_buddy.o
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> new file mode 100644
> index 000000000000..a4bcf3a6dfe3
> --- /dev/null
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -0,0 +1,9 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* List each unit test as selftest(name, function)
> + *
> + * The name is used as both an enum and expanded as igt__name to create
> + * a module parameter. It must be unique and legal for a C identifier.
> + *
> + * Tests are executed in order by igt/drm_buddy
> + */
> +selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> new file mode 100644
> index 000000000000..51e4d393d22c
> --- /dev/null
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -0,0 +1,49 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2019 Intel Corporation
> + */
> +
> +#define pr_fmt(fmt) "drm_buddy: " fmt
> +
> +#include <linux/module.h>
> +
> +#include <drm/drm_buddy.h>
> +
> +#include "../lib/drm_random.h"
> +
> +#define TESTS "drm_buddy_selftests.h"
> +#include "drm_selftest.h"
> +
> +static unsigned int random_seed;
> +
> +static int igt_sanitycheck(void *ignored)
> +{
> +	pr_info("%s - ok!\n", __func__);
> +	return 0;
> +}
> +
> +#include "drm_selftest.c"
> +
> +static int __init test_drm_buddy_init(void)
> +{
> +	int err;
> +
> +	while (!random_seed)
> +		random_seed = get_random_int();
> +
> +	pr_info("Testing DRM buddy manager (struct drm_buddy), with random_seed=0x%x\n",
> +		random_seed);
> +	err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
> +
> +	return err > 0 ? 0 : err;
> +}
> +
> +static void __exit test_drm_buddy_exit(void)
> +{
> +}
> +
> +module_init(test_drm_buddy_init);
> +module_exit(test_drm_buddy_exit);
> +
> +MODULE_AUTHOR("Intel Corporation");
> +MODULE_LICENSE("GPL");


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 2/7] drm/selftests: add drm buddy alloc limit testcase
  2022-02-03 13:32   ` [Intel-gfx] " Arunpravin
  (?)
@ 2022-02-08  9:40     ` Matthew Auld
  -1 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08  9:40 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig

On 03/02/2022 13:32, Arunpravin wrote:
> add a test to check the maximum allocation limit
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |  1 +
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 60 +++++++++++++++++++
>   2 files changed, 61 insertions(+)
> 
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> index a4bcf3a6dfe3..ebe16162762f 100644
> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -7,3 +7,4 @@
>    * Tests are executed in order by igt/drm_buddy
>    */
>   selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
> +selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> index 51e4d393d22c..fd7d1a112458 100644
> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -16,6 +16,66 @@
>   
>   static unsigned int random_seed;
>   
> +static int igt_buddy_alloc_limit(void *arg)
> +{
> +	u64 end, size = U64_MAX, start = 0;
> +	struct drm_buddy_block *block;
> +	unsigned long flags = 0;
> +	LIST_HEAD(allocated);
> +	struct drm_buddy mm;
> +	int err;
> +
> +	size = end = round_down(size, 4096);
> +	err = drm_buddy_init(&mm, size, PAGE_SIZE);
> +	if (err)
> +		return err;
> +
> +	if (mm.max_order != DRM_BUDDY_MAX_ORDER) {
> +		pr_err("mm.max_order(%d) != %d\n",
> +		       mm.max_order, DRM_BUDDY_MAX_ORDER);
> +		err = -EINVAL;
> +		goto out_fini;
> +	}
> +
> +	err = drm_buddy_alloc_blocks(&mm, start, end, size,
> +				     PAGE_SIZE, &allocated, flags);
> +
> +	if (unlikely(err))
> +		goto out_free;
> +
> +	block = list_first_entry_or_null(&allocated,
> +					 struct drm_buddy_block,
> +					 link);
> +
> +	if (!block)

err = -EINVAL;

> +		goto out_fini;
> +
> +	if (drm_buddy_block_order(block) != mm.max_order) {
> +		pr_err("block order(%d) != %d\n",
> +		       drm_buddy_block_order(block), mm.max_order);
> +		err = -EINVAL;
> +		goto out_free;
> +	}
> +
> +	if (drm_buddy_block_size(&mm, block) !=
> +	    BIT_ULL(mm.max_order) * PAGE_SIZE) {
> +		pr_err("block size(%llu) != %llu\n",
> +		       drm_buddy_block_size(&mm, block),
> +		       BIT_ULL(mm.max_order) * PAGE_SIZE);
> +		err = -EINVAL;
> +		goto out_free;
> +	}
> +
> +	if (!err)

Always true AFAICT?

> +		pr_info("%s - succeeded\n", __func__);

I guess this could be made part of the run_selftests()? It looks like it 
already prints the current test, perhaps that is already enough?

With the err = -EINVAL change, feel free to add,
Reviewed-by: Matthew Auld <matthew.auld@intel.com>

> +
> +out_free:
> +	drm_buddy_free_list(&mm, &allocated);
> +out_fini:
> +	drm_buddy_fini(&mm);
> +	return err;
> +}
> +
>   static int igt_sanitycheck(void *ignored)
>   {
>   	pr_info("%s - ok!\n", __func__);

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Intel-gfx] [PATCH 2/7] drm/selftests: add drm buddy alloc limit testcase
@ 2022-02-08  9:40     ` Matthew Auld
  0 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08  9:40 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig

On 03/02/2022 13:32, Arunpravin wrote:
> add a test to check the maximum allocation limit
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |  1 +
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 60 +++++++++++++++++++
>   2 files changed, 61 insertions(+)
> 
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> index a4bcf3a6dfe3..ebe16162762f 100644
> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -7,3 +7,4 @@
>    * Tests are executed in order by igt/drm_buddy
>    */
>   selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
> +selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> index 51e4d393d22c..fd7d1a112458 100644
> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -16,6 +16,66 @@
>   
>   static unsigned int random_seed;
>   
> +static int igt_buddy_alloc_limit(void *arg)
> +{
> +	u64 end, size = U64_MAX, start = 0;
> +	struct drm_buddy_block *block;
> +	unsigned long flags = 0;
> +	LIST_HEAD(allocated);
> +	struct drm_buddy mm;
> +	int err;
> +
> +	size = end = round_down(size, 4096);
> +	err = drm_buddy_init(&mm, size, PAGE_SIZE);
> +	if (err)
> +		return err;
> +
> +	if (mm.max_order != DRM_BUDDY_MAX_ORDER) {
> +		pr_err("mm.max_order(%d) != %d\n",
> +		       mm.max_order, DRM_BUDDY_MAX_ORDER);
> +		err = -EINVAL;
> +		goto out_fini;
> +	}
> +
> +	err = drm_buddy_alloc_blocks(&mm, start, end, size,
> +				     PAGE_SIZE, &allocated, flags);
> +
> +	if (unlikely(err))
> +		goto out_free;
> +
> +	block = list_first_entry_or_null(&allocated,
> +					 struct drm_buddy_block,
> +					 link);
> +
> +	if (!block)

err = -EINVAL;

> +		goto out_fini;
> +
> +	if (drm_buddy_block_order(block) != mm.max_order) {
> +		pr_err("block order(%d) != %d\n",
> +		       drm_buddy_block_order(block), mm.max_order);
> +		err = -EINVAL;
> +		goto out_free;
> +	}
> +
> +	if (drm_buddy_block_size(&mm, block) !=
> +	    BIT_ULL(mm.max_order) * PAGE_SIZE) {
> +		pr_err("block size(%llu) != %llu\n",
> +		       drm_buddy_block_size(&mm, block),
> +		       BIT_ULL(mm.max_order) * PAGE_SIZE);
> +		err = -EINVAL;
> +		goto out_free;
> +	}
> +
> +	if (!err)

Always true AFAICT?

> +		pr_info("%s - succeeded\n", __func__);

I guess this could be made part of the run_selftests()? It looks like it 
already prints the current test, perhaps that is already enough?

With the err = -EINVAL change, feel free to add,
Reviewed-by: Matthew Auld <matthew.auld@intel.com>

> +
> +out_free:
> +	drm_buddy_free_list(&mm, &allocated);
> +out_fini:
> +	drm_buddy_fini(&mm);
> +	return err;
> +}
> +
>   static int igt_sanitycheck(void *ignored)
>   {
>   	pr_info("%s - ok!\n", __func__);

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 2/7] drm/selftests: add drm buddy alloc limit testcase
@ 2022-02-08  9:40     ` Matthew Auld
  0 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08  9:40 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig, daniel

On 03/02/2022 13:32, Arunpravin wrote:
> add a test to check the maximum allocation limit
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |  1 +
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 60 +++++++++++++++++++
>   2 files changed, 61 insertions(+)
> 
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> index a4bcf3a6dfe3..ebe16162762f 100644
> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -7,3 +7,4 @@
>    * Tests are executed in order by igt/drm_buddy
>    */
>   selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
> +selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> index 51e4d393d22c..fd7d1a112458 100644
> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -16,6 +16,66 @@
>   
>   static unsigned int random_seed;
>   
> +static int igt_buddy_alloc_limit(void *arg)
> +{
> +	u64 end, size = U64_MAX, start = 0;
> +	struct drm_buddy_block *block;
> +	unsigned long flags = 0;
> +	LIST_HEAD(allocated);
> +	struct drm_buddy mm;
> +	int err;
> +
> +	size = end = round_down(size, 4096);
> +	err = drm_buddy_init(&mm, size, PAGE_SIZE);
> +	if (err)
> +		return err;
> +
> +	if (mm.max_order != DRM_BUDDY_MAX_ORDER) {
> +		pr_err("mm.max_order(%d) != %d\n",
> +		       mm.max_order, DRM_BUDDY_MAX_ORDER);
> +		err = -EINVAL;
> +		goto out_fini;
> +	}
> +
> +	err = drm_buddy_alloc_blocks(&mm, start, end, size,
> +				     PAGE_SIZE, &allocated, flags);
> +
> +	if (unlikely(err))
> +		goto out_free;
> +
> +	block = list_first_entry_or_null(&allocated,
> +					 struct drm_buddy_block,
> +					 link);
> +
> +	if (!block)

err = -EINVAL;

> +		goto out_fini;
> +
> +	if (drm_buddy_block_order(block) != mm.max_order) {
> +		pr_err("block order(%d) != %d\n",
> +		       drm_buddy_block_order(block), mm.max_order);
> +		err = -EINVAL;
> +		goto out_free;
> +	}
> +
> +	if (drm_buddy_block_size(&mm, block) !=
> +	    BIT_ULL(mm.max_order) * PAGE_SIZE) {
> +		pr_err("block size(%llu) != %llu\n",
> +		       drm_buddy_block_size(&mm, block),
> +		       BIT_ULL(mm.max_order) * PAGE_SIZE);
> +		err = -EINVAL;
> +		goto out_free;
> +	}
> +
> +	if (!err)

Always true AFAICT?

> +		pr_info("%s - succeeded\n", __func__);

I guess this could be made part of the run_selftests()? It looks like it 
already prints the current test, perhaps that is already enough?

With the err = -EINVAL change, feel free to add,
Reviewed-by: Matthew Auld <matthew.auld@intel.com>

> +
> +out_free:
> +	drm_buddy_free_list(&mm, &allocated);
> +out_fini:
> +	drm_buddy_fini(&mm);
> +	return err;
> +}
> +
>   static int igt_sanitycheck(void *ignored)
>   {
>   	pr_info("%s - ok!\n", __func__);

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 3/7] drm/selftests: add drm buddy alloc range testcase
  2022-02-03 13:32   ` [Intel-gfx] " Arunpravin
  (?)
@ 2022-02-08 10:03     ` Matthew Auld
  -1 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:03 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig

On 03/02/2022 13:32, Arunpravin wrote:
> - add a test to check the range allocation
> - export get_buddy() function in drm_buddy.c
> - export drm_prandom_u32_max_state() in lib/drm_random.c
> - include helper functions
> - include prime number header file
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>   drivers/gpu/drm/drm_buddy.c                   |  20 +-
>   drivers/gpu/drm/lib/drm_random.c              |   3 +-
>   drivers/gpu/drm/lib/drm_random.h              |   2 +
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 390 ++++++++++++++++++
>   include/drm/drm_buddy.h                       |   3 +
>   6 files changed, 414 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
> index 4845ef784b5e..501229d843c4 100644
> --- a/drivers/gpu/drm/drm_buddy.c
> +++ b/drivers/gpu/drm/drm_buddy.c
> @@ -211,7 +211,7 @@ static int split_block(struct drm_buddy *mm,
>   }
>   
>   static struct drm_buddy_block *
> -get_buddy(struct drm_buddy_block *block)
> +__get_buddy(struct drm_buddy_block *block)
>   {
>   	struct drm_buddy_block *parent;
>   
> @@ -225,6 +225,18 @@ get_buddy(struct drm_buddy_block *block)
>   	return parent->left;
>   }
>   
> +/**
> + * drm_get_buddy - get buddy address

Maybe add some more info here:

"Return the corresponding buddy block for @block, or NULL if this is a 
root block and can't be merged further. Requires some kind of locking to 
protect against any concurrent allocate and free operations."

?

Anyway,
Reviewed-by: Matthew Auld <matthew.auld@intel.com>


> + *
> + * @block: DRM buddy block
> + */
> +struct drm_buddy_block *
> +drm_get_buddy(struct drm_buddy_block *block)
> +{
> +	return __get_buddy(block);
> +}
> +EXPORT_SYMBOL(drm_get_buddy);
> +
>   static void __drm_buddy_free(struct drm_buddy *mm,
>   			     struct drm_buddy_block *block)
>   {
> @@ -233,7 +245,7 @@ static void __drm_buddy_free(struct drm_buddy *mm,
>   	while ((parent = block->parent)) {
>   		struct drm_buddy_block *buddy;
>   
> -		buddy = get_buddy(block);
> +		buddy = __get_buddy(block);
>   
>   		if (!drm_buddy_block_is_free(buddy))
>   			break;
> @@ -361,7 +373,7 @@ alloc_range_bias(struct drm_buddy *mm,
>   	 * bigger is better, so make sure we merge everything back before we
>   	 * free the allocated blocks.
>   	 */
> -	buddy = get_buddy(block);
> +	buddy = __get_buddy(block);
>   	if (buddy &&
>   	    (drm_buddy_block_is_free(block) &&
>   	     drm_buddy_block_is_free(buddy)))
> @@ -500,7 +512,7 @@ static int __alloc_range(struct drm_buddy *mm,
>   	 * bigger is better, so make sure we merge everything back before we
>   	 * free the allocated blocks.
>   	 */
> -	buddy = get_buddy(block);
> +	buddy = __get_buddy(block);
>   	if (buddy &&
>   	    (drm_buddy_block_is_free(block) &&
>   	     drm_buddy_block_is_free(buddy)))
> diff --git a/drivers/gpu/drm/lib/drm_random.c b/drivers/gpu/drm/lib/drm_random.c
> index eeb155826d27..31b5a3e21911 100644
> --- a/drivers/gpu/drm/lib/drm_random.c
> +++ b/drivers/gpu/drm/lib/drm_random.c
> @@ -7,10 +7,11 @@
>   
>   #include "drm_random.h"
>   
> -static inline u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
> +u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
>   {
>   	return upper_32_bits((u64)prandom_u32_state(state) * ep_ro);
>   }
> +EXPORT_SYMBOL(drm_prandom_u32_max_state);
>   
>   void drm_random_reorder(unsigned int *order, unsigned int count,
>   			struct rnd_state *state)
> diff --git a/drivers/gpu/drm/lib/drm_random.h b/drivers/gpu/drm/lib/drm_random.h
> index 4a3e94dfa0c0..5543bf0474bc 100644
> --- a/drivers/gpu/drm/lib/drm_random.h
> +++ b/drivers/gpu/drm/lib/drm_random.h
> @@ -22,5 +22,7 @@ unsigned int *drm_random_order(unsigned int count,
>   void drm_random_reorder(unsigned int *order,
>   			unsigned int count,
>   			struct rnd_state *state);
> +u32 drm_prandom_u32_max_state(u32 ep_ro,
> +			      struct rnd_state *state);
>   
>   #endif /* !__DRM_RANDOM_H__ */
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> index ebe16162762f..3230bfd2770b 100644
> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -8,3 +8,4 @@
>    */
>   selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
>   selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
> +selftest(buddy_alloc_range, igt_buddy_alloc_range)
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> index fd7d1a112458..e347060c05a2 100644
> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -6,6 +6,7 @@
>   #define pr_fmt(fmt) "drm_buddy: " fmt
>   
>   #include <linux/module.h>
> +#include <linux/prime_numbers.h>
>   
>   #include <drm/drm_buddy.h>
>   
> @@ -16,6 +17,395 @@
>   
>   static unsigned int random_seed;
>   
> +static inline const char *yesno(bool v)
> +{
> +	return v ? "yes" : "no";
> +}
> +
> +static void __igt_dump_block(struct drm_buddy *mm,
> +			     struct drm_buddy_block *block,
> +			     bool buddy)
> +{
> +	pr_err("block info: header=%llx, state=%u, order=%d, offset=%llx size=%llx root=%s buddy=%s\n",
> +	       block->header,
> +	       drm_buddy_block_state(block),
> +	       drm_buddy_block_order(block),
> +	       drm_buddy_block_offset(block),
> +	       drm_buddy_block_size(mm, block),
> +	       yesno(!block->parent),
> +	       yesno(buddy));
> +}
> +
> +static void igt_dump_block(struct drm_buddy *mm,
> +			   struct drm_buddy_block *block)
> +{
> +	struct drm_buddy_block *buddy;
> +
> +	__igt_dump_block(mm, block, false);
> +
> +	buddy = drm_get_buddy(block);
> +	if (buddy)
> +		__igt_dump_block(mm, buddy, true);
> +}
> +
> +static int igt_check_block(struct drm_buddy *mm,
> +			   struct drm_buddy_block *block)
> +{
> +	struct drm_buddy_block *buddy;
> +	unsigned int block_state;
> +	u64 block_size;
> +	u64 offset;
> +	int err = 0;
> +
> +	block_state = drm_buddy_block_state(block);
> +
> +	if (block_state != DRM_BUDDY_ALLOCATED &&
> +	    block_state != DRM_BUDDY_FREE &&
> +	    block_state != DRM_BUDDY_SPLIT) {
> +		pr_err("block state mismatch\n");
> +		err = -EINVAL;
> +	}
> +
> +	block_size = drm_buddy_block_size(mm, block);
> +	offset = drm_buddy_block_offset(block);
> +
> +	if (block_size < mm->chunk_size) {
> +		pr_err("block size smaller than min size\n");
> +		err = -EINVAL;
> +	}
> +
> +	if (!is_power_of_2(block_size)) {
> +		pr_err("block size not power of two\n");
> +		err = -EINVAL;
> +	}
> +
> +	if (!IS_ALIGNED(block_size, mm->chunk_size)) {
> +		pr_err("block size not aligned to min size\n");
> +		err = -EINVAL;
> +	}
> +
> +	if (!IS_ALIGNED(offset, mm->chunk_size)) {
> +		pr_err("block offset not aligned to min size\n");
> +		err = -EINVAL;
> +	}
> +
> +	if (!IS_ALIGNED(offset, block_size)) {
> +		pr_err("block offset not aligned to block size\n");
> +		err = -EINVAL;
> +	}
> +
> +	buddy = drm_get_buddy(block);
> +
> +	if (!buddy && block->parent) {
> +		pr_err("buddy has gone fishing\n");
> +		err = -EINVAL;
> +	}
> +
> +	if (buddy) {
> +		if (drm_buddy_block_offset(buddy) != (offset ^ block_size)) {
> +			pr_err("buddy has wrong offset\n");
> +			err = -EINVAL;
> +		}
> +
> +		if (drm_buddy_block_size(mm, buddy) != block_size) {
> +			pr_err("buddy size mismatch\n");
> +			err = -EINVAL;
> +		}
> +
> +		if (drm_buddy_block_state(buddy) == block_state &&
> +		    block_state == DRM_BUDDY_FREE) {
> +			pr_err("block and its buddy are free\n");
> +			err = -EINVAL;
> +		}
> +	}
> +
> +	return err;
> +}
> +
> +static int igt_check_blocks(struct drm_buddy *mm,
> +			    struct list_head *blocks,
> +			    u64 expected_size,
> +			    bool is_contiguous)
> +{
> +	struct drm_buddy_block *block;
> +	struct drm_buddy_block *prev;
> +	u64 total;
> +	int err = 0;
> +
> +	block = NULL;
> +	prev = NULL;
> +	total = 0;
> +
> +	list_for_each_entry(block, blocks, link) {
> +		err = igt_check_block(mm, block);
> +
> +		if (!drm_buddy_block_is_allocated(block)) {
> +			pr_err("block not allocated\n"),
> +			       err = -EINVAL;
> +		}
> +
> +		if (is_contiguous && prev) {
> +			u64 prev_block_size;
> +			u64 prev_offset;
> +			u64 offset;
> +
> +			prev_offset = drm_buddy_block_offset(prev);
> +			prev_block_size = drm_buddy_block_size(mm, prev);
> +			offset = drm_buddy_block_offset(block);
> +
> +			if (offset != (prev_offset + prev_block_size)) {
> +				pr_err("block offset mismatch\n");
> +				err = -EINVAL;
> +			}
> +		}
> +
> +		if (err)
> +			break;
> +
> +		total += drm_buddy_block_size(mm, block);
> +		prev = block;
> +	}
> +
> +	if (!err) {
> +		if (total != expected_size) {
> +			pr_err("size mismatch, expected=%llx, found=%llx\n",
> +			       expected_size, total);
> +			err = -EINVAL;
> +		}
> +		return err;
> +	}
> +
> +	if (prev) {
> +		pr_err("prev block, dump:\n");
> +		igt_dump_block(mm, prev);
> +	}
> +
> +	pr_err("bad block, dump:\n");
> +	igt_dump_block(mm, block);
> +
> +	return err;
> +}
> +
> +static int igt_check_mm(struct drm_buddy *mm)
> +{
> +	struct drm_buddy_block *root;
> +	struct drm_buddy_block *prev;
> +	unsigned int i;
> +	u64 total;
> +	int err = 0;
> +
> +	if (!mm->n_roots) {
> +		pr_err("n_roots is zero\n");
> +		return -EINVAL;
> +	}
> +
> +	if (mm->n_roots != hweight64(mm->size)) {
> +		pr_err("n_roots mismatch, n_roots=%u, expected=%lu\n",
> +		       mm->n_roots, hweight64(mm->size));
> +		return -EINVAL;
> +	}
> +
> +	root = NULL;
> +	prev = NULL;
> +	total = 0;
> +
> +	for (i = 0; i < mm->n_roots; ++i) {
> +		struct drm_buddy_block *block;
> +		unsigned int order;
> +
> +		root = mm->roots[i];
> +		if (!root) {
> +			pr_err("root(%u) is NULL\n", i);
> +			err = -EINVAL;
> +			break;
> +		}
> +
> +		err = igt_check_block(mm, root);
> +
> +		if (!drm_buddy_block_is_free(root)) {
> +			pr_err("root not free\n");
> +			err = -EINVAL;
> +		}
> +
> +		order = drm_buddy_block_order(root);
> +
> +		if (!i) {
> +			if (order != mm->max_order) {
> +				pr_err("max order root missing\n");
> +				err = -EINVAL;
> +			}
> +		}
> +
> +		if (prev) {
> +			u64 prev_block_size;
> +			u64 prev_offset;
> +			u64 offset;
> +
> +			prev_offset = drm_buddy_block_offset(prev);
> +			prev_block_size = drm_buddy_block_size(mm, prev);
> +			offset = drm_buddy_block_offset(root);
> +
> +			if (offset != (prev_offset + prev_block_size)) {
> +				pr_err("root offset mismatch\n");
> +				err = -EINVAL;
> +			}
> +		}
> +
> +		block = list_first_entry_or_null(&mm->free_list[order],
> +						 struct drm_buddy_block,
> +						 link);
> +		if (block != root) {
> +			pr_err("root mismatch at order=%u\n", order);
> +			err = -EINVAL;
> +		}
> +
> +		if (err)
> +			break;
> +
> +		prev = root;
> +		total += drm_buddy_block_size(mm, root);
> +	}
> +
> +	if (!err) {
> +		if (total != mm->size) {
> +			pr_err("expected mm size=%llx, found=%llx\n", mm->size,
> +			       total);
> +			err = -EINVAL;
> +		}
> +		return err;
> +	}
> +
> +	if (prev) {
> +		pr_err("prev root(%u), dump:\n", i - 1);
> +		igt_dump_block(mm, prev);
> +	}
> +
> +	if (root) {
> +		pr_err("bad root(%u), dump:\n", i);
> +		igt_dump_block(mm, root);
> +	}
> +
> +	return err;
> +}
> +
> +static void igt_mm_config(u64 *size, u64 *chunk_size)
> +{
> +	DRM_RND_STATE(prng, random_seed);
> +	u32 s, ms;
> +
> +	/* Nothing fancy, just try to get an interesting bit pattern */
> +
> +	prandom_seed_state(&prng, random_seed);
> +
> +	/* Let size be a random number of pages up to 8 GB (2M pages) */
> +	s = 1 + drm_prandom_u32_max_state((BIT(33 - 12)) - 1, &prng);
> +	/* Let the chunk size be a random power of 2 less than size */
> +	ms = BIT(drm_prandom_u32_max_state(ilog2(s), &prng));
> +	/* Round size down to the chunk size */
> +	s &= -ms;
> +
> +	/* Convert from pages to bytes */
> +	*chunk_size = (u64)ms << 12;
> +	*size = (u64)s << 12;
> +}
> +
> +static int igt_buddy_alloc_range(void *arg)
> +{
> +	unsigned long flags = DRM_BUDDY_RANGE_ALLOCATION;
> +	u64 offset, size, rem, chunk_size, end;
> +	unsigned long page_num;
> +	struct drm_buddy mm;
> +	LIST_HEAD(blocks);
> +	int err;
> +
> +	igt_mm_config(&size, &chunk_size);
> +
> +	err = drm_buddy_init(&mm, size, chunk_size);
> +	if (err) {
> +		pr_err("buddy_init failed(%d)\n", err);
> +		return err;
> +	}
> +
> +	err = igt_check_mm(&mm);
> +	if (err) {
> +		pr_err("pre-mm check failed, abort, abort, abort!\n");
> +		goto err_fini;
> +	}
> +
> +	rem = mm.size;
> +	offset = 0;
> +
> +	for_each_prime_number_from(page_num, 1, ULONG_MAX - 1) {
> +		struct drm_buddy_block *block;
> +		LIST_HEAD(tmp);
> +
> +		size = min(page_num * mm.chunk_size, rem);
> +		end = offset + size;
> +
> +		err = drm_buddy_alloc_blocks(&mm, offset, end, size, mm.chunk_size, &tmp, flags);
> +		if (err) {
> +			if (err == -ENOMEM) {
> +				pr_info("alloc_range hit -ENOMEM with size=%llx\n",
> +					size);
> +			} else {
> +				pr_err("alloc_range with offset=%llx, size=%llx failed(%d)\n",
> +				       offset, size, err);
> +			}
> +
> +			break;
> +		}
> +
> +		block = list_first_entry_or_null(&tmp,
> +						 struct drm_buddy_block,
> +						 link);
> +		if (!block) {
> +			pr_err("alloc_range has no blocks\n");
> +			err = -EINVAL;
> +			break;
> +		}
> +
> +		if (drm_buddy_block_offset(block) != offset) {
> +			pr_err("alloc_range start offset mismatch, found=%llx, expected=%llx\n",
> +			       drm_buddy_block_offset(block), offset);
> +			err = -EINVAL;
> +		}
> +
> +		if (!err)
> +			err = igt_check_blocks(&mm, &tmp, size, true);
> +
> +		list_splice_tail(&tmp, &blocks);
> +
> +		if (err)
> +			break;
> +
> +		offset += size;
> +
> +		rem -= size;
> +		if (!rem)
> +			break;
> +
> +		cond_resched();
> +	}
> +
> +	if (err == -ENOMEM)
> +		err = 0;
> +
> +	drm_buddy_free_list(&mm, &blocks);
> +
> +	if (!err) {
> +		err = igt_check_mm(&mm);
> +		if (err)
> +			pr_err("post-mm check failed\n");
> +		else
> +			pr_info("%s - succeeded\n", __func__);
> +	}
> +
> +err_fini:
> +	drm_buddy_fini(&mm);
> +
> +	return err;
> +}
> +
>   static int igt_buddy_alloc_limit(void *arg)
>   {
>   	u64 end, size = U64_MAX, start = 0;
> diff --git a/include/drm/drm_buddy.h b/include/drm/drm_buddy.h
> index bd21f9dfd15e..572077ff8ae7 100644
> --- a/include/drm/drm_buddy.h
> +++ b/include/drm/drm_buddy.h
> @@ -134,6 +134,9 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size);
>   
>   void drm_buddy_fini(struct drm_buddy *mm);
>   
> +struct drm_buddy_block *
> +drm_get_buddy(struct drm_buddy_block *block);
> +
>   int drm_buddy_alloc_blocks(struct drm_buddy *mm,
>   			   u64 start, u64 end, u64 size,
>   			   u64 min_page_size,

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Intel-gfx] [PATCH 3/7] drm/selftests: add drm buddy alloc range testcase
@ 2022-02-08 10:03     ` Matthew Auld
  0 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:03 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig

On 03/02/2022 13:32, Arunpravin wrote:
> - add a test to check the range allocation
> - export get_buddy() function in drm_buddy.c
> - export drm_prandom_u32_max_state() in lib/drm_random.c
> - include helper functions
> - include prime number header file
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>   drivers/gpu/drm/drm_buddy.c                   |  20 +-
>   drivers/gpu/drm/lib/drm_random.c              |   3 +-
>   drivers/gpu/drm/lib/drm_random.h              |   2 +
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 390 ++++++++++++++++++
>   include/drm/drm_buddy.h                       |   3 +
>   6 files changed, 414 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
> index 4845ef784b5e..501229d843c4 100644
> --- a/drivers/gpu/drm/drm_buddy.c
> +++ b/drivers/gpu/drm/drm_buddy.c
> @@ -211,7 +211,7 @@ static int split_block(struct drm_buddy *mm,
>   }
>   
>   static struct drm_buddy_block *
> -get_buddy(struct drm_buddy_block *block)
> +__get_buddy(struct drm_buddy_block *block)
>   {
>   	struct drm_buddy_block *parent;
>   
> @@ -225,6 +225,18 @@ get_buddy(struct drm_buddy_block *block)
>   	return parent->left;
>   }
>   
> +/**
> + * drm_get_buddy - get buddy address

Maybe add some more info here:

"Return the corresponding buddy block for @block, or NULL if this is a 
root block and can't be merged further. Requires some kind of locking to 
protect against any concurrent allocate and free operations."

?

Anyway,
Reviewed-by: Matthew Auld <matthew.auld@intel.com>


> + *
> + * @block: DRM buddy block
> + */
> +struct drm_buddy_block *
> +drm_get_buddy(struct drm_buddy_block *block)
> +{
> +	return __get_buddy(block);
> +}
> +EXPORT_SYMBOL(drm_get_buddy);
> +
>   static void __drm_buddy_free(struct drm_buddy *mm,
>   			     struct drm_buddy_block *block)
>   {
> @@ -233,7 +245,7 @@ static void __drm_buddy_free(struct drm_buddy *mm,
>   	while ((parent = block->parent)) {
>   		struct drm_buddy_block *buddy;
>   
> -		buddy = get_buddy(block);
> +		buddy = __get_buddy(block);
>   
>   		if (!drm_buddy_block_is_free(buddy))
>   			break;
> @@ -361,7 +373,7 @@ alloc_range_bias(struct drm_buddy *mm,
>   	 * bigger is better, so make sure we merge everything back before we
>   	 * free the allocated blocks.
>   	 */
> -	buddy = get_buddy(block);
> +	buddy = __get_buddy(block);
>   	if (buddy &&
>   	    (drm_buddy_block_is_free(block) &&
>   	     drm_buddy_block_is_free(buddy)))
> @@ -500,7 +512,7 @@ static int __alloc_range(struct drm_buddy *mm,
>   	 * bigger is better, so make sure we merge everything back before we
>   	 * free the allocated blocks.
>   	 */
> -	buddy = get_buddy(block);
> +	buddy = __get_buddy(block);
>   	if (buddy &&
>   	    (drm_buddy_block_is_free(block) &&
>   	     drm_buddy_block_is_free(buddy)))
> diff --git a/drivers/gpu/drm/lib/drm_random.c b/drivers/gpu/drm/lib/drm_random.c
> index eeb155826d27..31b5a3e21911 100644
> --- a/drivers/gpu/drm/lib/drm_random.c
> +++ b/drivers/gpu/drm/lib/drm_random.c
> @@ -7,10 +7,11 @@
>   
>   #include "drm_random.h"
>   
> -static inline u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
> +u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
>   {
>   	return upper_32_bits((u64)prandom_u32_state(state) * ep_ro);
>   }
> +EXPORT_SYMBOL(drm_prandom_u32_max_state);
>   
>   void drm_random_reorder(unsigned int *order, unsigned int count,
>   			struct rnd_state *state)
> diff --git a/drivers/gpu/drm/lib/drm_random.h b/drivers/gpu/drm/lib/drm_random.h
> index 4a3e94dfa0c0..5543bf0474bc 100644
> --- a/drivers/gpu/drm/lib/drm_random.h
> +++ b/drivers/gpu/drm/lib/drm_random.h
> @@ -22,5 +22,7 @@ unsigned int *drm_random_order(unsigned int count,
>   void drm_random_reorder(unsigned int *order,
>   			unsigned int count,
>   			struct rnd_state *state);
> +u32 drm_prandom_u32_max_state(u32 ep_ro,
> +			      struct rnd_state *state);
>   
>   #endif /* !__DRM_RANDOM_H__ */
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> index ebe16162762f..3230bfd2770b 100644
> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -8,3 +8,4 @@
>    */
>   selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
>   selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
> +selftest(buddy_alloc_range, igt_buddy_alloc_range)
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> index fd7d1a112458..e347060c05a2 100644
> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -6,6 +6,7 @@
>   #define pr_fmt(fmt) "drm_buddy: " fmt
>   
>   #include <linux/module.h>
> +#include <linux/prime_numbers.h>
>   
>   #include <drm/drm_buddy.h>
>   
> @@ -16,6 +17,395 @@
>   
>   static unsigned int random_seed;
>   
> +static inline const char *yesno(bool v)
> +{
> +	return v ? "yes" : "no";
> +}
> +
> +static void __igt_dump_block(struct drm_buddy *mm,
> +			     struct drm_buddy_block *block,
> +			     bool buddy)
> +{
> +	pr_err("block info: header=%llx, state=%u, order=%d, offset=%llx size=%llx root=%s buddy=%s\n",
> +	       block->header,
> +	       drm_buddy_block_state(block),
> +	       drm_buddy_block_order(block),
> +	       drm_buddy_block_offset(block),
> +	       drm_buddy_block_size(mm, block),
> +	       yesno(!block->parent),
> +	       yesno(buddy));
> +}
> +
> +static void igt_dump_block(struct drm_buddy *mm,
> +			   struct drm_buddy_block *block)
> +{
> +	struct drm_buddy_block *buddy;
> +
> +	__igt_dump_block(mm, block, false);
> +
> +	buddy = drm_get_buddy(block);
> +	if (buddy)
> +		__igt_dump_block(mm, buddy, true);
> +}
> +
> +static int igt_check_block(struct drm_buddy *mm,
> +			   struct drm_buddy_block *block)
> +{
> +	struct drm_buddy_block *buddy;
> +	unsigned int block_state;
> +	u64 block_size;
> +	u64 offset;
> +	int err = 0;
> +
> +	block_state = drm_buddy_block_state(block);
> +
> +	if (block_state != DRM_BUDDY_ALLOCATED &&
> +	    block_state != DRM_BUDDY_FREE &&
> +	    block_state != DRM_BUDDY_SPLIT) {
> +		pr_err("block state mismatch\n");
> +		err = -EINVAL;
> +	}
> +
> +	block_size = drm_buddy_block_size(mm, block);
> +	offset = drm_buddy_block_offset(block);
> +
> +	if (block_size < mm->chunk_size) {
> +		pr_err("block size smaller than min size\n");
> +		err = -EINVAL;
> +	}
> +
> +	if (!is_power_of_2(block_size)) {
> +		pr_err("block size not power of two\n");
> +		err = -EINVAL;
> +	}
> +
> +	if (!IS_ALIGNED(block_size, mm->chunk_size)) {
> +		pr_err("block size not aligned to min size\n");
> +		err = -EINVAL;
> +	}
> +
> +	if (!IS_ALIGNED(offset, mm->chunk_size)) {
> +		pr_err("block offset not aligned to min size\n");
> +		err = -EINVAL;
> +	}
> +
> +	if (!IS_ALIGNED(offset, block_size)) {
> +		pr_err("block offset not aligned to block size\n");
> +		err = -EINVAL;
> +	}
> +
> +	buddy = drm_get_buddy(block);
> +
> +	if (!buddy && block->parent) {
> +		pr_err("buddy has gone fishing\n");
> +		err = -EINVAL;
> +	}
> +
> +	if (buddy) {
> +		if (drm_buddy_block_offset(buddy) != (offset ^ block_size)) {
> +			pr_err("buddy has wrong offset\n");
> +			err = -EINVAL;
> +		}
> +
> +		if (drm_buddy_block_size(mm, buddy) != block_size) {
> +			pr_err("buddy size mismatch\n");
> +			err = -EINVAL;
> +		}
> +
> +		if (drm_buddy_block_state(buddy) == block_state &&
> +		    block_state == DRM_BUDDY_FREE) {
> +			pr_err("block and its buddy are free\n");
> +			err = -EINVAL;
> +		}
> +	}
> +
> +	return err;
> +}
> +
> +static int igt_check_blocks(struct drm_buddy *mm,
> +			    struct list_head *blocks,
> +			    u64 expected_size,
> +			    bool is_contiguous)
> +{
> +	struct drm_buddy_block *block;
> +	struct drm_buddy_block *prev;
> +	u64 total;
> +	int err = 0;
> +
> +	block = NULL;
> +	prev = NULL;
> +	total = 0;
> +
> +	list_for_each_entry(block, blocks, link) {
> +		err = igt_check_block(mm, block);
> +
> +		if (!drm_buddy_block_is_allocated(block)) {
> +			pr_err("block not allocated\n"),
> +			       err = -EINVAL;
> +		}
> +
> +		if (is_contiguous && prev) {
> +			u64 prev_block_size;
> +			u64 prev_offset;
> +			u64 offset;
> +
> +			prev_offset = drm_buddy_block_offset(prev);
> +			prev_block_size = drm_buddy_block_size(mm, prev);
> +			offset = drm_buddy_block_offset(block);
> +
> +			if (offset != (prev_offset + prev_block_size)) {
> +				pr_err("block offset mismatch\n");
> +				err = -EINVAL;
> +			}
> +		}
> +
> +		if (err)
> +			break;
> +
> +		total += drm_buddy_block_size(mm, block);
> +		prev = block;
> +	}
> +
> +	if (!err) {
> +		if (total != expected_size) {
> +			pr_err("size mismatch, expected=%llx, found=%llx\n",
> +			       expected_size, total);
> +			err = -EINVAL;
> +		}
> +		return err;
> +	}
> +
> +	if (prev) {
> +		pr_err("prev block, dump:\n");
> +		igt_dump_block(mm, prev);
> +	}
> +
> +	pr_err("bad block, dump:\n");
> +	igt_dump_block(mm, block);
> +
> +	return err;
> +}
> +
> +static int igt_check_mm(struct drm_buddy *mm)
> +{
> +	struct drm_buddy_block *root;
> +	struct drm_buddy_block *prev;
> +	unsigned int i;
> +	u64 total;
> +	int err = 0;
> +
> +	if (!mm->n_roots) {
> +		pr_err("n_roots is zero\n");
> +		return -EINVAL;
> +	}
> +
> +	if (mm->n_roots != hweight64(mm->size)) {
> +		pr_err("n_roots mismatch, n_roots=%u, expected=%lu\n",
> +		       mm->n_roots, hweight64(mm->size));
> +		return -EINVAL;
> +	}
> +
> +	root = NULL;
> +	prev = NULL;
> +	total = 0;
> +
> +	for (i = 0; i < mm->n_roots; ++i) {
> +		struct drm_buddy_block *block;
> +		unsigned int order;
> +
> +		root = mm->roots[i];
> +		if (!root) {
> +			pr_err("root(%u) is NULL\n", i);
> +			err = -EINVAL;
> +			break;
> +		}
> +
> +		err = igt_check_block(mm, root);
> +
> +		if (!drm_buddy_block_is_free(root)) {
> +			pr_err("root not free\n");
> +			err = -EINVAL;
> +		}
> +
> +		order = drm_buddy_block_order(root);
> +
> +		if (!i) {
> +			if (order != mm->max_order) {
> +				pr_err("max order root missing\n");
> +				err = -EINVAL;
> +			}
> +		}
> +
> +		if (prev) {
> +			u64 prev_block_size;
> +			u64 prev_offset;
> +			u64 offset;
> +
> +			prev_offset = drm_buddy_block_offset(prev);
> +			prev_block_size = drm_buddy_block_size(mm, prev);
> +			offset = drm_buddy_block_offset(root);
> +
> +			if (offset != (prev_offset + prev_block_size)) {
> +				pr_err("root offset mismatch\n");
> +				err = -EINVAL;
> +			}
> +		}
> +
> +		block = list_first_entry_or_null(&mm->free_list[order],
> +						 struct drm_buddy_block,
> +						 link);
> +		if (block != root) {
> +			pr_err("root mismatch at order=%u\n", order);
> +			err = -EINVAL;
> +		}
> +
> +		if (err)
> +			break;
> +
> +		prev = root;
> +		total += drm_buddy_block_size(mm, root);
> +	}
> +
> +	if (!err) {
> +		if (total != mm->size) {
> +			pr_err("expected mm size=%llx, found=%llx\n", mm->size,
> +			       total);
> +			err = -EINVAL;
> +		}
> +		return err;
> +	}
> +
> +	if (prev) {
> +		pr_err("prev root(%u), dump:\n", i - 1);
> +		igt_dump_block(mm, prev);
> +	}
> +
> +	if (root) {
> +		pr_err("bad root(%u), dump:\n", i);
> +		igt_dump_block(mm, root);
> +	}
> +
> +	return err;
> +}
> +
> +static void igt_mm_config(u64 *size, u64 *chunk_size)
> +{
> +	DRM_RND_STATE(prng, random_seed);
> +	u32 s, ms;
> +
> +	/* Nothing fancy, just try to get an interesting bit pattern */
> +
> +	prandom_seed_state(&prng, random_seed);
> +
> +	/* Let size be a random number of pages up to 8 GB (2M pages) */
> +	s = 1 + drm_prandom_u32_max_state((BIT(33 - 12)) - 1, &prng);
> +	/* Let the chunk size be a random power of 2 less than size */
> +	ms = BIT(drm_prandom_u32_max_state(ilog2(s), &prng));
> +	/* Round size down to the chunk size */
> +	s &= -ms;
> +
> +	/* Convert from pages to bytes */
> +	*chunk_size = (u64)ms << 12;
> +	*size = (u64)s << 12;
> +}
> +
> +static int igt_buddy_alloc_range(void *arg)
> +{
> +	unsigned long flags = DRM_BUDDY_RANGE_ALLOCATION;
> +	u64 offset, size, rem, chunk_size, end;
> +	unsigned long page_num;
> +	struct drm_buddy mm;
> +	LIST_HEAD(blocks);
> +	int err;
> +
> +	igt_mm_config(&size, &chunk_size);
> +
> +	err = drm_buddy_init(&mm, size, chunk_size);
> +	if (err) {
> +		pr_err("buddy_init failed(%d)\n", err);
> +		return err;
> +	}
> +
> +	err = igt_check_mm(&mm);
> +	if (err) {
> +		pr_err("pre-mm check failed, abort, abort, abort!\n");
> +		goto err_fini;
> +	}
> +
> +	rem = mm.size;
> +	offset = 0;
> +
> +	for_each_prime_number_from(page_num, 1, ULONG_MAX - 1) {
> +		struct drm_buddy_block *block;
> +		LIST_HEAD(tmp);
> +
> +		size = min(page_num * mm.chunk_size, rem);
> +		end = offset + size;
> +
> +		err = drm_buddy_alloc_blocks(&mm, offset, end, size, mm.chunk_size, &tmp, flags);
> +		if (err) {
> +			if (err == -ENOMEM) {
> +				pr_info("alloc_range hit -ENOMEM with size=%llx\n",
> +					size);
> +			} else {
> +				pr_err("alloc_range with offset=%llx, size=%llx failed(%d)\n",
> +				       offset, size, err);
> +			}
> +
> +			break;
> +		}
> +
> +		block = list_first_entry_or_null(&tmp,
> +						 struct drm_buddy_block,
> +						 link);
> +		if (!block) {
> +			pr_err("alloc_range has no blocks\n");
> +			err = -EINVAL;
> +			break;
> +		}
> +
> +		if (drm_buddy_block_offset(block) != offset) {
> +			pr_err("alloc_range start offset mismatch, found=%llx, expected=%llx\n",
> +			       drm_buddy_block_offset(block), offset);
> +			err = -EINVAL;
> +		}
> +
> +		if (!err)
> +			err = igt_check_blocks(&mm, &tmp, size, true);
> +
> +		list_splice_tail(&tmp, &blocks);
> +
> +		if (err)
> +			break;
> +
> +		offset += size;
> +
> +		rem -= size;
> +		if (!rem)
> +			break;
> +
> +		cond_resched();
> +	}
> +
> +	if (err == -ENOMEM)
> +		err = 0;
> +
> +	drm_buddy_free_list(&mm, &blocks);
> +
> +	if (!err) {
> +		err = igt_check_mm(&mm);
> +		if (err)
> +			pr_err("post-mm check failed\n");
> +		else
> +			pr_info("%s - succeeded\n", __func__);
> +	}
> +
> +err_fini:
> +	drm_buddy_fini(&mm);
> +
> +	return err;
> +}
> +
>   static int igt_buddy_alloc_limit(void *arg)
>   {
>   	u64 end, size = U64_MAX, start = 0;
> diff --git a/include/drm/drm_buddy.h b/include/drm/drm_buddy.h
> index bd21f9dfd15e..572077ff8ae7 100644
> --- a/include/drm/drm_buddy.h
> +++ b/include/drm/drm_buddy.h
> @@ -134,6 +134,9 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size);
>   
>   void drm_buddy_fini(struct drm_buddy *mm);
>   
> +struct drm_buddy_block *
> +drm_get_buddy(struct drm_buddy_block *block);
> +
>   int drm_buddy_alloc_blocks(struct drm_buddy *mm,
>   			   u64 start, u64 end, u64 size,
>   			   u64 min_page_size,

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 3/7] drm/selftests: add drm buddy alloc range testcase
@ 2022-02-08 10:03     ` Matthew Auld
  0 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:03 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig, daniel

On 03/02/2022 13:32, Arunpravin wrote:
> - add a test to check the range allocation
> - export get_buddy() function in drm_buddy.c
> - export drm_prandom_u32_max_state() in lib/drm_random.c
> - include helper functions
> - include prime number header file
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>   drivers/gpu/drm/drm_buddy.c                   |  20 +-
>   drivers/gpu/drm/lib/drm_random.c              |   3 +-
>   drivers/gpu/drm/lib/drm_random.h              |   2 +
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 390 ++++++++++++++++++
>   include/drm/drm_buddy.h                       |   3 +
>   6 files changed, 414 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
> index 4845ef784b5e..501229d843c4 100644
> --- a/drivers/gpu/drm/drm_buddy.c
> +++ b/drivers/gpu/drm/drm_buddy.c
> @@ -211,7 +211,7 @@ static int split_block(struct drm_buddy *mm,
>   }
>   
>   static struct drm_buddy_block *
> -get_buddy(struct drm_buddy_block *block)
> +__get_buddy(struct drm_buddy_block *block)
>   {
>   	struct drm_buddy_block *parent;
>   
> @@ -225,6 +225,18 @@ get_buddy(struct drm_buddy_block *block)
>   	return parent->left;
>   }
>   
> +/**
> + * drm_get_buddy - get buddy address

Maybe add some more info here:

"Return the corresponding buddy block for @block, or NULL if this is a 
root block and can't be merged further. Requires some kind of locking to 
protect against any concurrent allocate and free operations."

?

Anyway,
Reviewed-by: Matthew Auld <matthew.auld@intel.com>


> + *
> + * @block: DRM buddy block
> + */
> +struct drm_buddy_block *
> +drm_get_buddy(struct drm_buddy_block *block)
> +{
> +	return __get_buddy(block);
> +}
> +EXPORT_SYMBOL(drm_get_buddy);
> +
>   static void __drm_buddy_free(struct drm_buddy *mm,
>   			     struct drm_buddy_block *block)
>   {
> @@ -233,7 +245,7 @@ static void __drm_buddy_free(struct drm_buddy *mm,
>   	while ((parent = block->parent)) {
>   		struct drm_buddy_block *buddy;
>   
> -		buddy = get_buddy(block);
> +		buddy = __get_buddy(block);
>   
>   		if (!drm_buddy_block_is_free(buddy))
>   			break;
> @@ -361,7 +373,7 @@ alloc_range_bias(struct drm_buddy *mm,
>   	 * bigger is better, so make sure we merge everything back before we
>   	 * free the allocated blocks.
>   	 */
> -	buddy = get_buddy(block);
> +	buddy = __get_buddy(block);
>   	if (buddy &&
>   	    (drm_buddy_block_is_free(block) &&
>   	     drm_buddy_block_is_free(buddy)))
> @@ -500,7 +512,7 @@ static int __alloc_range(struct drm_buddy *mm,
>   	 * bigger is better, so make sure we merge everything back before we
>   	 * free the allocated blocks.
>   	 */
> -	buddy = get_buddy(block);
> +	buddy = __get_buddy(block);
>   	if (buddy &&
>   	    (drm_buddy_block_is_free(block) &&
>   	     drm_buddy_block_is_free(buddy)))
> diff --git a/drivers/gpu/drm/lib/drm_random.c b/drivers/gpu/drm/lib/drm_random.c
> index eeb155826d27..31b5a3e21911 100644
> --- a/drivers/gpu/drm/lib/drm_random.c
> +++ b/drivers/gpu/drm/lib/drm_random.c
> @@ -7,10 +7,11 @@
>   
>   #include "drm_random.h"
>   
> -static inline u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
> +u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
>   {
>   	return upper_32_bits((u64)prandom_u32_state(state) * ep_ro);
>   }
> +EXPORT_SYMBOL(drm_prandom_u32_max_state);
>   
>   void drm_random_reorder(unsigned int *order, unsigned int count,
>   			struct rnd_state *state)
> diff --git a/drivers/gpu/drm/lib/drm_random.h b/drivers/gpu/drm/lib/drm_random.h
> index 4a3e94dfa0c0..5543bf0474bc 100644
> --- a/drivers/gpu/drm/lib/drm_random.h
> +++ b/drivers/gpu/drm/lib/drm_random.h
> @@ -22,5 +22,7 @@ unsigned int *drm_random_order(unsigned int count,
>   void drm_random_reorder(unsigned int *order,
>   			unsigned int count,
>   			struct rnd_state *state);
> +u32 drm_prandom_u32_max_state(u32 ep_ro,
> +			      struct rnd_state *state);
>   
>   #endif /* !__DRM_RANDOM_H__ */
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> index ebe16162762f..3230bfd2770b 100644
> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -8,3 +8,4 @@
>    */
>   selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
>   selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
> +selftest(buddy_alloc_range, igt_buddy_alloc_range)
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> index fd7d1a112458..e347060c05a2 100644
> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -6,6 +6,7 @@
>   #define pr_fmt(fmt) "drm_buddy: " fmt
>   
>   #include <linux/module.h>
> +#include <linux/prime_numbers.h>
>   
>   #include <drm/drm_buddy.h>
>   
> @@ -16,6 +17,395 @@
>   
>   static unsigned int random_seed;
>   
> +static inline const char *yesno(bool v)
> +{
> +	return v ? "yes" : "no";
> +}
> +
> +static void __igt_dump_block(struct drm_buddy *mm,
> +			     struct drm_buddy_block *block,
> +			     bool buddy)
> +{
> +	pr_err("block info: header=%llx, state=%u, order=%d, offset=%llx size=%llx root=%s buddy=%s\n",
> +	       block->header,
> +	       drm_buddy_block_state(block),
> +	       drm_buddy_block_order(block),
> +	       drm_buddy_block_offset(block),
> +	       drm_buddy_block_size(mm, block),
> +	       yesno(!block->parent),
> +	       yesno(buddy));
> +}
> +
> +static void igt_dump_block(struct drm_buddy *mm,
> +			   struct drm_buddy_block *block)
> +{
> +	struct drm_buddy_block *buddy;
> +
> +	__igt_dump_block(mm, block, false);
> +
> +	buddy = drm_get_buddy(block);
> +	if (buddy)
> +		__igt_dump_block(mm, buddy, true);
> +}
> +
> +static int igt_check_block(struct drm_buddy *mm,
> +			   struct drm_buddy_block *block)
> +{
> +	struct drm_buddy_block *buddy;
> +	unsigned int block_state;
> +	u64 block_size;
> +	u64 offset;
> +	int err = 0;
> +
> +	block_state = drm_buddy_block_state(block);
> +
> +	if (block_state != DRM_BUDDY_ALLOCATED &&
> +	    block_state != DRM_BUDDY_FREE &&
> +	    block_state != DRM_BUDDY_SPLIT) {
> +		pr_err("block state mismatch\n");
> +		err = -EINVAL;
> +	}
> +
> +	block_size = drm_buddy_block_size(mm, block);
> +	offset = drm_buddy_block_offset(block);
> +
> +	if (block_size < mm->chunk_size) {
> +		pr_err("block size smaller than min size\n");
> +		err = -EINVAL;
> +	}
> +
> +	if (!is_power_of_2(block_size)) {
> +		pr_err("block size not power of two\n");
> +		err = -EINVAL;
> +	}
> +
> +	if (!IS_ALIGNED(block_size, mm->chunk_size)) {
> +		pr_err("block size not aligned to min size\n");
> +		err = -EINVAL;
> +	}
> +
> +	if (!IS_ALIGNED(offset, mm->chunk_size)) {
> +		pr_err("block offset not aligned to min size\n");
> +		err = -EINVAL;
> +	}
> +
> +	if (!IS_ALIGNED(offset, block_size)) {
> +		pr_err("block offset not aligned to block size\n");
> +		err = -EINVAL;
> +	}
> +
> +	buddy = drm_get_buddy(block);
> +
> +	if (!buddy && block->parent) {
> +		pr_err("buddy has gone fishing\n");
> +		err = -EINVAL;
> +	}
> +
> +	if (buddy) {
> +		if (drm_buddy_block_offset(buddy) != (offset ^ block_size)) {
> +			pr_err("buddy has wrong offset\n");
> +			err = -EINVAL;
> +		}
> +
> +		if (drm_buddy_block_size(mm, buddy) != block_size) {
> +			pr_err("buddy size mismatch\n");
> +			err = -EINVAL;
> +		}
> +
> +		if (drm_buddy_block_state(buddy) == block_state &&
> +		    block_state == DRM_BUDDY_FREE) {
> +			pr_err("block and its buddy are free\n");
> +			err = -EINVAL;
> +		}
> +	}
> +
> +	return err;
> +}
> +
> +static int igt_check_blocks(struct drm_buddy *mm,
> +			    struct list_head *blocks,
> +			    u64 expected_size,
> +			    bool is_contiguous)
> +{
> +	struct drm_buddy_block *block;
> +	struct drm_buddy_block *prev;
> +	u64 total;
> +	int err = 0;
> +
> +	block = NULL;
> +	prev = NULL;
> +	total = 0;
> +
> +	list_for_each_entry(block, blocks, link) {
> +		err = igt_check_block(mm, block);
> +
> +		if (!drm_buddy_block_is_allocated(block)) {
> +			pr_err("block not allocated\n"),
> +			       err = -EINVAL;
> +		}
> +
> +		if (is_contiguous && prev) {
> +			u64 prev_block_size;
> +			u64 prev_offset;
> +			u64 offset;
> +
> +			prev_offset = drm_buddy_block_offset(prev);
> +			prev_block_size = drm_buddy_block_size(mm, prev);
> +			offset = drm_buddy_block_offset(block);
> +
> +			if (offset != (prev_offset + prev_block_size)) {
> +				pr_err("block offset mismatch\n");
> +				err = -EINVAL;
> +			}
> +		}
> +
> +		if (err)
> +			break;
> +
> +		total += drm_buddy_block_size(mm, block);
> +		prev = block;
> +	}
> +
> +	if (!err) {
> +		if (total != expected_size) {
> +			pr_err("size mismatch, expected=%llx, found=%llx\n",
> +			       expected_size, total);
> +			err = -EINVAL;
> +		}
> +		return err;
> +	}
> +
> +	if (prev) {
> +		pr_err("prev block, dump:\n");
> +		igt_dump_block(mm, prev);
> +	}
> +
> +	pr_err("bad block, dump:\n");
> +	igt_dump_block(mm, block);
> +
> +	return err;
> +}
> +
> +static int igt_check_mm(struct drm_buddy *mm)
> +{
> +	struct drm_buddy_block *root;
> +	struct drm_buddy_block *prev;
> +	unsigned int i;
> +	u64 total;
> +	int err = 0;
> +
> +	if (!mm->n_roots) {
> +		pr_err("n_roots is zero\n");
> +		return -EINVAL;
> +	}
> +
> +	if (mm->n_roots != hweight64(mm->size)) {
> +		pr_err("n_roots mismatch, n_roots=%u, expected=%lu\n",
> +		       mm->n_roots, hweight64(mm->size));
> +		return -EINVAL;
> +	}
> +
> +	root = NULL;
> +	prev = NULL;
> +	total = 0;
> +
> +	for (i = 0; i < mm->n_roots; ++i) {
> +		struct drm_buddy_block *block;
> +		unsigned int order;
> +
> +		root = mm->roots[i];
> +		if (!root) {
> +			pr_err("root(%u) is NULL\n", i);
> +			err = -EINVAL;
> +			break;
> +		}
> +
> +		err = igt_check_block(mm, root);
> +
> +		if (!drm_buddy_block_is_free(root)) {
> +			pr_err("root not free\n");
> +			err = -EINVAL;
> +		}
> +
> +		order = drm_buddy_block_order(root);
> +
> +		if (!i) {
> +			if (order != mm->max_order) {
> +				pr_err("max order root missing\n");
> +				err = -EINVAL;
> +			}
> +		}
> +
> +		if (prev) {
> +			u64 prev_block_size;
> +			u64 prev_offset;
> +			u64 offset;
> +
> +			prev_offset = drm_buddy_block_offset(prev);
> +			prev_block_size = drm_buddy_block_size(mm, prev);
> +			offset = drm_buddy_block_offset(root);
> +
> +			if (offset != (prev_offset + prev_block_size)) {
> +				pr_err("root offset mismatch\n");
> +				err = -EINVAL;
> +			}
> +		}
> +
> +		block = list_first_entry_or_null(&mm->free_list[order],
> +						 struct drm_buddy_block,
> +						 link);
> +		if (block != root) {
> +			pr_err("root mismatch at order=%u\n", order);
> +			err = -EINVAL;
> +		}
> +
> +		if (err)
> +			break;
> +
> +		prev = root;
> +		total += drm_buddy_block_size(mm, root);
> +	}
> +
> +	if (!err) {
> +		if (total != mm->size) {
> +			pr_err("expected mm size=%llx, found=%llx\n", mm->size,
> +			       total);
> +			err = -EINVAL;
> +		}
> +		return err;
> +	}
> +
> +	if (prev) {
> +		pr_err("prev root(%u), dump:\n", i - 1);
> +		igt_dump_block(mm, prev);
> +	}
> +
> +	if (root) {
> +		pr_err("bad root(%u), dump:\n", i);
> +		igt_dump_block(mm, root);
> +	}
> +
> +	return err;
> +}
> +
> +static void igt_mm_config(u64 *size, u64 *chunk_size)
> +{
> +	DRM_RND_STATE(prng, random_seed);
> +	u32 s, ms;
> +
> +	/* Nothing fancy, just try to get an interesting bit pattern */
> +
> +	prandom_seed_state(&prng, random_seed);
> +
> +	/* Let size be a random number of pages up to 8 GB (2M pages) */
> +	s = 1 + drm_prandom_u32_max_state((BIT(33 - 12)) - 1, &prng);
> +	/* Let the chunk size be a random power of 2 less than size */
> +	ms = BIT(drm_prandom_u32_max_state(ilog2(s), &prng));
> +	/* Round size down to the chunk size */
> +	s &= -ms;
> +
> +	/* Convert from pages to bytes */
> +	*chunk_size = (u64)ms << 12;
> +	*size = (u64)s << 12;
> +}
> +
> +static int igt_buddy_alloc_range(void *arg)
> +{
> +	unsigned long flags = DRM_BUDDY_RANGE_ALLOCATION;
> +	u64 offset, size, rem, chunk_size, end;
> +	unsigned long page_num;
> +	struct drm_buddy mm;
> +	LIST_HEAD(blocks);
> +	int err;
> +
> +	igt_mm_config(&size, &chunk_size);
> +
> +	err = drm_buddy_init(&mm, size, chunk_size);
> +	if (err) {
> +		pr_err("buddy_init failed(%d)\n", err);
> +		return err;
> +	}
> +
> +	err = igt_check_mm(&mm);
> +	if (err) {
> +		pr_err("pre-mm check failed, abort, abort, abort!\n");
> +		goto err_fini;
> +	}
> +
> +	rem = mm.size;
> +	offset = 0;
> +
> +	for_each_prime_number_from(page_num, 1, ULONG_MAX - 1) {
> +		struct drm_buddy_block *block;
> +		LIST_HEAD(tmp);
> +
> +		size = min(page_num * mm.chunk_size, rem);
> +		end = offset + size;
> +
> +		err = drm_buddy_alloc_blocks(&mm, offset, end, size, mm.chunk_size, &tmp, flags);
> +		if (err) {
> +			if (err == -ENOMEM) {
> +				pr_info("alloc_range hit -ENOMEM with size=%llx\n",
> +					size);
> +			} else {
> +				pr_err("alloc_range with offset=%llx, size=%llx failed(%d)\n",
> +				       offset, size, err);
> +			}
> +
> +			break;
> +		}
> +
> +		block = list_first_entry_or_null(&tmp,
> +						 struct drm_buddy_block,
> +						 link);
> +		if (!block) {
> +			pr_err("alloc_range has no blocks\n");
> +			err = -EINVAL;
> +			break;
> +		}
> +
> +		if (drm_buddy_block_offset(block) != offset) {
> +			pr_err("alloc_range start offset mismatch, found=%llx, expected=%llx\n",
> +			       drm_buddy_block_offset(block), offset);
> +			err = -EINVAL;
> +		}
> +
> +		if (!err)
> +			err = igt_check_blocks(&mm, &tmp, size, true);
> +
> +		list_splice_tail(&tmp, &blocks);
> +
> +		if (err)
> +			break;
> +
> +		offset += size;
> +
> +		rem -= size;
> +		if (!rem)
> +			break;
> +
> +		cond_resched();
> +	}
> +
> +	if (err == -ENOMEM)
> +		err = 0;
> +
> +	drm_buddy_free_list(&mm, &blocks);
> +
> +	if (!err) {
> +		err = igt_check_mm(&mm);
> +		if (err)
> +			pr_err("post-mm check failed\n");
> +		else
> +			pr_info("%s - succeeded\n", __func__);
> +	}
> +
> +err_fini:
> +	drm_buddy_fini(&mm);
> +
> +	return err;
> +}
> +
>   static int igt_buddy_alloc_limit(void *arg)
>   {
>   	u64 end, size = U64_MAX, start = 0;
> diff --git a/include/drm/drm_buddy.h b/include/drm/drm_buddy.h
> index bd21f9dfd15e..572077ff8ae7 100644
> --- a/include/drm/drm_buddy.h
> +++ b/include/drm/drm_buddy.h
> @@ -134,6 +134,9 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size);
>   
>   void drm_buddy_fini(struct drm_buddy *mm);
>   
> +struct drm_buddy_block *
> +drm_get_buddy(struct drm_buddy_block *block);
> +
>   int drm_buddy_alloc_blocks(struct drm_buddy *mm,
>   			   u64 start, u64 end, u64 size,
>   			   u64 min_page_size,

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 4/7] drm/selftests: add drm buddy optimistic testcase
  2022-02-03 13:32   ` [Intel-gfx] " Arunpravin
  (?)
@ 2022-02-08 10:12     ` Matthew Auld
  -1 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:12 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig

On 03/02/2022 13:32, Arunpravin wrote:
> create a mm with one block of each order available, and
> try to allocate them all.
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Intel-gfx] [PATCH 4/7] drm/selftests: add drm buddy optimistic testcase
@ 2022-02-08 10:12     ` Matthew Auld
  0 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:12 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig

On 03/02/2022 13:32, Arunpravin wrote:
> create a mm with one block of each order available, and
> try to allocate them all.
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 4/7] drm/selftests: add drm buddy optimistic testcase
@ 2022-02-08 10:12     ` Matthew Auld
  0 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:12 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig, daniel

On 03/02/2022 13:32, Arunpravin wrote:
> create a mm with one block of each order available, and
> try to allocate them all.
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 5/7] drm/selftests: add drm buddy pessimistic testcase
  2022-02-03 13:32   ` [Intel-gfx] " Arunpravin
  (?)
@ 2022-02-08 10:17     ` Matthew Auld
  -1 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:17 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig

On 03/02/2022 13:32, Arunpravin wrote:
> create a pot-sized mm, then allocate one of each possible
> order within. This should leave the mm with exactly one
> page left.
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 153 ++++++++++++++++++
>   2 files changed, 154 insertions(+)
> 
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> index 21a6bd38864f..b14f04a1de19 100644
> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -10,3 +10,4 @@ selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
>   selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
>   selftest(buddy_alloc_range, igt_buddy_alloc_range)
>   selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
> +selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> index b193d9556fb4..e97f583ed0cd 100644
> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -314,6 +314,159 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
>   	*size = (u64)s << 12;
>   }
>   
> +static int igt_buddy_alloc_pessimistic(void *arg)
> +{
> +	u64 mm_size, size, min_page_size, start = 0;
> +	struct drm_buddy_block *block, *bn;
> +	const unsigned int max_order = 16;
> +	unsigned long flags = 0;
> +	struct drm_buddy mm;
> +	unsigned int order;
> +	LIST_HEAD(blocks);
> +	LIST_HEAD(tmp);
> +	int err;
> +
> +	/*
> +	 * Create a pot-sized mm, then allocate one of each possible
> +	 * order within. This should leave the mm with exactly one
> +	 * page left.
> +	 */
> +
> +	mm_size = PAGE_SIZE << max_order;
> +	err = drm_buddy_init(&mm, mm_size, PAGE_SIZE);
> +	if (err) {
> +		pr_err("buddy_init failed(%d)\n", err);
> +		return err;
> +	}
> +	BUG_ON(mm.max_order != max_order);
> +
> +	for (order = 0; order < max_order; order++) {
> +		size = min_page_size = get_size(order, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (err) {
> +			pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
> +				order);
> +			goto err;
> +		}
> +
> +		block = list_first_entry_or_null(&tmp,
> +						 struct drm_buddy_block,
> +						 link);
> +		if (!block) {
> +			pr_err("alloc_blocks has no blocks\n");
> +			err = -EINVAL;
> +			goto err;
> +		}
> +
> +		list_del(&block->link);
> +		list_add_tail(&block->link, &blocks);
> +	}
> +
> +	/* And now the last remaining block available */
> +	size = min_page_size = get_size(0, PAGE_SIZE);
> +	err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +	if (err) {
> +		pr_info("buddy_alloc hit -ENOMEM on final alloc\n");
> +		goto err;
> +	}
> +
> +	block = list_first_entry_or_null(&tmp,
> +					 struct drm_buddy_block,
> +					 link);
> +	if (!block) {
> +		pr_err("alloc_blocks has no blocks\n");
> +		err = -EINVAL;
> +		goto err;
> +	}
> +
> +	list_del(&block->link);
> +	list_add_tail(&block->link, &blocks);
> +
> +	/* Should be completely full! */
> +	for (order = max_order; order--; ) {
> +		size = min_page_size = get_size(order, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (!err) {
> +			pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
> +				order);
> +			block = list_first_entry_or_null(&tmp,
> +							 struct drm_buddy_block,
> +							 link);
> +			if (!block) {
> +				pr_err("alloc_blocks has no blocks\n");
> +				err = -EINVAL;
> +				goto err;
> +			}
> +
> +			list_del(&block->link);
> +			list_add_tail(&block->link, &blocks);
> +			err = -EINVAL;
> +			goto err;
> +		}
> +	}
> +
> +	block = list_last_entry(&blocks, typeof(*block), link);
> +	list_del(&block->link);
> +	drm_buddy_free_block(&mm, block);
> +
> +	/* As we free in increasing size, we make available larger blocks */
> +	order = 1;
> +	list_for_each_entry_safe(block, bn, &blocks, link) {
> +		list_del(&block->link);
> +		drm_buddy_free_block(&mm, block);
> +
> +		size = min_page_size = get_size(order, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (err) {
> +			pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
> +				order);
> +			goto err;
> +		}
> +
> +		block = list_first_entry_or_null(&tmp,
> +						 struct drm_buddy_block,
> +						 link);
> +		if (!block) {
> +			pr_err("alloc_blocks has no blocks\n");
> +			err = -EINVAL;
> +			goto err;
> +		}
> +
> +		list_del(&block->link);
> +		drm_buddy_free_block(&mm, block);
> +		order++;
> +	}
> +
> +	/* To confirm, now the whole mm should be available */
> +	size = min_page_size = get_size(max_order, PAGE_SIZE);
> +	err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +	if (err) {
> +		pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
> +			max_order);
> +		goto err;
> +	}
> +
> +	block = list_first_entry_or_null(&tmp,
> +					 struct drm_buddy_block,
> +					 link);
> +	if (!block) {
> +		pr_err("alloc_blocks has no blocks\n");
> +		err = -EINVAL;
> +		goto err;
> +	}
> +
> +	list_del(&block->link);
> +	drm_buddy_free_block(&mm, block);
> +
> +	if (!err)

Always true?

Reviewed-by: Matthew Auld <matthew.auld@intel.com>

> +		pr_info("%s - succeeded\n", __func__);
> +
> +err:
> +	drm_buddy_free_list(&mm, &blocks);
> +	drm_buddy_fini(&mm);
> +	return err;
> +}
> +
>   static int igt_buddy_alloc_optimistic(void *arg)
>   {
>   	u64 mm_size, size, min_page_size, start = 0;

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Intel-gfx] [PATCH 5/7] drm/selftests: add drm buddy pessimistic testcase
@ 2022-02-08 10:17     ` Matthew Auld
  0 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:17 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig

On 03/02/2022 13:32, Arunpravin wrote:
> create a pot-sized mm, then allocate one of each possible
> order within. This should leave the mm with exactly one
> page left.
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 153 ++++++++++++++++++
>   2 files changed, 154 insertions(+)
> 
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> index 21a6bd38864f..b14f04a1de19 100644
> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -10,3 +10,4 @@ selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
>   selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
>   selftest(buddy_alloc_range, igt_buddy_alloc_range)
>   selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
> +selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> index b193d9556fb4..e97f583ed0cd 100644
> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -314,6 +314,159 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
>   	*size = (u64)s << 12;
>   }
>   
> +static int igt_buddy_alloc_pessimistic(void *arg)
> +{
> +	u64 mm_size, size, min_page_size, start = 0;
> +	struct drm_buddy_block *block, *bn;
> +	const unsigned int max_order = 16;
> +	unsigned long flags = 0;
> +	struct drm_buddy mm;
> +	unsigned int order;
> +	LIST_HEAD(blocks);
> +	LIST_HEAD(tmp);
> +	int err;
> +
> +	/*
> +	 * Create a pot-sized mm, then allocate one of each possible
> +	 * order within. This should leave the mm with exactly one
> +	 * page left.
> +	 */
> +
> +	mm_size = PAGE_SIZE << max_order;
> +	err = drm_buddy_init(&mm, mm_size, PAGE_SIZE);
> +	if (err) {
> +		pr_err("buddy_init failed(%d)\n", err);
> +		return err;
> +	}
> +	BUG_ON(mm.max_order != max_order);
> +
> +	for (order = 0; order < max_order; order++) {
> +		size = min_page_size = get_size(order, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (err) {
> +			pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
> +				order);
> +			goto err;
> +		}
> +
> +		block = list_first_entry_or_null(&tmp,
> +						 struct drm_buddy_block,
> +						 link);
> +		if (!block) {
> +			pr_err("alloc_blocks has no blocks\n");
> +			err = -EINVAL;
> +			goto err;
> +		}
> +
> +		list_del(&block->link);
> +		list_add_tail(&block->link, &blocks);
> +	}
> +
> +	/* And now the last remaining block available */
> +	size = min_page_size = get_size(0, PAGE_SIZE);
> +	err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +	if (err) {
> +		pr_info("buddy_alloc hit -ENOMEM on final alloc\n");
> +		goto err;
> +	}
> +
> +	block = list_first_entry_or_null(&tmp,
> +					 struct drm_buddy_block,
> +					 link);
> +	if (!block) {
> +		pr_err("alloc_blocks has no blocks\n");
> +		err = -EINVAL;
> +		goto err;
> +	}
> +
> +	list_del(&block->link);
> +	list_add_tail(&block->link, &blocks);
> +
> +	/* Should be completely full! */
> +	for (order = max_order; order--; ) {
> +		size = min_page_size = get_size(order, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (!err) {
> +			pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
> +				order);
> +			block = list_first_entry_or_null(&tmp,
> +							 struct drm_buddy_block,
> +							 link);
> +			if (!block) {
> +				pr_err("alloc_blocks has no blocks\n");
> +				err = -EINVAL;
> +				goto err;
> +			}
> +
> +			list_del(&block->link);
> +			list_add_tail(&block->link, &blocks);
> +			err = -EINVAL;
> +			goto err;
> +		}
> +	}
> +
> +	block = list_last_entry(&blocks, typeof(*block), link);
> +	list_del(&block->link);
> +	drm_buddy_free_block(&mm, block);
> +
> +	/* As we free in increasing size, we make available larger blocks */
> +	order = 1;
> +	list_for_each_entry_safe(block, bn, &blocks, link) {
> +		list_del(&block->link);
> +		drm_buddy_free_block(&mm, block);
> +
> +		size = min_page_size = get_size(order, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (err) {
> +			pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
> +				order);
> +			goto err;
> +		}
> +
> +		block = list_first_entry_or_null(&tmp,
> +						 struct drm_buddy_block,
> +						 link);
> +		if (!block) {
> +			pr_err("alloc_blocks has no blocks\n");
> +			err = -EINVAL;
> +			goto err;
> +		}
> +
> +		list_del(&block->link);
> +		drm_buddy_free_block(&mm, block);
> +		order++;
> +	}
> +
> +	/* To confirm, now the whole mm should be available */
> +	size = min_page_size = get_size(max_order, PAGE_SIZE);
> +	err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +	if (err) {
> +		pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
> +			max_order);
> +		goto err;
> +	}
> +
> +	block = list_first_entry_or_null(&tmp,
> +					 struct drm_buddy_block,
> +					 link);
> +	if (!block) {
> +		pr_err("alloc_blocks has no blocks\n");
> +		err = -EINVAL;
> +		goto err;
> +	}
> +
> +	list_del(&block->link);
> +	drm_buddy_free_block(&mm, block);
> +
> +	if (!err)

Always true?

Reviewed-by: Matthew Auld <matthew.auld@intel.com>

> +		pr_info("%s - succeeded\n", __func__);
> +
> +err:
> +	drm_buddy_free_list(&mm, &blocks);
> +	drm_buddy_fini(&mm);
> +	return err;
> +}
> +
>   static int igt_buddy_alloc_optimistic(void *arg)
>   {
>   	u64 mm_size, size, min_page_size, start = 0;

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 5/7] drm/selftests: add drm buddy pessimistic testcase
@ 2022-02-08 10:17     ` Matthew Auld
  0 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:17 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig, daniel

On 03/02/2022 13:32, Arunpravin wrote:
> create a pot-sized mm, then allocate one of each possible
> order within. This should leave the mm with exactly one
> page left.
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 153 ++++++++++++++++++
>   2 files changed, 154 insertions(+)
> 
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> index 21a6bd38864f..b14f04a1de19 100644
> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -10,3 +10,4 @@ selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
>   selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
>   selftest(buddy_alloc_range, igt_buddy_alloc_range)
>   selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
> +selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> index b193d9556fb4..e97f583ed0cd 100644
> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -314,6 +314,159 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
>   	*size = (u64)s << 12;
>   }
>   
> +static int igt_buddy_alloc_pessimistic(void *arg)
> +{
> +	u64 mm_size, size, min_page_size, start = 0;
> +	struct drm_buddy_block *block, *bn;
> +	const unsigned int max_order = 16;
> +	unsigned long flags = 0;
> +	struct drm_buddy mm;
> +	unsigned int order;
> +	LIST_HEAD(blocks);
> +	LIST_HEAD(tmp);
> +	int err;
> +
> +	/*
> +	 * Create a pot-sized mm, then allocate one of each possible
> +	 * order within. This should leave the mm with exactly one
> +	 * page left.
> +	 */
> +
> +	mm_size = PAGE_SIZE << max_order;
> +	err = drm_buddy_init(&mm, mm_size, PAGE_SIZE);
> +	if (err) {
> +		pr_err("buddy_init failed(%d)\n", err);
> +		return err;
> +	}
> +	BUG_ON(mm.max_order != max_order);
> +
> +	for (order = 0; order < max_order; order++) {
> +		size = min_page_size = get_size(order, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (err) {
> +			pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
> +				order);
> +			goto err;
> +		}
> +
> +		block = list_first_entry_or_null(&tmp,
> +						 struct drm_buddy_block,
> +						 link);
> +		if (!block) {
> +			pr_err("alloc_blocks has no blocks\n");
> +			err = -EINVAL;
> +			goto err;
> +		}
> +
> +		list_del(&block->link);
> +		list_add_tail(&block->link, &blocks);
> +	}
> +
> +	/* And now the last remaining block available */
> +	size = min_page_size = get_size(0, PAGE_SIZE);
> +	err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +	if (err) {
> +		pr_info("buddy_alloc hit -ENOMEM on final alloc\n");
> +		goto err;
> +	}
> +
> +	block = list_first_entry_or_null(&tmp,
> +					 struct drm_buddy_block,
> +					 link);
> +	if (!block) {
> +		pr_err("alloc_blocks has no blocks\n");
> +		err = -EINVAL;
> +		goto err;
> +	}
> +
> +	list_del(&block->link);
> +	list_add_tail(&block->link, &blocks);
> +
> +	/* Should be completely full! */
> +	for (order = max_order; order--; ) {
> +		size = min_page_size = get_size(order, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (!err) {
> +			pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
> +				order);
> +			block = list_first_entry_or_null(&tmp,
> +							 struct drm_buddy_block,
> +							 link);
> +			if (!block) {
> +				pr_err("alloc_blocks has no blocks\n");
> +				err = -EINVAL;
> +				goto err;
> +			}
> +
> +			list_del(&block->link);
> +			list_add_tail(&block->link, &blocks);
> +			err = -EINVAL;
> +			goto err;
> +		}
> +	}
> +
> +	block = list_last_entry(&blocks, typeof(*block), link);
> +	list_del(&block->link);
> +	drm_buddy_free_block(&mm, block);
> +
> +	/* As we free in increasing size, we make available larger blocks */
> +	order = 1;
> +	list_for_each_entry_safe(block, bn, &blocks, link) {
> +		list_del(&block->link);
> +		drm_buddy_free_block(&mm, block);
> +
> +		size = min_page_size = get_size(order, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (err) {
> +			pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
> +				order);
> +			goto err;
> +		}
> +
> +		block = list_first_entry_or_null(&tmp,
> +						 struct drm_buddy_block,
> +						 link);
> +		if (!block) {
> +			pr_err("alloc_blocks has no blocks\n");
> +			err = -EINVAL;
> +			goto err;
> +		}
> +
> +		list_del(&block->link);
> +		drm_buddy_free_block(&mm, block);
> +		order++;
> +	}
> +
> +	/* To confirm, now the whole mm should be available */
> +	size = min_page_size = get_size(max_order, PAGE_SIZE);
> +	err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +	if (err) {
> +		pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
> +			max_order);
> +		goto err;
> +	}
> +
> +	block = list_first_entry_or_null(&tmp,
> +					 struct drm_buddy_block,
> +					 link);
> +	if (!block) {
> +		pr_err("alloc_blocks has no blocks\n");
> +		err = -EINVAL;
> +		goto err;
> +	}
> +
> +	list_del(&block->link);
> +	drm_buddy_free_block(&mm, block);
> +
> +	if (!err)

Always true?

Reviewed-by: Matthew Auld <matthew.auld@intel.com>

> +		pr_info("%s - succeeded\n", __func__);
> +
> +err:
> +	drm_buddy_free_list(&mm, &blocks);
> +	drm_buddy_fini(&mm);
> +	return err;
> +}
> +
>   static int igt_buddy_alloc_optimistic(void *arg)
>   {
>   	u64 mm_size, size, min_page_size, start = 0;

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 6/7] drm/selftests: add drm buddy smoke testcase
  2022-02-03 13:32   ` [Intel-gfx] " Arunpravin
  (?)
@ 2022-02-08 10:22     ` Matthew Auld
  -1 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:22 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig

On 03/02/2022 13:32, Arunpravin wrote:
> - add a test to ascertain that the critical functionalities
>    of the program is working fine
> - add a timeout helper function
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 143 ++++++++++++++++++
>   2 files changed, 144 insertions(+)
> 
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> index b14f04a1de19..411d072cbfc5 100644
> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -11,3 +11,4 @@ selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
>   selftest(buddy_alloc_range, igt_buddy_alloc_range)
>   selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
>   selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
> +selftest(buddy_alloc_smoke, igt_buddy_alloc_smoke)
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> index e97f583ed0cd..2074e8c050a4 100644
> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -7,6 +7,7 @@
>   
>   #include <linux/module.h>
>   #include <linux/prime_numbers.h>
> +#include <linux/sched/signal.h>
>   
>   #include <drm/drm_buddy.h>
>   
> @@ -15,6 +16,9 @@
>   #define TESTS "drm_buddy_selftests.h"
>   #include "drm_selftest.h"
>   
> +#define IGT_TIMEOUT(name__) \
> +	unsigned long name__ = jiffies + MAX_SCHEDULE_TIMEOUT
> +
>   static unsigned int random_seed;
>   
>   static inline u64 get_size(int order, u64 chunk_size)
> @@ -22,6 +26,26 @@ static inline u64 get_size(int order, u64 chunk_size)
>   	return (1 << order) * chunk_size;
>   }
>   
> +__printf(2, 3)
> +static bool __igt_timeout(unsigned long timeout, const char *fmt, ...)
> +{
> +	va_list va;
> +
> +	if (!signal_pending(current)) {
> +		cond_resched();
> +		if (time_before(jiffies, timeout))
> +			return false;
> +	}
> +
> +	if (fmt) {
> +		va_start(va, fmt);
> +		vprintk(fmt, va);
> +		va_end(va);
> +	}
> +
> +	return true;
> +}
> +
>   static inline const char *yesno(bool v)
>   {
>   	return v ? "yes" : "no";
> @@ -314,6 +338,125 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
>   	*size = (u64)s << 12;
>   }
>   
> +static int igt_buddy_alloc_smoke(void *arg)
> +{
> +	u64 mm_size, min_page_size, chunk_size, start = 0;
> +	unsigned long flags = 0;
> +	struct drm_buddy mm;
> +	int *order;
> +	int err, i;
> +
> +	DRM_RND_STATE(prng, random_seed);
> +	IGT_TIMEOUT(end_time);
> +
> +	igt_mm_config(&mm_size, &chunk_size);
> +
> +	err = drm_buddy_init(&mm, mm_size, chunk_size);
> +	if (err) {
> +		pr_err("buddy_init failed(%d)\n", err);
> +		return err;
> +	}
> +
> +	order = drm_random_order(mm.max_order + 1, &prng);
> +	if (!order)
> +		goto out_fini;
> +
> +	for (i = 0; i <= mm.max_order; ++i) {
> +		struct drm_buddy_block *block;
> +		int max_order = order[i];
> +		bool timeout = false;
> +		LIST_HEAD(blocks);
> +		u64 total, size;
> +		LIST_HEAD(tmp);
> +		int order;
> +
> +		err = igt_check_mm(&mm);
> +		if (err) {
> +			pr_err("pre-mm check failed, abort\n");
> +			break;
> +		}
> +
> +		order = max_order;
> +		total = 0;
> +
> +		do {
> +retry:
> +			size = min_page_size = get_size(order, chunk_size);
> +			err = drm_buddy_alloc_blocks(&mm, start, mm_size, size,
> +						     min_page_size, &tmp, flags);
> +			if (err) {
> +				if (err == -ENOMEM) {
> +					pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
> +						order);
> +				} else {
> +					if (order--) {
> +						err = 0;
> +						goto retry;
> +					}
> +
> +					pr_err("buddy_alloc with order=%d failed(%d)\n",
> +					       order, err);
> +				}
> +
> +				break;
> +			}
> +
> +			block = list_first_entry_or_null(&tmp,
> +							 struct drm_buddy_block,
> +							 link);
> +			if (!block) {
> +				pr_err("alloc_blocks has no blocks\n");
> +				err = -EINVAL;
> +				break;
> +			}
> +
> +			list_del(&block->link);
> +			list_add_tail(&block->link, &blocks);

Could just make this list_move_tail()? Elsewhere also.

Anyway,
Reviewed-by: Matthew Auld <matthew.auld@intel.com>

> +
> +			if (drm_buddy_block_order(block) != order) {
> +				pr_err("buddy_alloc order mismatch\n");
> +				err = -EINVAL;
> +				break;
> +			}
> +
> +			total += drm_buddy_block_size(&mm, block);
> +
> +			if (__igt_timeout(end_time, NULL)) {
> +				timeout = true;
> +				break;
> +			}
> +		} while (total < mm.size);
> +
> +		if (!err)
> +			err = igt_check_blocks(&mm, &blocks, total, false);
> +
> +		drm_buddy_free_list(&mm, &blocks);
> +
> +		if (!err) {
> +			err = igt_check_mm(&mm);
> +			if (err)
> +				pr_err("post-mm check failed\n");
> +		}
> +
> +		if (err || timeout)
> +			break;
> +
> +		cond_resched();
> +	}
> +
> +	if (err == -ENOMEM)
> +		err = 0;
> +
> +	if (!err)
> +		pr_info("%s - succeeded\n", __func__);
> +
> +	kfree(order);
> +out_fini:
> +	drm_buddy_fini(&mm);
> +
> +	return err;
> +}
> +
>   static int igt_buddy_alloc_pessimistic(void *arg)
>   {
>   	u64 mm_size, size, min_page_size, start = 0;

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Intel-gfx] [PATCH 6/7] drm/selftests: add drm buddy smoke testcase
@ 2022-02-08 10:22     ` Matthew Auld
  0 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:22 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig

On 03/02/2022 13:32, Arunpravin wrote:
> - add a test to ascertain that the critical functionalities
>    of the program is working fine
> - add a timeout helper function
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 143 ++++++++++++++++++
>   2 files changed, 144 insertions(+)
> 
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> index b14f04a1de19..411d072cbfc5 100644
> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -11,3 +11,4 @@ selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
>   selftest(buddy_alloc_range, igt_buddy_alloc_range)
>   selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
>   selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
> +selftest(buddy_alloc_smoke, igt_buddy_alloc_smoke)
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> index e97f583ed0cd..2074e8c050a4 100644
> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -7,6 +7,7 @@
>   
>   #include <linux/module.h>
>   #include <linux/prime_numbers.h>
> +#include <linux/sched/signal.h>
>   
>   #include <drm/drm_buddy.h>
>   
> @@ -15,6 +16,9 @@
>   #define TESTS "drm_buddy_selftests.h"
>   #include "drm_selftest.h"
>   
> +#define IGT_TIMEOUT(name__) \
> +	unsigned long name__ = jiffies + MAX_SCHEDULE_TIMEOUT
> +
>   static unsigned int random_seed;
>   
>   static inline u64 get_size(int order, u64 chunk_size)
> @@ -22,6 +26,26 @@ static inline u64 get_size(int order, u64 chunk_size)
>   	return (1 << order) * chunk_size;
>   }
>   
> +__printf(2, 3)
> +static bool __igt_timeout(unsigned long timeout, const char *fmt, ...)
> +{
> +	va_list va;
> +
> +	if (!signal_pending(current)) {
> +		cond_resched();
> +		if (time_before(jiffies, timeout))
> +			return false;
> +	}
> +
> +	if (fmt) {
> +		va_start(va, fmt);
> +		vprintk(fmt, va);
> +		va_end(va);
> +	}
> +
> +	return true;
> +}
> +
>   static inline const char *yesno(bool v)
>   {
>   	return v ? "yes" : "no";
> @@ -314,6 +338,125 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
>   	*size = (u64)s << 12;
>   }
>   
> +static int igt_buddy_alloc_smoke(void *arg)
> +{
> +	u64 mm_size, min_page_size, chunk_size, start = 0;
> +	unsigned long flags = 0;
> +	struct drm_buddy mm;
> +	int *order;
> +	int err, i;
> +
> +	DRM_RND_STATE(prng, random_seed);
> +	IGT_TIMEOUT(end_time);
> +
> +	igt_mm_config(&mm_size, &chunk_size);
> +
> +	err = drm_buddy_init(&mm, mm_size, chunk_size);
> +	if (err) {
> +		pr_err("buddy_init failed(%d)\n", err);
> +		return err;
> +	}
> +
> +	order = drm_random_order(mm.max_order + 1, &prng);
> +	if (!order)
> +		goto out_fini;
> +
> +	for (i = 0; i <= mm.max_order; ++i) {
> +		struct drm_buddy_block *block;
> +		int max_order = order[i];
> +		bool timeout = false;
> +		LIST_HEAD(blocks);
> +		u64 total, size;
> +		LIST_HEAD(tmp);
> +		int order;
> +
> +		err = igt_check_mm(&mm);
> +		if (err) {
> +			pr_err("pre-mm check failed, abort\n");
> +			break;
> +		}
> +
> +		order = max_order;
> +		total = 0;
> +
> +		do {
> +retry:
> +			size = min_page_size = get_size(order, chunk_size);
> +			err = drm_buddy_alloc_blocks(&mm, start, mm_size, size,
> +						     min_page_size, &tmp, flags);
> +			if (err) {
> +				if (err == -ENOMEM) {
> +					pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
> +						order);
> +				} else {
> +					if (order--) {
> +						err = 0;
> +						goto retry;
> +					}
> +
> +					pr_err("buddy_alloc with order=%d failed(%d)\n",
> +					       order, err);
> +				}
> +
> +				break;
> +			}
> +
> +			block = list_first_entry_or_null(&tmp,
> +							 struct drm_buddy_block,
> +							 link);
> +			if (!block) {
> +				pr_err("alloc_blocks has no blocks\n");
> +				err = -EINVAL;
> +				break;
> +			}
> +
> +			list_del(&block->link);
> +			list_add_tail(&block->link, &blocks);

Could just make this list_move_tail()? Elsewhere also.

Anyway,
Reviewed-by: Matthew Auld <matthew.auld@intel.com>

> +
> +			if (drm_buddy_block_order(block) != order) {
> +				pr_err("buddy_alloc order mismatch\n");
> +				err = -EINVAL;
> +				break;
> +			}
> +
> +			total += drm_buddy_block_size(&mm, block);
> +
> +			if (__igt_timeout(end_time, NULL)) {
> +				timeout = true;
> +				break;
> +			}
> +		} while (total < mm.size);
> +
> +		if (!err)
> +			err = igt_check_blocks(&mm, &blocks, total, false);
> +
> +		drm_buddy_free_list(&mm, &blocks);
> +
> +		if (!err) {
> +			err = igt_check_mm(&mm);
> +			if (err)
> +				pr_err("post-mm check failed\n");
> +		}
> +
> +		if (err || timeout)
> +			break;
> +
> +		cond_resched();
> +	}
> +
> +	if (err == -ENOMEM)
> +		err = 0;
> +
> +	if (!err)
> +		pr_info("%s - succeeded\n", __func__);
> +
> +	kfree(order);
> +out_fini:
> +	drm_buddy_fini(&mm);
> +
> +	return err;
> +}
> +
>   static int igt_buddy_alloc_pessimistic(void *arg)
>   {
>   	u64 mm_size, size, min_page_size, start = 0;

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 6/7] drm/selftests: add drm buddy smoke testcase
@ 2022-02-08 10:22     ` Matthew Auld
  0 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:22 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig, daniel

On 03/02/2022 13:32, Arunpravin wrote:
> - add a test to ascertain that the critical functionalities
>    of the program is working fine
> - add a timeout helper function
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 143 ++++++++++++++++++
>   2 files changed, 144 insertions(+)
> 
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> index b14f04a1de19..411d072cbfc5 100644
> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -11,3 +11,4 @@ selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
>   selftest(buddy_alloc_range, igt_buddy_alloc_range)
>   selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
>   selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
> +selftest(buddy_alloc_smoke, igt_buddy_alloc_smoke)
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> index e97f583ed0cd..2074e8c050a4 100644
> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -7,6 +7,7 @@
>   
>   #include <linux/module.h>
>   #include <linux/prime_numbers.h>
> +#include <linux/sched/signal.h>
>   
>   #include <drm/drm_buddy.h>
>   
> @@ -15,6 +16,9 @@
>   #define TESTS "drm_buddy_selftests.h"
>   #include "drm_selftest.h"
>   
> +#define IGT_TIMEOUT(name__) \
> +	unsigned long name__ = jiffies + MAX_SCHEDULE_TIMEOUT
> +
>   static unsigned int random_seed;
>   
>   static inline u64 get_size(int order, u64 chunk_size)
> @@ -22,6 +26,26 @@ static inline u64 get_size(int order, u64 chunk_size)
>   	return (1 << order) * chunk_size;
>   }
>   
> +__printf(2, 3)
> +static bool __igt_timeout(unsigned long timeout, const char *fmt, ...)
> +{
> +	va_list va;
> +
> +	if (!signal_pending(current)) {
> +		cond_resched();
> +		if (time_before(jiffies, timeout))
> +			return false;
> +	}
> +
> +	if (fmt) {
> +		va_start(va, fmt);
> +		vprintk(fmt, va);
> +		va_end(va);
> +	}
> +
> +	return true;
> +}
> +
>   static inline const char *yesno(bool v)
>   {
>   	return v ? "yes" : "no";
> @@ -314,6 +338,125 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
>   	*size = (u64)s << 12;
>   }
>   
> +static int igt_buddy_alloc_smoke(void *arg)
> +{
> +	u64 mm_size, min_page_size, chunk_size, start = 0;
> +	unsigned long flags = 0;
> +	struct drm_buddy mm;
> +	int *order;
> +	int err, i;
> +
> +	DRM_RND_STATE(prng, random_seed);
> +	IGT_TIMEOUT(end_time);
> +
> +	igt_mm_config(&mm_size, &chunk_size);
> +
> +	err = drm_buddy_init(&mm, mm_size, chunk_size);
> +	if (err) {
> +		pr_err("buddy_init failed(%d)\n", err);
> +		return err;
> +	}
> +
> +	order = drm_random_order(mm.max_order + 1, &prng);
> +	if (!order)
> +		goto out_fini;
> +
> +	for (i = 0; i <= mm.max_order; ++i) {
> +		struct drm_buddy_block *block;
> +		int max_order = order[i];
> +		bool timeout = false;
> +		LIST_HEAD(blocks);
> +		u64 total, size;
> +		LIST_HEAD(tmp);
> +		int order;
> +
> +		err = igt_check_mm(&mm);
> +		if (err) {
> +			pr_err("pre-mm check failed, abort\n");
> +			break;
> +		}
> +
> +		order = max_order;
> +		total = 0;
> +
> +		do {
> +retry:
> +			size = min_page_size = get_size(order, chunk_size);
> +			err = drm_buddy_alloc_blocks(&mm, start, mm_size, size,
> +						     min_page_size, &tmp, flags);
> +			if (err) {
> +				if (err == -ENOMEM) {
> +					pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
> +						order);
> +				} else {
> +					if (order--) {
> +						err = 0;
> +						goto retry;
> +					}
> +
> +					pr_err("buddy_alloc with order=%d failed(%d)\n",
> +					       order, err);
> +				}
> +
> +				break;
> +			}
> +
> +			block = list_first_entry_or_null(&tmp,
> +							 struct drm_buddy_block,
> +							 link);
> +			if (!block) {
> +				pr_err("alloc_blocks has no blocks\n");
> +				err = -EINVAL;
> +				break;
> +			}
> +
> +			list_del(&block->link);
> +			list_add_tail(&block->link, &blocks);

Could just make this list_move_tail()? Elsewhere also.

Anyway,
Reviewed-by: Matthew Auld <matthew.auld@intel.com>

> +
> +			if (drm_buddy_block_order(block) != order) {
> +				pr_err("buddy_alloc order mismatch\n");
> +				err = -EINVAL;
> +				break;
> +			}
> +
> +			total += drm_buddy_block_size(&mm, block);
> +
> +			if (__igt_timeout(end_time, NULL)) {
> +				timeout = true;
> +				break;
> +			}
> +		} while (total < mm.size);
> +
> +		if (!err)
> +			err = igt_check_blocks(&mm, &blocks, total, false);
> +
> +		drm_buddy_free_list(&mm, &blocks);
> +
> +		if (!err) {
> +			err = igt_check_mm(&mm);
> +			if (err)
> +				pr_err("post-mm check failed\n");
> +		}
> +
> +		if (err || timeout)
> +			break;
> +
> +		cond_resched();
> +	}
> +
> +	if (err == -ENOMEM)
> +		err = 0;
> +
> +	if (!err)
> +		pr_info("%s - succeeded\n", __func__);
> +
> +	kfree(order);
> +out_fini:
> +	drm_buddy_fini(&mm);
> +
> +	return err;
> +}
> +
>   static int igt_buddy_alloc_pessimistic(void *arg)
>   {
>   	u64 mm_size, size, min_page_size, start = 0;

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 7/7] drm/selftests: add drm buddy pathological testcase
  2022-02-03 13:32   ` [Intel-gfx] " Arunpravin
  (?)
@ 2022-02-08 10:26     ` Matthew Auld
  -1 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:26 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig

On 03/02/2022 13:32, Arunpravin wrote:
> create a pot-sized mm, then allocate one of each possible
> order within. This should leave the mm with exactly one
> page left. Free the largest block, then whittle down again.
> Eventually we will have a fully 50% fragmented mm.
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 136 ++++++++++++++++++
>   2 files changed, 137 insertions(+)
> 
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> index 411d072cbfc5..455b756c4ae5 100644
> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -12,3 +12,4 @@ selftest(buddy_alloc_range, igt_buddy_alloc_range)
>   selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
>   selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
>   selftest(buddy_alloc_smoke, igt_buddy_alloc_smoke)
> +selftest(buddy_alloc_pathological, igt_buddy_alloc_pathological)
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> index 2074e8c050a4..b2d0313a4bc5 100644
> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -338,6 +338,142 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
>   	*size = (u64)s << 12;
>   }
>   
> +static int igt_buddy_alloc_pathological(void *arg)
> +{
> +	u64 mm_size, size, min_page_size, start = 0;
> +	struct drm_buddy_block *block;
> +	const int max_order = 3;
> +	unsigned long flags = 0;
> +	int order, top, err;
> +	struct drm_buddy mm;
> +	LIST_HEAD(blocks);
> +	LIST_HEAD(holes);
> +	LIST_HEAD(tmp);
> +
> +	/*
> +	 * Create a pot-sized mm, then allocate one of each possible
> +	 * order within. This should leave the mm with exactly one
> +	 * page left. Free the largest block, then whittle down again.
> +	 * Eventually we will have a fully 50% fragmented mm.
> +	 */
> +
> +	mm_size = PAGE_SIZE << max_order;
> +	err = drm_buddy_init(&mm, mm_size, PAGE_SIZE);
> +	if (err) {
> +		pr_err("buddy_init failed(%d)\n", err);
> +		return err;
> +	}
> +	BUG_ON(mm.max_order != max_order);
> +
> +	for (top = max_order; top; top--) {
> +		/* Make room by freeing the largest allocated block */
> +		block = list_first_entry_or_null(&blocks, typeof(*block), link);
> +		if (block) {
> +			list_del(&block->link);
> +			drm_buddy_free_block(&mm, block);
> +		}
> +
> +		for (order = top; order--; ) {
> +			size = min_page_size = get_size(order, PAGE_SIZE);
> +			err = drm_buddy_alloc_blocks(&mm, start, mm_size, size,
> +						     min_page_size, &tmp, flags);
> +			if (err) {
> +				pr_info("buddy_alloc hit -ENOMEM with order=%d, top=%d\n",
> +					order, top);
> +				goto err;
> +			}
> +
> +			block = list_first_entry_or_null(&tmp,
> +							 struct drm_buddy_block,
> +							 link);
> +			if (!block) {
> +				pr_err("alloc_blocks has no blocks\n");
> +				err = -EINVAL;
> +				goto err;
> +			}
> +
> +			list_del(&block->link);
> +			list_add_tail(&block->link, &blocks);
> +		}
> +
> +		/* There should be one final page for this sub-allocation */
> +		size = min_page_size = get_size(0, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (err) {
> +			pr_info("buddy_alloc hit -ENOME for hole\n");

ENOMEM

Reviewed-by: Matthew Auld <matthew.auld@intel.com>

> +			goto err;
> +		}
> +
> +		block = list_first_entry_or_null(&tmp,
> +						 struct drm_buddy_block,
> +						 link);
> +		if (!block) {
> +			pr_err("alloc_blocks has no blocks\n");
> +			err = -EINVAL;
> +			goto err;
> +		}
> +
> +		list_del(&block->link);
> +		list_add_tail(&block->link, &holes);
> +
> +		size = min_page_size = get_size(top, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (!err) {
> +			pr_info("buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!",
> +				top, max_order);
> +			block = list_first_entry_or_null(&tmp,
> +							 struct drm_buddy_block,
> +							 link);
> +			if (!block) {
> +				pr_err("alloc_blocks has no blocks\n");
> +				err = -EINVAL;
> +				goto err;
> +			}
> +
> +			list_del(&block->link);
> +			list_add_tail(&block->link, &blocks);
> +			err = -EINVAL;
> +			goto err;
> +		}
> +	}
> +
> +	drm_buddy_free_list(&mm, &holes);
> +
> +	/* Nothing larger than blocks of chunk_size now available */
> +	for (order = 1; order <= max_order; order++) {
> +		size = min_page_size = get_size(order, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (!err) {
> +			pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
> +				order);
> +			block = list_first_entry_or_null(&tmp,
> +							 struct drm_buddy_block,
> +							 link);
> +			if (!block) {
> +				pr_err("alloc_blocks has no blocks\n");
> +				err = -EINVAL;
> +				goto err;
> +			}
> +
> +			list_del(&block->link);
> +			list_add_tail(&block->link, &blocks);
> +			err = -EINVAL;
> +			goto err;
> +		}
> +	}
> +
> +	if (err) {
> +		pr_info("%s - succeeded\n", __func__);
> +		err = 0;
> +	}
> +
> +err:
> +	list_splice_tail(&holes, &blocks);
> +	drm_buddy_free_list(&mm, &blocks);
> +	drm_buddy_fini(&mm);
> +	return err;
> +}
> +
>   static int igt_buddy_alloc_smoke(void *arg)
>   {
>   	u64 mm_size, min_page_size, chunk_size, start = 0;

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Intel-gfx] [PATCH 7/7] drm/selftests: add drm buddy pathological testcase
@ 2022-02-08 10:26     ` Matthew Auld
  0 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:26 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig

On 03/02/2022 13:32, Arunpravin wrote:
> create a pot-sized mm, then allocate one of each possible
> order within. This should leave the mm with exactly one
> page left. Free the largest block, then whittle down again.
> Eventually we will have a fully 50% fragmented mm.
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 136 ++++++++++++++++++
>   2 files changed, 137 insertions(+)
> 
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> index 411d072cbfc5..455b756c4ae5 100644
> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -12,3 +12,4 @@ selftest(buddy_alloc_range, igt_buddy_alloc_range)
>   selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
>   selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
>   selftest(buddy_alloc_smoke, igt_buddy_alloc_smoke)
> +selftest(buddy_alloc_pathological, igt_buddy_alloc_pathological)
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> index 2074e8c050a4..b2d0313a4bc5 100644
> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -338,6 +338,142 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
>   	*size = (u64)s << 12;
>   }
>   
> +static int igt_buddy_alloc_pathological(void *arg)
> +{
> +	u64 mm_size, size, min_page_size, start = 0;
> +	struct drm_buddy_block *block;
> +	const int max_order = 3;
> +	unsigned long flags = 0;
> +	int order, top, err;
> +	struct drm_buddy mm;
> +	LIST_HEAD(blocks);
> +	LIST_HEAD(holes);
> +	LIST_HEAD(tmp);
> +
> +	/*
> +	 * Create a pot-sized mm, then allocate one of each possible
> +	 * order within. This should leave the mm with exactly one
> +	 * page left. Free the largest block, then whittle down again.
> +	 * Eventually we will have a fully 50% fragmented mm.
> +	 */
> +
> +	mm_size = PAGE_SIZE << max_order;
> +	err = drm_buddy_init(&mm, mm_size, PAGE_SIZE);
> +	if (err) {
> +		pr_err("buddy_init failed(%d)\n", err);
> +		return err;
> +	}
> +	BUG_ON(mm.max_order != max_order);
> +
> +	for (top = max_order; top; top--) {
> +		/* Make room by freeing the largest allocated block */
> +		block = list_first_entry_or_null(&blocks, typeof(*block), link);
> +		if (block) {
> +			list_del(&block->link);
> +			drm_buddy_free_block(&mm, block);
> +		}
> +
> +		for (order = top; order--; ) {
> +			size = min_page_size = get_size(order, PAGE_SIZE);
> +			err = drm_buddy_alloc_blocks(&mm, start, mm_size, size,
> +						     min_page_size, &tmp, flags);
> +			if (err) {
> +				pr_info("buddy_alloc hit -ENOMEM with order=%d, top=%d\n",
> +					order, top);
> +				goto err;
> +			}
> +
> +			block = list_first_entry_or_null(&tmp,
> +							 struct drm_buddy_block,
> +							 link);
> +			if (!block) {
> +				pr_err("alloc_blocks has no blocks\n");
> +				err = -EINVAL;
> +				goto err;
> +			}
> +
> +			list_del(&block->link);
> +			list_add_tail(&block->link, &blocks);
> +		}
> +
> +		/* There should be one final page for this sub-allocation */
> +		size = min_page_size = get_size(0, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (err) {
> +			pr_info("buddy_alloc hit -ENOME for hole\n");

ENOMEM

Reviewed-by: Matthew Auld <matthew.auld@intel.com>

> +			goto err;
> +		}
> +
> +		block = list_first_entry_or_null(&tmp,
> +						 struct drm_buddy_block,
> +						 link);
> +		if (!block) {
> +			pr_err("alloc_blocks has no blocks\n");
> +			err = -EINVAL;
> +			goto err;
> +		}
> +
> +		list_del(&block->link);
> +		list_add_tail(&block->link, &holes);
> +
> +		size = min_page_size = get_size(top, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (!err) {
> +			pr_info("buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!",
> +				top, max_order);
> +			block = list_first_entry_or_null(&tmp,
> +							 struct drm_buddy_block,
> +							 link);
> +			if (!block) {
> +				pr_err("alloc_blocks has no blocks\n");
> +				err = -EINVAL;
> +				goto err;
> +			}
> +
> +			list_del(&block->link);
> +			list_add_tail(&block->link, &blocks);
> +			err = -EINVAL;
> +			goto err;
> +		}
> +	}
> +
> +	drm_buddy_free_list(&mm, &holes);
> +
> +	/* Nothing larger than blocks of chunk_size now available */
> +	for (order = 1; order <= max_order; order++) {
> +		size = min_page_size = get_size(order, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (!err) {
> +			pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
> +				order);
> +			block = list_first_entry_or_null(&tmp,
> +							 struct drm_buddy_block,
> +							 link);
> +			if (!block) {
> +				pr_err("alloc_blocks has no blocks\n");
> +				err = -EINVAL;
> +				goto err;
> +			}
> +
> +			list_del(&block->link);
> +			list_add_tail(&block->link, &blocks);
> +			err = -EINVAL;
> +			goto err;
> +		}
> +	}
> +
> +	if (err) {
> +		pr_info("%s - succeeded\n", __func__);
> +		err = 0;
> +	}
> +
> +err:
> +	list_splice_tail(&holes, &blocks);
> +	drm_buddy_free_list(&mm, &blocks);
> +	drm_buddy_fini(&mm);
> +	return err;
> +}
> +
>   static int igt_buddy_alloc_smoke(void *arg)
>   {
>   	u64 mm_size, min_page_size, chunk_size, start = 0;

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 7/7] drm/selftests: add drm buddy pathological testcase
@ 2022-02-08 10:26     ` Matthew Auld
  0 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:26 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig, daniel

On 03/02/2022 13:32, Arunpravin wrote:
> create a pot-sized mm, then allocate one of each possible
> order within. This should leave the mm with exactly one
> page left. Free the largest block, then whittle down again.
> Eventually we will have a fully 50% fragmented mm.
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |   1 +
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 136 ++++++++++++++++++
>   2 files changed, 137 insertions(+)
> 
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> index 411d072cbfc5..455b756c4ae5 100644
> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -12,3 +12,4 @@ selftest(buddy_alloc_range, igt_buddy_alloc_range)
>   selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
>   selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
>   selftest(buddy_alloc_smoke, igt_buddy_alloc_smoke)
> +selftest(buddy_alloc_pathological, igt_buddy_alloc_pathological)
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> index 2074e8c050a4..b2d0313a4bc5 100644
> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -338,6 +338,142 @@ static void igt_mm_config(u64 *size, u64 *chunk_size)
>   	*size = (u64)s << 12;
>   }
>   
> +static int igt_buddy_alloc_pathological(void *arg)
> +{
> +	u64 mm_size, size, min_page_size, start = 0;
> +	struct drm_buddy_block *block;
> +	const int max_order = 3;
> +	unsigned long flags = 0;
> +	int order, top, err;
> +	struct drm_buddy mm;
> +	LIST_HEAD(blocks);
> +	LIST_HEAD(holes);
> +	LIST_HEAD(tmp);
> +
> +	/*
> +	 * Create a pot-sized mm, then allocate one of each possible
> +	 * order within. This should leave the mm with exactly one
> +	 * page left. Free the largest block, then whittle down again.
> +	 * Eventually we will have a fully 50% fragmented mm.
> +	 */
> +
> +	mm_size = PAGE_SIZE << max_order;
> +	err = drm_buddy_init(&mm, mm_size, PAGE_SIZE);
> +	if (err) {
> +		pr_err("buddy_init failed(%d)\n", err);
> +		return err;
> +	}
> +	BUG_ON(mm.max_order != max_order);
> +
> +	for (top = max_order; top; top--) {
> +		/* Make room by freeing the largest allocated block */
> +		block = list_first_entry_or_null(&blocks, typeof(*block), link);
> +		if (block) {
> +			list_del(&block->link);
> +			drm_buddy_free_block(&mm, block);
> +		}
> +
> +		for (order = top; order--; ) {
> +			size = min_page_size = get_size(order, PAGE_SIZE);
> +			err = drm_buddy_alloc_blocks(&mm, start, mm_size, size,
> +						     min_page_size, &tmp, flags);
> +			if (err) {
> +				pr_info("buddy_alloc hit -ENOMEM with order=%d, top=%d\n",
> +					order, top);
> +				goto err;
> +			}
> +
> +			block = list_first_entry_or_null(&tmp,
> +							 struct drm_buddy_block,
> +							 link);
> +			if (!block) {
> +				pr_err("alloc_blocks has no blocks\n");
> +				err = -EINVAL;
> +				goto err;
> +			}
> +
> +			list_del(&block->link);
> +			list_add_tail(&block->link, &blocks);
> +		}
> +
> +		/* There should be one final page for this sub-allocation */
> +		size = min_page_size = get_size(0, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (err) {
> +			pr_info("buddy_alloc hit -ENOME for hole\n");

ENOMEM

Reviewed-by: Matthew Auld <matthew.auld@intel.com>

> +			goto err;
> +		}
> +
> +		block = list_first_entry_or_null(&tmp,
> +						 struct drm_buddy_block,
> +						 link);
> +		if (!block) {
> +			pr_err("alloc_blocks has no blocks\n");
> +			err = -EINVAL;
> +			goto err;
> +		}
> +
> +		list_del(&block->link);
> +		list_add_tail(&block->link, &holes);
> +
> +		size = min_page_size = get_size(top, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (!err) {
> +			pr_info("buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!",
> +				top, max_order);
> +			block = list_first_entry_or_null(&tmp,
> +							 struct drm_buddy_block,
> +							 link);
> +			if (!block) {
> +				pr_err("alloc_blocks has no blocks\n");
> +				err = -EINVAL;
> +				goto err;
> +			}
> +
> +			list_del(&block->link);
> +			list_add_tail(&block->link, &blocks);
> +			err = -EINVAL;
> +			goto err;
> +		}
> +	}
> +
> +	drm_buddy_free_list(&mm, &holes);
> +
> +	/* Nothing larger than blocks of chunk_size now available */
> +	for (order = 1; order <= max_order; order++) {
> +		size = min_page_size = get_size(order, PAGE_SIZE);
> +		err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
> +		if (!err) {
> +			pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
> +				order);
> +			block = list_first_entry_or_null(&tmp,
> +							 struct drm_buddy_block,
> +							 link);
> +			if (!block) {
> +				pr_err("alloc_blocks has no blocks\n");
> +				err = -EINVAL;
> +				goto err;
> +			}
> +
> +			list_del(&block->link);
> +			list_add_tail(&block->link, &blocks);
> +			err = -EINVAL;
> +			goto err;
> +		}
> +	}
> +
> +	if (err) {
> +		pr_info("%s - succeeded\n", __func__);
> +		err = 0;
> +	}
> +
> +err:
> +	list_splice_tail(&holes, &blocks);
> +	drm_buddy_free_list(&mm, &blocks);
> +	drm_buddy_fini(&mm);
> +	return err;
> +}
> +
>   static int igt_buddy_alloc_smoke(void *arg)
>   {
>   	u64 mm_size, min_page_size, chunk_size, start = 0;

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 1/7] drm/selftests: Move i915 buddy selftests into drm
  2022-02-03 13:32 ` [Intel-gfx] " Arunpravin
  (?)
@ 2022-02-08 10:35   ` Matthew Auld
  -1 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:35 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig

On 03/02/2022 13:32, Arunpravin wrote:
> - move i915 buddy selftests into drm selftests folder
> - add Makefile and Kconfig support
> - add sanitycheck testcase
> 
> Prerequisites
> - These series of selftests patches are created on top of
>    drm buddy series
> - Enable kselftests for DRM as a module in .config
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>

At some point I guess we also want some IGT that picks this up? Like we 
do in tests/drm_mm.c? That way this can get picked up by CI?

Acked-by: Matthew Auld <matthew.auld@intel.com>

> ---
>   drivers/gpu/drm/Kconfig                       |  1 +
>   drivers/gpu/drm/selftests/Makefile            |  3 +-
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |  9 ++++
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 49 +++++++++++++++++++
>   4 files changed, 61 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/gpu/drm/selftests/drm_buddy_selftests.h
>   create mode 100644 drivers/gpu/drm/selftests/test-drm_buddy.c
> 
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index eb5a57ae3c5c..ff856df3f97f 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -71,6 +71,7 @@ config DRM_DEBUG_SELFTEST
>   	select DRM_DP_HELPER
>   	select DRM_LIB_RANDOM
>   	select DRM_KMS_HELPER
> +	select DRM_BUDDY
>   	select DRM_EXPORT_FOR_TESTS if m
>   	default n
>   	help
> diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile
> index 0856e4b12f70..5ba5f9138c95 100644
> --- a/drivers/gpu/drm/selftests/Makefile
> +++ b/drivers/gpu/drm/selftests/Makefile
> @@ -4,4 +4,5 @@ test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
>   		      test-drm_damage_helper.o test-drm_dp_mst_helper.o \
>   		      test-drm_rect.o
>   
> -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o
> +obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o \
> +				    test-drm_buddy.o
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> new file mode 100644
> index 000000000000..a4bcf3a6dfe3
> --- /dev/null
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -0,0 +1,9 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* List each unit test as selftest(name, function)
> + *
> + * The name is used as both an enum and expanded as igt__name to create
> + * a module parameter. It must be unique and legal for a C identifier.
> + *
> + * Tests are executed in order by igt/drm_buddy
> + */
> +selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> new file mode 100644
> index 000000000000..51e4d393d22c
> --- /dev/null
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -0,0 +1,49 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2019 Intel Corporation
> + */
> +
> +#define pr_fmt(fmt) "drm_buddy: " fmt
> +
> +#include <linux/module.h>
> +
> +#include <drm/drm_buddy.h>
> +
> +#include "../lib/drm_random.h"
> +
> +#define TESTS "drm_buddy_selftests.h"
> +#include "drm_selftest.h"
> +
> +static unsigned int random_seed;
> +
> +static int igt_sanitycheck(void *ignored)
> +{
> +	pr_info("%s - ok!\n", __func__);
> +	return 0;
> +}
> +
> +#include "drm_selftest.c"
> +
> +static int __init test_drm_buddy_init(void)
> +{
> +	int err;
> +
> +	while (!random_seed)
> +		random_seed = get_random_int();
> +
> +	pr_info("Testing DRM buddy manager (struct drm_buddy), with random_seed=0x%x\n",
> +		random_seed);
> +	err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
> +
> +	return err > 0 ? 0 : err;
> +}
> +
> +static void __exit test_drm_buddy_exit(void)
> +{
> +}
> +
> +module_init(test_drm_buddy_init);
> +module_exit(test_drm_buddy_exit);
> +
> +MODULE_AUTHOR("Intel Corporation");
> +MODULE_LICENSE("GPL");

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Intel-gfx] [PATCH 1/7] drm/selftests: Move i915 buddy selftests into drm
@ 2022-02-08 10:35   ` Matthew Auld
  0 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:35 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig

On 03/02/2022 13:32, Arunpravin wrote:
> - move i915 buddy selftests into drm selftests folder
> - add Makefile and Kconfig support
> - add sanitycheck testcase
> 
> Prerequisites
> - These series of selftests patches are created on top of
>    drm buddy series
> - Enable kselftests for DRM as a module in .config
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>

At some point I guess we also want some IGT that picks this up? Like we 
do in tests/drm_mm.c? That way this can get picked up by CI?

Acked-by: Matthew Auld <matthew.auld@intel.com>

> ---
>   drivers/gpu/drm/Kconfig                       |  1 +
>   drivers/gpu/drm/selftests/Makefile            |  3 +-
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |  9 ++++
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 49 +++++++++++++++++++
>   4 files changed, 61 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/gpu/drm/selftests/drm_buddy_selftests.h
>   create mode 100644 drivers/gpu/drm/selftests/test-drm_buddy.c
> 
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index eb5a57ae3c5c..ff856df3f97f 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -71,6 +71,7 @@ config DRM_DEBUG_SELFTEST
>   	select DRM_DP_HELPER
>   	select DRM_LIB_RANDOM
>   	select DRM_KMS_HELPER
> +	select DRM_BUDDY
>   	select DRM_EXPORT_FOR_TESTS if m
>   	default n
>   	help
> diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile
> index 0856e4b12f70..5ba5f9138c95 100644
> --- a/drivers/gpu/drm/selftests/Makefile
> +++ b/drivers/gpu/drm/selftests/Makefile
> @@ -4,4 +4,5 @@ test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
>   		      test-drm_damage_helper.o test-drm_dp_mst_helper.o \
>   		      test-drm_rect.o
>   
> -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o
> +obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o \
> +				    test-drm_buddy.o
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> new file mode 100644
> index 000000000000..a4bcf3a6dfe3
> --- /dev/null
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -0,0 +1,9 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* List each unit test as selftest(name, function)
> + *
> + * The name is used as both an enum and expanded as igt__name to create
> + * a module parameter. It must be unique and legal for a C identifier.
> + *
> + * Tests are executed in order by igt/drm_buddy
> + */
> +selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> new file mode 100644
> index 000000000000..51e4d393d22c
> --- /dev/null
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -0,0 +1,49 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2019 Intel Corporation
> + */
> +
> +#define pr_fmt(fmt) "drm_buddy: " fmt
> +
> +#include <linux/module.h>
> +
> +#include <drm/drm_buddy.h>
> +
> +#include "../lib/drm_random.h"
> +
> +#define TESTS "drm_buddy_selftests.h"
> +#include "drm_selftest.h"
> +
> +static unsigned int random_seed;
> +
> +static int igt_sanitycheck(void *ignored)
> +{
> +	pr_info("%s - ok!\n", __func__);
> +	return 0;
> +}
> +
> +#include "drm_selftest.c"
> +
> +static int __init test_drm_buddy_init(void)
> +{
> +	int err;
> +
> +	while (!random_seed)
> +		random_seed = get_random_int();
> +
> +	pr_info("Testing DRM buddy manager (struct drm_buddy), with random_seed=0x%x\n",
> +		random_seed);
> +	err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
> +
> +	return err > 0 ? 0 : err;
> +}
> +
> +static void __exit test_drm_buddy_exit(void)
> +{
> +}
> +
> +module_init(test_drm_buddy_init);
> +module_exit(test_drm_buddy_exit);
> +
> +MODULE_AUTHOR("Intel Corporation");
> +MODULE_LICENSE("GPL");

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 1/7] drm/selftests: Move i915 buddy selftests into drm
@ 2022-02-08 10:35   ` Matthew Auld
  0 siblings, 0 replies; 52+ messages in thread
From: Matthew Auld @ 2022-02-08 10:35 UTC (permalink / raw)
  To: Arunpravin, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig, daniel

On 03/02/2022 13:32, Arunpravin wrote:
> - move i915 buddy selftests into drm selftests folder
> - add Makefile and Kconfig support
> - add sanitycheck testcase
> 
> Prerequisites
> - These series of selftests patches are created on top of
>    drm buddy series
> - Enable kselftests for DRM as a module in .config
> 
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>

At some point I guess we also want some IGT that picks this up? Like we 
do in tests/drm_mm.c? That way this can get picked up by CI?

Acked-by: Matthew Auld <matthew.auld@intel.com>

> ---
>   drivers/gpu/drm/Kconfig                       |  1 +
>   drivers/gpu/drm/selftests/Makefile            |  3 +-
>   .../gpu/drm/selftests/drm_buddy_selftests.h   |  9 ++++
>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 49 +++++++++++++++++++
>   4 files changed, 61 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/gpu/drm/selftests/drm_buddy_selftests.h
>   create mode 100644 drivers/gpu/drm/selftests/test-drm_buddy.c
> 
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index eb5a57ae3c5c..ff856df3f97f 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -71,6 +71,7 @@ config DRM_DEBUG_SELFTEST
>   	select DRM_DP_HELPER
>   	select DRM_LIB_RANDOM
>   	select DRM_KMS_HELPER
> +	select DRM_BUDDY
>   	select DRM_EXPORT_FOR_TESTS if m
>   	default n
>   	help
> diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile
> index 0856e4b12f70..5ba5f9138c95 100644
> --- a/drivers/gpu/drm/selftests/Makefile
> +++ b/drivers/gpu/drm/selftests/Makefile
> @@ -4,4 +4,5 @@ test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
>   		      test-drm_damage_helper.o test-drm_dp_mst_helper.o \
>   		      test-drm_rect.o
>   
> -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o
> +obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o \
> +				    test-drm_buddy.o
> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> new file mode 100644
> index 000000000000..a4bcf3a6dfe3
> --- /dev/null
> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
> @@ -0,0 +1,9 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* List each unit test as selftest(name, function)
> + *
> + * The name is used as both an enum and expanded as igt__name to create
> + * a module parameter. It must be unique and legal for a C identifier.
> + *
> + * Tests are executed in order by igt/drm_buddy
> + */
> +selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
> new file mode 100644
> index 000000000000..51e4d393d22c
> --- /dev/null
> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
> @@ -0,0 +1,49 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2019 Intel Corporation
> + */
> +
> +#define pr_fmt(fmt) "drm_buddy: " fmt
> +
> +#include <linux/module.h>
> +
> +#include <drm/drm_buddy.h>
> +
> +#include "../lib/drm_random.h"
> +
> +#define TESTS "drm_buddy_selftests.h"
> +#include "drm_selftest.h"
> +
> +static unsigned int random_seed;
> +
> +static int igt_sanitycheck(void *ignored)
> +{
> +	pr_info("%s - ok!\n", __func__);
> +	return 0;
> +}
> +
> +#include "drm_selftest.c"
> +
> +static int __init test_drm_buddy_init(void)
> +{
> +	int err;
> +
> +	while (!random_seed)
> +		random_seed = get_random_int();
> +
> +	pr_info("Testing DRM buddy manager (struct drm_buddy), with random_seed=0x%x\n",
> +		random_seed);
> +	err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
> +
> +	return err > 0 ? 0 : err;
> +}
> +
> +static void __exit test_drm_buddy_exit(void)
> +{
> +}
> +
> +module_init(test_drm_buddy_init);
> +module_exit(test_drm_buddy_exit);
> +
> +MODULE_AUTHOR("Intel Corporation");
> +MODULE_LICENSE("GPL");

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 1/7] drm/selftests: Move i915 buddy selftests into drm
  2022-02-08 10:35   ` [Intel-gfx] " Matthew Auld
  (?)
@ 2022-02-22 18:35     ` Arunpravin
  -1 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-22 18:35 UTC (permalink / raw)
  To: Matthew Auld, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig



On 08/02/22 4:05 pm, Matthew Auld wrote:
> On 03/02/2022 13:32, Arunpravin wrote:
>> - move i915 buddy selftests into drm selftests folder
>> - add Makefile and Kconfig support
>> - add sanitycheck testcase
>>
>> Prerequisites
>> - These series of selftests patches are created on top of
>>    drm buddy series
>> - Enable kselftests for DRM as a module in .config
>>
>> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> 
> At some point I guess we also want some IGT that picks this up? Like we 
> do in tests/drm_mm.c? That way this can get picked up by CI?

igt-gpu-tools? we need to create tests/drm_buddy.c to pick these tests.
I will create a patch to include drm buddy selftests into igt-gpu-tools
> 
> Acked-by: Matthew Auld <matthew.auld@intel.com>
> 
>> ---
>>   drivers/gpu/drm/Kconfig                       |  1 +
>>   drivers/gpu/drm/selftests/Makefile            |  3 +-
>>   .../gpu/drm/selftests/drm_buddy_selftests.h   |  9 ++++
>>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 49 +++++++++++++++++++
>>   4 files changed, 61 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/gpu/drm/selftests/drm_buddy_selftests.h
>>   create mode 100644 drivers/gpu/drm/selftests/test-drm_buddy.c
>>
>> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
>> index eb5a57ae3c5c..ff856df3f97f 100644
>> --- a/drivers/gpu/drm/Kconfig
>> +++ b/drivers/gpu/drm/Kconfig
>> @@ -71,6 +71,7 @@ config DRM_DEBUG_SELFTEST
>>   	select DRM_DP_HELPER
>>   	select DRM_LIB_RANDOM
>>   	select DRM_KMS_HELPER
>> +	select DRM_BUDDY
>>   	select DRM_EXPORT_FOR_TESTS if m
>>   	default n
>>   	help
>> diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile
>> index 0856e4b12f70..5ba5f9138c95 100644
>> --- a/drivers/gpu/drm/selftests/Makefile
>> +++ b/drivers/gpu/drm/selftests/Makefile
>> @@ -4,4 +4,5 @@ test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
>>   		      test-drm_damage_helper.o test-drm_dp_mst_helper.o \
>>   		      test-drm_rect.o
>>   
>> -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o
>> +obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o \
>> +				    test-drm_buddy.o
>> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
>> new file mode 100644
>> index 000000000000..a4bcf3a6dfe3
>> --- /dev/null
>> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
>> @@ -0,0 +1,9 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/* List each unit test as selftest(name, function)
>> + *
>> + * The name is used as both an enum and expanded as igt__name to create
>> + * a module parameter. It must be unique and legal for a C identifier.
>> + *
>> + * Tests are executed in order by igt/drm_buddy
>> + */
>> +selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
>> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
>> new file mode 100644
>> index 000000000000..51e4d393d22c
>> --- /dev/null
>> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
>> @@ -0,0 +1,49 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright © 2019 Intel Corporation
>> + */
>> +
>> +#define pr_fmt(fmt) "drm_buddy: " fmt
>> +
>> +#include <linux/module.h>
>> +
>> +#include <drm/drm_buddy.h>
>> +
>> +#include "../lib/drm_random.h"
>> +
>> +#define TESTS "drm_buddy_selftests.h"
>> +#include "drm_selftest.h"
>> +
>> +static unsigned int random_seed;
>> +
>> +static int igt_sanitycheck(void *ignored)
>> +{
>> +	pr_info("%s - ok!\n", __func__);
>> +	return 0;
>> +}
>> +
>> +#include "drm_selftest.c"
>> +
>> +static int __init test_drm_buddy_init(void)
>> +{
>> +	int err;
>> +
>> +	while (!random_seed)
>> +		random_seed = get_random_int();
>> +
>> +	pr_info("Testing DRM buddy manager (struct drm_buddy), with random_seed=0x%x\n",
>> +		random_seed);
>> +	err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
>> +
>> +	return err > 0 ? 0 : err;
>> +}
>> +
>> +static void __exit test_drm_buddy_exit(void)
>> +{
>> +}
>> +
>> +module_init(test_drm_buddy_init);
>> +module_exit(test_drm_buddy_exit);
>> +
>> +MODULE_AUTHOR("Intel Corporation");
>> +MODULE_LICENSE("GPL");

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Intel-gfx] [PATCH 1/7] drm/selftests: Move i915 buddy selftests into drm
@ 2022-02-22 18:35     ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-22 18:35 UTC (permalink / raw)
  To: Matthew Auld, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig



On 08/02/22 4:05 pm, Matthew Auld wrote:
> On 03/02/2022 13:32, Arunpravin wrote:
>> - move i915 buddy selftests into drm selftests folder
>> - add Makefile and Kconfig support
>> - add sanitycheck testcase
>>
>> Prerequisites
>> - These series of selftests patches are created on top of
>>    drm buddy series
>> - Enable kselftests for DRM as a module in .config
>>
>> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> 
> At some point I guess we also want some IGT that picks this up? Like we 
> do in tests/drm_mm.c? That way this can get picked up by CI?

igt-gpu-tools? we need to create tests/drm_buddy.c to pick these tests.
I will create a patch to include drm buddy selftests into igt-gpu-tools
> 
> Acked-by: Matthew Auld <matthew.auld@intel.com>
> 
>> ---
>>   drivers/gpu/drm/Kconfig                       |  1 +
>>   drivers/gpu/drm/selftests/Makefile            |  3 +-
>>   .../gpu/drm/selftests/drm_buddy_selftests.h   |  9 ++++
>>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 49 +++++++++++++++++++
>>   4 files changed, 61 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/gpu/drm/selftests/drm_buddy_selftests.h
>>   create mode 100644 drivers/gpu/drm/selftests/test-drm_buddy.c
>>
>> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
>> index eb5a57ae3c5c..ff856df3f97f 100644
>> --- a/drivers/gpu/drm/Kconfig
>> +++ b/drivers/gpu/drm/Kconfig
>> @@ -71,6 +71,7 @@ config DRM_DEBUG_SELFTEST
>>   	select DRM_DP_HELPER
>>   	select DRM_LIB_RANDOM
>>   	select DRM_KMS_HELPER
>> +	select DRM_BUDDY
>>   	select DRM_EXPORT_FOR_TESTS if m
>>   	default n
>>   	help
>> diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile
>> index 0856e4b12f70..5ba5f9138c95 100644
>> --- a/drivers/gpu/drm/selftests/Makefile
>> +++ b/drivers/gpu/drm/selftests/Makefile
>> @@ -4,4 +4,5 @@ test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
>>   		      test-drm_damage_helper.o test-drm_dp_mst_helper.o \
>>   		      test-drm_rect.o
>>   
>> -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o
>> +obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o \
>> +				    test-drm_buddy.o
>> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
>> new file mode 100644
>> index 000000000000..a4bcf3a6dfe3
>> --- /dev/null
>> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
>> @@ -0,0 +1,9 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/* List each unit test as selftest(name, function)
>> + *
>> + * The name is used as both an enum and expanded as igt__name to create
>> + * a module parameter. It must be unique and legal for a C identifier.
>> + *
>> + * Tests are executed in order by igt/drm_buddy
>> + */
>> +selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
>> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
>> new file mode 100644
>> index 000000000000..51e4d393d22c
>> --- /dev/null
>> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
>> @@ -0,0 +1,49 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright © 2019 Intel Corporation
>> + */
>> +
>> +#define pr_fmt(fmt) "drm_buddy: " fmt
>> +
>> +#include <linux/module.h>
>> +
>> +#include <drm/drm_buddy.h>
>> +
>> +#include "../lib/drm_random.h"
>> +
>> +#define TESTS "drm_buddy_selftests.h"
>> +#include "drm_selftest.h"
>> +
>> +static unsigned int random_seed;
>> +
>> +static int igt_sanitycheck(void *ignored)
>> +{
>> +	pr_info("%s - ok!\n", __func__);
>> +	return 0;
>> +}
>> +
>> +#include "drm_selftest.c"
>> +
>> +static int __init test_drm_buddy_init(void)
>> +{
>> +	int err;
>> +
>> +	while (!random_seed)
>> +		random_seed = get_random_int();
>> +
>> +	pr_info("Testing DRM buddy manager (struct drm_buddy), with random_seed=0x%x\n",
>> +		random_seed);
>> +	err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
>> +
>> +	return err > 0 ? 0 : err;
>> +}
>> +
>> +static void __exit test_drm_buddy_exit(void)
>> +{
>> +}
>> +
>> +module_init(test_drm_buddy_init);
>> +module_exit(test_drm_buddy_exit);
>> +
>> +MODULE_AUTHOR("Intel Corporation");
>> +MODULE_LICENSE("GPL");

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 1/7] drm/selftests: Move i915 buddy selftests into drm
@ 2022-02-22 18:35     ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-22 18:35 UTC (permalink / raw)
  To: Matthew Auld, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig, daniel



On 08/02/22 4:05 pm, Matthew Auld wrote:
> On 03/02/2022 13:32, Arunpravin wrote:
>> - move i915 buddy selftests into drm selftests folder
>> - add Makefile and Kconfig support
>> - add sanitycheck testcase
>>
>> Prerequisites
>> - These series of selftests patches are created on top of
>>    drm buddy series
>> - Enable kselftests for DRM as a module in .config
>>
>> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> 
> At some point I guess we also want some IGT that picks this up? Like we 
> do in tests/drm_mm.c? That way this can get picked up by CI?

igt-gpu-tools? we need to create tests/drm_buddy.c to pick these tests.
I will create a patch to include drm buddy selftests into igt-gpu-tools
> 
> Acked-by: Matthew Auld <matthew.auld@intel.com>
> 
>> ---
>>   drivers/gpu/drm/Kconfig                       |  1 +
>>   drivers/gpu/drm/selftests/Makefile            |  3 +-
>>   .../gpu/drm/selftests/drm_buddy_selftests.h   |  9 ++++
>>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 49 +++++++++++++++++++
>>   4 files changed, 61 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/gpu/drm/selftests/drm_buddy_selftests.h
>>   create mode 100644 drivers/gpu/drm/selftests/test-drm_buddy.c
>>
>> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
>> index eb5a57ae3c5c..ff856df3f97f 100644
>> --- a/drivers/gpu/drm/Kconfig
>> +++ b/drivers/gpu/drm/Kconfig
>> @@ -71,6 +71,7 @@ config DRM_DEBUG_SELFTEST
>>   	select DRM_DP_HELPER
>>   	select DRM_LIB_RANDOM
>>   	select DRM_KMS_HELPER
>> +	select DRM_BUDDY
>>   	select DRM_EXPORT_FOR_TESTS if m
>>   	default n
>>   	help
>> diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile
>> index 0856e4b12f70..5ba5f9138c95 100644
>> --- a/drivers/gpu/drm/selftests/Makefile
>> +++ b/drivers/gpu/drm/selftests/Makefile
>> @@ -4,4 +4,5 @@ test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
>>   		      test-drm_damage_helper.o test-drm_dp_mst_helper.o \
>>   		      test-drm_rect.o
>>   
>> -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o
>> +obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o \
>> +				    test-drm_buddy.o
>> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
>> new file mode 100644
>> index 000000000000..a4bcf3a6dfe3
>> --- /dev/null
>> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
>> @@ -0,0 +1,9 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/* List each unit test as selftest(name, function)
>> + *
>> + * The name is used as both an enum and expanded as igt__name to create
>> + * a module parameter. It must be unique and legal for a C identifier.
>> + *
>> + * Tests are executed in order by igt/drm_buddy
>> + */
>> +selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
>> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
>> new file mode 100644
>> index 000000000000..51e4d393d22c
>> --- /dev/null
>> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
>> @@ -0,0 +1,49 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright © 2019 Intel Corporation
>> + */
>> +
>> +#define pr_fmt(fmt) "drm_buddy: " fmt
>> +
>> +#include <linux/module.h>
>> +
>> +#include <drm/drm_buddy.h>
>> +
>> +#include "../lib/drm_random.h"
>> +
>> +#define TESTS "drm_buddy_selftests.h"
>> +#include "drm_selftest.h"
>> +
>> +static unsigned int random_seed;
>> +
>> +static int igt_sanitycheck(void *ignored)
>> +{
>> +	pr_info("%s - ok!\n", __func__);
>> +	return 0;
>> +}
>> +
>> +#include "drm_selftest.c"
>> +
>> +static int __init test_drm_buddy_init(void)
>> +{
>> +	int err;
>> +
>> +	while (!random_seed)
>> +		random_seed = get_random_int();
>> +
>> +	pr_info("Testing DRM buddy manager (struct drm_buddy), with random_seed=0x%x\n",
>> +		random_seed);
>> +	err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
>> +
>> +	return err > 0 ? 0 : err;
>> +}
>> +
>> +static void __exit test_drm_buddy_exit(void)
>> +{
>> +}
>> +
>> +module_init(test_drm_buddy_init);
>> +module_exit(test_drm_buddy_exit);
>> +
>> +MODULE_AUTHOR("Intel Corporation");
>> +MODULE_LICENSE("GPL");

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 2/7] drm/selftests: add drm buddy alloc limit testcase
  2022-02-08  9:40     ` [Intel-gfx] " Matthew Auld
  (?)
@ 2022-02-22 19:07       ` Arunpravin
  -1 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-22 19:07 UTC (permalink / raw)
  To: Matthew Auld, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig



On 08/02/22 3:10 pm, Matthew Auld wrote:
> On 03/02/2022 13:32, Arunpravin wrote:
>> add a test to check the maximum allocation limit
>>
>> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
>> ---
>>   .../gpu/drm/selftests/drm_buddy_selftests.h   |  1 +
>>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 60 +++++++++++++++++++
>>   2 files changed, 61 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
>> index a4bcf3a6dfe3..ebe16162762f 100644
>> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
>> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
>> @@ -7,3 +7,4 @@
>>    * Tests are executed in order by igt/drm_buddy
>>    */
>>   selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
>> +selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
>> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
>> index 51e4d393d22c..fd7d1a112458 100644
>> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
>> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
>> @@ -16,6 +16,66 @@
>>   
>>   static unsigned int random_seed;
>>   
>> +static int igt_buddy_alloc_limit(void *arg)
>> +{
>> +	u64 end, size = U64_MAX, start = 0;
>> +	struct drm_buddy_block *block;
>> +	unsigned long flags = 0;
>> +	LIST_HEAD(allocated);
>> +	struct drm_buddy mm;
>> +	int err;
>> +
>> +	size = end = round_down(size, 4096);
>> +	err = drm_buddy_init(&mm, size, PAGE_SIZE);
>> +	if (err)
>> +		return err;
>> +
>> +	if (mm.max_order != DRM_BUDDY_MAX_ORDER) {
>> +		pr_err("mm.max_order(%d) != %d\n",
>> +		       mm.max_order, DRM_BUDDY_MAX_ORDER);
>> +		err = -EINVAL;
>> +		goto out_fini;
>> +	}
>> +
>> +	err = drm_buddy_alloc_blocks(&mm, start, end, size,
>> +				     PAGE_SIZE, &allocated, flags);
>> +
>> +	if (unlikely(err))
>> +		goto out_free;
>> +
>> +	block = list_first_entry_or_null(&allocated,
>> +					 struct drm_buddy_block,
>> +					 link);
>> +
>> +	if (!block)
> 
> err = -EINVAL;
> 
>> +		goto out_fini;
>> +
>> +	if (drm_buddy_block_order(block) != mm.max_order) {
>> +		pr_err("block order(%d) != %d\n",
>> +		       drm_buddy_block_order(block), mm.max_order);
>> +		err = -EINVAL;
>> +		goto out_free;
>> +	}
>> +
>> +	if (drm_buddy_block_size(&mm, block) !=
>> +	    BIT_ULL(mm.max_order) * PAGE_SIZE) {
>> +		pr_err("block size(%llu) != %llu\n",
>> +		       drm_buddy_block_size(&mm, block),
>> +		       BIT_ULL(mm.max_order) * PAGE_SIZE);
>> +		err = -EINVAL;
>> +		goto out_free;
>> +	}
>> +
>> +	if (!err)
> 
> Always true AFAICT?
> 
>> +		pr_info("%s - succeeded\n", __func__);
> 
> I guess this could be made part of the run_selftests()? It looks like it 
> already prints the current test, perhaps that is already enough?

removed all unnecessary succeeded prints

Thanks,
Arun
> 
> With the err = -EINVAL change, feel free to add,
> Reviewed-by: Matthew Auld <matthew.auld@intel.com>
> 
>> +
>> +out_free:
>> +	drm_buddy_free_list(&mm, &allocated);
>> +out_fini:
>> +	drm_buddy_fini(&mm);
>> +	return err;
>> +}
>> +
>>   static int igt_sanitycheck(void *ignored)
>>   {
>>   	pr_info("%s - ok!\n", __func__);

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [Intel-gfx] [PATCH 2/7] drm/selftests: add drm buddy alloc limit testcase
@ 2022-02-22 19:07       ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-22 19:07 UTC (permalink / raw)
  To: Matthew Auld, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig



On 08/02/22 3:10 pm, Matthew Auld wrote:
> On 03/02/2022 13:32, Arunpravin wrote:
>> add a test to check the maximum allocation limit
>>
>> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
>> ---
>>   .../gpu/drm/selftests/drm_buddy_selftests.h   |  1 +
>>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 60 +++++++++++++++++++
>>   2 files changed, 61 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
>> index a4bcf3a6dfe3..ebe16162762f 100644
>> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
>> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
>> @@ -7,3 +7,4 @@
>>    * Tests are executed in order by igt/drm_buddy
>>    */
>>   selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
>> +selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
>> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
>> index 51e4d393d22c..fd7d1a112458 100644
>> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
>> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
>> @@ -16,6 +16,66 @@
>>   
>>   static unsigned int random_seed;
>>   
>> +static int igt_buddy_alloc_limit(void *arg)
>> +{
>> +	u64 end, size = U64_MAX, start = 0;
>> +	struct drm_buddy_block *block;
>> +	unsigned long flags = 0;
>> +	LIST_HEAD(allocated);
>> +	struct drm_buddy mm;
>> +	int err;
>> +
>> +	size = end = round_down(size, 4096);
>> +	err = drm_buddy_init(&mm, size, PAGE_SIZE);
>> +	if (err)
>> +		return err;
>> +
>> +	if (mm.max_order != DRM_BUDDY_MAX_ORDER) {
>> +		pr_err("mm.max_order(%d) != %d\n",
>> +		       mm.max_order, DRM_BUDDY_MAX_ORDER);
>> +		err = -EINVAL;
>> +		goto out_fini;
>> +	}
>> +
>> +	err = drm_buddy_alloc_blocks(&mm, start, end, size,
>> +				     PAGE_SIZE, &allocated, flags);
>> +
>> +	if (unlikely(err))
>> +		goto out_free;
>> +
>> +	block = list_first_entry_or_null(&allocated,
>> +					 struct drm_buddy_block,
>> +					 link);
>> +
>> +	if (!block)
> 
> err = -EINVAL;
> 
>> +		goto out_fini;
>> +
>> +	if (drm_buddy_block_order(block) != mm.max_order) {
>> +		pr_err("block order(%d) != %d\n",
>> +		       drm_buddy_block_order(block), mm.max_order);
>> +		err = -EINVAL;
>> +		goto out_free;
>> +	}
>> +
>> +	if (drm_buddy_block_size(&mm, block) !=
>> +	    BIT_ULL(mm.max_order) * PAGE_SIZE) {
>> +		pr_err("block size(%llu) != %llu\n",
>> +		       drm_buddy_block_size(&mm, block),
>> +		       BIT_ULL(mm.max_order) * PAGE_SIZE);
>> +		err = -EINVAL;
>> +		goto out_free;
>> +	}
>> +
>> +	if (!err)
> 
> Always true AFAICT?
> 
>> +		pr_info("%s - succeeded\n", __func__);
> 
> I guess this could be made part of the run_selftests()? It looks like it 
> already prints the current test, perhaps that is already enough?

removed all unnecessary succeeded prints

Thanks,
Arun
> 
> With the err = -EINVAL change, feel free to add,
> Reviewed-by: Matthew Auld <matthew.auld@intel.com>
> 
>> +
>> +out_free:
>> +	drm_buddy_free_list(&mm, &allocated);
>> +out_fini:
>> +	drm_buddy_fini(&mm);
>> +	return err;
>> +}
>> +
>>   static int igt_sanitycheck(void *ignored)
>>   {
>>   	pr_info("%s - ok!\n", __func__);

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 2/7] drm/selftests: add drm buddy alloc limit testcase
@ 2022-02-22 19:07       ` Arunpravin
  0 siblings, 0 replies; 52+ messages in thread
From: Arunpravin @ 2022-02-22 19:07 UTC (permalink / raw)
  To: Matthew Auld, dri-devel, intel-gfx, amd-gfx
  Cc: alexander.deucher, tzimmermann, christian.koenig, daniel



On 08/02/22 3:10 pm, Matthew Auld wrote:
> On 03/02/2022 13:32, Arunpravin wrote:
>> add a test to check the maximum allocation limit
>>
>> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
>> ---
>>   .../gpu/drm/selftests/drm_buddy_selftests.h   |  1 +
>>   drivers/gpu/drm/selftests/test-drm_buddy.c    | 60 +++++++++++++++++++
>>   2 files changed, 61 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
>> index a4bcf3a6dfe3..ebe16162762f 100644
>> --- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
>> +++ b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
>> @@ -7,3 +7,4 @@
>>    * Tests are executed in order by igt/drm_buddy
>>    */
>>   selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
>> +selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
>> diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
>> index 51e4d393d22c..fd7d1a112458 100644
>> --- a/drivers/gpu/drm/selftests/test-drm_buddy.c
>> +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c
>> @@ -16,6 +16,66 @@
>>   
>>   static unsigned int random_seed;
>>   
>> +static int igt_buddy_alloc_limit(void *arg)
>> +{
>> +	u64 end, size = U64_MAX, start = 0;
>> +	struct drm_buddy_block *block;
>> +	unsigned long flags = 0;
>> +	LIST_HEAD(allocated);
>> +	struct drm_buddy mm;
>> +	int err;
>> +
>> +	size = end = round_down(size, 4096);
>> +	err = drm_buddy_init(&mm, size, PAGE_SIZE);
>> +	if (err)
>> +		return err;
>> +
>> +	if (mm.max_order != DRM_BUDDY_MAX_ORDER) {
>> +		pr_err("mm.max_order(%d) != %d\n",
>> +		       mm.max_order, DRM_BUDDY_MAX_ORDER);
>> +		err = -EINVAL;
>> +		goto out_fini;
>> +	}
>> +
>> +	err = drm_buddy_alloc_blocks(&mm, start, end, size,
>> +				     PAGE_SIZE, &allocated, flags);
>> +
>> +	if (unlikely(err))
>> +		goto out_free;
>> +
>> +	block = list_first_entry_or_null(&allocated,
>> +					 struct drm_buddy_block,
>> +					 link);
>> +
>> +	if (!block)
> 
> err = -EINVAL;
> 
>> +		goto out_fini;
>> +
>> +	if (drm_buddy_block_order(block) != mm.max_order) {
>> +		pr_err("block order(%d) != %d\n",
>> +		       drm_buddy_block_order(block), mm.max_order);
>> +		err = -EINVAL;
>> +		goto out_free;
>> +	}
>> +
>> +	if (drm_buddy_block_size(&mm, block) !=
>> +	    BIT_ULL(mm.max_order) * PAGE_SIZE) {
>> +		pr_err("block size(%llu) != %llu\n",
>> +		       drm_buddy_block_size(&mm, block),
>> +		       BIT_ULL(mm.max_order) * PAGE_SIZE);
>> +		err = -EINVAL;
>> +		goto out_free;
>> +	}
>> +
>> +	if (!err)
> 
> Always true AFAICT?
> 
>> +		pr_info("%s - succeeded\n", __func__);
> 
> I guess this could be made part of the run_selftests()? It looks like it 
> already prints the current test, perhaps that is already enough?

removed all unnecessary succeeded prints

Thanks,
Arun
> 
> With the err = -EINVAL change, feel free to add,
> Reviewed-by: Matthew Auld <matthew.auld@intel.com>
> 
>> +
>> +out_free:
>> +	drm_buddy_free_list(&mm, &allocated);
>> +out_fini:
>> +	drm_buddy_fini(&mm);
>> +	return err;
>> +}
>> +
>>   static int igt_sanitycheck(void *ignored)
>>   {
>>   	pr_info("%s - ok!\n", __func__);

^ permalink raw reply	[flat|nested] 52+ messages in thread

end of thread, other threads:[~2022-02-22 18:57 UTC | newest]

Thread overview: 52+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-03 13:32 [PATCH 1/7] drm/selftests: Move i915 buddy selftests into drm Arunpravin
2022-02-03 13:32 ` Arunpravin
2022-02-03 13:32 ` [Intel-gfx] " Arunpravin
2022-02-03 13:32 ` [PATCH 2/7] drm/selftests: add drm buddy alloc limit testcase Arunpravin
2022-02-03 13:32   ` Arunpravin
2022-02-03 13:32   ` [Intel-gfx] " Arunpravin
2022-02-08  9:40   ` Matthew Auld
2022-02-08  9:40     ` Matthew Auld
2022-02-08  9:40     ` [Intel-gfx] " Matthew Auld
2022-02-22 19:07     ` Arunpravin
2022-02-22 19:07       ` Arunpravin
2022-02-22 19:07       ` [Intel-gfx] " Arunpravin
2022-02-03 13:32 ` [PATCH 3/7] drm/selftests: add drm buddy alloc range testcase Arunpravin
2022-02-03 13:32   ` Arunpravin
2022-02-03 13:32   ` [Intel-gfx] " Arunpravin
2022-02-08 10:03   ` Matthew Auld
2022-02-08 10:03     ` Matthew Auld
2022-02-08 10:03     ` [Intel-gfx] " Matthew Auld
2022-02-03 13:32 ` [PATCH 4/7] drm/selftests: add drm buddy optimistic testcase Arunpravin
2022-02-03 13:32   ` Arunpravin
2022-02-03 13:32   ` [Intel-gfx] " Arunpravin
2022-02-08 10:12   ` Matthew Auld
2022-02-08 10:12     ` Matthew Auld
2022-02-08 10:12     ` [Intel-gfx] " Matthew Auld
2022-02-03 13:32 ` [PATCH 5/7] drm/selftests: add drm buddy pessimistic testcase Arunpravin
2022-02-03 13:32   ` Arunpravin
2022-02-03 13:32   ` [Intel-gfx] " Arunpravin
2022-02-08 10:17   ` Matthew Auld
2022-02-08 10:17     ` Matthew Auld
2022-02-08 10:17     ` [Intel-gfx] " Matthew Auld
2022-02-03 13:32 ` [PATCH 6/7] drm/selftests: add drm buddy smoke testcase Arunpravin
2022-02-03 13:32   ` Arunpravin
2022-02-03 13:32   ` [Intel-gfx] " Arunpravin
2022-02-08 10:22   ` Matthew Auld
2022-02-08 10:22     ` Matthew Auld
2022-02-08 10:22     ` [Intel-gfx] " Matthew Auld
2022-02-03 13:32 ` [PATCH 7/7] drm/selftests: add drm buddy pathological testcase Arunpravin
2022-02-03 13:32   ` Arunpravin
2022-02-03 13:32   ` [Intel-gfx] " Arunpravin
2022-02-08 10:26   ` Matthew Auld
2022-02-08 10:26     ` Matthew Auld
2022-02-08 10:26     ` [Intel-gfx] " Matthew Auld
2022-02-03 14:12 ` [Intel-gfx] ✗ Fi.CI.BUILD: failure for series starting with [1/7] drm/selftests: Move i915 buddy selftests into drm Patchwork
2022-02-03 14:33 ` [PATCH 1/7] " Christian König
2022-02-03 14:33   ` Christian König
2022-02-03 14:33   ` [Intel-gfx] " Christian König
2022-02-08 10:35 ` Matthew Auld
2022-02-08 10:35   ` Matthew Auld
2022-02-08 10:35   ` [Intel-gfx] " Matthew Auld
2022-02-22 18:35   ` Arunpravin
2022-02-22 18:35     ` Arunpravin
2022-02-22 18:35     ` [Intel-gfx] " Arunpravin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.