From 2b50aae61f94bc76dde7d4c87b610ffe45ca1b02 Mon Sep 17 00:00:00 2001 From: Martin Jücker Date: Mon, 16 May 2022 21:37:07 +0200 Subject: dt-bindings: display: simple: add support for Samsung LTL101AL01 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the Samsung LTL101AL01 WXGA LCD panel to the list. Signed-off-by: Martin Jücker Acked-by: Krzysztof Kozlowski Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20220516193709.10037-1-martin.juecker@gmail.com --- Documentation/devicetree/bindings/display/panel/panel-simple.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml index bc8e9c0c1dc3..133f2bae04b5 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml @@ -280,6 +280,8 @@ properties: - samsung,atna33xc20 # Samsung 12.2" (2560x1600 pixels) TFT LCD panel - samsung,lsn122dl01-c01 + # Samsung Electronics 10.1" WXGA (1280x800) TFT LCD panel + - samsung,ltl101al01 # Samsung Electronics 10.1" WSVGA TFT LCD panel - samsung,ltn101nt05 # Samsung Electronics 14" WXGA (1366x768) TFT LCD panel -- cgit v1.3-14-g43fede From 46f4433550084de3bb288cbb32fbdad7688de11e Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Fri, 8 Jul 2022 21:54:01 +0100 Subject: dt-bindings/display: ingenic: Add compatible string for the JZ4760(B) Add compatible strings for the LCD controllers found in the JZ4760 and JZ4760B SoCs from Ingenic. Signed-off-by: Paul Cercueil Acked-by: Sam Ravnborg Cc: Rob Herring Cc: Krzysztof Kozlowski Cc: devicetree@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20220708205406.96473-2-paul@crapouillou.net --- Documentation/devicetree/bindings/display/ingenic,lcd.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/ingenic,lcd.yaml b/Documentation/devicetree/bindings/display/ingenic,lcd.yaml index 0049010b37ca..c0bb02fb49f4 100644 --- a/Documentation/devicetree/bindings/display/ingenic,lcd.yaml +++ b/Documentation/devicetree/bindings/display/ingenic,lcd.yaml @@ -17,6 +17,8 @@ properties: enum: - ingenic,jz4740-lcd - ingenic,jz4725b-lcd + - ingenic,jz4760-lcd + - ingenic,jz4760b-lcd - ingenic,jz4770-lcd - ingenic,jz4780-lcd -- cgit v1.3-14-g43fede From fc8d29e298cf47e07c2764ec1c340c1df8e50431 Mon Sep 17 00:00:00 2001 From: Arthur Grillo Date: Fri, 8 Jul 2022 17:30:52 -0300 Subject: drm: selftest: convert drm_mm selftest to KUnit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Considering the current adoption of the KUnit framework, convert the DRM mm selftest to the KUnit API. Signed-off-by: Arthur Grillo Tested-by: David Gow Acked-by: Daniel Latypov Reviewed-by: Javier Martinez Canillas Signed-off-by: Maíra Canal Signed-off-by: Javier Martinez Canillas Link: https://patchwork.freedesktop.org/patch/msgid/20220708203052.236290-10-maira.canal@usp.br --- Documentation/gpu/todo.rst | 11 - drivers/gpu/drm/Kconfig | 20 - drivers/gpu/drm/Makefile | 1 - drivers/gpu/drm/selftests/Makefile | 2 - drivers/gpu/drm/selftests/drm_mm_selftests.h | 28 - drivers/gpu/drm/selftests/drm_selftest.c | 109 -- drivers/gpu/drm/selftests/drm_selftest.h | 41 - drivers/gpu/drm/selftests/test-drm_mm.c | 2487 -------------------------- drivers/gpu/drm/tests/Makefile | 2 +- drivers/gpu/drm/tests/drm_mm_test.c | 2255 +++++++++++++++++++++++ 10 files changed, 2256 insertions(+), 2700 deletions(-) delete mode 100644 drivers/gpu/drm/selftests/Makefile delete mode 100644 drivers/gpu/drm/selftests/drm_mm_selftests.h delete mode 100644 drivers/gpu/drm/selftests/drm_selftest.c delete mode 100644 drivers/gpu/drm/selftests/drm_selftest.h delete mode 100644 drivers/gpu/drm/selftests/test-drm_mm.c create mode 100644 drivers/gpu/drm/tests/drm_mm_test.c (limited to 'Documentation') diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 513b20ccef1e..10bfb50908d1 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -617,17 +617,6 @@ Contact: Javier Martinez Canillas Level: Intermediate -Convert Kernel Selftests (kselftest) to KUnit tests when appropriate --------------------------------------------------------------------- - -Many of the `Kselftest `_ -tests in DRM could be converted to Kunit tests instead, since that framework -is more suitable for unit testing. - -Contact: Javier Martinez Canillas - -Level: Starter - Enable trinity for DRM ---------------------- diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 06822ecf51c6..1c91e1e861a5 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -50,26 +50,6 @@ config DRM_DEBUG_MM If in doubt, say "N". -config DRM_DEBUG_SELFTEST - tristate "kselftests for DRM" - depends on DRM - depends on DEBUG_KERNEL - select PRIME_NUMBERS - select DRM_DISPLAY_DP_HELPER - select DRM_DISPLAY_HELPER - select DRM_LIB_RANDOM - select DRM_KMS_HELPER - select DRM_BUDDY - select DRM_EXPORT_FOR_TESTS if m - default n - help - This option provides kernel modules that can be used to run - various selftests on parts of the DRM api. This option is not - useful for distributions or general kernels, but only for kernel - developers working on DRM and associated drivers. - - If in doubt, say "N". - config DRM_KUNIT_TEST tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS depends on DRM && KUNIT diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index e7af358e6dda..25016dcab55e 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -75,7 +75,6 @@ obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o # Drivers and the rest # -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/ obj-$(CONFIG_DRM_KUNIT_TEST) += tests/ obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile deleted file mode 100644 index a4ebecb8146b..000000000000 --- a/drivers/gpu/drm/selftests/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h deleted file mode 100644 index 8c87c964176b..000000000000 --- a/drivers/gpu/drm/selftests/drm_mm_selftests.h +++ /dev/null @@ -1,28 +0,0 @@ -/* 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_mm - */ -selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */ -selftest(init, igt_init) -selftest(debug, igt_debug) -selftest(reserve, igt_reserve) -selftest(insert, igt_insert) -selftest(replace, igt_replace) -selftest(insert_range, igt_insert_range) -selftest(align, igt_align) -selftest(frag, igt_frag) -selftest(align32, igt_align32) -selftest(align64, igt_align64) -selftest(evict, igt_evict) -selftest(evict_range, igt_evict_range) -selftest(bottomup, igt_bottomup) -selftest(lowest, igt_lowest) -selftest(topdown, igt_topdown) -selftest(highest, igt_highest) -selftest(color, igt_color) -selftest(color_evict, igt_color_evict) -selftest(color_evict_range, igt_color_evict_range) diff --git a/drivers/gpu/drm/selftests/drm_selftest.c b/drivers/gpu/drm/selftests/drm_selftest.c deleted file mode 100644 index e29ed9faef5b..000000000000 --- a/drivers/gpu/drm/selftests/drm_selftest.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright © 2016 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include - -#define selftest(name, func) __idx_##name, -enum { -#include TESTS -}; -#undef selftest - -#define selftest(n, f) [__idx_##n] = { .name = #n, .func = f }, -static struct drm_selftest { - bool enabled; - const char *name; - int (*func)(void *); -} selftests[] = { -#include TESTS -}; -#undef selftest - -/* Embed the line number into the parameter name so that we can order tests */ -#define param(n) __PASTE(igt__, __PASTE(__PASTE(__LINE__, __), n)) -#define selftest_0(n, func, id) \ -module_param_named(id, selftests[__idx_##n].enabled, bool, 0400); -#define selftest(n, func) selftest_0(n, func, param(n)) -#include TESTS -#undef selftest - -static void set_default_test_all(struct drm_selftest *st, unsigned long count) -{ - unsigned long i; - - for (i = 0; i < count; i++) - if (st[i].enabled) - return; - - for (i = 0; i < count; i++) - st[i].enabled = true; -} - -static int run_selftests(struct drm_selftest *st, - unsigned long count, - void *data) -{ - int err = 0; - - set_default_test_all(st, count); - - /* Tests are listed in natural order in drm_*_selftests.h */ - for (; count--; st++) { - if (!st->enabled) - continue; - - pr_debug("drm: Running %s\n", st->name); - err = st->func(data); - if (err) - break; - } - - if (WARN(err > 0 || err == -ENOTTY, - "%s returned %d, conflicting with selftest's magic values!\n", - st->name, err)) - err = -1; - - rcu_barrier(); - return err; -} - -static int __maybe_unused -__drm_subtests(const char *caller, - const struct drm_subtest *st, - int count, - void *data) -{ - int err; - - for (; count--; st++) { - pr_debug("Running %s/%s\n", caller, st->name); - err = st->func(data); - if (err) { - pr_err("%s: %s failed with error %d\n", - caller, st->name, err); - return err; - } - } - - return 0; -} diff --git a/drivers/gpu/drm/selftests/drm_selftest.h b/drivers/gpu/drm/selftests/drm_selftest.h deleted file mode 100644 index c784ec02ff53..000000000000 --- a/drivers/gpu/drm/selftests/drm_selftest.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright © 2016 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef __DRM_SELFTEST_H__ -#define __DRM_SELFTEST_H__ - -struct drm_subtest { - int (*func)(void *data); - const char *name; -}; - -static int __drm_subtests(const char *caller, - const struct drm_subtest *st, - int count, - void *data); -#define drm_subtests(T, data) \ - __drm_subtests(__func__, T, ARRAY_SIZE(T), data) - -#define SUBTEST(x) { x, #x } - -#endif /* __DRM_SELFTEST_H__ */ diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c deleted file mode 100644 index b768b53c4aee..000000000000 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ /dev/null @@ -1,2487 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Test cases for the drm_mm range manager - */ - -#define pr_fmt(fmt) "drm_mm: " fmt - -#include -#include -#include -#include -#include -#include - -#include - -#include "../lib/drm_random.h" - -#define TESTS "drm_mm_selftests.h" -#include "drm_selftest.h" - -static unsigned int random_seed; -static unsigned int max_iterations = 8192; -static unsigned int max_prime = 128; - -enum { - BEST, - BOTTOMUP, - TOPDOWN, - EVICT, -}; - -static const struct insert_mode { - const char *name; - enum drm_mm_insert_mode mode; -} insert_modes[] = { - [BEST] = { "best", DRM_MM_INSERT_BEST }, - [BOTTOMUP] = { "bottom-up", DRM_MM_INSERT_LOW }, - [TOPDOWN] = { "top-down", DRM_MM_INSERT_HIGH }, - [EVICT] = { "evict", DRM_MM_INSERT_EVICT }, - {} -}, evict_modes[] = { - { "bottom-up", DRM_MM_INSERT_LOW }, - { "top-down", DRM_MM_INSERT_HIGH }, - {} -}; - -static int igt_sanitycheck(void *ignored) -{ - pr_info("%s - ok!\n", __func__); - return 0; -} - -static bool assert_no_holes(const struct drm_mm *mm) -{ - struct drm_mm_node *hole; - u64 hole_start, __always_unused hole_end; - unsigned long count; - - count = 0; - drm_mm_for_each_hole(hole, mm, hole_start, hole_end) - count++; - if (count) { - pr_err("Expected to find no holes (after reserve), found %lu instead\n", count); - return false; - } - - drm_mm_for_each_node(hole, mm) { - if (drm_mm_hole_follows(hole)) { - pr_err("Hole follows node, expected none!\n"); - return false; - } - } - - return true; -} - -static bool assert_one_hole(const struct drm_mm *mm, u64 start, u64 end) -{ - struct drm_mm_node *hole; - u64 hole_start, hole_end; - unsigned long count; - bool ok = true; - - if (end <= start) - return true; - - count = 0; - drm_mm_for_each_hole(hole, mm, hole_start, hole_end) { - if (start != hole_start || end != hole_end) { - if (ok) - pr_err("empty mm has incorrect hole, found (%llx, %llx), expect (%llx, %llx)\n", - hole_start, hole_end, - start, end); - ok = false; - } - count++; - } - if (count != 1) { - pr_err("Expected to find one hole, found %lu instead\n", count); - ok = false; - } - - return ok; -} - -static bool assert_continuous(const struct drm_mm *mm, u64 size) -{ - struct drm_mm_node *node, *check, *found; - unsigned long n; - u64 addr; - - if (!assert_no_holes(mm)) - return false; - - n = 0; - addr = 0; - drm_mm_for_each_node(node, mm) { - if (node->start != addr) { - pr_err("node[%ld] list out of order, expected %llx found %llx\n", - n, addr, node->start); - return false; - } - - if (node->size != size) { - pr_err("node[%ld].size incorrect, expected %llx, found %llx\n", - n, size, node->size); - return false; - } - - if (drm_mm_hole_follows(node)) { - pr_err("node[%ld] is followed by a hole!\n", n); - return false; - } - - found = NULL; - drm_mm_for_each_node_in_range(check, mm, addr, addr + size) { - if (node != check) { - pr_err("lookup return wrong node, expected start %llx, found %llx\n", - node->start, check->start); - return false; - } - found = check; - } - if (!found) { - pr_err("lookup failed for node %llx + %llx\n", - addr, size); - return false; - } - - addr += size; - n++; - } - - return true; -} - -static u64 misalignment(struct drm_mm_node *node, u64 alignment) -{ - u64 rem; - - if (!alignment) - return 0; - - div64_u64_rem(node->start, alignment, &rem); - return rem; -} - -static bool assert_node(struct drm_mm_node *node, struct drm_mm *mm, - u64 size, u64 alignment, unsigned long color) -{ - bool ok = true; - - if (!drm_mm_node_allocated(node) || node->mm != mm) { - pr_err("node not allocated\n"); - ok = false; - } - - if (node->size != size) { - pr_err("node has wrong size, found %llu, expected %llu\n", - node->size, size); - ok = false; - } - - if (misalignment(node, alignment)) { - pr_err("node is misaligned, start %llx rem %llu, expected alignment %llu\n", - node->start, misalignment(node, alignment), alignment); - ok = false; - } - - if (node->color != color) { - pr_err("node has wrong color, found %lu, expected %lu\n", - node->color, color); - ok = false; - } - - return ok; -} - -#define show_mm(mm) do { \ - struct drm_printer __p = drm_debug_printer(__func__); \ - drm_mm_print((mm), &__p); } while (0) - -static int igt_init(void *ignored) -{ - const unsigned int size = 4096; - struct drm_mm mm; - struct drm_mm_node tmp; - int ret = -EINVAL; - - /* Start with some simple checks on initialising the struct drm_mm */ - memset(&mm, 0, sizeof(mm)); - if (drm_mm_initialized(&mm)) { - pr_err("zeroed mm claims to be initialized\n"); - return ret; - } - - memset(&mm, 0xff, sizeof(mm)); - drm_mm_init(&mm, 0, size); - if (!drm_mm_initialized(&mm)) { - pr_err("mm claims not to be initialized\n"); - goto out; - } - - if (!drm_mm_clean(&mm)) { - pr_err("mm not empty on creation\n"); - goto out; - } - - /* After creation, it should all be one massive hole */ - if (!assert_one_hole(&mm, 0, size)) { - ret = -EINVAL; - goto out; - } - - memset(&tmp, 0, sizeof(tmp)); - tmp.start = 0; - tmp.size = size; - ret = drm_mm_reserve_node(&mm, &tmp); - if (ret) { - pr_err("failed to reserve whole drm_mm\n"); - goto out; - } - - /* After filling the range entirely, there should be no holes */ - if (!assert_no_holes(&mm)) { - ret = -EINVAL; - goto out; - } - - /* And then after emptying it again, the massive hole should be back */ - drm_mm_remove_node(&tmp); - if (!assert_one_hole(&mm, 0, size)) { - ret = -EINVAL; - goto out; - } - -out: - if (ret) - show_mm(&mm); - drm_mm_takedown(&mm); - return ret; -} - -static int igt_debug(void *ignored) -{ - struct drm_mm mm; - struct drm_mm_node nodes[2]; - int ret; - - /* Create a small drm_mm with a couple of nodes and a few holes, and - * check that the debug iterator doesn't explode over a trivial drm_mm. - */ - - drm_mm_init(&mm, 0, 4096); - - memset(nodes, 0, sizeof(nodes)); - nodes[0].start = 512; - nodes[0].size = 1024; - ret = drm_mm_reserve_node(&mm, &nodes[0]); - if (ret) { - pr_err("failed to reserve node[0] {start=%lld, size=%lld)\n", - nodes[0].start, nodes[0].size); - return ret; - } - - nodes[1].size = 1024; - nodes[1].start = 4096 - 512 - nodes[1].size; - ret = drm_mm_reserve_node(&mm, &nodes[1]); - if (ret) { - pr_err("failed to reserve node[1] {start=%lld, size=%lld)\n", - nodes[1].start, nodes[1].size); - return ret; - } - - show_mm(&mm); - return 0; -} - -static struct drm_mm_node *set_node(struct drm_mm_node *node, - u64 start, u64 size) -{ - node->start = start; - node->size = size; - return node; -} - -static bool expect_reserve_fail(struct drm_mm *mm, struct drm_mm_node *node) -{ - int err; - - err = drm_mm_reserve_node(mm, node); - if (likely(err == -ENOSPC)) - return true; - - if (!err) { - pr_err("impossible reserve succeeded, node %llu + %llu\n", - node->start, node->size); - drm_mm_remove_node(node); - } else { - pr_err("impossible reserve failed with wrong error %d [expected %d], node %llu + %llu\n", - err, -ENOSPC, node->start, node->size); - } - return false; -} - -static bool check_reserve_boundaries(struct drm_mm *mm, - unsigned int count, - u64 size) -{ - const struct boundary { - u64 start, size; - const char *name; - } boundaries[] = { -#define B(st, sz) { (st), (sz), "{ " #st ", " #sz "}" } - B(0, 0), - B(-size, 0), - B(size, 0), - B(size * count, 0), - B(-size, size), - B(-size, -size), - B(-size, 2*size), - B(0, -size), - B(size, -size), - B(count*size, size), - B(count*size, -size), - B(count*size, count*size), - B(count*size, -count*size), - B(count*size, -(count+1)*size), - B((count+1)*size, size), - B((count+1)*size, -size), - B((count+1)*size, -2*size), -#undef B - }; - struct drm_mm_node tmp = {}; - int n; - - for (n = 0; n < ARRAY_SIZE(boundaries); n++) { - if (!expect_reserve_fail(mm, - set_node(&tmp, - boundaries[n].start, - boundaries[n].size))) { - pr_err("boundary[%d:%s] failed, count=%u, size=%lld\n", - n, boundaries[n].name, count, size); - return false; - } - } - - return true; -} - -static int __igt_reserve(unsigned int count, u64 size) -{ - DRM_RND_STATE(prng, random_seed); - struct drm_mm mm; - struct drm_mm_node tmp, *nodes, *node, *next; - unsigned int *order, n, m, o = 0; - int ret, err; - - /* For exercising drm_mm_reserve_node(), we want to check that - * reservations outside of the drm_mm range are rejected, and to - * overlapping and otherwise already occupied ranges. Afterwards, - * the tree and nodes should be intact. - */ - - DRM_MM_BUG_ON(!count); - DRM_MM_BUG_ON(!size); - - ret = -ENOMEM; - order = drm_random_order(count, &prng); - if (!order) - goto err; - - nodes = vzalloc(array_size(count, sizeof(*nodes))); - if (!nodes) - goto err_order; - - ret = -EINVAL; - drm_mm_init(&mm, 0, count * size); - - if (!check_reserve_boundaries(&mm, count, size)) - goto out; - - for (n = 0; n < count; n++) { - nodes[n].start = order[n] * size; - nodes[n].size = size; - - err = drm_mm_reserve_node(&mm, &nodes[n]); - if (err) { - pr_err("reserve failed, step %d, start %llu\n", - n, nodes[n].start); - ret = err; - goto out; - } - - if (!drm_mm_node_allocated(&nodes[n])) { - pr_err("reserved node not allocated! step %d, start %llu\n", - n, nodes[n].start); - goto out; - } - - if (!expect_reserve_fail(&mm, &nodes[n])) - goto out; - } - - /* After random insertion the nodes should be in order */ - if (!assert_continuous(&mm, size)) - goto out; - - /* Repeated use should then fail */ - drm_random_reorder(order, count, &prng); - for (n = 0; n < count; n++) { - if (!expect_reserve_fail(&mm, - set_node(&tmp, order[n] * size, 1))) - goto out; - - /* Remove and reinsert should work */ - drm_mm_remove_node(&nodes[order[n]]); - err = drm_mm_reserve_node(&mm, &nodes[order[n]]); - if (err) { - pr_err("reserve failed, step %d, start %llu\n", - n, nodes[n].start); - ret = err; - goto out; - } - } - - if (!assert_continuous(&mm, size)) - goto out; - - /* Overlapping use should then fail */ - for (n = 0; n < count; n++) { - if (!expect_reserve_fail(&mm, set_node(&tmp, 0, size*count))) - goto out; - } - for (n = 0; n < count; n++) { - if (!expect_reserve_fail(&mm, - set_node(&tmp, - size * n, - size * (count - n)))) - goto out; - } - - /* Remove several, reinsert, check full */ - for_each_prime_number(n, min(max_prime, count)) { - for (m = 0; m < n; m++) { - node = &nodes[order[(o + m) % count]]; - drm_mm_remove_node(node); - } - - for (m = 0; m < n; m++) { - node = &nodes[order[(o + m) % count]]; - err = drm_mm_reserve_node(&mm, node); - if (err) { - pr_err("reserve failed, step %d/%d, start %llu\n", - m, n, node->start); - ret = err; - goto out; - } - } - - o += n; - - if (!assert_continuous(&mm, size)) - goto out; - } - - ret = 0; -out: - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - drm_mm_takedown(&mm); - vfree(nodes); -err_order: - kfree(order); -err: - return ret; -} - -static int igt_reserve(void *ignored) -{ - const unsigned int count = min_t(unsigned int, BIT(10), max_iterations); - int n, ret; - - for_each_prime_number_from(n, 1, 54) { - u64 size = BIT_ULL(n); - - ret = __igt_reserve(count, size - 1); - if (ret) - return ret; - - ret = __igt_reserve(count, size); - if (ret) - return ret; - - ret = __igt_reserve(count, size + 1); - if (ret) - return ret; - - cond_resched(); - } - - return 0; -} - -static bool expect_insert(struct drm_mm *mm, struct drm_mm_node *node, - u64 size, u64 alignment, unsigned long color, - const struct insert_mode *mode) -{ - int err; - - err = drm_mm_insert_node_generic(mm, node, - size, alignment, color, - mode->mode); - if (err) { - pr_err("insert (size=%llu, alignment=%llu, color=%lu, mode=%s) failed with err=%d\n", - size, alignment, color, mode->name, err); - return false; - } - - if (!assert_node(node, mm, size, alignment, color)) { - drm_mm_remove_node(node); - return false; - } - - return true; -} - -static bool expect_insert_fail(struct drm_mm *mm, u64 size) -{ - struct drm_mm_node tmp = {}; - int err; - - err = drm_mm_insert_node(mm, &tmp, size); - if (likely(err == -ENOSPC)) - return true; - - if (!err) { - pr_err("impossible insert succeeded, node %llu + %llu\n", - tmp.start, tmp.size); - drm_mm_remove_node(&tmp); - } else { - pr_err("impossible insert failed with wrong error %d [expected %d], size %llu\n", - err, -ENOSPC, size); - } - return false; -} - -static int __igt_insert(unsigned int count, u64 size, bool replace) -{ - DRM_RND_STATE(prng, random_seed); - const struct insert_mode *mode; - struct drm_mm mm; - struct drm_mm_node *nodes, *node, *next; - unsigned int *order, n, m, o = 0; - int ret; - - /* Fill a range with lots of nodes, check it doesn't fail too early */ - - DRM_MM_BUG_ON(!count); - DRM_MM_BUG_ON(!size); - - ret = -ENOMEM; - nodes = vmalloc(array_size(count, sizeof(*nodes))); - if (!nodes) - goto err; - - order = drm_random_order(count, &prng); - if (!order) - goto err_nodes; - - ret = -EINVAL; - drm_mm_init(&mm, 0, count * size); - - for (mode = insert_modes; mode->name; mode++) { - for (n = 0; n < count; n++) { - struct drm_mm_node tmp; - - node = replace ? &tmp : &nodes[n]; - memset(node, 0, sizeof(*node)); - if (!expect_insert(&mm, node, size, 0, n, mode)) { - pr_err("%s insert failed, size %llu step %d\n", - mode->name, size, n); - goto out; - } - - if (replace) { - drm_mm_replace_node(&tmp, &nodes[n]); - if (drm_mm_node_allocated(&tmp)) { - pr_err("replaced old-node still allocated! step %d\n", - n); - goto out; - } - - if (!assert_node(&nodes[n], &mm, size, 0, n)) { - pr_err("replaced node did not inherit parameters, size %llu step %d\n", - size, n); - goto out; - } - - if (tmp.start != nodes[n].start) { - pr_err("replaced node mismatch location expected [%llx + %llx], found [%llx + %llx]\n", - tmp.start, size, - nodes[n].start, nodes[n].size); - goto out; - } - } - } - - /* After random insertion the nodes should be in order */ - if (!assert_continuous(&mm, size)) - goto out; - - /* Repeated use should then fail */ - if (!expect_insert_fail(&mm, size)) - goto out; - - /* Remove one and reinsert, as the only hole it should refill itself */ - for (n = 0; n < count; n++) { - u64 addr = nodes[n].start; - - drm_mm_remove_node(&nodes[n]); - if (!expect_insert(&mm, &nodes[n], size, 0, n, mode)) { - pr_err("%s reinsert failed, size %llu step %d\n", - mode->name, size, n); - goto out; - } - - if (nodes[n].start != addr) { - pr_err("%s reinsert node moved, step %d, expected %llx, found %llx\n", - mode->name, n, addr, nodes[n].start); - goto out; - } - - if (!assert_continuous(&mm, size)) - goto out; - } - - /* Remove several, reinsert, check full */ - for_each_prime_number(n, min(max_prime, count)) { - for (m = 0; m < n; m++) { - node = &nodes[order[(o + m) % count]]; - drm_mm_remove_node(node); - } - - for (m = 0; m < n; m++) { - node = &nodes[order[(o + m) % count]]; - if (!expect_insert(&mm, node, size, 0, n, mode)) { - pr_err("%s multiple reinsert failed, size %llu step %d\n", - mode->name, size, n); - goto out; - } - } - - o += n; - - if (!assert_continuous(&mm, size)) - goto out; - - if (!expect_insert_fail(&mm, size)) - goto out; - } - - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - DRM_MM_BUG_ON(!drm_mm_clean(&mm)); - - cond_resched(); - } - - ret = 0; -out: - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - drm_mm_takedown(&mm); - kfree(order); -err_nodes: - vfree(nodes); -err: - return ret; -} - -static int igt_insert(void *ignored) -{ - const unsigned int count = min_t(unsigned int, BIT(10), max_iterations); - unsigned int n; - int ret; - - for_each_prime_number_from(n, 1, 54) { - u64 size = BIT_ULL(n); - - ret = __igt_insert(count, size - 1, false); - if (ret) - return ret; - - ret = __igt_insert(count, size, false); - if (ret) - return ret; - - ret = __igt_insert(count, size + 1, false); - if (ret) - return ret; - - cond_resched(); - } - - return 0; -} - -static int igt_replace(void *ignored) -{ - const unsigned int count = min_t(unsigned int, BIT(10), max_iterations); - unsigned int n; - int ret; - - /* Reuse igt_insert to exercise replacement by inserting a dummy node, - * then replacing it with the intended node. We want to check that - * the tree is intact and all the information we need is carried - * across to the target node. - */ - - for_each_prime_number_from(n, 1, 54) { - u64 size = BIT_ULL(n); - - ret = __igt_insert(count, size - 1, true); - if (ret) - return ret; - - ret = __igt_insert(count, size, true); - if (ret) - return ret; - - ret = __igt_insert(count, size + 1, true); - if (ret) - return ret; - - cond_resched(); - } - - return 0; -} - -static bool expect_insert_in_range(struct drm_mm *mm, struct drm_mm_node *node, - u64 size, u64 alignment, unsigned long color, - u64 range_start, u64 range_end, - const struct insert_mode *mode) -{ - int err; - - err = drm_mm_insert_node_in_range(mm, node, - size, alignment, color, - range_start, range_end, - mode->mode); - if (err) { - pr_err("insert (size=%llu, alignment=%llu, color=%lu, mode=%s) nto range [%llx, %llx] failed with err=%d\n", - size, alignment, color, mode->name, - range_start, range_end, err); - return false; - } - - if (!assert_node(node, mm, size, alignment, color)) { - drm_mm_remove_node(node); - return false; - } - - return true; -} - -static bool expect_insert_in_range_fail(struct drm_mm *mm, - u64 size, - u64 range_start, - u64 range_end) -{ - struct drm_mm_node tmp = {}; - int err; - - err = drm_mm_insert_node_in_range(mm, &tmp, - size, 0, 0, - range_start, range_end, - 0); - if (likely(err == -ENOSPC)) - return true; - - if (!err) { - pr_err("impossible insert succeeded, node %llx + %llu, range [%llx, %llx]\n", - tmp.start, tmp.size, range_start, range_end); - drm_mm_remove_node(&tmp); - } else { - pr_err("impossible insert failed with wrong error %d [expected %d], size %llu, range [%llx, %llx]\n", - err, -ENOSPC, size, range_start, range_end); - } - - return false; -} - -static bool assert_contiguous_in_range(struct drm_mm *mm, - u64 size, - u64 start, - u64 end) -{ - struct drm_mm_node *node; - unsigned int n; - - if (!expect_insert_in_range_fail(mm, size, start, end)) - return false; - - n = div64_u64(start + size - 1, size); - drm_mm_for_each_node(node, mm) { - if (node->start < start || node->start + node->size > end) { - pr_err("node %d out of range, address [%llx + %llu], range [%llx, %llx]\n", - n, node->start, node->start + node->size, start, end); - return false; - } - - if (node->start != n * size) { - pr_err("node %d out of order, expected start %llx, found %llx\n", - n, n * size, node->start); - return false; - } - - if (node->size != size) { - pr_err("node %d has wrong size, expected size %llx, found %llx\n", - n, size, node->size); - return false; - } - - if (drm_mm_hole_follows(node) && - drm_mm_hole_node_end(node) < end) { - pr_err("node %d is followed by a hole!\n", n); - return false; - } - - n++; - } - - if (start > 0) { - node = __drm_mm_interval_first(mm, 0, start - 1); - if (drm_mm_node_allocated(node)) { - pr_err("node before start: node=%llx+%llu, start=%llx\n", - node->start, node->size, start); - return false; - } - } - - if (end < U64_MAX) { - node = __drm_mm_interval_first(mm, end, U64_MAX); - if (drm_mm_node_allocated(node)) { - pr_err("node after end: node=%llx+%llu, end=%llx\n", - node->start, node->size, end); - return false; - } - } - - return true; -} - -static int __igt_insert_range(unsigned int count, u64 size, u64 start, u64 end) -{ - const struct insert_mode *mode; - struct drm_mm mm; - struct drm_mm_node *nodes, *node, *next; - unsigned int n, start_n, end_n; - int ret; - - DRM_MM_BUG_ON(!count); - DRM_MM_BUG_ON(!size); - DRM_MM_BUG_ON(end <= start); - - /* Very similar to __igt_insert(), but now instead of populating the - * full range of the drm_mm, we try to fill a small portion of it. - */ - - ret = -ENOMEM; - nodes = vzalloc(array_size(count, sizeof(*nodes))); - if (!nodes) - goto err; - - ret = -EINVAL; - drm_mm_init(&mm, 0, count * size); - - start_n = div64_u64(start + size - 1, size); - end_n = div64_u64(end - size, size); - - for (mode = insert_modes; mode->name; mode++) { - for (n = start_n; n <= end_n; n++) { - if (!expect_insert_in_range(&mm, &nodes[n], - size, size, n, - start, end, mode)) { - pr_err("%s insert failed, size %llu, step %d [%d, %d], range [%llx, %llx]\n", - mode->name, size, n, - start_n, end_n, - start, end); - goto out; - } - } - - if (!assert_contiguous_in_range(&mm, size, start, end)) { - pr_err("%s: range [%llx, %llx] not full after initialisation, size=%llu\n", - mode->name, start, end, size); - goto out; - } - - /* Remove one and reinsert, it should refill itself */ - for (n = start_n; n <= end_n; n++) { - u64 addr = nodes[n].start; - - drm_mm_remove_node(&nodes[n]); - if (!expect_insert_in_range(&mm, &nodes[n], - size, size, n, - start, end, mode)) { - pr_err("%s reinsert failed, step %d\n", mode->name, n); - goto out; - } - - if (nodes[n].start != addr) { - pr_err("%s reinsert node moved, step %d, expected %llx, found %llx\n", - mode->name, n, addr, nodes[n].start); - goto out; - } - } - - if (!assert_contiguous_in_range(&mm, size, start, end)) { - pr_err("%s: range [%llx, %llx] not full after reinsertion, size=%llu\n", - mode->name, start, end, size); - goto out; - } - - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - DRM_MM_BUG_ON(!drm_mm_clean(&mm)); - - cond_resched(); - } - - ret = 0; -out: - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - drm_mm_takedown(&mm); - vfree(nodes); -err: - return ret; -} - -static int insert_outside_range(void) -{ - struct drm_mm mm; - const unsigned int start = 1024; - const unsigned int end = 2048; - const unsigned int size = end - start; - - drm_mm_init(&mm, start, size); - - if (!expect_insert_in_range_fail(&mm, 1, 0, start)) - return -EINVAL; - - if (!expect_insert_in_range_fail(&mm, size, - start - size/2, start + (size+1)/2)) - return -EINVAL; - - if (!expect_insert_in_range_fail(&mm, size, - end - (size+1)/2, end + size/2)) - return -EINVAL; - - if (!expect_insert_in_range_fail(&mm, 1, end, end + size)) - return -EINVAL; - - drm_mm_takedown(&mm); - return 0; -} - -static int igt_insert_range(void *ignored) -{ - const unsigned int count = min_t(unsigned int, BIT(13), max_iterations); - unsigned int n; - int ret; - - /* Check that requests outside the bounds of drm_mm are rejected. */ - ret = insert_outside_range(); - if (ret) - return ret; - - for_each_prime_number_from(n, 1, 50) { - const u64 size = BIT_ULL(n); - const u64 max = count * size; - - ret = __igt_insert_range(count, size, 0, max); - if (ret) - return ret; - - ret = __igt_insert_range(count, size, 1, max); - if (ret) - return ret; - - ret = __igt_insert_range(count, size, 0, max - 1); - if (ret) - return ret; - - ret = __igt_insert_range(count, size, 0, max/2); - if (ret) - return ret; - - ret = __igt_insert_range(count, size, max/2, max); - if (ret) - return ret; - - ret = __igt_insert_range(count, size, max/4+1, 3*max/4-1); - if (ret) - return ret; - - cond_resched(); - } - - return 0; -} - -static int prepare_igt_frag(struct drm_mm *mm, - struct drm_mm_node *nodes, - unsigned int num_insert, - const struct insert_mode *mode) -{ - unsigned int size = 4096; - unsigned int i; - - for (i = 0; i < num_insert; i++) { - if (!expect_insert(mm, &nodes[i], size, 0, i, - mode) != 0) { - pr_err("%s insert failed\n", mode->name); - return -EINVAL; - } - } - - /* introduce fragmentation by freeing every other node */ - for (i = 0; i < num_insert; i++) { - if (i % 2 == 0) - drm_mm_remove_node(&nodes[i]); - } - - return 0; - -} - -static u64 get_insert_time(struct drm_mm *mm, - unsigned int num_insert, - struct drm_mm_node *nodes, - const struct insert_mode *mode) -{ - unsigned int size = 8192; - ktime_t start; - unsigned int i; - - start = ktime_get(); - for (i = 0; i < num_insert; i++) { - if (!expect_insert(mm, &nodes[i], size, 0, i, mode) != 0) { - pr_err("%s insert failed\n", mode->name); - return 0; - } - } - - return ktime_to_ns(ktime_sub(ktime_get(), start)); -} - -static int igt_frag(void *ignored) -{ - struct drm_mm mm; - const struct insert_mode *mode; - struct drm_mm_node *nodes, *node, *next; - unsigned int insert_size = 10000; - unsigned int scale_factor = 4; - int ret = -EINVAL; - - /* We need 4 * insert_size nodes to hold intermediate allocated - * drm_mm nodes. - * 1 times for prepare_igt_frag() - * 1 times for get_insert_time() - * 2 times for get_insert_time() - */ - nodes = vzalloc(array_size(insert_size * 4, sizeof(*nodes))); - if (!nodes) - return -ENOMEM; - - /* For BOTTOMUP and TOPDOWN, we first fragment the - * address space using prepare_igt_frag() and then try to verify - * that that insertions scale quadratically from 10k to 20k insertions - */ - drm_mm_init(&mm, 1, U64_MAX - 2); - for (mode = insert_modes; mode->name; mode++) { - u64 insert_time1, insert_time2; - - if (mode->mode != DRM_MM_INSERT_LOW && - mode->mode != DRM_MM_INSERT_HIGH) - continue; - - ret = prepare_igt_frag(&mm, nodes, insert_size, mode); - if (ret) - goto err; - - insert_time1 = get_insert_time(&mm, insert_size, - nodes + insert_size, mode); - if (insert_time1 == 0) - goto err; - - insert_time2 = get_insert_time(&mm, (insert_size * 2), - nodes + insert_size * 2, mode); - if (insert_time2 == 0) - goto err; - - pr_info("%s fragmented insert of %u and %u insertions took %llu and %llu nsecs\n", - mode->name, insert_size, insert_size * 2, - insert_time1, insert_time2); - - if (insert_time2 > (scale_factor * insert_time1)) { - pr_err("%s fragmented insert took %llu nsecs more\n", - mode->name, - insert_time2 - (scale_factor * insert_time1)); - goto err; - } - - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - } - - ret = 0; -err: - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - drm_mm_takedown(&mm); - vfree(nodes); - - return ret; -} - -static int igt_align(void *ignored) -{ - const struct insert_mode *mode; - const unsigned int max_count = min(8192u, max_prime); - struct drm_mm mm; - struct drm_mm_node *nodes, *node, *next; - unsigned int prime; - int ret = -EINVAL; - - /* For each of the possible insertion modes, we pick a few - * arbitrary alignments and check that the inserted node - * meets our requirements. - */ - - nodes = vzalloc(array_size(max_count, sizeof(*nodes))); - if (!nodes) - goto err; - - drm_mm_init(&mm, 1, U64_MAX - 2); - - for (mode = insert_modes; mode->name; mode++) { - unsigned int i = 0; - - for_each_prime_number_from(prime, 1, max_count) { - u64 size = next_prime_number(prime); - - if (!expect_insert(&mm, &nodes[i], - size, prime, i, - mode)) { - pr_err("%s insert failed with alignment=%d", - mode->name, prime); - goto out; - } - - i++; - } - - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - DRM_MM_BUG_ON(!drm_mm_clean(&mm)); - - cond_resched(); - } - - ret = 0; -out: - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - drm_mm_takedown(&mm); - vfree(nodes); -err: - return ret; -} - -static int igt_align_pot(int max) -{ - struct drm_mm mm; - struct drm_mm_node *node, *next; - int bit; - int ret = -EINVAL; - - /* Check that we can align to the full u64 address space */ - - drm_mm_init(&mm, 1, U64_MAX - 2); - - for (bit = max - 1; bit; bit--) { - u64 align, size; - - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) { - ret = -ENOMEM; - goto out; - } - - align = BIT_ULL(bit); - size = BIT_ULL(bit-1) + 1; - if (!expect_insert(&mm, node, - size, align, bit, - &insert_modes[0])) { - pr_err("insert failed with alignment=%llx [%d]", - align, bit); - goto out; - } - - cond_resched(); - } - - ret = 0; -out: - drm_mm_for_each_node_safe(node, next, &mm) { - drm_mm_remove_node(node); - kfree(node); - } - drm_mm_takedown(&mm); - return ret; -} - -static int igt_align32(void *ignored) -{ - return igt_align_pot(32); -} - -static int igt_align64(void *ignored) -{ - return igt_align_pot(64); -} - -static void show_scan(const struct drm_mm_scan *scan) -{ - pr_info("scan: hit [%llx, %llx], size=%lld, align=%lld, color=%ld\n", - scan->hit_start, scan->hit_end, - scan->size, scan->alignment, scan->color); -} - -static void show_holes(const struct drm_mm *mm, int count) -{ - u64 hole_start, hole_end; - struct drm_mm_node *hole; - - drm_mm_for_each_hole(hole, mm, hole_start, hole_end) { - struct drm_mm_node *next = list_next_entry(hole, node_list); - const char *node1 = NULL, *node2 = NULL; - - if (drm_mm_node_allocated(hole)) - node1 = kasprintf(GFP_KERNEL, - "[%llx + %lld, color=%ld], ", - hole->start, hole->size, hole->color); - - if (drm_mm_node_allocated(next)) - node2 = kasprintf(GFP_KERNEL, - ", [%llx + %lld, color=%ld]", - next->start, next->size, next->color); - - pr_info("%sHole [%llx - %llx, size %lld]%s\n", - node1, - hole_start, hole_end, hole_end - hole_start, - node2); - - kfree(node2); - kfree(node1); - - if (!--count) - break; - } -} - -struct evict_node { - struct drm_mm_node node; - struct list_head link; -}; - -static bool evict_nodes(struct drm_mm_scan *scan, - struct evict_node *nodes, - unsigned int *order, - unsigned int count, - bool use_color, - struct list_head *evict_list) -{ - struct evict_node *e, *en; - unsigned int i; - - for (i = 0; i < count; i++) { - e = &nodes[order ? order[i] : i]; - list_add(&e->link, evict_list); - if (drm_mm_scan_add_block(scan, &e->node)) - break; - } - list_for_each_entry_safe(e, en, evict_list, link) { - if (!drm_mm_scan_remove_block(scan, &e->node)) - list_del(&e->link); - } - if (list_empty(evict_list)) { - pr_err("Failed to find eviction: size=%lld [avail=%d], align=%lld (color=%lu)\n", - scan->size, count, scan->alignment, scan->color); - return false; - } - - list_for_each_entry(e, evict_list, link) - drm_mm_remove_node(&e->node); - - if (use_color) { - struct drm_mm_node *node; - - while ((node = drm_mm_scan_color_evict(scan))) { - e = container_of(node, typeof(*e), node); - drm_mm_remove_node(&e->node); - list_add(&e->link, evict_list); - } - } else { - if (drm_mm_scan_color_evict(scan)) { - pr_err("drm_mm_scan_color_evict unexpectedly reported overlapping nodes!\n"); - return false; - } - } - - return true; -} - -static bool evict_nothing(struct drm_mm *mm, - unsigned int total_size, - struct evict_node *nodes) -{ - struct drm_mm_scan scan; - LIST_HEAD(evict_list); - struct evict_node *e; - struct drm_mm_node *node; - unsigned int n; - - drm_mm_scan_init(&scan, mm, 1, 0, 0, 0); - for (n = 0; n < total_size; n++) { - e = &nodes[n]; - list_add(&e->link, &evict_list); - drm_mm_scan_add_block(&scan, &e->node); - } - list_for_each_entry(e, &evict_list, link) - drm_mm_scan_remove_block(&scan, &e->node); - - for (n = 0; n < total_size; n++) { - e = &nodes[n]; - - if (!drm_mm_node_allocated(&e->node)) { - pr_err("node[%d] no longer allocated!\n", n); - return false; - } - - e->link.next = NULL; - } - - drm_mm_for_each_node(node, mm) { - e = container_of(node, typeof(*e), node); - e->link.next = &e->link; - } - - for (n = 0; n < total_size; n++) { - e = &nodes[n]; - - if (!e->link.next) { - pr_err("node[%d] no longer connected!\n", n); - return false; - } - } - - return assert_continuous(mm, nodes[0].node.size); -} - -static bool evict_everything(struct drm_mm *mm, - unsigned int total_size, - struct evict_node *nodes) -{ - struct drm_mm_scan scan; - LIST_HEAD(evict_list); - struct evict_node *e; - unsigned int n; - int err; - - drm_mm_scan_init(&scan, mm, total_size, 0, 0, 0); - for (n = 0; n < total_size; n++) { - e = &nodes[n]; - list_add(&e->link, &evict_list); - if (drm_mm_scan_add_block(&scan, &e->node)) - break; - } - - err = 0; - list_for_each_entry(e, &evict_list, link) { - if (!drm_mm_scan_remove_block(&scan, &e->node)) { - if (!err) { - pr_err("Node %lld not marked for eviction!\n", - e->node.start); - err = -EINVAL; - } - } - } - if (err) - return false; - - list_for_each_entry(e, &evict_list, link) - drm_mm_remove_node(&e->node); - - if (!assert_one_hole(mm, 0, total_size)) - return false; - - list_for_each_entry(e, &evict_list, link) { - err = drm_mm_reserve_node(mm, &e->node); - if (err) { - pr_err("Failed to reinsert node after eviction: start=%llx\n", - e->node.start); - return false; - } - } - - return assert_continuous(mm, nodes[0].node.size); -} - -static int evict_something(struct drm_mm *mm, - u64 range_start, u64 range_end, - struct evict_node *nodes, - unsigned int *order, - unsigned int count, - unsigned int size, - unsigned int alignment, - const struct insert_mode *mode) -{ - struct drm_mm_scan scan; - LIST_HEAD(evict_list); - struct evict_node *e; - struct drm_mm_node tmp; - int err; - - drm_mm_scan_init_with_range(&scan, mm, - size, alignment, 0, - range_start, range_end, - mode->mode); - if (!evict_nodes(&scan, - nodes, order, count, false, - &evict_list)) - return -EINVAL; - - memset(&tmp, 0, sizeof(tmp)); - err = drm_mm_insert_node_generic(mm, &tmp, size, alignment, 0, - DRM_MM_INSERT_EVICT); - if (err) { - pr_err("Failed to insert into eviction hole: size=%d, align=%d\n", - size, alignment); - show_scan(&scan); - show_holes(mm, 3); - return err; - } - - if (tmp.start < range_start || tmp.start + tmp.size > range_end) { - pr_err("Inserted [address=%llu + %llu] did not fit into the request range [%llu, %llu]\n", - tmp.start, tmp.size, range_start, range_end); - err = -EINVAL; - } - - if (!assert_node(&tmp, mm, size, alignment, 0) || - drm_mm_hole_follows(&tmp)) { - pr_err("Inserted did not fill the eviction hole: size=%lld [%d], align=%d [rem=%lld], start=%llx, hole-follows?=%d\n", - tmp.size, size, - alignment, misalignment(&tmp, alignment), - tmp.start, drm_mm_hole_follows(&tmp)); - err = -EINVAL; - } - - drm_mm_remove_node(&tmp); - if (err) - return err; - - list_for_each_entry(e, &evict_list, link) { - err = drm_mm_reserve_node(mm, &e->node); - if (err) { - pr_err("Failed to reinsert node after eviction: start=%llx\n", - e->node.start); - return err; - } - } - - if (!assert_continuous(mm, nodes[0].node.size)) { - pr_err("range is no longer continuous\n"); - return -EINVAL; - } - - return 0; -} - -static int igt_evict(void *ignored) -{ - DRM_RND_STATE(prng, random_seed); - const unsigned int size = 8192; - const struct insert_mode *mode; - struct drm_mm mm; - struct evict_node *nodes; - struct drm_mm_node *node, *next; - unsigned int *order, n; - int ret, err; - - /* Here we populate a full drm_mm and then try and insert a new node - * by evicting other nodes in a random order. The drm_mm_scan should - * pick the first matching hole it finds from the random list. We - * repeat that for different allocation strategies, alignments and - * sizes to try and stress the hole finder. - */ - - ret = -ENOMEM; - nodes = vzalloc(array_size(size, sizeof(*nodes))); - if (!nodes) - goto err; - - order = drm_random_order(size, &prng); - if (!order) - goto err_nodes; - - ret = -EINVAL; - drm_mm_init(&mm, 0, size); - for (n = 0; n < size; n++) { - err = drm_mm_insert_node(&mm, &nodes[n].node, 1); - if (err) { - pr_err("insert failed, step %d\n", n); - ret = err; - goto out; - } - } - - /* First check that using the scanner doesn't break the mm */ - if (!evict_nothing(&mm, size, nodes)) { - pr_err("evict_nothing() failed\n"); - goto out; - } - if (!evict_everything(&mm, size, nodes)) { - pr_err("evict_everything() failed\n"); - goto out; - } - - for (mode = evict_modes; mode->name; mode++) { - for (n = 1; n <= size; n <<= 1) { - drm_random_reorder(order, size, &prng); - err = evict_something(&mm, 0, U64_MAX, - nodes, order, size, - n, 1, - mode); - if (err) { - pr_err("%s evict_something(size=%u) failed\n", - mode->name, n); - ret = err; - goto out; - } - } - - for (n = 1; n < size; n <<= 1) { - drm_random_reorder(order, size, &prng); - err = evict_something(&mm, 0, U64_MAX, - nodes, order, size, - size/2, n, - mode); - if (err) { - pr_err("%s evict_something(size=%u, alignment=%u) failed\n", - mode->name, size/2, n); - ret = err; - goto out; - } - } - - for_each_prime_number_from(n, 1, min(size, max_prime)) { - unsigned int nsize = (size - n + 1) / 2; - - DRM_MM_BUG_ON(!nsize); - - drm_random_reorder(order, size, &prng); - err = evict_something(&mm, 0, U64_MAX, - nodes, order, size, - nsize, n, - mode); - if (err) { - pr_err("%s evict_something(size=%u, alignment=%u) failed\n", - mode->name, nsize, n); - ret = err; - goto out; - } - } - - cond_resched(); - } - - ret = 0; -out: - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - drm_mm_takedown(&mm); - kfree(order); -err_nodes: - vfree(nodes); -err: - return ret; -} - -static int igt_evict_range(void *ignored) -{ - DRM_RND_STATE(prng, random_seed); - const unsigned int size = 8192; - const unsigned int range_size = size / 2; - const unsigned int range_start = size / 4; - const unsigned int range_end = range_start + range_size; - const struct insert_mode *mode; - struct drm_mm mm; - struct evict_node *nodes; - struct drm_mm_node *node, *next; - unsigned int *order, n; - int ret, err; - - /* Like igt_evict() but now we are limiting the search to a - * small portion of the full drm_mm. - */ - - ret = -ENOMEM; - nodes = vzalloc(array_size(size, sizeof(*nodes))); - if (!nodes) - goto err; - - order = drm_random_order(size, &prng); - if (!order) - goto err_nodes; - - ret = -EINVAL; - drm_mm_init(&mm, 0, size); - for (n = 0; n < size; n++) { - err = drm_mm_insert_node(&mm, &nodes[n].node, 1); - if (err) { - pr_err("insert failed, step %d\n", n); - ret = err; - goto out; - } - } - - for (mode = evict_modes; mode->name; mode++) { - for (n = 1; n <= range_size; n <<= 1) { - drm_random_reorder(order, size, &prng); - err = evict_something(&mm, range_start, range_end, - nodes, order, size, - n, 1, - mode); - if (err) { - pr_err("%s evict_something(size=%u) failed with range [%u, %u]\n", - mode->name, n, range_start, range_end); - goto out; - } - } - - for (n = 1; n <= range_size; n <<= 1) { - drm_random_reorder(order, size, &prng); - err = evict_something(&mm, range_start, range_end, - nodes, order, size, - range_size/2, n, - mode); - if (err) { - pr_err("%s evict_something(size=%u, alignment=%u) failed with range [%u, %u]\n", - mode->name, range_size/2, n, range_start, range_end); - goto out; - } - } - - for_each_prime_number_from(n, 1, min(range_size, max_prime)) { - unsigned int nsize = (range_size - n + 1) / 2; - - DRM_MM_BUG_ON(!nsize); - - drm_random_reorder(order, size, &prng); - err = evict_something(&mm, range_start, range_end, - nodes, order, size, - nsize, n, - mode); - if (err) { - pr_err("%s evict_something(size=%u, alignment=%u) failed with range [%u, %u]\n", - mode->name, nsize, n, range_start, range_end); - goto out; - } - } - - cond_resched(); - } - - ret = 0; -out: - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - drm_mm_takedown(&mm); - kfree(order); -err_nodes: - vfree(nodes); -err: - return ret; -} - -static unsigned int node_index(const struct drm_mm_node *node) -{ - return div64_u64(node->start, node->size); -} - -static int igt_topdown(void *ignored) -{ - const struct insert_mode *topdown = &insert_modes[TOPDOWN]; - DRM_RND_STATE(prng, random_seed); - const unsigned int count = 8192; - unsigned int size; - unsigned long *bitmap; - struct drm_mm mm; - struct drm_mm_node *nodes, *node, *next; - unsigned int *order, n, m, o = 0; - int ret; - - /* When allocating top-down, we expect to be returned a node - * from a suitable hole at the top of the drm_mm. We check that - * the returned node does match the highest available slot. - */ - - ret = -ENOMEM; - nodes = vzalloc(array_size(count, sizeof(*nodes))); - if (!nodes) - goto err; - - bitmap = bitmap_zalloc(count, GFP_KERNEL); - if (!bitmap) - goto err_nodes; - - order = drm_random_order(count, &prng); - if (!order) - goto err_bitmap; - - ret = -EINVAL; - for (size = 1; size <= 64; size <<= 1) { - drm_mm_init(&mm, 0, size*count); - for (n = 0; n < count; n++) { - if (!expect_insert(&mm, &nodes[n], - size, 0, n, - topdown)) { - pr_err("insert failed, size %u step %d\n", size, n); - goto out; - } - - if (drm_mm_hole_follows(&nodes[n])) { - pr_err("hole after topdown insert %d, start=%llx\n, size=%u", - n, nodes[n].start, size); - goto out; - } - - if (!assert_one_hole(&mm, 0, size*(count - n - 1))) - goto out; - } - - if (!assert_continuous(&mm, size)) - goto out; - - drm_random_reorder(order, count, &prng); - for_each_prime_number_from(n, 1, min(count, max_prime)) { - for (m = 0; m < n; m++) { - node = &nodes[order[(o + m) % count]]; - drm_mm_remove_node(node); - __set_bit(node_index(node), bitmap); - } - - for (m = 0; m < n; m++) { - unsigned int last; - - node = &nodes[order[(o + m) % count]]; - if (!expect_insert(&mm, node, - size, 0, 0, - topdown)) { - pr_err("insert failed, step %d/%d\n", m, n); - goto out; - } - - if (drm_mm_hole_follows(node)) { - pr_err("hole after topdown insert %d/%d, start=%llx\n", - m, n, node->start); - goto out; - } - - last = find_last_bit(bitmap, count); - if (node_index(node) != last) { - pr_err("node %d/%d, size %d, not inserted into upmost hole, expected %d, found %d\n", - m, n, size, last, node_index(node)); - goto out; - } - - __clear_bit(last, bitmap); - } - - DRM_MM_BUG_ON(find_first_bit(bitmap, count) != count); - - o += n; - } - - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - DRM_MM_BUG_ON(!drm_mm_clean(&mm)); - cond_resched(); - } - - ret = 0; -out: - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - drm_mm_takedown(&mm); - kfree(order); -err_bitmap: - bitmap_free(bitmap); -err_nodes: - vfree(nodes); -err: - return ret; -} - -static int igt_bottomup(void *ignored) -{ - const struct insert_mode *bottomup = &insert_modes[BOTTOMUP]; - DRM_RND_STATE(prng, random_seed); - const unsigned int count = 8192; - unsigned int size; - unsigned long *bitmap; - struct drm_mm mm; - struct drm_mm_node *nodes, *node, *next; - unsigned int *order, n, m, o = 0; - int ret; - - /* Like igt_topdown, but instead of searching for the last hole, - * we search for the first. - */ - - ret = -ENOMEM; - nodes = vzalloc(array_size(count, sizeof(*nodes))); - if (!nodes) - goto err; - - bitmap = bitmap_zalloc(count, GFP_KERNEL); - if (!bitmap) - goto err_nodes; - - order = drm_random_order(count, &prng); - if (!order) - goto err_bitmap; - - ret = -EINVAL; - for (size = 1; size <= 64; size <<= 1) { - drm_mm_init(&mm, 0, size*count); - for (n = 0; n < count; n++) { - if (!expect_insert(&mm, &nodes[n], - size, 0, n, - bottomup)) { - pr_err("bottomup insert failed, size %u step %d\n", size, n); - goto out; - } - - if (!assert_one_hole(&mm, size*(n + 1), size*count)) - goto out; - } - - if (!assert_continuous(&mm, size)) - goto out; - - drm_random_reorder(order, count, &prng); - for_each_prime_number_from(n, 1, min(count, max_prime)) { - for (m = 0; m < n; m++) { - node = &nodes[order[(o + m) % count]]; - drm_mm_remove_node(node); - __set_bit(node_index(node), bitmap); - } - - for (m = 0; m < n; m++) { - unsigned int first; - - node = &nodes[order[(o + m) % count]]; - if (!expect_insert(&mm, node, - size, 0, 0, - bottomup)) { - pr_err("insert failed, step %d/%d\n", m, n); - goto out; - } - - first = find_first_bit(bitmap, count); - if (node_index(node) != first) { - pr_err("node %d/%d not inserted into bottom hole, expected %d, found %d\n", - m, n, first, node_index(node)); - goto out; - } - __clear_bit(first, bitmap); - } - - DRM_MM_BUG_ON(find_first_bit(bitmap, count) != count); - - o += n; - } - - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - DRM_MM_BUG_ON(!drm_mm_clean(&mm)); - cond_resched(); - } - - ret = 0; -out: - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - drm_mm_takedown(&mm); - kfree(order); -err_bitmap: - bitmap_free(bitmap); -err_nodes: - vfree(nodes); -err: - return ret; -} - -static int __igt_once(unsigned int mode) -{ - struct drm_mm mm; - struct drm_mm_node rsvd_lo, rsvd_hi, node; - int err; - - drm_mm_init(&mm, 0, 7); - - memset(&rsvd_lo, 0, sizeof(rsvd_lo)); - rsvd_lo.start = 1; - rsvd_lo.size = 1; - err = drm_mm_reserve_node(&mm, &rsvd_lo); - if (err) { - pr_err("Could not reserve low node\n"); - goto err; - } - - memset(&rsvd_hi, 0, sizeof(rsvd_hi)); - rsvd_hi.start = 5; - rsvd_hi.size = 1; - err = drm_mm_reserve_node(&mm, &rsvd_hi); - if (err) { - pr_err("Could not reserve low node\n"); - goto err_lo; - } - - if (!drm_mm_hole_follows(&rsvd_lo) || !drm_mm_hole_follows(&rsvd_hi)) { - pr_err("Expected a hole after lo and high nodes!\n"); - err = -EINVAL; - goto err_hi; - } - - memset(&node, 0, sizeof(node)); - err = drm_mm_insert_node_generic(&mm, &node, 2, 0, 0, mode); - if (err) { - pr_err("Could not insert the node into the available hole!\n"); - err = -EINVAL; - goto err_hi; - } - - drm_mm_remove_node(&node); -err_hi: - drm_mm_remove_node(&rsvd_hi); -err_lo: - drm_mm_remove_node(&rsvd_lo); -err: - drm_mm_takedown(&mm); - return err; -} - -static int igt_lowest(void *ignored) -{ - return __igt_once(DRM_MM_INSERT_LOW); -} - -static int igt_highest(void *ignored) -{ - return __igt_once(DRM_MM_INSERT_HIGH); -} - -static void separate_adjacent_colors(const struct drm_mm_node *node, - unsigned long color, - u64 *start, - u64 *end) -{ - if (drm_mm_node_allocated(node) && node->color != color) - ++*start; - - node = list_next_entry(node, node_list); - if (drm_mm_node_allocated(node) && node->color != color) - --*end; -} - -static bool colors_abutt(const struct drm_mm_node *node) -{ - if (!drm_mm_hole_follows(node) && - drm_mm_node_allocated(list_next_entry(node, node_list))) { - pr_err("colors abutt; %ld [%llx + %llx] is next to %ld [%llx + %llx]!\n", - node->color, node->start, node->size, - list_next_entry(node, node_list)->color, - list_next_entry(node, node_list)->start, - list_next_entry(node, node_list)->size); - return true; - } - - return false; -} - -static int igt_color(void *ignored) -{ - const unsigned int count = min(4096u, max_iterations); - const struct insert_mode *mode; - struct drm_mm mm; - struct drm_mm_node *node, *nn; - unsigned int n; - int ret = -EINVAL, err; - - /* Color adjustment complicates everything. First we just check - * that when we insert a node we apply any color_adjustment callback. - * The callback we use should ensure that there is a gap between - * any two nodes, and so after each insertion we check that those - * holes are inserted and that they are preserved. - */ - - drm_mm_init(&mm, 0, U64_MAX); - - for (n = 1; n <= count; n++) { - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) { - ret = -ENOMEM; - goto out; - } - - if (!expect_insert(&mm, node, - n, 0, n, - &insert_modes[0])) { - pr_err("insert failed, step %d\n", n); - kfree(node); - goto out; - } - } - - drm_mm_for_each_node_safe(node, nn, &mm) { - if (node->color != node->size) { - pr_err("invalid color stored: expected %lld, found %ld\n", - node->size, node->color); - - goto out; - } - - drm_mm_remove_node(node); - kfree(node); - } - - /* Now, let's start experimenting with applying a color callback */ - mm.color_adjust = separate_adjacent_colors; - for (mode = insert_modes; mode->name; mode++) { - u64 last; - - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) { - ret = -ENOMEM; - goto out; - } - - node->size = 1 + 2*count; - node->color = node->size; - - err = drm_mm_reserve_node(&mm, node); - if (err) { - pr_err("initial reserve failed!\n"); - ret = err; - goto out; - } - - last = node->start + node->size; - - for (n = 1; n <= count; n++) { - int rem; - - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) { - ret = -ENOMEM; - goto out; - } - - node->start = last; - node->size = n + count; - node->color = node->size; - - err = drm_mm_reserve_node(&mm, node); - if (err != -ENOSPC) { - pr_err("reserve %d did not report color overlap! err=%d\n", - n, err); - goto out; - } - - node->start += n + 1; - rem = misalignment(node, n + count); - node->start += n + count - rem; - - err = drm_mm_reserve_node(&mm, node); - if (err) { - pr_err("reserve %d failed, err=%d\n", n, err); - ret = err; - goto out; - } - - last = node->start + node->size; - } - - for (n = 1; n <= count; n++) { - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) { - ret = -ENOMEM; - goto out; - } - - if (!expect_insert(&mm, node, - n, n, n, - mode)) { - pr_err("%s insert failed, step %d\n", - mode->name, n); - kfree(node); - goto out; - } - } - - drm_mm_for_each_node_safe(node, nn, &mm) { - u64 rem; - - if (node->color != node->size) { - pr_err("%s invalid color stored: expected %lld, found %ld\n", - mode->name, node->size, node->color); - - goto out; - } - - if (colors_abutt(node)) - goto out; - - div64_u64_rem(node->start, node->size, &rem); - if (rem) { - pr_err("%s colored node misaligned, start=%llx expected alignment=%lld [rem=%lld]\n", - mode->name, node->start, node->size, rem); - goto out; - } - - drm_mm_remove_node(node); - kfree(node); - } - - cond_resched(); - } - - ret = 0; -out: - drm_mm_for_each_node_safe(node, nn, &mm) { - drm_mm_remove_node(node); - kfree(node); - } - drm_mm_takedown(&mm); - return ret; -} - -static int evict_color(struct drm_mm *mm, - u64 range_start, u64 range_end, - struct evict_node *nodes, - unsigned int *order, - unsigned int count, - unsigned int size, - unsigned int alignment, - unsigned long color, - const struct insert_mode *mode) -{ - struct drm_mm_scan scan; - LIST_HEAD(evict_list); - struct evict_node *e; - struct drm_mm_node tmp; - int err; - - drm_mm_scan_init_with_range(&scan, mm, - size, alignment, color, - range_start, range_end, - mode->mode); - if (!evict_nodes(&scan, - nodes, order, count, true, - &evict_list)) - return -EINVAL; - - memset(&tmp, 0, sizeof(tmp)); - err = drm_mm_insert_node_generic(mm, &tmp, size, alignment, color, - DRM_MM_INSERT_EVICT); - if (err) { - pr_err("Failed to insert into eviction hole: size=%d, align=%d, color=%lu, err=%d\n", - size, alignment, color, err); - show_scan(&scan); - show_holes(mm, 3); - return err; - } - - if (tmp.start < range_start || tmp.start + tmp.size > range_end) { - pr_err("Inserted [address=%llu + %llu] did not fit into the request range [%llu, %llu]\n", - tmp.start, tmp.size, range_start, range_end); - err = -EINVAL; - } - - if (colors_abutt(&tmp)) - err = -EINVAL; - - if (!assert_node(&tmp, mm, size, alignment, color)) { - pr_err("Inserted did not fit the eviction hole: size=%lld [%d], align=%d [rem=%lld], start=%llx\n", - tmp.size, size, - alignment, misalignment(&tmp, alignment), tmp.start); - err = -EINVAL; - } - - drm_mm_remove_node(&tmp); - if (err) - return err; - - list_for_each_entry(e, &evict_list, link) { - err = drm_mm_reserve_node(mm, &e->node); - if (err) { - pr_err("Failed to reinsert node after eviction: start=%llx\n", - e->node.start); - return err; - } - } - - cond_resched(); - return 0; -} - -static int igt_color_evict(void *ignored) -{ - DRM_RND_STATE(prng, random_seed); - const unsigned int total_size = min(8192u, max_iterations); - const struct insert_mode *mode; - unsigned long color = 0; - struct drm_mm mm; - struct evict_node *nodes; - struct drm_mm_node *node, *next; - unsigned int *order, n; - int ret, err; - - /* Check that the drm_mm_scan also honours color adjustment when - * choosing its victims to create a hole. Our color_adjust does not - * allow two nodes to be placed together without an intervening hole - * enlarging the set of victims that must be evicted. - */ - - ret = -ENOMEM; - nodes = vzalloc(array_size(total_size, sizeof(*nodes))); - if (!nodes) - goto err; - - order = drm_random_order(total_size, &prng); - if (!order) - goto err_nodes; - - ret = -EINVAL; - drm_mm_init(&mm, 0, 2*total_size - 1); - mm.color_adjust = separate_adjacent_colors; - for (n = 0; n < total_size; n++) { - if (!expect_insert(&mm, &nodes[n].node, - 1, 0, color++, - &insert_modes[0])) { - pr_err("insert failed, step %d\n", n); - goto out; - } - } - - for (mode = evict_modes; mode->name; mode++) { - for (n = 1; n <= total_size; n <<= 1) { - drm_random_reorder(order, total_size, &prng); - err = evict_color(&mm, 0, U64_MAX, - nodes, order, total_size, - n, 1, color++, - mode); - if (err) { - pr_err("%s evict_color(size=%u) failed\n", - mode->name, n); - goto out; - } - } - - for (n = 1; n < total_size; n <<= 1) { - drm_random_reorder(order, total_size, &prng); - err = evict_color(&mm, 0, U64_MAX, - nodes, order, total_size, - total_size/2, n, color++, - mode); - if (err) { - pr_err("%s evict_color(size=%u, alignment=%u) failed\n", - mode->name, total_size/2, n); - goto out; - } - } - - for_each_prime_number_from(n, 1, min(total_size, max_prime)) { - unsigned int nsize = (total_size - n + 1) / 2; - - DRM_MM_BUG_ON(!nsize); - - drm_random_reorder(order, total_size, &prng); - err = evict_color(&mm, 0, U64_MAX, - nodes, order, total_size, - nsize, n, color++, - mode); - if (err) { - pr_err("%s evict_color(size=%u, alignment=%u) failed\n", - mode->name, nsize, n); - goto out; - } - } - - cond_resched(); - } - - ret = 0; -out: - if (ret) - show_mm(&mm); - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - drm_mm_takedown(&mm); - kfree(order); -err_nodes: - vfree(nodes); -err: - return ret; -} - -static int igt_color_evict_range(void *ignored) -{ - DRM_RND_STATE(prng, random_seed); - const unsigned int total_size = 8192; - const unsigned int range_size = total_size / 2; - const unsigned int range_start = total_size / 4; - const unsigned int range_end = range_start + range_size; - const struct insert_mode *mode; - unsigned long color = 0; - struct drm_mm mm; - struct evict_node *nodes; - struct drm_mm_node *node, *next; - unsigned int *order, n; - int ret, err; - - /* Like igt_color_evict(), but limited to small portion of the full - * drm_mm range. - */ - - ret = -ENOMEM; - nodes = vzalloc(array_size(total_size, sizeof(*nodes))); - if (!nodes) - goto err; - - order = drm_random_order(total_size, &prng); - if (!order) - goto err_nodes; - - ret = -EINVAL; - drm_mm_init(&mm, 0, 2*total_size - 1); - mm.color_adjust = separate_adjacent_colors; - for (n = 0; n < total_size; n++) { - if (!expect_insert(&mm, &nodes[n].node, - 1, 0, color++, - &insert_modes[0])) { - pr_err("insert failed, step %d\n", n); - goto out; - } - } - - for (mode = evict_modes; mode->name; mode++) { - for (n = 1; n <= range_size; n <<= 1) { - drm_random_reorder(order, range_size, &prng); - err = evict_color(&mm, range_start, range_end, - nodes, order, total_size, - n, 1, color++, - mode); - if (err) { - pr_err("%s evict_color(size=%u) failed for range [%x, %x]\n", - mode->name, n, range_start, range_end); - goto out; - } - } - - for (n = 1; n < range_size; n <<= 1) { - drm_random_reorder(order, total_size, &prng); - err = evict_color(&mm, range_start, range_end, - nodes, order, total_size, - range_size/2, n, color++, - mode); - if (err) { - pr_err("%s evict_color(size=%u, alignment=%u) failed for range [%x, %x]\n", - mode->name, total_size/2, n, range_start, range_end); - goto out; - } - } - - for_each_prime_number_from(n, 1, min(range_size, max_prime)) { - unsigned int nsize = (range_size - n + 1) / 2; - - DRM_MM_BUG_ON(!nsize); - - drm_random_reorder(order, total_size, &prng); - err = evict_color(&mm, range_start, range_end, - nodes, order, total_size, - nsize, n, color++, - mode); - if (err) { - pr_err("%s evict_color(size=%u, alignment=%u) failed for range [%x, %x]\n", - mode->name, nsize, n, range_start, range_end); - goto out; - } - } - - cond_resched(); - } - - ret = 0; -out: - if (ret) - show_mm(&mm); - drm_mm_for_each_node_safe(node, next, &mm) - drm_mm_remove_node(node); - drm_mm_takedown(&mm); - kfree(order); -err_nodes: - vfree(nodes); -err: - return ret; -} - -#include "drm_selftest.c" - -static int __init test_drm_mm_init(void) -{ - int err; - - while (!random_seed) - random_seed = get_random_int(); - - pr_info("Testing DRM range manager (struct drm_mm), with random_seed=0x%x max_iterations=%u max_prime=%u\n", - random_seed, max_iterations, max_prime); - err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL); - - return err > 0 ? 0 : err; -} - -static void __exit test_drm_mm_exit(void) -{ -} - -module_init(test_drm_mm_init); -module_exit(test_drm_mm_exit); - -module_param(random_seed, uint, 0400); -module_param(max_iterations, uint, 0400); -module_param(max_prime, uint, 0400); - -MODULE_AUTHOR("Intel Corporation"); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index cff59189598f..91b70f7d2769 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -2,4 +2,4 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o drm_damage_helper_test.o \ drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o drm_plane_helper_test.o \ - drm_dp_mst_helper_test.o drm_framebuffer_test.o drm_buddy_test.o + drm_dp_mst_helper_test.o drm_framebuffer_test.o drm_buddy_test.o drm_mm_test.o diff --git a/drivers/gpu/drm/tests/drm_mm_test.c b/drivers/gpu/drm/tests/drm_mm_test.c new file mode 100644 index 000000000000..1e2c1aa524bd --- /dev/null +++ b/drivers/gpu/drm/tests/drm_mm_test.c @@ -0,0 +1,2255 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Test cases for the drm_mm range manager + * + * Copyright (c) 2022 Arthur Grillo + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "../lib/drm_random.h" + +static unsigned int random_seed; +static unsigned int max_iterations = 8192; +static unsigned int max_prime = 128; + +enum { + BEST, + BOTTOMUP, + TOPDOWN, + EVICT, +}; + +static const struct insert_mode { + const char *name; + enum drm_mm_insert_mode mode; +} insert_modes[] = { + [BEST] = { "best", DRM_MM_INSERT_BEST }, + [BOTTOMUP] = { "bottom-up", DRM_MM_INSERT_LOW }, + [TOPDOWN] = { "top-down", DRM_MM_INSERT_HIGH }, + [EVICT] = { "evict", DRM_MM_INSERT_EVICT }, + {} +}, evict_modes[] = { + { "bottom-up", DRM_MM_INSERT_LOW }, + { "top-down", DRM_MM_INSERT_HIGH }, + {} +}; + +static bool assert_no_holes(struct kunit *test, const struct drm_mm *mm) +{ + struct drm_mm_node *hole; + u64 hole_start, __always_unused hole_end; + unsigned long count; + + count = 0; + drm_mm_for_each_hole(hole, mm, hole_start, hole_end) + count++; + if (count) { + KUNIT_FAIL(test, + "Expected to find no holes (after reserve), found %lu instead\n", count); + return false; + } + + drm_mm_for_each_node(hole, mm) { + if (drm_mm_hole_follows(hole)) { + KUNIT_FAIL(test, "Hole follows node, expected none!\n"); + return false; + } + } + + return true; +} + +static bool assert_one_hole(struct kunit *test, const struct drm_mm *mm, u64 start, u64 end) +{ + struct drm_mm_node *hole; + u64 hole_start, hole_end; + unsigned long count; + bool ok = true; + + if (end <= start) + return true; + + count = 0; + drm_mm_for_each_hole(hole, mm, hole_start, hole_end) { + if (start != hole_start || end != hole_end) { + if (ok) + KUNIT_FAIL(test, + "empty mm has incorrect hole, found (%llx, %llx), expect (%llx, %llx)\n", + hole_start, hole_end, start, end); + ok = false; + } + count++; + } + if (count != 1) { + KUNIT_FAIL(test, "Expected to find one hole, found %lu instead\n", count); + ok = false; + } + + return ok; +} + +static bool assert_continuous(struct kunit *test, const struct drm_mm *mm, u64 size) +{ + struct drm_mm_node *node, *check, *found; + unsigned long n; + u64 addr; + + if (!assert_no_holes(test, mm)) + return false; + + n = 0; + addr = 0; + drm_mm_for_each_node(node, mm) { + if (node->start != addr) { + KUNIT_FAIL(test, "node[%ld] list out of order, expected %llx found %llx\n", + n, addr, node->start); + return false; + } + + if (node->size != size) { + KUNIT_FAIL(test, "node[%ld].size incorrect, expected %llx, found %llx\n", + n, size, node->size); + return false; + } + + if (drm_mm_hole_follows(node)) { + KUNIT_FAIL(test, "node[%ld] is followed by a hole!\n", n); + return false; + } + + found = NULL; + drm_mm_for_each_node_in_range(check, mm, addr, addr + size) { + if (node != check) { + KUNIT_FAIL(test, + "lookup return wrong node, expected start %llx, found %llx\n", + node->start, check->start); + return false; + } + found = check; + } + if (!found) { + KUNIT_FAIL(test, "lookup failed for node %llx + %llx\n", addr, size); + return false; + } + + addr += size; + n++; + } + + return true; +} + +static u64 misalignment(struct drm_mm_node *node, u64 alignment) +{ + u64 rem; + + if (!alignment) + return 0; + + div64_u64_rem(node->start, alignment, &rem); + return rem; +} + +static bool assert_node(struct kunit *test, struct drm_mm_node *node, struct drm_mm *mm, + u64 size, u64 alignment, unsigned long color) +{ + bool ok = true; + + if (!drm_mm_node_allocated(node) || node->mm != mm) { + KUNIT_FAIL(test, "node not allocated\n"); + ok = false; + } + + if (node->size != size) { + KUNIT_FAIL(test, "node has wrong size, found %llu, expected %llu\n", + node->size, size); + ok = false; + } + + if (misalignment(node, alignment)) { + KUNIT_FAIL(test, + "node is misaligned, start %llx rem %llu, expected alignment %llu\n", + node->start, misalignment(node, alignment), alignment); + ok = false; + } + + if (node->color != color) { + KUNIT_FAIL(test, "node has wrong color, found %lu, expected %lu\n", + node->color, color); + ok = false; + } + + return ok; +} + +static void igt_mm_init(struct kunit *test) +{ + const unsigned int size = 4096; + struct drm_mm mm; + struct drm_mm_node tmp; + + /* Start with some simple checks on initialising the struct drm_mm */ + memset(&mm, 0, sizeof(mm)); + KUNIT_ASSERT_FALSE_MSG(test, drm_mm_initialized(&mm), + "zeroed mm claims to be initialized\n"); + + memset(&mm, 0xff, sizeof(mm)); + drm_mm_init(&mm, 0, size); + if (!drm_mm_initialized(&mm)) { + KUNIT_FAIL(test, "mm claims not to be initialized\n"); + goto out; + } + + if (!drm_mm_clean(&mm)) { + KUNIT_FAIL(test, "mm not empty on creation\n"); + goto out; + } + + /* After creation, it should all be one massive hole */ + if (!assert_one_hole(test, &mm, 0, size)) { + KUNIT_FAIL(test, ""); + goto out; + } + + memset(&tmp, 0, sizeof(tmp)); + tmp.start = 0; + tmp.size = size; + if (drm_mm_reserve_node(&mm, &tmp)) { + KUNIT_FAIL(test, "failed to reserve whole drm_mm\n"); + goto out; + } + + /* After filling the range entirely, there should be no holes */ + if (!assert_no_holes(test, &mm)) { + KUNIT_FAIL(test, ""); + goto out; + } + + /* And then after emptying it again, the massive hole should be back */ + drm_mm_remove_node(&tmp); + if (!assert_one_hole(test, &mm, 0, size)) { + KUNIT_FAIL(test, ""); + goto out; + } + +out: + drm_mm_takedown(&mm); +} + +static void igt_mm_debug(struct kunit *test) +{ + struct drm_mm mm; + struct drm_mm_node nodes[2]; + + /* Create a small drm_mm with a couple of nodes and a few holes, and + * check that the debug iterator doesn't explode over a trivial drm_mm. + */ + + drm_mm_init(&mm, 0, 4096); + + memset(nodes, 0, sizeof(nodes)); + nodes[0].start = 512; + nodes[0].size = 1024; + KUNIT_ASSERT_FALSE_MSG(test, drm_mm_reserve_node(&mm, &nodes[0]), + "failed to reserve node[0] {start=%lld, size=%lld)\n", + nodes[0].start, nodes[0].size); + + nodes[1].size = 1024; + nodes[1].start = 4096 - 512 - nodes[1].size; + KUNIT_ASSERT_FALSE_MSG(test, drm_mm_reserve_node(&mm, &nodes[1]), + "failed to reserve node[0] {start=%lld, size=%lld)\n", + nodes[0].start, nodes[0].size); +} + +static struct drm_mm_node *set_node(struct drm_mm_node *node, + u64 start, u64 size) +{ + node->start = start; + node->size = size; + return node; +} + +static bool expect_reserve_fail(struct kunit *test, struct drm_mm *mm, struct drm_mm_node *node) +{ + int err; + + err = drm_mm_reserve_node(mm, node); + if (likely(err == -ENOSPC)) + return true; + + if (!err) { + KUNIT_FAIL(test, "impossible reserve succeeded, node %llu + %llu\n", + node->start, node->size); + drm_mm_remove_node(node); + } else { + KUNIT_FAIL(test, + "impossible reserve failed with wrong error %d [expected %d], node %llu + %llu\n", + err, -ENOSPC, node->start, node->size); + } + return false; +} + +static bool check_reserve_boundaries(struct kunit *test, struct drm_mm *mm, + unsigned int count, + u64 size) +{ + const struct boundary { + u64 start, size; + const char *name; + } boundaries[] = { +#define B(st, sz) { (st), (sz), "{ " #st ", " #sz "}" } + B(0, 0), + B(-size, 0), + B(size, 0), + B(size * count, 0), + B(-size, size), + B(-size, -size), + B(-size, 2 * size), + B(0, -size), + B(size, -size), + B(count * size, size), + B(count * size, -size), + B(count * size, count * size), + B(count * size, -count * size), + B(count * size, -(count + 1) * size), + B((count + 1) * size, size), + B((count + 1) * size, -size), + B((count + 1) * size, -2 * size), +#undef B + }; + struct drm_mm_node tmp = {}; + int n; + + for (n = 0; n < ARRAY_SIZE(boundaries); n++) { + if (!expect_reserve_fail(test, mm, set_node(&tmp, boundaries[n].start, + boundaries[n].size))) { + KUNIT_FAIL(test, "boundary[%d:%s] failed, count=%u, size=%lld\n", + n, boundaries[n].name, count, size); + return false; + } + } + + return true; +} + +static int __igt_reserve(struct kunit *test, unsigned int count, u64 size) +{ + DRM_RND_STATE(prng, random_seed); + struct drm_mm mm; + struct drm_mm_node tmp, *nodes, *node, *next; + unsigned int *order, n, m, o = 0; + int ret, err; + + /* For exercising drm_mm_reserve_node(struct kunit *test, ), we want to check that + * reservations outside of the drm_mm range are rejected, and to + * overlapping and otherwise already occupied ranges. Afterwards, + * the tree and nodes should be intact. + */ + + DRM_MM_BUG_ON(!count); + DRM_MM_BUG_ON(!size); + + ret = -ENOMEM; + order = drm_random_order(count, &prng); + if (!order) + goto err; + + nodes = vzalloc(array_size(count, sizeof(*nodes))); + KUNIT_ASSERT_TRUE(test, nodes); + + ret = -EINVAL; + drm_mm_init(&mm, 0, count * size); + + if (!check_reserve_boundaries(test, &mm, count, size)) + goto out; + + for (n = 0; n < count; n++) { + nodes[n].start = order[n] * size; + nodes[n].size = size; + + err = drm_mm_reserve_node(&mm, &nodes[n]); + if (err) { + KUNIT_FAIL(test, "reserve failed, step %d, start %llu\n", + n, nodes[n].start); + ret = err; + goto out; + } + + if (!drm_mm_node_allocated(&nodes[n])) { + KUNIT_FAIL(test, "reserved node not allocated! step %d, start %llu\n", + n, nodes[n].start); + goto out; + } + + if (!expect_reserve_fail(test, &mm, &nodes[n])) + goto out; + } + + /* After random insertion the nodes should be in order */ + if (!assert_continuous(test, &mm, size)) + goto out; + + /* Repeated use should then fail */ + drm_random_reorder(order, count, &prng); + for (n = 0; n < count; n++) { + if (!expect_reserve_fail(test, &mm, set_node(&tmp, order[n] * size, 1))) + goto out; + + /* Remove and reinsert should work */ + drm_mm_remove_node(&nodes[order[n]]); + err = drm_mm_reserve_node(&mm, &nodes[order[n]]); + if (err) { + KUNIT_FAIL(test, "reserve failed, step %d, start %llu\n", + n, nodes[n].start); + ret = err; + goto out; + } + } + + if (!assert_continuous(test, &mm, size)) + goto out; + + /* Overlapping use should then fail */ + for (n = 0; n < count; n++) { + if (!expect_reserve_fail(test, &mm, set_node(&tmp, 0, size * count))) + goto out; + } + for (n = 0; n < count; n++) { + if (!expect_reserve_fail(test, &mm, set_node(&tmp, size * n, size * (count - n)))) + goto out; + } + + /* Remove several, reinsert, check full */ + for_each_prime_number(n, min(max_prime, count)) { + for (m = 0; m < n; m++) { + node = &nodes[order[(o + m) % count]]; + drm_mm_remove_node(node); + } + + for (m = 0; m < n; m++) { + node = &nodes[order[(o + m) % count]]; + err = drm_mm_reserve_node(&mm, node); + if (err) { + KUNIT_FAIL(test, "reserve failed, step %d/%d, start %llu\n", + m, n, node->start); + ret = err; + goto out; + } + } + + o += n; + + if (!assert_continuous(test, &mm, size)) + goto out; + } + + ret = 0; +out: + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + drm_mm_takedown(&mm); + vfree(nodes); + kfree(order); +err: + return ret; +} + +static void igt_mm_reserve(struct kunit *test) +{ + const unsigned int count = min_t(unsigned int, BIT(10), max_iterations); + int n; + + for_each_prime_number_from(n, 1, 54) { + u64 size = BIT_ULL(n); + + KUNIT_ASSERT_FALSE(test, __igt_reserve(test, count, size - 1)); + KUNIT_ASSERT_FALSE(test, __igt_reserve(test, count, size)); + KUNIT_ASSERT_FALSE(test, __igt_reserve(test, count, size + 1)); + + cond_resched(); + } +} + +static bool expect_insert(struct kunit *test, struct drm_mm *mm, + struct drm_mm_node *node, u64 size, u64 alignment, unsigned long color, + const struct insert_mode *mode) +{ + int err; + + err = drm_mm_insert_node_generic(mm, node, + size, alignment, color, + mode->mode); + if (err) { + KUNIT_FAIL(test, + "insert (size=%llu, alignment=%llu, color=%lu, mode=%s) failed with err=%d\n", + size, alignment, color, mode->name, err); + return false; + } + + if (!assert_node(test, node, mm, size, alignment, color)) { + drm_mm_remove_node(node); + return false; + } + + return true; +} + +static bool expect_insert_fail(struct kunit *test, struct drm_mm *mm, u64 size) +{ + struct drm_mm_node tmp = {}; + int err; + + err = drm_mm_insert_node(mm, &tmp, size); + if (likely(err == -ENOSPC)) + return true; + + if (!err) { + KUNIT_FAIL(test, "impossible insert succeeded, node %llu + %llu\n", + tmp.start, tmp.size); + drm_mm_remove_node(&tmp); + } else { + KUNIT_FAIL(test, + "impossible insert failed with wrong error %d [expected %d], size %llu\n", + err, -ENOSPC, size); + } + return false; +} + +static int __igt_insert(struct kunit *test, unsigned int count, u64 size, bool replace) +{ + DRM_RND_STATE(prng, random_seed); + const struct insert_mode *mode; + struct drm_mm mm; + struct drm_mm_node *nodes, *node, *next; + unsigned int *order, n, m, o = 0; + int ret; + + /* Fill a range with lots of nodes, check it doesn't fail too early */ + + DRM_MM_BUG_ON(!count); + DRM_MM_BUG_ON(!size); + + ret = -ENOMEM; + nodes = vmalloc(array_size(count, sizeof(*nodes))); + KUNIT_ASSERT_TRUE(test, nodes); + + order = drm_random_order(count, &prng); + if (!order) + goto err_nodes; + + ret = -EINVAL; + drm_mm_init(&mm, 0, count * size); + + for (mode = insert_modes; mode->name; mode++) { + for (n = 0; n < count; n++) { + struct drm_mm_node tmp; + + node = replace ? &tmp : &nodes[n]; + memset(node, 0, sizeof(*node)); + if (!expect_insert(test, &mm, node, size, 0, n, mode)) { + KUNIT_FAIL(test, "%s insert failed, size %llu step %d\n", + mode->name, size, n); + goto out; + } + + if (replace) { + drm_mm_replace_node(&tmp, &nodes[n]); + if (drm_mm_node_allocated(&tmp)) { + KUNIT_FAIL(test, + "replaced old-node still allocated! step %d\n", + n); + goto out; + } + + if (!assert_node(test, &nodes[n], &mm, size, 0, n)) { + KUNIT_FAIL(test, + "replaced node did not inherit parameters, size %llu step %d\n", + size, n); + goto out; + } + + if (tmp.start != nodes[n].start) { + KUNIT_FAIL(test, + "replaced node mismatch location expected [%llx + %llx], found [%llx + %llx]\n", + tmp.start, size, nodes[n].start, nodes[n].size); + goto out; + } + } + } + + /* After random insertion the nodes should be in order */ + if (!assert_continuous(test, &mm, size)) + goto out; + + /* Repeated use should then fail */ + if (!expect_insert_fail(test, &mm, size)) + goto out; + + /* Remove one and reinsert, as the only hole it should refill itself */ + for (n = 0; n < count; n++) { + u64 addr = nodes[n].start; + + drm_mm_remove_node(&nodes[n]); + if (!expect_insert(test, &mm, &nodes[n], size, 0, n, mode)) { + KUNIT_FAIL(test, "%s reinsert failed, size %llu step %d\n", + mode->name, size, n); + goto out; + } + + if (nodes[n].start != addr) { + KUNIT_FAIL(test, + "%s reinsert node moved, step %d, expected %llx, found %llx\n", + mode->name, n, addr, nodes[n].start); + goto out; + } + + if (!assert_continuous(test, &mm, size)) + goto out; + } + + /* Remove several, reinsert, check full */ + for_each_prime_number(n, min(max_prime, count)) { + for (m = 0; m < n; m++) { + node = &nodes[order[(o + m) % count]]; + drm_mm_remove_node(node); + } + + for (m = 0; m < n; m++) { + node = &nodes[order[(o + m) % count]]; + if (!expect_insert(test, &mm, node, size, 0, n, mode)) { + KUNIT_FAIL(test, + "%s multiple reinsert failed, size %llu step %d\n", + mode->name, size, n); + goto out; + } + } + + o += n; + + if (!assert_continuous(test, &mm, size)) + goto out; + + if (!expect_insert_fail(test, &mm, size)) + goto out; + } + + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + DRM_MM_BUG_ON(!drm_mm_clean(&mm)); + + cond_resched(); + } + + ret = 0; +out: + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + drm_mm_takedown(&mm); + kfree(order); +err_nodes: + vfree(nodes); + return ret; +} + +static void igt_mm_insert(struct kunit *test) +{ + const unsigned int count = min_t(unsigned int, BIT(10), max_iterations); + unsigned int n; + + for_each_prime_number_from(n, 1, 54) { + u64 size = BIT_ULL(n); + + KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size - 1, false)); + KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size, false)); + KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size + 1, false)); + + cond_resched(); + } +} + +static void igt_mm_replace(struct kunit *test) +{ + const unsigned int count = min_t(unsigned int, BIT(10), max_iterations); + unsigned int n; + + /* Reuse igt_insert to exercise replacement by inserting a dummy node, + * then replacing it with the intended node. We want to check that + * the tree is intact and all the information we need is carried + * across to the target node. + */ + + for_each_prime_number_from(n, 1, 54) { + u64 size = BIT_ULL(n); + + KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size - 1, true)); + KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size, true)); + KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size + 1, true)); + + cond_resched(); + } +} + +static bool expect_insert_in_range(struct kunit *test, struct drm_mm *mm, struct drm_mm_node *node, + u64 size, u64 alignment, unsigned long color, + u64 range_start, u64 range_end, const struct insert_mode *mode) +{ + int err; + + err = drm_mm_insert_node_in_range(mm, node, + size, alignment, color, + range_start, range_end, + mode->mode); + if (err) { + KUNIT_FAIL(test, + "insert (size=%llu, alignment=%llu, color=%lu, mode=%s) nto range [%llx, %llx] failed with err=%d\n", + size, alignment, color, mode->name, + range_start, range_end, err); + return false; + } + + if (!assert_node(test, node, mm, size, alignment, color)) { + drm_mm_remove_node(node); + return false; + } + + return true; +} + +static bool expect_insert_in_range_fail(struct kunit *test, struct drm_mm *mm, + u64 size, u64 range_start, u64 range_end) +{ + struct drm_mm_node tmp = {}; + int err; + + err = drm_mm_insert_node_in_range(mm, &tmp, size, 0, 0, range_start, range_end, + 0); + if (likely(err == -ENOSPC)) + return true; + + if (!err) { + KUNIT_FAIL(test, + "impossible insert succeeded, node %llx + %llu, range [%llx, %llx]\n", + tmp.start, tmp.size, range_start, range_end); + drm_mm_remove_node(&tmp); + } else { + KUNIT_FAIL(test, + "impossible insert failed with wrong error %d [expected %d], size %llu, range [%llx, %llx]\n", + err, -ENOSPC, size, range_start, range_end); + } + + return false; +} + +static bool assert_contiguous_in_range(struct kunit *test, struct drm_mm *mm, + u64 size, u64 start, u64 end) +{ + struct drm_mm_node *node; + unsigned int n; + + if (!expect_insert_in_range_fail(test, mm, size, start, end)) + return false; + + n = div64_u64(start + size - 1, size); + drm_mm_for_each_node(node, mm) { + if (node->start < start || node->start + node->size > end) { + KUNIT_FAIL(test, + "node %d out of range, address [%llx + %llu], range [%llx, %llx]\n", + n, node->start, node->start + node->size, start, end); + return false; + } + + if (node->start != n * size) { + KUNIT_FAIL(test, "node %d out of order, expected start %llx, found %llx\n", + n, n * size, node->start); + return false; + } + + if (node->size != size) { + KUNIT_FAIL(test, "node %d has wrong size, expected size %llx, found %llx\n", + n, size, node->size); + return false; + } + + if (drm_mm_hole_follows(node) && drm_mm_hole_node_end(node) < end) { + KUNIT_FAIL(test, "node %d is followed by a hole!\n", n); + return false; + } + + n++; + } + + if (start > 0) { + node = __drm_mm_interval_first(mm, 0, start - 1); + if (drm_mm_node_allocated(node)) { + KUNIT_FAIL(test, "node before start: node=%llx+%llu, start=%llx\n", + node->start, node->size, start); + return false; + } + } + + if (end < U64_MAX) { + node = __drm_mm_interval_first(mm, end, U64_MAX); + if (drm_mm_node_allocated(node)) { + KUNIT_FAIL(test, "node after end: node=%llx+%llu, end=%llx\n", + node->start, node->size, end); + return false; + } + } + + return true; +} + +static int __igt_insert_range(struct kunit *test, unsigned int count, u64 size, u64 start, u64 end) +{ + const struct insert_mode *mode; + struct drm_mm mm; + struct drm_mm_node *nodes, *node, *next; + unsigned int n, start_n, end_n; + int ret; + + DRM_MM_BUG_ON(!count); + DRM_MM_BUG_ON(!size); + DRM_MM_BUG_ON(end <= start); + + /* Very similar to __igt_insert(struct kunit *test, ), but now instead of populating the + * full range of the drm_mm, we try to fill a small portion of it. + */ + + ret = -ENOMEM; + nodes = vzalloc(array_size(count, sizeof(*nodes))); + KUNIT_ASSERT_TRUE(test, nodes); + + ret = -EINVAL; + drm_mm_init(&mm, 0, count * size); + + start_n = div64_u64(start + size - 1, size); + end_n = div64_u64(end - size, size); + + for (mode = insert_modes; mode->name; mode++) { + for (n = start_n; n <= end_n; n++) { + if (!expect_insert_in_range(test, &mm, &nodes[n], size, size, n, + start, end, mode)) { + KUNIT_FAIL(test, + "%s insert failed, size %llu, step %d [%d, %d], range [%llx, %llx]\n", + mode->name, size, n, start_n, end_n, start, end); + goto out; + } + } + + if (!assert_contiguous_in_range(test, &mm, size, start, end)) { + KUNIT_FAIL(test, + "%s: range [%llx, %llx] not full after initialisation, size=%llu\n", + mode->name, start, end, size); + goto out; + } + + /* Remove one and reinsert, it should refill itself */ + for (n = start_n; n <= end_n; n++) { + u64 addr = nodes[n].start; + + drm_mm_remove_node(&nodes[n]); + if (!expect_insert_in_range(test, &mm, &nodes[n], size, size, n, + start, end, mode)) { + KUNIT_FAIL(test, "%s reinsert failed, step %d\n", mode->name, n); + goto out; + } + + if (nodes[n].start != addr) { + KUNIT_FAIL(test, + "%s reinsert node moved, step %d, expected %llx, found %llx\n", + mode->name, n, addr, nodes[n].start); + goto out; + } + } + + if (!assert_contiguous_in_range(test, &mm, size, start, end)) { + KUNIT_FAIL(test, + "%s: range [%llx, %llx] not full after reinsertion, size=%llu\n", + mode->name, start, end, size); + goto out; + } + + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + DRM_MM_BUG_ON(!drm_mm_clean(&mm)); + + cond_resched(); + } + + ret = 0; +out: + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + drm_mm_takedown(&mm); + vfree(nodes); + return ret; +} + +static int insert_outside_range(struct kunit *test) +{ + struct drm_mm mm; + const unsigned int start = 1024; + const unsigned int end = 2048; + const unsigned int size = end - start; + + drm_mm_init(&mm, start, size); + + if (!expect_insert_in_range_fail(test, &mm, 1, 0, start)) + return -EINVAL; + + if (!expect_insert_in_range_fail(test, &mm, size, + start - size / 2, start + (size + 1) / 2)) + return -EINVAL; + + if (!expect_insert_in_range_fail(test, &mm, size, + end - (size + 1) / 2, end + size / 2)) + return -EINVAL; + + if (!expect_insert_in_range_fail(test, &mm, 1, end, end + size)) + return -EINVAL; + + drm_mm_takedown(&mm); + return 0; +} + +static void igt_mm_insert_range(struct kunit *test) +{ + const unsigned int count = min_t(unsigned int, BIT(13), max_iterations); + unsigned int n; + + /* Check that requests outside the bounds of drm_mm are rejected. */ + KUNIT_ASSERT_FALSE(test, insert_outside_range(test)); + + for_each_prime_number_from(n, 1, 50) { + const u64 size = BIT_ULL(n); + const u64 max = count * size; + + KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, 0, max)); + KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, 1, max)); + KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, 0, max - 1)); + KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, 0, max / 2)); + KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, max / 2, max / 2)); + KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, + max / 4 + 1, 3 * max / 4 - 1)); + + cond_resched(); + } +} + +static int prepare_igt_frag(struct kunit *test, struct drm_mm *mm, + struct drm_mm_node *nodes, unsigned int num_insert, + const struct insert_mode *mode) +{ + unsigned int size = 4096; + unsigned int i; + + for (i = 0; i < num_insert; i++) { + if (!expect_insert(test, mm, &nodes[i], size, 0, i, mode) != 0) { + KUNIT_FAIL(test, "%s insert failed\n", mode->name); + return -EINVAL; + } + } + + /* introduce fragmentation by freeing every other node */ + for (i = 0; i < num_insert; i++) { + if (i % 2 == 0) + drm_mm_remove_node(&nodes[i]); + } + + return 0; +} + +static u64 get_insert_time(struct kunit *test, struct drm_mm *mm, + unsigned int num_insert, struct drm_mm_node *nodes, + const struct insert_mode *mode) +{ + unsigned int size = 8192; + ktime_t start; + unsigned int i; + + start = ktime_get(); + for (i = 0; i < num_insert; i++) { + if (!expect_insert(test, mm, &nodes[i], size, 0, i, mode) != 0) { + KUNIT_FAIL(test, "%s insert failed\n", mode->name); + return 0; + } + } + + return ktime_to_ns(ktime_sub(ktime_get(), start)); +} + +static void igt_mm_frag(struct kunit *test) +{ + struct drm_mm mm; + const struct insert_mode *mode; + struct drm_mm_node *nodes, *node, *next; + unsigned int insert_size = 10000; + unsigned int scale_factor = 4; + + /* We need 4 * insert_size nodes to hold intermediate allocated + * drm_mm nodes. + * 1 times for prepare_igt_frag(struct kunit *test, ) + * 1 times for get_insert_time(struct kunit *test, ) + * 2 times for get_insert_time(struct kunit *test, ) + */ + nodes = vzalloc(array_size(insert_size * 4, sizeof(*nodes))); + KUNIT_ASSERT_TRUE(test, nodes); + + /* For BOTTOMUP and TOPDOWN, we first fragment the + * address space using prepare_igt_frag(struct kunit *test, ) and then try to verify + * that insertions scale quadratically from 10k to 20k insertions + */ + drm_mm_init(&mm, 1, U64_MAX - 2); + for (mode = insert_modes; mode->name; mode++) { + u64 insert_time1, insert_time2; + + if (mode->mode != DRM_MM_INSERT_LOW && + mode->mode != DRM_MM_INSERT_HIGH) + continue; + + if (prepare_igt_frag(test, &mm, nodes, insert_size, mode)) + goto err; + + insert_time1 = get_insert_time(test, &mm, insert_size, + nodes + insert_size, mode); + if (insert_time1 == 0) + goto err; + + insert_time2 = get_insert_time(test, &mm, (insert_size * 2), + nodes + insert_size * 2, mode); + if (insert_time2 == 0) + goto err; + + kunit_info(test, "%s fragmented insert of %u and %u insertions took %llu and %llu nsecs\n", + mode->name, insert_size, insert_size * 2, insert_time1, insert_time2); + + if (insert_time2 > (scale_factor * insert_time1)) { + KUNIT_FAIL(test, "%s fragmented insert took %llu nsecs more\n", + mode->name, insert_time2 - (scale_factor * insert_time1)); + goto err; + } + + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + } + +err: + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + drm_mm_takedown(&mm); + vfree(nodes); +} + +static void igt_mm_align(struct kunit *test) +{ + const struct insert_mode *mode; + const unsigned int max_count = min(8192u, max_prime); + struct drm_mm mm; + struct drm_mm_node *nodes, *node, *next; + unsigned int prime; + + /* For each of the possible insertion modes, we pick a few + * arbitrary alignments and check that the inserted node + * meets our requirements. + */ + + nodes = vzalloc(array_size(max_count, sizeof(*nodes))); + KUNIT_ASSERT_TRUE(test, nodes); + + drm_mm_init(&mm, 1, U64_MAX - 2); + + for (mode = insert_modes; mode->name; mode++) { + unsigned int i = 0; + + for_each_prime_number_from(prime, 1, max_count) { + u64 size = next_prime_number(prime); + + if (!expect_insert(test, &mm, &nodes[i], size, prime, i, mode)) { + KUNIT_FAIL(test, "%s insert failed with alignment=%d", + mode->name, prime); + goto out; + } + + i++; + } + + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + DRM_MM_BUG_ON(!drm_mm_clean(&mm)); + + cond_resched(); + } + +out: + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + drm_mm_takedown(&mm); + vfree(nodes); +} + +static void igt_align_pot(struct kunit *test, int max) +{ + struct drm_mm mm; + struct drm_mm_node *node, *next; + int bit; + + /* Check that we can align to the full u64 address space */ + + drm_mm_init(&mm, 1, U64_MAX - 2); + + for (bit = max - 1; bit; bit--) { + u64 align, size; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) { + KUNIT_FAIL(test, "failed to allocate node"); + goto out; + } + + align = BIT_ULL(bit); + size = BIT_ULL(bit - 1) + 1; + if (!expect_insert(test, &mm, node, size, align, bit, &insert_modes[0])) { + KUNIT_FAIL(test, "insert failed with alignment=%llx [%d]", align, bit); + goto out; + } + + cond_resched(); + } + +out: + drm_mm_for_each_node_safe(node, next, &mm) { + drm_mm_remove_node(node); + kfree(node); + } + drm_mm_takedown(&mm); +} + +static void igt_mm_align32(struct kunit *test) +{ + igt_align_pot(test, 32); +} + +static void igt_mm_align64(struct kunit *test) +{ + igt_align_pot(test, 64); +} + +static void show_scan(struct kunit *test, const struct drm_mm_scan *scan) +{ + kunit_info(test, "scan: hit [%llx, %llx], size=%lld, align=%lld, color=%ld\n", + scan->hit_start, scan->hit_end, scan->size, scan->alignment, scan->color); +} + +static void show_holes(struct kunit *test, const struct drm_mm *mm, int count) +{ + u64 hole_start, hole_end; + struct drm_mm_node *hole; + + drm_mm_for_each_hole(hole, mm, hole_start, hole_end) { + struct drm_mm_node *next = list_next_entry(hole, node_list); + const char *node1 = NULL, *node2 = NULL; + + if (drm_mm_node_allocated(hole)) + node1 = kasprintf(GFP_KERNEL, "[%llx + %lld, color=%ld], ", + hole->start, hole->size, hole->color); + + if (drm_mm_node_allocated(next)) + node2 = kasprintf(GFP_KERNEL, ", [%llx + %lld, color=%ld]", + next->start, next->size, next->color); + + kunit_info(test, "%sHole [%llx - %llx, size %lld]%s\n", node1, + hole_start, hole_end, hole_end - hole_start, node2); + + kfree(node2); + kfree(node1); + + if (!--count) + break; + } +} + +struct evict_node { + struct drm_mm_node node; + struct list_head link; +}; + +static bool evict_nodes(struct kunit *test, struct drm_mm_scan *scan, + struct evict_node *nodes, unsigned int *order, unsigned int count, + bool use_color, struct list_head *evict_list) +{ + struct evict_node *e, *en; + unsigned int i; + + for (i = 0; i < count; i++) { + e = &nodes[order ? order[i] : i]; + list_add(&e->link, evict_list); + if (drm_mm_scan_add_block(scan, &e->node)) + break; + } + list_for_each_entry_safe(e, en, evict_list, link) { + if (!drm_mm_scan_remove_block(scan, &e->node)) + list_del(&e->link); + } + if (list_empty(evict_list)) { + KUNIT_FAIL(test, + "Failed to find eviction: size=%lld [avail=%d], align=%lld (color=%lu)\n", + scan->size, count, scan->alignment, scan->color); + return false; + } + + list_for_each_entry(e, evict_list, link) + drm_mm_remove_node(&e->node); + + if (use_color) { + struct drm_mm_node *node; + + while ((node = drm_mm_scan_color_evict(scan))) { + e = container_of(node, typeof(*e), node); + drm_mm_remove_node(&e->node); + list_add(&e->link, evict_list); + } + } else { + if (drm_mm_scan_color_evict(scan)) { + KUNIT_FAIL(test, + "drm_mm_scan_color_evict unexpectedly reported overlapping nodes!\n"); + return false; + } + } + + return true; +} + +static bool evict_nothing(struct kunit *test, struct drm_mm *mm, + unsigned int total_size, struct evict_node *nodes) +{ + struct drm_mm_scan scan; + LIST_HEAD(evict_list); + struct evict_node *e; + struct drm_mm_node *node; + unsigned int n; + + drm_mm_scan_init(&scan, mm, 1, 0, 0, 0); + for (n = 0; n < total_size; n++) { + e = &nodes[n]; + list_add(&e->link, &evict_list); + drm_mm_scan_add_block(&scan, &e->node); + } + list_for_each_entry(e, &evict_list, link) + drm_mm_scan_remove_block(&scan, &e->node); + + for (n = 0; n < total_size; n++) { + e = &nodes[n]; + + if (!drm_mm_node_allocated(&e->node)) { + KUNIT_FAIL(test, "node[%d] no longer allocated!\n", n); + return false; + } + + e->link.next = NULL; + } + + drm_mm_for_each_node(node, mm) { + e = container_of(node, typeof(*e), node); + e->link.next = &e->link; + } + + for (n = 0; n < total_size; n++) { + e = &nodes[n]; + + if (!e->link.next) { + KUNIT_FAIL(test, "node[%d] no longer connected!\n", n); + return false; + } + } + + return assert_continuous(test, mm, nodes[0].node.size); +} + +static bool evict_everything(struct kunit *test, struct drm_mm *mm, + unsigned int total_size, struct evict_node *nodes) +{ + struct drm_mm_scan scan; + LIST_HEAD(evict_list); + struct evict_node *e; + unsigned int n; + int err; + + drm_mm_scan_init(&scan, mm, total_size, 0, 0, 0); + for (n = 0; n < total_size; n++) { + e = &nodes[n]; + list_add(&e->link, &evict_list); + if (drm_mm_scan_add_block(&scan, &e->node)) + break; + } + + err = 0; + list_for_each_entry(e, &evict_list, link) { + if (!drm_mm_scan_remove_block(&scan, &e->node)) { + if (!err) { + KUNIT_FAIL(test, "Node %lld not marked for eviction!\n", + e->node.start); + err = -EINVAL; + } + } + } + if (err) + return false; + + list_for_each_entry(e, &evict_list, link) + drm_mm_remove_node(&e->node); + + if (!assert_one_hole(test, mm, 0, total_size)) + return false; + + list_for_each_entry(e, &evict_list, link) { + err = drm_mm_reserve_node(mm, &e->node); + if (err) { + KUNIT_FAIL(test, "Failed to reinsert node after eviction: start=%llx\n", + e->node.start); + return false; + } + } + + return assert_continuous(test, mm, nodes[0].node.size); +} + +static int evict_something(struct kunit *test, struct drm_mm *mm, + u64 range_start, u64 range_end, struct evict_node *nodes, + unsigned int *order, unsigned int count, unsigned int size, + unsigned int alignment, const struct insert_mode *mode) +{ + struct drm_mm_scan scan; + LIST_HEAD(evict_list); + struct evict_node *e; + struct drm_mm_node tmp; + int err; + + drm_mm_scan_init_with_range(&scan, mm, size, alignment, 0, range_start, + range_end, mode->mode); + if (!evict_nodes(test, &scan, nodes, order, count, false, &evict_list)) + return -EINVAL; + + memset(&tmp, 0, sizeof(tmp)); + err = drm_mm_insert_node_generic(mm, &tmp, size, alignment, 0, + DRM_MM_INSERT_EVICT); + if (err) { + KUNIT_FAIL(test, "Failed to insert into eviction hole: size=%d, align=%d\n", + size, alignment); + show_scan(test, &scan); + show_holes(test, mm, 3); + return err; + } + + if (tmp.start < range_start || tmp.start + tmp.size > range_end) { + KUNIT_FAIL(test, + "Inserted [address=%llu + %llu] did not fit into the request range [%llu, %llu]\n", + tmp.start, tmp.size, range_start, range_end); + err = -EINVAL; + } + + if (!assert_node(test, &tmp, mm, size, alignment, 0) || + drm_mm_hole_follows(&tmp)) { + KUNIT_FAIL(test, + "Inserted did not fill the eviction hole: size=%lld [%d], align=%d [rem=%lld], start=%llx, hole-follows?=%d\n", + tmp.size, size, alignment, misalignment(&tmp, alignment), + tmp.start, drm_mm_hole_follows(&tmp)); + err = -EINVAL; + } + + drm_mm_remove_node(&tmp); + if (err) + return err; + + list_for_each_entry(e, &evict_list, link) { + err = drm_mm_reserve_node(mm, &e->node); + if (err) { + KUNIT_FAIL(test, "Failed to reinsert node after eviction: start=%llx\n", + e->node.start); + return err; + } + } + + if (!assert_continuous(test, mm, nodes[0].node.size)) { + KUNIT_FAIL(test, "range is no longer continuous\n"); + return -EINVAL; + } + + return 0; +} + +static void igt_mm_evict(struct kunit *test) +{ + DRM_RND_STATE(prng, random_seed); + const unsigned int size = 8192; + const struct insert_mode *mode; + struct drm_mm mm; + struct evict_node *nodes; + struct drm_mm_node *node, *next; + unsigned int *order, n; + + /* Here we populate a full drm_mm and then try and insert a new node + * by evicting other nodes in a random order. The drm_mm_scan should + * pick the first matching hole it finds from the random list. We + * repeat that for different allocation strategies, alignments and + * sizes to try and stress the hole finder. + */ + + nodes = vzalloc(array_size(size, sizeof(*nodes))); + KUNIT_ASSERT_TRUE(test, nodes); + + order = drm_random_order(size, &prng); + if (!order) + goto err_nodes; + + drm_mm_init(&mm, 0, size); + for (n = 0; n < size; n++) { + if (drm_mm_insert_node(&mm, &nodes[n].node, 1)) { + KUNIT_FAIL(test, "insert failed, step %d\n", n); + goto out; + } + } + + /* First check that using the scanner doesn't break the mm */ + if (!evict_nothing(test, &mm, size, nodes)) { + KUNIT_FAIL(test, "evict_nothing() failed\n"); + goto out; + } + if (!evict_everything(test, &mm, size, nodes)) { + KUNIT_FAIL(test, "evict_everything() failed\n"); + goto out; + } + + for (mode = evict_modes; mode->name; mode++) { + for (n = 1; n <= size; n <<= 1) { + drm_random_reorder(order, size, &prng); + if (evict_something(test, &mm, 0, U64_MAX, nodes, order, size, n, 1, + mode)) { + KUNIT_FAIL(test, "%s evict_something(size=%u) failed\n", + mode->name, n); + goto out; + } + } + + for (n = 1; n < size; n <<= 1) { + drm_random_reorder(order, size, &prng); + if (evict_something(test, &mm, 0, U64_MAX, nodes, order, size, + size / 2, n, mode)) { + KUNIT_FAIL(test, + "%s evict_something(size=%u, alignment=%u) failed\n", + mode->name, size / 2, n); + goto out; + } + } + + for_each_prime_number_from(n, 1, min(size, max_prime)) { + unsigned int nsize = (size - n + 1) / 2; + + DRM_MM_BUG_ON(!nsize); + + drm_random_reorder(order, size, &prng); + if (evict_something(test, &mm, 0, U64_MAX, nodes, order, size, + nsize, n, mode)) { + KUNIT_FAIL(test, + "%s evict_something(size=%u, alignment=%u) failed\n", + mode->name, nsize, n); + goto out; + } + } + + cond_resched(); + } + +out: + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + drm_mm_takedown(&mm); + kfree(order); +err_nodes: + vfree(nodes); +} + +static void igt_mm_evict_range(struct kunit *test) +{ + DRM_RND_STATE(prng, random_seed); + const unsigned int size = 8192; + const unsigned int range_size = size / 2; + const unsigned int range_start = size / 4; + const unsigned int range_end = range_start + range_size; + const struct insert_mode *mode; + struct drm_mm mm; + struct evict_node *nodes; + struct drm_mm_node *node, *next; + unsigned int *order, n; + + /* Like igt_evict() but now we are limiting the search to a + * small portion of the full drm_mm. + */ + + nodes = vzalloc(array_size(size, sizeof(*nodes))); + KUNIT_ASSERT_TRUE(test, nodes); + + order = drm_random_order(size, &prng); + if (!order) + goto err_nodes; + + drm_mm_init(&mm, 0, size); + for (n = 0; n < size; n++) { + if (drm_mm_insert_node(&mm, &nodes[n].node, 1)) { + KUNIT_FAIL(test, "insert failed, step %d\n", n); + goto out; + } + } + + for (mode = evict_modes; mode->name; mode++) { + for (n = 1; n <= range_size; n <<= 1) { + drm_random_reorder(order, size, &prng); + if (evict_something(test, &mm, range_start, range_end, nodes, + order, size, n, 1, mode)) { + KUNIT_FAIL(test, + "%s evict_something(size=%u) failed with range [%u, %u]\n", + mode->name, n, range_start, range_end); + goto out; + } + } + + for (n = 1; n <= range_size; n <<= 1) { + drm_random_reorder(order, size, &prng); + if (evict_something(test, &mm, range_start, range_end, nodes, + order, size, range_size / 2, n, mode)) { + KUNIT_FAIL(test, + "%s evict_something(size=%u, alignment=%u) failed with range [%u, %u]\n", + mode->name, range_size / 2, n, range_start, range_end); + goto out; + } + } + + for_each_prime_number_from(n, 1, min(range_size, max_prime)) { + unsigned int nsize = (range_size - n + 1) / 2; + + DRM_MM_BUG_ON(!nsize); + + drm_random_reorder(order, size, &prng); + if (evict_something(test, &mm, range_start, range_end, nodes, + order, size, nsize, n, mode)) { + KUNIT_FAIL(test, + "%s evict_something(size=%u, alignment=%u) failed with range [%u, %u]\n", + mode->name, nsize, n, range_start, range_end); + goto out; + } + } + + cond_resched(); + } + +out: + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + drm_mm_takedown(&mm); + kfree(order); +err_nodes: + vfree(nodes); +} + +static unsigned int node_index(const struct drm_mm_node *node) +{ + return div64_u64(node->start, node->size); +} + +static void igt_mm_topdown(struct kunit *test) +{ + const struct insert_mode *topdown = &insert_modes[TOPDOWN]; + + DRM_RND_STATE(prng, random_seed); + const unsigned int count = 8192; + unsigned int size; + unsigned long *bitmap; + struct drm_mm mm; + struct drm_mm_node *nodes, *node, *next; + unsigned int *order, n, m, o = 0; + + /* When allocating top-down, we expect to be returned a node + * from a suitable hole at the top of the drm_mm. We check that + * the returned node does match the highest available slot. + */ + + nodes = vzalloc(array_size(count, sizeof(*nodes))); + KUNIT_ASSERT_TRUE(test, nodes); + + bitmap = bitmap_zalloc(count, GFP_KERNEL); + if (!bitmap) + goto err_nodes; + + order = drm_random_order(count, &prng); + if (!order) + goto err_bitmap; + + for (size = 1; size <= 64; size <<= 1) { + drm_mm_init(&mm, 0, size * count); + for (n = 0; n < count; n++) { + if (!expect_insert(test, &mm, &nodes[n], size, 0, n, topdown)) { + KUNIT_FAIL(test, "insert failed, size %u step %d\n", size, n); + goto out; + } + + if (drm_mm_hole_follows(&nodes[n])) { + KUNIT_FAIL(test, + "hole after topdown insert %d, start=%llx\n, size=%u", + n, nodes[n].start, size); + goto out; + } + + if (!assert_one_hole(test, &mm, 0, size * (count - n - 1))) + goto out; + } + + if (!assert_continuous(test, &mm, size)) + goto out; + + drm_random_reorder(order, count, &prng); + for_each_prime_number_from(n, 1, min(count, max_prime)) { + for (m = 0; m < n; m++) { + node = &nodes[order[(o + m) % count]]; + drm_mm_remove_node(node); + __set_bit(node_index(node), bitmap); + } + + for (m = 0; m < n; m++) { + unsigned int last; + + node = &nodes[order[(o + m) % count]]; + if (!expect_insert(test, &mm, node, size, 0, 0, topdown)) { + KUNIT_FAIL(test, "insert failed, step %d/%d\n", m, n); + goto out; + } + + if (drm_mm_hole_follows(node)) { + KUNIT_FAIL(test, + "hole after topdown insert %d/%d, start=%llx\n", + m, n, node->start); + goto out; + } + + last = find_last_bit(bitmap, count); + if (node_index(node) != last) { + KUNIT_FAIL(test, + "node %d/%d, size %d, not inserted into upmost hole, expected %d, found %d\n", + m, n, size, last, node_index(node)); + goto out; + } + + __clear_bit(last, bitmap); + } + + DRM_MM_BUG_ON(find_first_bit(bitmap, count) != count); + + o += n; + } + + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + DRM_MM_BUG_ON(!drm_mm_clean(&mm)); + cond_resched(); + } + +out: + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + drm_mm_takedown(&mm); + kfree(order); +err_bitmap: + bitmap_free(bitmap); +err_nodes: + vfree(nodes); +} + +static void igt_mm_bottomup(struct kunit *test) +{ + const struct insert_mode *bottomup = &insert_modes[BOTTOMUP]; + + DRM_RND_STATE(prng, random_seed); + const unsigned int count = 8192; + unsigned int size; + unsigned long *bitmap; + struct drm_mm mm; + struct drm_mm_node *nodes, *node, *next; + unsigned int *order, n, m, o = 0; + + /* Like igt_topdown, but instead of searching for the last hole, + * we search for the first. + */ + + nodes = vzalloc(array_size(count, sizeof(*nodes))); + KUNIT_ASSERT_TRUE(test, nodes); + + bitmap = bitmap_zalloc(count, GFP_KERNEL); + if (!bitmap) + goto err_nodes; + + order = drm_random_order(count, &prng); + if (!order) + goto err_bitmap; + + for (size = 1; size <= 64; size <<= 1) { + drm_mm_init(&mm, 0, size * count); + for (n = 0; n < count; n++) { + if (!expect_insert(test, &mm, &nodes[n], size, 0, n, bottomup)) { + KUNIT_FAIL(test, + "bottomup insert failed, size %u step %d\n", size, n); + goto out; + } + + if (!assert_one_hole(test, &mm, size * (n + 1), size * count)) + goto out; + } + + if (!assert_continuous(test, &mm, size)) + goto out; + + drm_random_reorder(order, count, &prng); + for_each_prime_number_from(n, 1, min(count, max_prime)) { + for (m = 0; m < n; m++) { + node = &nodes[order[(o + m) % count]]; + drm_mm_remove_node(node); + __set_bit(node_index(node), bitmap); + } + + for (m = 0; m < n; m++) { + unsigned int first; + + node = &nodes[order[(o + m) % count]]; + if (!expect_insert(test, &mm, node, size, 0, 0, bottomup)) { + KUNIT_FAIL(test, "insert failed, step %d/%d\n", m, n); + goto out; + } + + first = find_first_bit(bitmap, count); + if (node_index(node) != first) { + KUNIT_FAIL(test, + "node %d/%d not inserted into bottom hole, expected %d, found %d\n", + m, n, first, node_index(node)); + goto out; + } + __clear_bit(first, bitmap); + } + + DRM_MM_BUG_ON(find_first_bit(bitmap, count) != count); + + o += n; + } + + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + DRM_MM_BUG_ON(!drm_mm_clean(&mm)); + cond_resched(); + } + +out: + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + drm_mm_takedown(&mm); + kfree(order); +err_bitmap: + bitmap_free(bitmap); +err_nodes: + vfree(nodes); +} + +static void __igt_once(struct kunit *test, unsigned int mode) +{ + struct drm_mm mm; + struct drm_mm_node rsvd_lo, rsvd_hi, node; + + drm_mm_init(&mm, 0, 7); + + memset(&rsvd_lo, 0, sizeof(rsvd_lo)); + rsvd_lo.start = 1; + rsvd_lo.size = 1; + if (drm_mm_reserve_node(&mm, &rsvd_lo)) { + KUNIT_FAIL(test, "Could not reserve low node\n"); + goto err; + } + + memset(&rsvd_hi, 0, sizeof(rsvd_hi)); + rsvd_hi.start = 5; + rsvd_hi.size = 1; + if (drm_mm_reserve_node(&mm, &rsvd_hi)) { + KUNIT_FAIL(test, "Could not reserve low node\n"); + goto err_lo; + } + + if (!drm_mm_hole_follows(&rsvd_lo) || !drm_mm_hole_follows(&rsvd_hi)) { + KUNIT_FAIL(test, "Expected a hole after lo and high nodes!\n"); + goto err_hi; + } + + memset(&node, 0, sizeof(node)); + if (drm_mm_insert_node_generic(&mm, &node, 2, 0, 0, mode)) { + KUNIT_FAIL(test, "Could not insert the node into the available hole!\n"); + goto err_hi; + } + + drm_mm_remove_node(&node); +err_hi: + drm_mm_remove_node(&rsvd_hi); +err_lo: + drm_mm_remove_node(&rsvd_lo); +err: + drm_mm_takedown(&mm); +} + +static void igt_mm_lowest(struct kunit *test) +{ + __igt_once(test, DRM_MM_INSERT_LOW); +} + +static void igt_mm_highest(struct kunit *test) +{ + __igt_once(test, DRM_MM_INSERT_HIGH); +} + +static void separate_adjacent_colors(const struct drm_mm_node *node, + unsigned long color, u64 *start, u64 *end) +{ + if (drm_mm_node_allocated(node) && node->color != color) + ++*start; + + node = list_next_entry(node, node_list); + if (drm_mm_node_allocated(node) && node->color != color) + --*end; +} + +static bool colors_abutt(struct kunit *test, const struct drm_mm_node *node) +{ + if (!drm_mm_hole_follows(node) && + drm_mm_node_allocated(list_next_entry(node, node_list))) { + KUNIT_FAIL(test, "colors abutt; %ld [%llx + %llx] is next to %ld [%llx + %llx]!\n", + node->color, node->start, node->size, + list_next_entry(node, node_list)->color, + list_next_entry(node, node_list)->start, + list_next_entry(node, node_list)->size); + return true; + } + + return false; +} + +static void igt_mm_color(struct kunit *test) +{ + const unsigned int count = min(4096u, max_iterations); + const struct insert_mode *mode; + struct drm_mm mm; + struct drm_mm_node *node, *nn; + unsigned int n; + + /* Color adjustment complicates everything. First we just check + * that when we insert a node we apply any color_adjustment callback. + * The callback we use should ensure that there is a gap between + * any two nodes, and so after each insertion we check that those + * holes are inserted and that they are preserved. + */ + + drm_mm_init(&mm, 0, U64_MAX); + + for (n = 1; n <= count; n++) { + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + goto out; + + if (!expect_insert(test, &mm, node, n, 0, n, &insert_modes[0])) { + KUNIT_FAIL(test, "insert failed, step %d\n", n); + kfree(node); + goto out; + } + } + + drm_mm_for_each_node_safe(node, nn, &mm) { + if (node->color != node->size) { + KUNIT_FAIL(test, "invalid color stored: expected %lld, found %ld\n", + node->size, node->color); + + goto out; + } + + drm_mm_remove_node(node); + kfree(node); + } + + /* Now, let's start experimenting with applying a color callback */ + mm.color_adjust = separate_adjacent_colors; + for (mode = insert_modes; mode->name; mode++) { + u64 last; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + goto out; + + node->size = 1 + 2 * count; + node->color = node->size; + + if (drm_mm_reserve_node(&mm, node)) { + KUNIT_FAIL(test, "initial reserve failed!\n"); + goto out; + } + + last = node->start + node->size; + + for (n = 1; n <= count; n++) { + int rem; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + goto out; + + node->start = last; + node->size = n + count; + node->color = node->size; + + if (drm_mm_reserve_node(&mm, node) != -ENOSPC) { + KUNIT_FAIL(test, "reserve %d did not report color overlap!", n); + goto out; + } + + node->start += n + 1; + rem = misalignment(node, n + count); + node->start += n + count - rem; + + if (drm_mm_reserve_node(&mm, node)) { + KUNIT_FAIL(test, "reserve %d failed", n); + goto out; + } + + last = node->start + node->size; + } + + for (n = 1; n <= count; n++) { + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + goto out; + + if (!expect_insert(test, &mm, node, n, n, n, mode)) { + KUNIT_FAIL(test, "%s insert failed, step %d\n", mode->name, n); + kfree(node); + goto out; + } + } + + drm_mm_for_each_node_safe(node, nn, &mm) { + u64 rem; + + if (node->color != node->size) { + KUNIT_FAIL(test, + "%s invalid color stored: expected %lld, found %ld\n", + mode->name, node->size, node->color); + + goto out; + } + + if (colors_abutt(test, node)) + goto out; + + div64_u64_rem(node->start, node->size, &rem); + if (rem) { + KUNIT_FAIL(test, + "%s colored node misaligned, start=%llx expected alignment=%lld [rem=%lld]\n", + mode->name, node->start, node->size, rem); + goto out; + } + + drm_mm_remove_node(node); + kfree(node); + } + + cond_resched(); + } + +out: + drm_mm_for_each_node_safe(node, nn, &mm) { + drm_mm_remove_node(node); + kfree(node); + } + drm_mm_takedown(&mm); +} + +static int evict_color(struct kunit *test, struct drm_mm *mm, u64 range_start, + u64 range_end, struct evict_node *nodes, unsigned int *order, + unsigned int count, unsigned int size, unsigned int alignment, + unsigned long color, const struct insert_mode *mode) +{ + struct drm_mm_scan scan; + LIST_HEAD(evict_list); + struct evict_node *e; + struct drm_mm_node tmp; + int err; + + drm_mm_scan_init_with_range(&scan, mm, size, alignment, color, range_start, + range_end, mode->mode); + if (!evict_nodes(test, &scan, nodes, order, count, true, &evict_list)) + return -EINVAL; + + memset(&tmp, 0, sizeof(tmp)); + err = drm_mm_insert_node_generic(mm, &tmp, size, alignment, color, + DRM_MM_INSERT_EVICT); + if (err) { + KUNIT_FAIL(test, + "Failed to insert into eviction hole: size=%d, align=%d, color=%lu, err=%d\n", + size, alignment, color, err); + show_scan(test, &scan); + show_holes(test, mm, 3); + return err; + } + + if (tmp.start < range_start || tmp.start + tmp.size > range_end) { + KUNIT_FAIL(test, + "Inserted [address=%llu + %llu] did not fit into the request range [%llu, %llu]\n", + tmp.start, tmp.size, range_start, range_end); + err = -EINVAL; + } + + if (colors_abutt(test, &tmp)) + err = -EINVAL; + + if (!assert_node(test, &tmp, mm, size, alignment, color)) { + KUNIT_FAIL(test, + "Inserted did not fit the eviction hole: size=%lld [%d], align=%d [rem=%lld], start=%llx\n", + tmp.size, size, alignment, misalignment(&tmp, alignment), tmp.start); + err = -EINVAL; + } + + drm_mm_remove_node(&tmp); + if (err) + return err; + + list_for_each_entry(e, &evict_list, link) { + err = drm_mm_reserve_node(mm, &e->node); + if (err) { + KUNIT_FAIL(test, "Failed to reinsert node after eviction: start=%llx\n", + e->node.start); + return err; + } + } + + cond_resched(); + return 0; +} + +static void igt_mm_color_evict(struct kunit *test) +{ + DRM_RND_STATE(prng, random_seed); + const unsigned int total_size = min(8192u, max_iterations); + const struct insert_mode *mode; + unsigned long color = 0; + struct drm_mm mm; + struct evict_node *nodes; + struct drm_mm_node *node, *next; + unsigned int *order, n; + + /* Check that the drm_mm_scan also honours color adjustment when + * choosing its victims to create a hole. Our color_adjust does not + * allow two nodes to be placed together without an intervening hole + * enlarging the set of victims that must be evicted. + */ + + nodes = vzalloc(array_size(total_size, sizeof(*nodes))); + KUNIT_ASSERT_TRUE(test, nodes); + + order = drm_random_order(total_size, &prng); + if (!order) + goto err_nodes; + + drm_mm_init(&mm, 0, 2 * total_size - 1); + mm.color_adjust = separate_adjacent_colors; + for (n = 0; n < total_size; n++) { + if (!expect_insert(test, &mm, &nodes[n].node, + 1, 0, color++, + &insert_modes[0])) { + KUNIT_FAIL(test, "insert failed, step %d\n", n); + goto out; + } + } + + for (mode = evict_modes; mode->name; mode++) { + for (n = 1; n <= total_size; n <<= 1) { + drm_random_reorder(order, total_size, &prng); + if (evict_color(test, &mm, 0, U64_MAX, nodes, order, total_size, + n, 1, color++, mode)) { + KUNIT_FAIL(test, "%s evict_color(size=%u) failed\n", mode->name, n); + goto out; + } + } + + for (n = 1; n < total_size; n <<= 1) { + drm_random_reorder(order, total_size, &prng); + if (evict_color(test, &mm, 0, U64_MAX, nodes, order, total_size, + total_size / 2, n, color++, mode)) { + KUNIT_FAIL(test, "%s evict_color(size=%u, alignment=%u) failed\n", + mode->name, total_size / 2, n); + goto out; + } + } + + for_each_prime_number_from(n, 1, min(total_size, max_prime)) { + unsigned int nsize = (total_size - n + 1) / 2; + + DRM_MM_BUG_ON(!nsize); + + drm_random_reorder(order, total_size, &prng); + if (evict_color(test, &mm, 0, U64_MAX, nodes, order, total_size, + nsize, n, color++, mode)) { + KUNIT_FAIL(test, "%s evict_color(size=%u, alignment=%u) failed\n", + mode->name, nsize, n); + goto out; + } + } + + cond_resched(); + } + +out: + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + drm_mm_takedown(&mm); + kfree(order); +err_nodes: + vfree(nodes); +} + +static void igt_mm_color_evict_range(struct kunit *test) +{ + DRM_RND_STATE(prng, random_seed); + const unsigned int total_size = 8192; + const unsigned int range_size = total_size / 2; + const unsigned int range_start = total_size / 4; + const unsigned int range_end = range_start + range_size; + const struct insert_mode *mode; + unsigned long color = 0; + struct drm_mm mm; + struct evict_node *nodes; + struct drm_mm_node *node, *next; + unsigned int *order, n; + + /* Like igt_color_evict(), but limited to small portion of the full + * drm_mm range. + */ + + nodes = vzalloc(array_size(total_size, sizeof(*nodes))); + KUNIT_ASSERT_TRUE(test, nodes); + + order = drm_random_order(total_size, &prng); + if (!order) + goto err_nodes; + + drm_mm_init(&mm, 0, 2 * total_size - 1); + mm.color_adjust = separate_adjacent_colors; + for (n = 0; n < total_size; n++) { + if (!expect_insert(test, &mm, &nodes[n].node, + 1, 0, color++, + &insert_modes[0])) { + KUNIT_FAIL(test, "insert failed, step %d\n", n); + goto out; + } + } + + for (mode = evict_modes; mode->name; mode++) { + for (n = 1; n <= range_size; n <<= 1) { + drm_random_reorder(order, range_size, &prng); + if (evict_color(test, &mm, range_start, range_end, nodes, order, + total_size, n, 1, color++, mode)) { + KUNIT_FAIL(test, + "%s evict_color(size=%u) failed for range [%x, %x]\n", + mode->name, n, range_start, range_end); + goto out; + } + } + + for (n = 1; n < range_size; n <<= 1) { + drm_random_reorder(order, total_size, &prng); + if (evict_color(test, &mm, range_start, range_end, nodes, order, + total_size, range_size / 2, n, color++, mode)) { + KUNIT_FAIL(test, + "%s evict_color(size=%u, alignment=%u) failed for range [%x, %x]\n", + mode->name, total_size / 2, n, range_start, range_end); + goto out; + } + } + + for_each_prime_number_from(n, 1, min(range_size, max_prime)) { + unsigned int nsize = (range_size - n + 1) / 2; + + DRM_MM_BUG_ON(!nsize); + + drm_random_reorder(order, total_size, &prng); + if (evict_color(test, &mm, range_start, range_end, nodes, order, + total_size, nsize, n, color++, mode)) { + KUNIT_FAIL(test, + "%s evict_color(size=%u, alignment=%u) failed for range [%x, %x]\n", + mode->name, nsize, n, range_start, range_end); + goto out; + } + } + + cond_resched(); + } + +out: + drm_mm_for_each_node_safe(node, next, &mm) + drm_mm_remove_node(node); + drm_mm_takedown(&mm); + kfree(order); +err_nodes: + vfree(nodes); +} + +static int drm_mm_init_test(struct kunit *test) +{ + while (!random_seed) + random_seed = get_random_int(); + + return 0; +} + +module_param(random_seed, uint, 0400); +module_param(max_iterations, uint, 0400); +module_param(max_prime, uint, 0400); + +static struct kunit_case drm_mm_tests[] = { + KUNIT_CASE(igt_mm_init), + KUNIT_CASE(igt_mm_debug), + KUNIT_CASE(igt_mm_reserve), + KUNIT_CASE(igt_mm_insert), + KUNIT_CASE(igt_mm_replace), + KUNIT_CASE(igt_mm_insert_range), + KUNIT_CASE(igt_mm_frag), + KUNIT_CASE(igt_mm_align), + KUNIT_CASE(igt_mm_align32), + KUNIT_CASE(igt_mm_align64), + KUNIT_CASE(igt_mm_evict), + KUNIT_CASE(igt_mm_evict_range), + KUNIT_CASE(igt_mm_topdown), + KUNIT_CASE(igt_mm_bottomup), + KUNIT_CASE(igt_mm_lowest), + KUNIT_CASE(igt_mm_highest), + KUNIT_CASE(igt_mm_color), + KUNIT_CASE(igt_mm_color_evict), + KUNIT_CASE(igt_mm_color_evict_range), + {} +}; + +static struct kunit_suite drm_mm_test_suite = { + .name = "drm_mm", + .init = drm_mm_init_test, + .test_cases = drm_mm_tests, +}; + +kunit_test_suite(drm_mm_test_suite); + +MODULE_AUTHOR("Intel Corporation"); +MODULE_LICENSE("GPL"); -- cgit v1.3-14-g43fede From e6e627482a19a34b68116cdb5756bb199b5e2e52 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 25 Jul 2022 17:17:02 +0200 Subject: dt-bindings: display: panel: sitronix,st7701: Add Densitron DMT028VGHMCMI-1A TFT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add compatible string for Densitron DMT028VGHMCMI-1A TFT matrix. This is a DSI-attached 480x640 2.83 inch panel. Signed-off-by: Marek Vasut Cc: Guido Günther Cc: Jagan Teki Cc: Laurent Pinchart Cc: Linus Walleij Cc: Rob Herring Cc: Sam Ravnborg Cc: Thierry Reding Cc: devicetree@vger.kernel.org Acked-by: Rob Herring Signed-off-by: Linus Walleij Link: https://patchwork.freedesktop.org/patch/msgid/20220725151703.319939-1-marex@denx.de --- Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml b/Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml index 6dff59fe4be1..34d5e20c6cb3 100644 --- a/Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml +++ b/Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml @@ -17,6 +17,9 @@ description: | Techstar TS8550B is 480x854, 2-lane MIPI DSI LCD panel which has inbuilt ST7701 chip. + Densitron DMT028VGHMCMI-1A is 480x640, 2-lane MIPI DSI LCD panel + which has built-in ST7701 chip. + allOf: - $ref: panel-common.yaml# @@ -24,6 +27,7 @@ properties: compatible: items: - enum: + - densitron,dmt028vghmcmi-1a - techstar,ts8550b - const: sitronix,st7701 -- cgit v1.3-14-g43fede From 8e61cbd483aee6ac6be9f5821e1bf22bed0710ff Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Fri, 1 Jul 2022 21:02:27 +0200 Subject: drm/todo: remove task for idr_init_base() All IDRs in the DRM core and drivers which are applicable for using idr_init_base() over idr_init() should be set up to use a proper base in order to avoid unnecessary tree walks. Signed-off-by: Danilo Krummrich Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20220701190227.284783-3-dakr@redhat.com --- Documentation/gpu/todo.rst | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'Documentation') diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 10bfb50908d1..de226ccc2c54 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -322,18 +322,6 @@ Contact: Daniel Vetter, Noralf Tronnes Level: Advanced -idr_init_base() ---------------- - -DRM core&drivers uses a lot of idr (integer lookup directories) for mapping -userspace IDs to internal objects, and in most places ID=0 means NULL and hence -is never used. Switching to idr_init_base() for these would make the idr more -efficient. - -Contact: Daniel Vetter - -Level: Starter - struct drm_gem_object_funcs --------------------------- -- cgit v1.3-14-g43fede From 6bcfe8eaeef01fb389e951e7c648b934dfd62f15 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Tue, 2 Aug 2022 02:04:02 +0200 Subject: drm/fb: rename FB CMA helpers to FB DMA helpers Rename "FB CMA" helpers to "FB DMA" helpers - considering the hierarchy of APIs (mm/cma -> dma -> fb dma) calling them "FB DMA" seems to be more applicable. Besides that, commit e57924d4ae80 ("drm/doc: Task to rename CMA helpers") requests to rename the CMA helpers and implies that people seem to be confused about the naming. In order to do this renaming the following script was used: ``` #!/bin/bash DIRS="drivers/gpu include/drm Documentation/gpu" REGEX_SYM_UPPER="[0-9A-Z_\-]" REGEX_SYM_LOWER="[0-9a-z_\-]" REGEX_GREP_UPPER="(${REGEX_SYM_UPPER}*)(FB)_CMA_(${REGEX_SYM_UPPER}*)" REGEX_GREP_LOWER="(${REGEX_SYM_LOWER}*)(fb)_cma_(${REGEX_SYM_LOWER}*)" REGEX_SED_UPPER="s/${REGEX_GREP_UPPER}/\1\2_DMA_\3/g" REGEX_SED_LOWER="s/${REGEX_GREP_LOWER}/\1\2_dma_\3/g" # Find all upper case 'CMA' symbols and replace them with 'DMA'. for ff in $(grep -REHl "${REGEX_GREP_UPPER}" $DIRS) do sed -i -E "$REGEX_SED_UPPER" $ff done # Find all lower case 'cma' symbols and replace them with 'dma'. for ff in $(grep -REHl "${REGEX_GREP_LOWER}" $DIRS) do sed -i -E "$REGEX_SED_LOWER" $ff done # Replace all occurrences of 'CMA' / 'cma' in comments and # documentation files with 'DMA' / 'dma'. for ff in $(grep -RiHl " cma " $DIRS) do sed -i -E "s/ cma / dma /g" $ff sed -i -E "s/ CMA / DMA /g" $ff done ``` Only a few more manual modifications were needed, e.g. reverting the following modifications in some DRM Kconfig files - select CMA if HAVE_DMA_CONTIGUOUS + select DMA if HAVE_DMA_CONTIGUOUS as well as manually picking the occurrences of 'CMA'/'cma' in comments and documentation which relate to "FB CMA", but not "GEM CMA". This patch is compile-time tested building a x86_64 kernel with `make allyesconfig && make drivers/gpu/drm`. Acked-by: Sam Ravnborg Acked-by: Thomas Zimmermann Reviewed-by: Laurent Pinchart Signed-off-by: Danilo Krummrich Reviewed-by: Liviu Dudau #drivers/gpu/drm/arm Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20220802000405.949236-3-dakr@redhat.com --- Documentation/gpu/drm-kms-helpers.rst | 8 +- drivers/gpu/drm/Makefile | 2 +- .../drm/arm/display/komeda/komeda_framebuffer.c | 4 +- drivers/gpu/drm/arm/hdlcd_crtc.c | 4 +- drivers/gpu/drm/arm/malidp_mw.c | 4 +- drivers/gpu/drm/arm/malidp_planes.c | 8 +- drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c | 4 +- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 4 +- drivers/gpu/drm/drm_fb_cma_helper.c | 145 -------------------- drivers/gpu/drm/drm_fb_dma_helper.c | 150 +++++++++++++++++++++ drivers/gpu/drm/drm_format_helper.c | 4 +- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c | 4 +- drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 4 +- drivers/gpu/drm/imx/dcss/dcss-plane.c | 6 +- drivers/gpu/drm/imx/ipuv3-plane.c | 8 +- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 6 +- drivers/gpu/drm/ingenic/ingenic-ipu.c | 10 +- drivers/gpu/drm/kmb/kmb_plane.c | 8 +- drivers/gpu/drm/logicvc/Kconfig | 2 +- drivers/gpu/drm/logicvc/logicvc_layer.c | 6 +- drivers/gpu/drm/mcde/mcde_display.c | 6 +- drivers/gpu/drm/mcde/mcde_drv.c | 4 +- drivers/gpu/drm/meson/meson_overlay.c | 8 +- drivers/gpu/drm/meson/meson_plane.c | 4 +- drivers/gpu/drm/mxsfb/lcdif_kms.c | 6 +- drivers/gpu/drm/mxsfb/mxsfb_kms.c | 8 +- drivers/gpu/drm/pl111/pl111_display.c | 6 +- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 4 +- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 4 +- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 6 +- drivers/gpu/drm/shmobile/shmob_drm_plane.c | 6 +- drivers/gpu/drm/sprd/sprd_dpu.c | 4 +- drivers/gpu/drm/sti/sti_cursor.c | 6 +- drivers/gpu/drm/sti/sti_gdp.c | 6 +- drivers/gpu/drm/sti/sti_hqvdp.c | 6 +- drivers/gpu/drm/stm/ltdc.c | 14 +- drivers/gpu/drm/sun4i/sun4i_backend.c | 4 +- drivers/gpu/drm/sun4i/sun4i_frontend.c | 8 +- drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 4 +- drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 4 +- drivers/gpu/drm/tegra/fb.c | 2 +- drivers/gpu/drm/tidss/tidss_dispc.c | 6 +- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 4 +- drivers/gpu/drm/tiny/arcpgu.c | 4 +- drivers/gpu/drm/tiny/ili9225.c | 4 +- drivers/gpu/drm/tiny/repaper.c | 4 +- drivers/gpu/drm/tiny/st7586.c | 4 +- drivers/gpu/drm/tve200/tve200_display.c | 10 +- drivers/gpu/drm/vc4/vc4_crtc.c | 8 +- drivers/gpu/drm/vc4/vc4_plane.c | 10 +- drivers/gpu/drm/vc4/vc4_txp.c | 4 +- drivers/gpu/drm/xlnx/zynqmp_disp.c | 4 +- include/drm/drm_fb_cma_helper.h | 23 ---- include/drm/drm_fb_dma_helper.h | 23 ++++ 54 files changed, 312 insertions(+), 307 deletions(-) delete mode 100644 drivers/gpu/drm/drm_fb_cma_helper.c create mode 100644 drivers/gpu/drm/drm_fb_dma_helper.c delete mode 100644 include/drm/drm_fb_cma_helper.h create mode 100644 include/drm/drm_fb_dma_helper.h (limited to 'Documentation') diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst index 2d473bc64c9f..dbc85fd7a971 100644 --- a/Documentation/gpu/drm-kms-helpers.rst +++ b/Documentation/gpu/drm-kms-helpers.rst @@ -122,13 +122,13 @@ format Helper Functions Reference .. kernel-doc:: drivers/gpu/drm/drm_format_helper.c :export: -Framebuffer CMA Helper Functions Reference +Framebuffer DMA Helper Functions Reference ========================================== -.. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c - :doc: framebuffer cma helper functions +.. kernel-doc:: drivers/gpu/drm/drm_fb_dma_helper.c + :doc: framebuffer dma helper functions -.. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c +.. kernel-doc:: drivers/gpu/drm/drm_fb_dma_helper.c :export: Framebuffer GEM Helper Reference diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 25016dcab55e..1d6e4f672b59 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -41,7 +41,7 @@ obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o obj-$(CONFIG_DRM_BUDDY) += drm_buddy.o drm_cma_helper-y := drm_gem_cma_helper.o -drm_cma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_cma_helper.o +drm_cma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_dma_helper.o obj-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_cma_helper.o drm_shmem_helper-y := drm_gem_shmem_helper.o diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c index 3c372d2deb0a..ea45da663dfb 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c @@ -5,7 +5,7 @@ * */ #include -#include +#include #include #include #include @@ -247,7 +247,7 @@ komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane) return -EINVAL; } - obj = drm_fb_cma_get_gem_obj(fb, plane); + obj = drm_fb_dma_get_gem_obj(fb, plane); offset = fb->offsets[plane]; if (!fb->modifier) { diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 636ef9447830..d3cf788c0fa9 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -273,7 +273,7 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane, return; dest_h = drm_rect_height(&new_plane_state->dst); - scanout_start = drm_fb_cma_get_gem_addr(fb, new_plane_state, 0); + scanout_start = drm_fb_dma_get_gem_addr(fb, new_plane_state, 0); hdlcd = plane->dev->dev_private; hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, fb->pitches[0]); diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c index b66ca5b33a7f..7a9c900626ec 100644 --- a/drivers/gpu/drm/arm/malidp_mw.c +++ b/drivers/gpu/drm/arm/malidp_mw.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -160,7 +160,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder, n_planes = fb->format->num_planes; for (i = 0; i < n_planes; i++) { - struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, i); + struct drm_gem_cma_object *obj = drm_fb_dma_get_gem_obj(fb, i); /* memory write buffers are never rotated */ u8 alignment = malidp_hw_get_pitch_align(malidp->dev, 0); diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index a1cee1a5b523..72e0162735fa 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -722,19 +722,19 @@ static void malidp_set_plane_base_addr(struct drm_framebuffer *fb, ptr = mp->layer->ptr + (plane_index << 4); /* - * drm_fb_cma_get_gem_addr() alters the physical base address of the + * drm_fb_dma_get_gem_addr() alters the physical base address of the * framebuffer as per the plane's src_x, src_y co-ordinates (ie to * take care of source cropping). * For AFBC, this is not needed as the cropping is handled by _AD_CROP_H * and _AD_CROP_V registers. */ if (!afbc) { - paddr = drm_fb_cma_get_gem_addr(fb, plane->state, + paddr = drm_fb_dma_get_gem_addr(fb, plane->state, plane_index); } else { struct drm_gem_cma_object *obj; - obj = drm_fb_cma_get_gem_obj(fb, plane_index); + obj = drm_fb_dma_get_gem_obj(fb, plane_index); if (WARN_ON(!obj)) return; diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c index f3788d7d82d6..cc4d0fa6262c 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include @@ -185,7 +185,7 @@ static void aspeed_gfx_pipe_update(struct drm_simple_display_pipe *pipe, if (!fb) return; - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); if (!gem) return; writel(gem->paddr, priv->base + CRT_ADDR); diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index 10f31faf140c..ddcbfe7ea0c8 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -448,7 +448,7 @@ static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane, sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR); for (i = 0; i < state->nplanes; i++) { - struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i); + struct drm_gem_cma_object *gem = drm_fb_dma_get_gem_obj(fb, i); state->dscrs[i]->addr = gem->paddr + state->offsets[i]; diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c deleted file mode 100644 index 69c57273b184..000000000000 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ /dev/null @@ -1,145 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * drm kms/fb cma (contiguous memory allocator) helper functions - * - * Copyright (C) 2012 Analog Devices Inc. - * Author: Lars-Peter Clausen - * - * Based on udl_fbdev.c - * Copyright (C) 2012 Red Hat - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * DOC: framebuffer cma helper functions - * - * Provides helper functions for creating a cma (contiguous memory allocator) - * backed framebuffer. - * - * drm_gem_fb_create() is used in the &drm_mode_config_funcs.fb_create - * callback function to create a cma backed framebuffer. - */ - -/** - * drm_fb_cma_get_gem_obj() - Get CMA GEM object for framebuffer - * @fb: The framebuffer - * @plane: Which plane - * - * Return the CMA GEM object for given framebuffer. - * - * This function will usually be called from the CRTC callback functions. - */ -struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb, - unsigned int plane) -{ - struct drm_gem_object *gem; - - gem = drm_gem_fb_get_obj(fb, plane); - if (!gem) - return NULL; - - return to_drm_gem_cma_obj(gem); -} -EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj); - -/** - * drm_fb_cma_get_gem_addr() - Get physical address for framebuffer, for pixel - * formats where values are grouped in blocks this will get you the beginning of - * the block - * @fb: The framebuffer - * @state: Which state of drm plane - * @plane: Which plane - * Return the CMA GEM address for given framebuffer. - * - * This function will usually be called from the PLANE callback functions. - */ -dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb, - struct drm_plane_state *state, - unsigned int plane) -{ - struct drm_gem_cma_object *obj; - dma_addr_t paddr; - u8 h_div = 1, v_div = 1; - u32 block_w = drm_format_info_block_width(fb->format, plane); - u32 block_h = drm_format_info_block_height(fb->format, plane); - u32 block_size = fb->format->char_per_block[plane]; - u32 sample_x; - u32 sample_y; - u32 block_start_y; - u32 num_hblocks; - - obj = drm_fb_cma_get_gem_obj(fb, plane); - if (!obj) - return 0; - - paddr = obj->paddr + fb->offsets[plane]; - - if (plane > 0) { - h_div = fb->format->hsub; - v_div = fb->format->vsub; - } - - sample_x = (state->src_x >> 16) / h_div; - sample_y = (state->src_y >> 16) / v_div; - block_start_y = (sample_y / block_h) * block_h; - num_hblocks = sample_x / block_w; - - paddr += fb->pitches[plane] * block_start_y; - paddr += block_size * num_hblocks; - - return paddr; -} -EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr); - -/** - * drm_fb_cma_sync_non_coherent - Sync GEM object to non-coherent backing - * memory - * @drm: DRM device - * @old_state: Old plane state - * @state: New plane state - * - * This function can be used by drivers that use damage clips and have - * CMA GEM objects backed by non-coherent memory. Calling this function - * in a plane's .atomic_update ensures that all the data in the backing - * memory have been written to RAM. - */ -void drm_fb_cma_sync_non_coherent(struct drm_device *drm, - struct drm_plane_state *old_state, - struct drm_plane_state *state) -{ - const struct drm_format_info *finfo = state->fb->format; - struct drm_atomic_helper_damage_iter iter; - const struct drm_gem_cma_object *cma_obj; - unsigned int offset, i; - struct drm_rect clip; - dma_addr_t daddr; - size_t nb_bytes; - - for (i = 0; i < finfo->num_planes; i++) { - cma_obj = drm_fb_cma_get_gem_obj(state->fb, i); - if (!cma_obj->map_noncoherent) - continue; - - daddr = drm_fb_cma_get_gem_addr(state->fb, state, i); - drm_atomic_helper_damage_iter_init(&iter, old_state, state); - - drm_atomic_for_each_plane_damage(&iter, &clip) { - /* Ignore x1/x2 values, invalidate complete lines */ - offset = clip.y1 * state->fb->pitches[i]; - - nb_bytes = (clip.y2 - clip.y1) * state->fb->pitches[i]; - dma_sync_single_for_device(drm->dev, daddr + offset, - nb_bytes, DMA_TO_DEVICE); - } - } -} -EXPORT_SYMBOL_GPL(drm_fb_cma_sync_non_coherent); diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c b/drivers/gpu/drm/drm_fb_dma_helper.c new file mode 100644 index 000000000000..85fd21cd9dda --- /dev/null +++ b/drivers/gpu/drm/drm_fb_dma_helper.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * drm kms/fb dma helper functions + * + * Copyright (C) 2012 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Based on udl_fbdev.c + * Copyright (C) 2012 Red Hat + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * DOC: framebuffer dma helper functions + * + * Provides helper functions for creating a DMA-contiguous framebuffer. + * + * Depending on the platform, the buffers may be physically non-contiguous and + * mapped through an IOMMU or a similar mechanism, or allocated from + * physically-contiguous memory (using, for instance, CMA or a pool of memory + * reserved at early boot). This is handled behind the scenes by the DMA mapping + * API. + * + * drm_gem_fb_create() is used in the &drm_mode_config_funcs.fb_create + * callback function to create a DMA-contiguous framebuffer. + */ + +/** + * drm_fb_dma_get_gem_obj() - Get CMA GEM object for framebuffer + * @fb: The framebuffer + * @plane: Which plane + * + * Return the CMA GEM object for given framebuffer. + * + * This function will usually be called from the CRTC callback functions. + */ +struct drm_gem_cma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb, + unsigned int plane) +{ + struct drm_gem_object *gem; + + gem = drm_gem_fb_get_obj(fb, plane); + if (!gem) + return NULL; + + return to_drm_gem_cma_obj(gem); +} +EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_obj); + +/** + * drm_fb_dma_get_gem_addr() - Get DMA (bus) address for framebuffer, for pixel + * formats where values are grouped in blocks this will get you the beginning of + * the block + * @fb: The framebuffer + * @state: Which state of drm plane + * @plane: Which plane + * Return the DMA GEM address for given framebuffer. + * + * This function will usually be called from the PLANE callback functions. + */ +dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb, + struct drm_plane_state *state, + unsigned int plane) +{ + struct drm_gem_cma_object *obj; + dma_addr_t paddr; + u8 h_div = 1, v_div = 1; + u32 block_w = drm_format_info_block_width(fb->format, plane); + u32 block_h = drm_format_info_block_height(fb->format, plane); + u32 block_size = fb->format->char_per_block[plane]; + u32 sample_x; + u32 sample_y; + u32 block_start_y; + u32 num_hblocks; + + obj = drm_fb_dma_get_gem_obj(fb, plane); + if (!obj) + return 0; + + paddr = obj->paddr + fb->offsets[plane]; + + if (plane > 0) { + h_div = fb->format->hsub; + v_div = fb->format->vsub; + } + + sample_x = (state->src_x >> 16) / h_div; + sample_y = (state->src_y >> 16) / v_div; + block_start_y = (sample_y / block_h) * block_h; + num_hblocks = sample_x / block_w; + + paddr += fb->pitches[plane] * block_start_y; + paddr += block_size * num_hblocks; + + return paddr; +} +EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_addr); + +/** + * drm_fb_dma_sync_non_coherent - Sync GEM object to non-coherent backing + * memory + * @drm: DRM device + * @old_state: Old plane state + * @state: New plane state + * + * This function can be used by drivers that use damage clips and have + * CMA GEM objects backed by non-coherent memory. Calling this function + * in a plane's .atomic_update ensures that all the data in the backing + * memory have been written to RAM. + */ +void drm_fb_dma_sync_non_coherent(struct drm_device *drm, + struct drm_plane_state *old_state, + struct drm_plane_state *state) +{ + const struct drm_format_info *finfo = state->fb->format; + struct drm_atomic_helper_damage_iter iter; + const struct drm_gem_cma_object *cma_obj; + unsigned int offset, i; + struct drm_rect clip; + dma_addr_t daddr; + size_t nb_bytes; + + for (i = 0; i < finfo->num_planes; i++) { + cma_obj = drm_fb_dma_get_gem_obj(state->fb, i); + if (!cma_obj->map_noncoherent) + continue; + + daddr = drm_fb_dma_get_gem_addr(state->fb, state, i); + drm_atomic_helper_damage_iter_init(&iter, old_state, state); + + drm_atomic_for_each_plane_damage(&iter, &clip) { + /* Ignore x1/x2 values, invalidate complete lines */ + offset = clip.y1 * state->fb->pitches[i]; + + nb_bytes = (clip.y2 - clip.y1) * state->fb->pitches[i]; + dma_sync_single_for_device(drm->dev, daddr + offset, + nb_bytes, DMA_TO_DEVICE); + } + } +} +EXPORT_SYMBOL_GPL(drm_fb_dma_sync_non_coherent); diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index c6182b5de78b..400b16d9147d 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -54,7 +54,7 @@ static int drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pix const void *sbuf; /* - * Some source buffers, such as CMA memory, use write-combine + * Some source buffers, such as DMA memory, use write-combine * caching, so reads are uncached. Speed up access by fetching * one line at a time. */ @@ -676,7 +676,7 @@ void drm_fb_xrgb8888_to_mono(void *dst, unsigned int dst_pitch, const void *vadd dst_pitch = DIV_ROUND_UP(linepixels, 8); /* - * The cma memory is write-combined so reads are uncached. + * The dma memory is write-combined so reads are uncached. * Speed up by fetching one line at a time. * * Also, format conversion from XR24 to monochrome are done diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c index 3b20e79158c8..aba2b714e8a6 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -95,7 +95,7 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane, if (index < 0) return; - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); switch (fb->format->format) { case DRM_FORMAT_RGB565: diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c index 2c7059b775a1..c5d304826c3b 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -548,7 +548,7 @@ static const struct drm_crtc_funcs ade_crtc_funcs = { static void ade_rdma_set(void __iomem *base, struct drm_framebuffer *fb, u32 ch, u32 y, u32 in_h, u32 fmt) { - struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *obj = drm_fb_dma_get_gem_obj(fb, 0); u32 reg_ctrl, reg_addr, reg_size, reg_stride, reg_space, reg_en; u32 stride = fb->pitches[0]; u32 addr = (u32)obj->paddr + y * stride; diff --git a/drivers/gpu/drm/imx/dcss/dcss-plane.c b/drivers/gpu/drm/imx/dcss/dcss-plane.c index c29f343f33e5..a333c13c9ebc 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-plane.c +++ b/drivers/gpu/drm/imx/dcss/dcss-plane.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -156,7 +156,7 @@ static int dcss_plane_atomic_check(struct drm_plane *plane, if (!fb || !new_plane_state->crtc) return 0; - cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + cma_obj = drm_fb_dma_get_gem_obj(fb, 0); WARN_ON(!cma_obj); crtc_state = drm_atomic_get_existing_crtc_state(state, @@ -218,7 +218,7 @@ static void dcss_plane_atomic_set_base(struct dcss_plane *dcss_plane) struct dcss_dev *dcss = plane->dev->dev_private; struct drm_framebuffer *fb = state->fb; const struct drm_format_info *format = fb->format; - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *cma_obj = drm_fb_dma_get_gem_obj(fb, 0); unsigned long p1_ba = 0, p2_ba = 0; if (!format->is_yuv || diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index f1b397693af8..27bd16418002 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -129,7 +129,7 @@ drm_plane_state_to_eba(struct drm_plane_state *state, int plane) int x = state->src.x1 >> 16; int y = state->src.y1 >> 16; - cma_obj = drm_fb_cma_get_gem_obj(fb, plane); + cma_obj = drm_fb_dma_get_gem_obj(fb, plane); BUG_ON(!cma_obj); return cma_obj->paddr + fb->offsets[plane] + fb->pitches[plane] * y + @@ -145,7 +145,7 @@ drm_plane_state_to_ubo(struct drm_plane_state *state) int x = state->src.x1 >> 16; int y = state->src.y1 >> 16; - cma_obj = drm_fb_cma_get_gem_obj(fb, 1); + cma_obj = drm_fb_dma_get_gem_obj(fb, 1); BUG_ON(!cma_obj); x /= fb->format->hsub; @@ -164,7 +164,7 @@ drm_plane_state_to_vbo(struct drm_plane_state *state) int x = state->src.x1 >> 16; int y = state->src.y1 >> 16; - cma_obj = drm_fb_cma_get_gem_obj(fb, 2); + cma_obj = drm_fb_dma_get_gem_obj(fb, 2); BUG_ON(!cma_obj); x /= fb->format->hsub; diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index f5835e6bf877..1dd78145b4b9 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include @@ -669,12 +669,12 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, if (newstate && newstate->fb) { if (priv->soc_info->map_noncoherent) - drm_fb_cma_sync_non_coherent(&priv->drm, oldstate, newstate); + drm_fb_dma_sync_non_coherent(&priv->drm, oldstate, newstate); crtc_state = newstate->crtc->state; plane_id = !!(priv->soc_info->has_osd && plane != &priv->f0); - addr = drm_fb_cma_get_gem_addr(newstate->fb, newstate, 0); + addr = drm_fb_dma_get_gem_addr(newstate->fb, newstate, 0); width = newstate->src_w >> 16; height = newstate->src_h >> 16; cpp = newstate->fb->format->cpp[0]; diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index c117073fd61e..21052600cef4 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -362,15 +362,15 @@ static void ingenic_ipu_plane_atomic_update(struct drm_plane *plane, } if (ingenic_drm_map_noncoherent(ipu->master)) - drm_fb_cma_sync_non_coherent(ipu->drm, oldstate, newstate); + drm_fb_dma_sync_non_coherent(ipu->drm, oldstate, newstate); /* New addresses will be committed in vblank handler... */ - ipu->addr_y = drm_fb_cma_get_gem_addr(newstate->fb, newstate, 0); + ipu->addr_y = drm_fb_dma_get_gem_addr(newstate->fb, newstate, 0); if (finfo->num_planes > 1) - ipu->addr_u = drm_fb_cma_get_gem_addr(newstate->fb, newstate, + ipu->addr_u = drm_fb_dma_get_gem_addr(newstate->fb, newstate, 1); if (finfo->num_planes > 2) - ipu->addr_v = drm_fb_cma_get_gem_addr(newstate->fb, newstate, + ipu->addr_v = drm_fb_dma_get_gem_addr(newstate->fb, newstate, 2); if (!needs_modeset) diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c index e385b8741776..ca3246e48e45 100644 --- a/drivers/gpu/drm/kmb/kmb_plane.c +++ b/drivers/gpu/drm/kmb/kmb_plane.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -403,7 +403,7 @@ static void kmb_plane_atomic_update(struct drm_plane *plane, kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_WIDTH(plane_id), (width * fb->format->cpp[0])); - addr[Y_PLANE] = drm_fb_cma_get_gem_addr(fb, new_plane_state, 0); + addr[Y_PLANE] = drm_fb_dma_get_gem_addr(fb, new_plane_state, 0); kmb_write_lcd(kmb, LCD_LAYERn_DMA_START_ADDR(plane_id), addr[Y_PLANE] + fb->offsets[0]); val = get_pixel_format(fb->format->format); @@ -415,7 +415,7 @@ static void kmb_plane_atomic_update(struct drm_plane *plane, kmb_write_lcd(kmb, LCD_LAYERn_DMA_CB_LINE_WIDTH(plane_id), (width * fb->format->cpp[0])); - addr[U_PLANE] = drm_fb_cma_get_gem_addr(fb, new_plane_state, + addr[U_PLANE] = drm_fb_dma_get_gem_addr(fb, new_plane_state, U_PLANE); /* check if Cb/Cr is swapped*/ if (num_planes == 3 && (val & LCD_LAYER_CRCB_ORDER)) @@ -436,7 +436,7 @@ static void kmb_plane_atomic_update(struct drm_plane *plane, LCD_LAYERn_DMA_CR_LINE_WIDTH(plane_id), ((width) * fb->format->cpp[0])); - addr[V_PLANE] = drm_fb_cma_get_gem_addr(fb, + addr[V_PLANE] = drm_fb_dma_get_gem_addr(fb, new_plane_state, V_PLANE); diff --git a/drivers/gpu/drm/logicvc/Kconfig b/drivers/gpu/drm/logicvc/Kconfig index 300b2be07385..73be27cc749c 100644 --- a/drivers/gpu/drm/logicvc/Kconfig +++ b/drivers/gpu/drm/logicvc/Kconfig @@ -3,7 +3,7 @@ config DRM_LOGICVC depends on DRM depends on OF || COMPILE_TEST select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER + select DRM_KMS_DMA_HELPER select DRM_GEM_CMA_HELPER help DRM display driver for the logiCVC programmable logic block from Xylon diff --git a/drivers/gpu/drm/logicvc/logicvc_layer.c b/drivers/gpu/drm/logicvc/logicvc_layer.c index 466f9bd88bc1..464000aea765 100644 --- a/drivers/gpu/drm/logicvc/logicvc_layer.c +++ b/drivers/gpu/drm/logicvc/logicvc_layer.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -157,7 +157,7 @@ static void logicvc_plane_atomic_update(struct drm_plane *drm_plane, new_state->crtc_h - 1); if (logicvc->caps->layer_address) { - phys_addr_t fb_addr = drm_fb_cma_get_gem_addr(fb, new_state, 0); + phys_addr_t fb_addr = drm_fb_dma_get_gem_addr(fb, new_state, 0); regmap_write(logicvc->regmap, LOGICVC_LAYER_ADDRESS_REG(index), fb_addr); @@ -280,7 +280,7 @@ int logicvc_layer_buffer_find_setup(struct logicvc_drm *logicvc, return -ENOMEM; } - fb_addr = drm_fb_cma_get_gem_addr(fb, state, 0); + fb_addr = drm_fb_dma_get_gem_addr(fb, state, 0); if (fb_addr < logicvc->reserved_mem_base) { drm_err(drm_dev, "Framebuffer memory below reserved memory base!\n"); diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c index 4df477540d07..9247da47f0cf 100644 --- a/drivers/gpu/drm/mcde/mcde_display.c +++ b/drivers/gpu/drm/mcde/mcde_display.c @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include #include @@ -165,7 +165,7 @@ static int mcde_display_check(struct drm_simple_display_pipe *pipe, struct drm_framebuffer *fb = pstate->fb; if (fb) { - u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0); + u32 offset = drm_fb_dma_get_gem_addr(fb, pstate, 0); /* FB base address must be dword aligned. */ if (offset & 3) { @@ -1424,7 +1424,7 @@ static void mcde_display_update(struct drm_simple_display_pipe *pipe, * from the DRM core before the display is enabled. */ if (fb) { - mcde_set_extsrc(mcde, drm_fb_cma_get_gem_addr(fb, pstate, 0)); + mcde_set_extsrc(mcde, drm_fb_dma_get_gem_addr(fb, pstate, 0)); dev_info_once(mcde->dev, "first update of display contents\n"); /* * Usually the flow is already active, unless we are in diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c index e601baa87e55..509c2b03bc42 100644 --- a/drivers/gpu/drm/mcde/mcde_drv.c +++ b/drivers/gpu/drm/mcde/mcde_drv.c @@ -37,7 +37,7 @@ * (effectively using channels 0..3) for concurrent use. * * In the current DRM/KMS setup, we use one external source, one overlay, - * one FIFO and one formatter which we connect to the simple CMA framebuffer + * one FIFO and one formatter which we connect to the simple DMA framebuffer * helpers. We then provide a bridge to the DSI port, and on the DSI port * bridge we connect hang a panel bridge or other bridge. This may be subject * to change as we exploit more of the hardware capabilities. @@ -68,7 +68,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c index 93c1cd2aab43..bfebf45d8402 100644 --- a/drivers/gpu/drm/meson/meson_overlay.c +++ b/drivers/gpu/drm/meson/meson_overlay.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include @@ -650,7 +650,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, switch (priv->viu.vd1_planes) { case 3: - gem = drm_fb_cma_get_gem_obj(fb, 2); + gem = drm_fb_dma_get_gem_obj(fb, 2); priv->viu.vd1_addr2 = gem->paddr + fb->offsets[2]; priv->viu.vd1_stride2 = fb->pitches[2]; priv->viu.vd1_height2 = @@ -662,7 +662,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, priv->viu.vd1_height2); fallthrough; case 2: - gem = drm_fb_cma_get_gem_obj(fb, 1); + gem = drm_fb_dma_get_gem_obj(fb, 1); priv->viu.vd1_addr1 = gem->paddr + fb->offsets[1]; priv->viu.vd1_stride1 = fb->pitches[1]; priv->viu.vd1_height1 = @@ -674,7 +674,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, priv->viu.vd1_height1); fallthrough; case 1: - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); priv->viu.vd1_addr0 = gem->paddr + fb->offsets[0]; priv->viu.vd1_stride0 = fb->pitches[0]; priv->viu.vd1_height0 = diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c index f3d49e81acf4..51479715cce7 100644 --- a/drivers/gpu/drm/meson/meson_plane.c +++ b/drivers/gpu/drm/meson/meson_plane.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -365,7 +365,7 @@ static void meson_plane_atomic_update(struct drm_plane *plane, } /* Update Canvas with buffer address */ - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); priv->viu.osd1_addr = gem->paddr; priv->viu.osd1_stride = fb->pitches[0]; diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c b/drivers/gpu/drm/mxsfb/lcdif_kms.c index b27a54e31343..0df418774035 100644 --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -296,7 +296,7 @@ static void lcdif_crtc_atomic_enable(struct drm_crtc *crtc, lcdif_crtc_mode_set_nofb(lcdif, bridge_state, bus_format); /* Write cur_buf as well to avoid an initial corrupt frame */ - paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0); + paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); if (paddr) { writel(lower_32_bits(paddr), lcdif->base + LCDC_V8_CTRLDESCL_LOW0_4); @@ -405,7 +405,7 @@ static void lcdif_plane_primary_atomic_update(struct drm_plane *plane, plane); dma_addr_t paddr; - paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0); + paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); if (paddr) { writel(lower_32_bits(paddr), lcdif->base + LCDC_V8_CTRLDESCL_LOW0_4); diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c index 2da2be6c11f2..e55e9262afb2 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -388,7 +388,7 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc, mxsfb_crtc_mode_set_nofb(mxsfb, bridge_state, bus_format); /* Write cur_buf as well to avoid an initial corrupt frame */ - paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0); + paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); if (paddr) { writel(paddr, mxsfb->base + mxsfb->devdata->cur_buf); writel(paddr, mxsfb->base + mxsfb->devdata->next_buf); @@ -543,7 +543,7 @@ static void mxsfb_plane_primary_atomic_update(struct drm_plane *plane, plane); dma_addr_t paddr; - paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0); + paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); if (paddr) writel(paddr, mxsfb->base + mxsfb->devdata->next_buf); } @@ -559,7 +559,7 @@ static void mxsfb_plane_overlay_atomic_update(struct drm_plane *plane, dma_addr_t paddr; u32 ctrl; - paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0); + paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); if (!paddr) { writel(0, mxsfb->base + LCDC_AS_CTRL); return; diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c index 6263346f24c6..5f2429c3633e 100644 --- a/drivers/gpu/drm/pl111/pl111_display.c +++ b/drivers/gpu/drm/pl111/pl111_display.c @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include @@ -94,7 +94,7 @@ static int pl111_display_check(struct drm_simple_display_pipe *pipe, return -EINVAL; if (fb) { - u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0); + u32 offset = drm_fb_dma_get_gem_addr(fb, pstate, 0); /* FB base address must be dword aligned. */ if (offset & 3) @@ -398,7 +398,7 @@ static void pl111_display_update(struct drm_simple_display_pipe *pipe, struct drm_framebuffer *fb = pstate->fb; if (fb) { - u32 addr = drm_fb_cma_get_gem_addr(fb, pstate, 0); + u32 addr = drm_fb_dma_get_gem_addr(fb, pstate, 0); writel(addr, priv->regs + CLCD_UBAS); } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 07ba6bff5f5d..4ae444346991 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -350,7 +350,7 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp, pitch = fb->pitches[0] * 8 / state->format->bpp; for (i = 0; i < state->format->planes; ++i) { - gem = drm_fb_cma_get_gem_obj(fb, i); + gem = drm_fb_dma_get_gem_obj(fb, i); dma[i] = gem->paddr + fb->offsets[i]; } } else { diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index 5e985d46d68e..99d32f42e46d 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include @@ -183,7 +183,7 @@ int rcar_du_vsp_map_fb(struct rcar_du_vsp *vsp, struct drm_framebuffer *fb, int ret; for (i = 0; i < fb->format->num_planes; ++i) { - struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i); + struct drm_gem_cma_object *gem = drm_fb_dma_get_gem_obj(fb, i); struct sg_table *sgt = &sg_tables[i]; if (gem->sgt) { diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 387fbd2ab32d..94318f858ed6 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include #include @@ -292,13 +292,13 @@ static void shmob_drm_crtc_compute_base(struct shmob_drm_crtc *scrtc, unsigned int bpp; bpp = scrtc->format->yuv ? 8 : scrtc->format->bpp; - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); scrtc->dma[0] = gem->paddr + fb->offsets[0] + y * fb->pitches[0] + x * bpp / 8; if (scrtc->format->yuv) { bpp = scrtc->format->bpp - 8; - gem = drm_fb_cma_get_gem_obj(fb, 1); + gem = drm_fb_dma_get_gem_obj(fb, 1); scrtc->dma[1] = gem->paddr + fb->offsets[1] + y / (bpp == 4 ? 2 : 1) * fb->pitches[1] + x * (bpp == 16 ? 2 : 1); diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c index 4763ea8e1af0..6fa64bce0c91 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include #include @@ -45,13 +45,13 @@ static void shmob_drm_plane_compute_base(struct shmob_drm_plane *splane, unsigned int bpp; bpp = splane->format->yuv ? 8 : splane->format->bpp; - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); splane->dma[0] = gem->paddr + fb->offsets[0] + y * fb->pitches[0] + x * bpp / 8; if (splane->format->yuv) { bpp = splane->format->bpp - 8; - gem = drm_fb_cma_get_gem_obj(fb, 1); + gem = drm_fb_dma_get_gem_obj(fb, 1); splane->dma[1] = gem->paddr + fb->offsets[1] + y / (bpp == 4 ? 2 : 1) * fb->pitches[1] + x * (bpp == 16 ? 2 : 1); diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c index 10d21f7ab02d..5ea104e0beb8 100644 --- a/drivers/gpu/drm/sprd/sprd_dpu.c +++ b/drivers/gpu/drm/sprd/sprd_dpu.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -340,7 +340,7 @@ static void sprd_dpu_layer(struct sprd_dpu *dpu, struct drm_plane_state *state) size = (src_w & 0xffff) | (src_h << 16); for (i = 0; i < fb->format->num_planes; i++) { - cma_obj = drm_fb_cma_get_gem_obj(fb, i); + cma_obj = drm_fb_dma_get_gem_obj(fb, i); addr = cma_obj->paddr + fb->offsets[i]; if (i == 0) diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c index 1e9bd4241f10..d374fa50be60 100644 --- a/drivers/gpu/drm/sti/sti_cursor.c +++ b/drivers/gpu/drm/sti/sti_cursor.c @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include @@ -243,7 +243,7 @@ static int sti_cursor_atomic_check(struct drm_plane *drm_plane, } } - if (!drm_fb_cma_get_gem_obj(fb, 0)) { + if (!drm_fb_dma_get_gem_obj(fb, 0)) { DRM_ERROR("Can't get CMA GEM object for fb\n"); return -EINVAL; } @@ -278,7 +278,7 @@ static void sti_cursor_atomic_update(struct drm_plane *drm_plane, dst_x = newstate->crtc_x; dst_y = newstate->crtc_y; - cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + cma_obj = drm_fb_dma_get_gem_obj(fb, 0); /* Convert ARGB8888 to CLUT8 */ sti_cursor_argb8888_to_clut8(cursor, (u32 *)cma_obj->vaddr); diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index af783f599306..623a09163f9f 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include #include @@ -658,7 +658,7 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane, return -EINVAL; } - if (!drm_fb_cma_get_gem_obj(fb, 0)) { + if (!drm_fb_dma_get_gem_obj(fb, 0)) { DRM_ERROR("Can't get CMA GEM object for fb\n"); return -EINVAL; } @@ -778,7 +778,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, top_field->gam_gdp_ctl |= sti_gdp_get_alpharange(format); top_field->gam_gdp_ppt &= ~GAM_GDP_PPT_IGNORE; - cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + cma_obj = drm_fb_dma_get_gem_obj(fb, 0); DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id, (char *)&fb->format->format, diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index 271982080437..26284c5f5b22 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include #include @@ -1055,7 +1055,7 @@ static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane, return -EINVAL; } - if (!drm_fb_cma_get_gem_obj(fb, 0)) { + if (!drm_fb_dma_get_gem_obj(fb, 0)) { DRM_ERROR("Can't get CMA GEM object for fb\n"); return -EINVAL; } @@ -1178,7 +1178,7 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane, cmd->iqi.sat_gain = IQI_SAT_GAIN_DFLT; cmd->iqi.pxf_conf = IQI_PXF_CONF_DFLT; - cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + cma_obj = drm_fb_dma_get_gem_obj(fb, 0); DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id, (char *)&fb->format->format, diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 8f3307b279e7..42a98ef73d03 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -1346,7 +1346,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, } /* Sets the FB address */ - paddr = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 0); + paddr = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 0); if (newstate->rotation & DRM_MODE_REFLECT_X) paddr += (fb->format->cpp[0] * (x1 - x0 + 1)) - 1; @@ -1380,7 +1380,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, case DRM_FORMAT_NV12: case DRM_FORMAT_NV21: /* Configure the auxiliary frame buffer address 0 */ - paddr1 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1); + paddr1 = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 1); if (newstate->rotation & DRM_MODE_REFLECT_X) paddr1 += ((fb->format->cpp[1] * (x1 - x0 + 1)) >> 1) - 1; @@ -1392,8 +1392,8 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, break; case DRM_FORMAT_YUV420: /* Configure the auxiliary frame buffer address 0 & 1 */ - paddr1 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1); - paddr2 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 2); + paddr1 = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 1); + paddr2 = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 2); if (newstate->rotation & DRM_MODE_REFLECT_X) { paddr1 += ((fb->format->cpp[1] * (x1 - x0 + 1)) >> 1) - 1; @@ -1410,8 +1410,8 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, break; case DRM_FORMAT_YVU420: /* Configure the auxiliary frame buffer address 0 & 1 */ - paddr1 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 2); - paddr2 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1); + paddr1 = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 2); + paddr2 = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 1); if (newstate->rotation & DRM_MODE_REFLECT_X) { paddr1 += ((fb->format->cpp[1] * (x1 - x0 + 1)) >> 1) - 1; diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 0c69eab1fd37..fa4539c3b149 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -338,7 +338,7 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, fb->pitches[0] * 8); /* Get the start of the displayed memory */ - paddr = drm_fb_cma_get_gem_addr(fb, state, 0); + paddr = drm_fb_dma_get_gem_addr(fb, state, 0); DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr); if (fb->format->is_yuv) diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index 462fae73eae9..4a811e803dac 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -221,19 +221,19 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend, swap = sun4i_frontend_format_chroma_requires_swap(fb->format->format); /* Set the physical address of the buffer in memory */ - paddr = drm_fb_cma_get_gem_addr(fb, state, 0); + paddr = drm_fb_dma_get_gem_addr(fb, state, 0); DRM_DEBUG_DRIVER("Setting buffer #0 address to %pad\n", &paddr); regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, paddr); if (fb->format->num_planes > 1) { - paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 2 : 1); + paddr = drm_fb_dma_get_gem_addr(fb, state, swap ? 2 : 1); DRM_DEBUG_DRIVER("Setting buffer #1 address to %pad\n", &paddr); regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR1_REG, paddr); } if (fb->format->num_planes > 2) { - paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 1 : 2); + paddr = drm_fb_dma_get_gem_addr(fb, state, swap ? 1 : 2); DRM_DEBUG_DRIVER("Setting buffer #2 address to %pad\n", &paddr); regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR2_REG, paddr); diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index 06ed571c37f0..900c71c47a3b 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -200,7 +200,7 @@ static int sun8i_ui_layer_update_buffer(struct sun8i_mixer *mixer, int channel, ch_base = sun8i_channel_base(mixer, channel); /* Get the physical address of the buffer in memory */ - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr); diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index b9473efa308d..8b5dae30c8c5 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -322,7 +322,7 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel, for (i = 0; i < format->num_planes; i++) { /* Get the physical address of the buffer in memory */ - gem = drm_fb_cma_get_gem_obj(fb, i); + gem = drm_fb_dma_get_gem_obj(fb, i); DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr); diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index ed828de5ac01..9291209154a7 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -3,7 +3,7 @@ * Copyright (C) 2012-2013 Avionic Design GmbH * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. * - * Based on the KMS/FB CMA helpers + * Based on the KMS/FB DMA helpers * Copyright (C) 2012 Analog Devices Inc. */ diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c index dd3c6a606ae2..cdd9a64f9736 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc.c +++ b/drivers/gpu/drm/tidss/tidss_dispc.c @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -1961,7 +1961,7 @@ dma_addr_t dispc_plane_state_paddr(const struct drm_plane_state *state) u32 x = state->src_x >> 16; u32 y = state->src_y >> 16; - gem = drm_fb_cma_get_gem_obj(state->fb, 0); + gem = drm_fb_dma_get_gem_obj(state->fb, 0); return gem->paddr + fb->offsets[0] + x * fb->format->cpp[0] + y * fb->pitches[0]; @@ -1978,7 +1978,7 @@ dma_addr_t dispc_plane_state_p_uv_addr(const struct drm_plane_state *state) if (WARN_ON(state->fb->format->num_planes != 2)) return 0; - gem = drm_fb_cma_get_gem_obj(fb, 1); + gem = drm_fb_dma_get_gem_obj(fb, 1); return gem->paddr + fb->offsets[1] + (x * fb->format->cpp[1] / fb->format->hsub) + diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 509fbae8c9a6..bd4f52242c0a 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -68,7 +68,7 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb) dma_addr_t start, end; u64 dma_base_and_ceiling; - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); start = gem->paddr + fb->offsets[0] + crtc->y * fb->pitches[0] + diff --git a/drivers/gpu/drm/tiny/arcpgu.c b/drivers/gpu/drm/tiny/arcpgu.c index 7461cb401407..cdf320c547fb 100644 --- a/drivers/gpu/drm/tiny/arcpgu.c +++ b/drivers/gpu/drm/tiny/arcpgu.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include @@ -226,7 +226,7 @@ static void arc_pgu_update(struct drm_simple_display_pipe *pipe, return; arcpgu = pipe_to_arcpgu_priv(pipe); - gem = drm_fb_cma_get_gem_obj(pipe->plane.state->fb, 0); + gem = drm_fb_dma_get_gem_obj(pipe->plane.state->fb, 0); arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->paddr); } diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c index 8d686eecd5f4..fc73ffa46a19 100644 --- a/drivers/gpu/drm/tiny/ili9225.c +++ b/drivers/gpu/drm/tiny/ili9225.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -78,7 +78,7 @@ static inline int ili9225_command(struct mipi_dbi *dbi, u8 cmd, u16 data) static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) { - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *cma_obj = drm_fb_dma_get_gem_obj(fb, 0); struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev); unsigned int height = rect->y2 - rect->y1; unsigned int width = rect->x2 - rect->x1; diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 013790c45d0a..6d3b5b3cb955 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -511,7 +511,7 @@ static void repaper_get_temperature(struct repaper_epd *epd) static int repaper_fb_dirty(struct drm_framebuffer *fb) { - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *cma_obj = drm_fb_dma_get_gem_obj(fb, 0); struct repaper_epd *epd = drm_to_epd(fb->dev); struct drm_rect clip; int idx, ret = 0; diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c index 8eddb020c43e..b1584b362c79 100644 --- a/drivers/gpu/drm/tiny/st7586.c +++ b/drivers/gpu/drm/tiny/st7586.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -92,7 +92,7 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr, static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb, struct drm_rect *clip) { - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *cma_obj = drm_fb_dma_get_gem_obj(fb, 0); void *src = cma_obj->vaddr; int ret = 0; diff --git a/drivers/gpu/drm/tve200/tve200_display.c b/drivers/gpu/drm/tve200/tve200_display.c index 771bad881714..6647aab8a25e 100644 --- a/drivers/gpu/drm/tve200/tve200_display.c +++ b/drivers/gpu/drm/tve200/tve200_display.c @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include @@ -90,7 +90,7 @@ static int tve200_display_check(struct drm_simple_display_pipe *pipe, } if (fb) { - u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0); + u32 offset = drm_fb_dma_get_gem_addr(fb, pstate, 0); /* FB base address must be dword aligned. */ if (offset & 3) { @@ -267,14 +267,14 @@ static void tve200_display_update(struct drm_simple_display_pipe *pipe, if (fb) { /* For RGB, the Y component is used as base address */ - writel(drm_fb_cma_get_gem_addr(fb, pstate, 0), + writel(drm_fb_dma_get_gem_addr(fb, pstate, 0), priv->regs + TVE200_Y_FRAME_BASE_ADDR); /* For three plane YUV we need two more addresses */ if (fb->format->format == DRM_FORMAT_YUV420) { - writel(drm_fb_cma_get_gem_addr(fb, pstate, 1), + writel(drm_fb_dma_get_gem_addr(fb, pstate, 1), priv->regs + TVE200_U_FRAME_BASE_ADDR); - writel(drm_fb_cma_get_gem_addr(fb, pstate, 2), + writel(drm_fb_dma_get_gem_addr(fb, pstate, 2), priv->regs + TVE200_V_FRAME_BASE_ADDR); } } diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index d3efa7e5b5ed..f85788401707 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include @@ -824,7 +824,7 @@ static void vc4_async_page_flip_seqno_complete(struct vc4_seqno_cb *cb) if (flip_state->old_fb) { struct drm_gem_cma_object *cma_bo = - drm_fb_cma_get_gem_obj(flip_state->old_fb, 0); + drm_fb_dma_get_gem_obj(flip_state->old_fb, 0); bo = to_vc4_bo(&cma_bo->base); } @@ -857,7 +857,7 @@ static int vc4_async_set_fence_cb(struct drm_device *dev, struct vc4_async_flip_state *flip_state) { struct drm_framebuffer *fb = flip_state->fb; - struct drm_gem_cma_object *cma_bo = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *cma_bo = drm_fb_dma_get_gem_obj(fb, 0); struct vc4_dev *vc4 = to_vc4_dev(dev); struct dma_fence *fence; int ret; @@ -945,7 +945,7 @@ static int vc4_async_page_flip(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); - struct drm_gem_cma_object *cma_bo = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *cma_bo = drm_fb_dma_get_gem_obj(fb, 0); struct vc4_bo *bo = to_vc4_bo(&cma_bo->base); int ret; diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 243b29ab6f85..51e0e8aa2135 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -339,7 +339,7 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) { struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); struct drm_framebuffer *fb = state->fb; - struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *bo = drm_fb_dma_get_gem_obj(fb, 0); int num_planes = fb->format->num_planes; struct drm_crtc_state *crtc_state; u32 h_subsample = fb->format->hsub; @@ -1243,7 +1243,7 @@ u32 vc4_plane_dlist_size(const struct drm_plane_state *state) void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb) { struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state); - struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_cma_object *bo = drm_fb_dma_get_gem_obj(fb, 0); uint32_t addr; /* We're skipping the address adjustment for negative origin, @@ -1387,7 +1387,7 @@ static int vc4_prepare_fb(struct drm_plane *plane, if (!state->fb) return 0; - bo = to_vc4_bo(&drm_fb_cma_get_gem_obj(state->fb, 0)->base); + bo = to_vc4_bo(&drm_fb_dma_get_gem_obj(state->fb, 0)->base); drm_gem_plane_helper_prepare_fb(plane, state); @@ -1405,7 +1405,7 @@ static void vc4_cleanup_fb(struct drm_plane *plane, if (plane->state->fb == state->fb || !state->fb) return; - bo = to_vc4_bo(&drm_fb_cma_get_gem_obj(state->fb, 0)->base); + bo = to_vc4_bo(&drm_fb_dma_get_gem_obj(state->fb, 0)->base); vc4_bo_dec_usecnt(bo); } diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index 913e26dd62d4..af48ae68f213 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -317,7 +317,7 @@ static void vc4_txp_connector_atomic_commit(struct drm_connector *conn, if (!drm_dev_enter(drm, &idx)) return; - gem = drm_fb_cma_get_gem_obj(fb, 0); + gem = drm_fb_dma_get_gem_obj(fb, 0); TXP_WRITE(TXP_DST_PTR, gem->paddr + fb->offsets[0]); TXP_WRITE(TXP_DST_PITCH, fb->pitches[0]); TXP_WRITE(TXP_DIM, diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c index a769422e3f1d..3bcb71c71db0 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_disp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -1100,7 +1100,7 @@ static int zynqmp_disp_layer_update(struct zynqmp_disp_layer *layer, struct dma_async_tx_descriptor *desc; dma_addr_t paddr; - paddr = drm_fb_cma_get_gem_addr(state->fb, state, i); + paddr = drm_fb_dma_get_gem_addr(state->fb, state, i); dma->xt.numf = height; dma->sgl.size = width * info->cpp[i]; diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h deleted file mode 100644 index 6447e34528f8..000000000000 --- a/include/drm/drm_fb_cma_helper.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __DRM_FB_CMA_HELPER_H__ -#define __DRM_FB_CMA_HELPER_H__ - -#include - -struct drm_device; -struct drm_framebuffer; -struct drm_plane_state; - -struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb, - unsigned int plane); - -dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb, - struct drm_plane_state *state, - unsigned int plane); - -void drm_fb_cma_sync_non_coherent(struct drm_device *drm, - struct drm_plane_state *old_state, - struct drm_plane_state *state); - -#endif - diff --git a/include/drm/drm_fb_dma_helper.h b/include/drm/drm_fb_dma_helper.h new file mode 100644 index 000000000000..05f657363b30 --- /dev/null +++ b/include/drm/drm_fb_dma_helper.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __DRM_FB_DMA_HELPER_H__ +#define __DRM_FB_DMA_HELPER_H__ + +#include + +struct drm_device; +struct drm_framebuffer; +struct drm_plane_state; + +struct drm_gem_cma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb, + unsigned int plane); + +dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb, + struct drm_plane_state *state, + unsigned int plane); + +void drm_fb_dma_sync_non_coherent(struct drm_device *drm, + struct drm_plane_state *old_state, + struct drm_plane_state *state); + +#endif + -- cgit v1.3-14-g43fede From 4a83c26a1d8702c516db77fc4423ae896ee904f1 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Tue, 2 Aug 2022 02:04:03 +0200 Subject: drm/gem: rename GEM CMA helpers to GEM DMA helpers Rename "GEM CMA" helpers to "GEM DMA" helpers - considering the hierarchy of APIs (mm/cma -> dma -> gem dma) calling them "GEM DMA" seems to be more applicable. Besides that, commit e57924d4ae80 ("drm/doc: Task to rename CMA helpers") requests to rename the CMA helpers and implies that people seem to be confused about the naming. In order to do this renaming the following script was used: ``` #!/bin/bash DIRS="drivers/gpu include/drm Documentation/gpu" REGEX_SYM_UPPER="[0-9A-Z_\-]" REGEX_SYM_LOWER="[0-9a-z_\-]" REGEX_GREP_UPPER="(${REGEX_SYM_UPPER}*)(GEM)_CMA_(${REGEX_SYM_UPPER}*)" REGEX_GREP_LOWER="(${REGEX_SYM_LOWER}*)(gem)_cma_(${REGEX_SYM_LOWER}*)" REGEX_SED_UPPER="s/${REGEX_GREP_UPPER}/\1\2_DMA_\3/g" REGEX_SED_LOWER="s/${REGEX_GREP_LOWER}/\1\2_dma_\3/g" # Find all upper case 'CMA' symbols and replace them with 'DMA'. for ff in $(grep -REHl "${REGEX_GREP_UPPER}" $DIRS) do sed -i -E "$REGEX_SED_UPPER" $ff done # Find all lower case 'cma' symbols and replace them with 'dma'. for ff in $(grep -REHl "${REGEX_GREP_LOWER}" $DIRS) do sed -i -E "$REGEX_SED_LOWER" $ff done # Replace all occurrences of 'CMA' / 'cma' in comments and # documentation files with 'DMA' / 'dma'. for ff in $(grep -RiHl " cma " $DIRS) do sed -i -E "s/ cma / dma /g" $ff sed -i -E "s/ CMA / DMA /g" $ff done # Rename all 'cma_obj's to 'dma_obj'. for ff in $(grep -RiHl "cma_obj" $DIRS) do sed -i -E "s/cma_obj/dma_obj/g" $ff done ``` Only a few more manual modifications were needed, e.g. reverting the following modifications in some DRM Kconfig files - select CMA if HAVE_DMA_CONTIGUOUS + select DMA if HAVE_DMA_CONTIGUOUS as well as manually picking the occurrences of 'CMA'/'cma' in comments and documentation which relate to "GEM CMA", but not "FB CMA". Also drivers/gpu/drm/Makefile was fixed up manually after renaming drm_gem_cma_helper.c to drm_gem_dma_helper.c. This patch is compile-time tested building a x86_64 kernel with `make allyesconfig && make drivers/gpu/drm`. Acked-by: Sam Ravnborg Acked-by: Thomas Zimmermann Reviewed-by: Laurent Pinchart Signed-off-by: Danilo Krummrich Reviewed-by: Liviu Dudau #drivers/gpu/drm/arm Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20220802000405.949236-4-dakr@redhat.com --- Documentation/gpu/drm-mm.rst | 16 +- drivers/gpu/drm/Kconfig | 4 +- drivers/gpu/drm/Makefile | 6 +- drivers/gpu/drm/arm/Kconfig | 4 +- drivers/gpu/drm/arm/display/Kconfig | 2 +- .../drm/arm/display/komeda/komeda_framebuffer.c | 6 +- drivers/gpu/drm/arm/display/komeda/komeda_kms.c | 10 +- drivers/gpu/drm/arm/hdlcd_crtc.c | 2 +- drivers/gpu/drm/arm/hdlcd_drv.c | 6 +- drivers/gpu/drm/arm/malidp_drv.c | 8 +- drivers/gpu/drm/arm/malidp_mw.c | 4 +- drivers/gpu/drm/arm/malidp_planes.c | 16 +- drivers/gpu/drm/armada/armada_gem.c | 6 +- drivers/gpu/drm/aspeed/Kconfig | 2 +- drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c | 4 +- drivers/gpu/drm/aspeed/aspeed_gfx_drv.c | 6 +- drivers/gpu/drm/atmel-hlcdc/Kconfig | 2 +- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 6 +- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 4 +- drivers/gpu/drm/drm_fb_dma_helper.c | 20 +- drivers/gpu/drm/drm_file.c | 2 +- drivers/gpu/drm/drm_gem_cma_helper.c | 605 --------------------- drivers/gpu/drm/drm_gem_dma_helper.c | 602 ++++++++++++++++++++ drivers/gpu/drm/drm_mipi_dbi.c | 2 +- drivers/gpu/drm/fsl-dcu/Kconfig | 2 +- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 6 +- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c | 4 +- drivers/gpu/drm/hisilicon/kirin/Kconfig | 2 +- drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 8 +- drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 2 +- drivers/gpu/drm/imx/Kconfig | 2 +- drivers/gpu/drm/imx/dcss/Kconfig | 2 +- drivers/gpu/drm/imx/dcss/dcss-kms.c | 6 +- drivers/gpu/drm/imx/dcss/dcss-plane.c | 16 +- drivers/gpu/drm/imx/imx-drm-core.c | 8 +- drivers/gpu/drm/imx/imx-drm.h | 2 +- drivers/gpu/drm/imx/ipuv3-crtc.c | 2 +- drivers/gpu/drm/imx/ipuv3-plane.c | 26 +- drivers/gpu/drm/ingenic/Kconfig | 2 +- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 8 +- drivers/gpu/drm/ingenic/ingenic-ipu.c | 2 +- drivers/gpu/drm/kmb/Kconfig | 2 +- drivers/gpu/drm/kmb/kmb_drv.c | 6 +- drivers/gpu/drm/kmb/kmb_plane.c | 2 +- drivers/gpu/drm/logicvc/Kconfig | 2 +- drivers/gpu/drm/logicvc/logicvc_crtc.c | 2 +- drivers/gpu/drm/logicvc/logicvc_drm.c | 10 +- drivers/gpu/drm/logicvc/logicvc_interface.c | 2 +- drivers/gpu/drm/logicvc/logicvc_mode.c | 2 +- drivers/gpu/drm/mcde/Kconfig | 2 +- drivers/gpu/drm/mcde/mcde_display.c | 2 +- drivers/gpu/drm/mcde/mcde_drv.c | 6 +- drivers/gpu/drm/mediatek/Kconfig | 2 +- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 +- drivers/gpu/drm/mediatek/mtk_drm_gem.c | 4 +- drivers/gpu/drm/meson/Kconfig | 2 +- drivers/gpu/drm/meson/meson_drv.c | 10 +- drivers/gpu/drm/meson/meson_overlay.c | 4 +- drivers/gpu/drm/meson/meson_plane.c | 4 +- drivers/gpu/drm/msm/msm_drv.c | 2 +- drivers/gpu/drm/mxsfb/Kconfig | 4 +- drivers/gpu/drm/mxsfb/lcdif_drv.c | 6 +- drivers/gpu/drm/mxsfb/lcdif_kms.c | 2 +- drivers/gpu/drm/mxsfb/mxsfb_drv.c | 6 +- drivers/gpu/drm/mxsfb/mxsfb_kms.c | 2 +- drivers/gpu/drm/panel/Kconfig | 2 +- drivers/gpu/drm/panel/panel-ilitek-ili9341.c | 6 +- drivers/gpu/drm/pl111/Kconfig | 2 +- drivers/gpu/drm/pl111/pl111_display.c | 2 +- drivers/gpu/drm/pl111/pl111_drv.c | 8 +- drivers/gpu/drm/rcar-du/Kconfig | 2 +- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 +- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 4 +- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 36 +- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 4 +- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 4 +- drivers/gpu/drm/rockchip/Kconfig | 2 +- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +- drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 4 +- drivers/gpu/drm/shmobile/Kconfig | 2 +- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 4 +- drivers/gpu/drm/shmobile/shmob_drm_drv.c | 6 +- drivers/gpu/drm/shmobile/shmob_drm_kms.c | 2 +- drivers/gpu/drm/shmobile/shmob_drm_kms.h | 2 +- drivers/gpu/drm/shmobile/shmob_drm_plane.c | 4 +- drivers/gpu/drm/sprd/Kconfig | 2 +- drivers/gpu/drm/sprd/sprd_dpu.c | 8 +- drivers/gpu/drm/sprd/sprd_drm.c | 6 +- drivers/gpu/drm/sti/Kconfig | 2 +- drivers/gpu/drm/sti/sti_cursor.c | 10 +- drivers/gpu/drm/sti/sti_drv.c | 6 +- drivers/gpu/drm/sti/sti_gdp.c | 14 +- drivers/gpu/drm/sti/sti_hqvdp.c | 14 +- drivers/gpu/drm/sti/sti_plane.c | 2 +- drivers/gpu/drm/stm/Kconfig | 2 +- drivers/gpu/drm/stm/drv.c | 10 +- drivers/gpu/drm/stm/ltdc.c | 2 +- drivers/gpu/drm/sun4i/Kconfig | 2 +- drivers/gpu/drm/sun4i/sun4i_backend.c | 2 +- drivers/gpu/drm/sun4i/sun4i_drv.c | 8 +- drivers/gpu/drm/sun4i/sun4i_frontend.c | 2 +- drivers/gpu/drm/sun4i/sun8i_mixer.c | 2 +- drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 4 +- drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 4 +- drivers/gpu/drm/tidss/Kconfig | 2 +- drivers/gpu/drm/tidss/tidss_crtc.c | 2 +- drivers/gpu/drm/tidss/tidss_dispc.c | 6 +- drivers/gpu/drm/tidss/tidss_drv.c | 6 +- drivers/gpu/drm/tilcdc/Kconfig | 2 +- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 4 +- drivers/gpu/drm/tilcdc/tilcdc_drv.c | 6 +- drivers/gpu/drm/tiny/Kconfig | 22 +- drivers/gpu/drm/tiny/arcpgu.c | 8 +- drivers/gpu/drm/tiny/hx8357d.c | 6 +- drivers/gpu/drm/tiny/ili9163.c | 6 +- drivers/gpu/drm/tiny/ili9225.c | 10 +- drivers/gpu/drm/tiny/ili9341.c | 6 +- drivers/gpu/drm/tiny/ili9486.c | 6 +- drivers/gpu/drm/tiny/mi0283qt.c | 6 +- drivers/gpu/drm/tiny/panel-mipi-dbi.c | 6 +- drivers/gpu/drm/tiny/repaper.c | 10 +- drivers/gpu/drm/tiny/st7586.c | 10 +- drivers/gpu/drm/tiny/st7735r.c | 6 +- drivers/gpu/drm/tve200/Kconfig | 2 +- drivers/gpu/drm/tve200/tve200_display.c | 2 +- drivers/gpu/drm/tve200/tve200_drv.c | 6 +- drivers/gpu/drm/v3d/v3d_gem.c | 4 +- drivers/gpu/drm/vc4/Kconfig | 2 +- drivers/gpu/drm/vc4/vc4_bo.c | 44 +- drivers/gpu/drm/vc4/vc4_crtc.c | 14 +- drivers/gpu/drm/vc4/vc4_drv.c | 6 +- drivers/gpu/drm/vc4/vc4_drv.h | 18 +- drivers/gpu/drm/vc4/vc4_gem.c | 4 +- drivers/gpu/drm/vc4/vc4_plane.c | 4 +- drivers/gpu/drm/vc4/vc4_render_cl.c | 26 +- drivers/gpu/drm/vc4/vc4_txp.c | 2 +- drivers/gpu/drm/vc4/vc4_v3d.c | 4 +- drivers/gpu/drm/vc4/vc4_validate.c | 16 +- drivers/gpu/drm/vc4/vc4_validate_shaders.c | 2 +- drivers/gpu/drm/xlnx/Kconfig | 2 +- drivers/gpu/drm/xlnx/zynqmp_dpsub.c | 8 +- include/drm/drm_fb_dma_helper.h | 2 +- include/drm/drm_gem.h | 2 +- include/drm/drm_gem_cma_helper.h | 279 ---------- include/drm/drm_gem_dma_helper.h | 279 ++++++++++ 145 files changed, 1295 insertions(+), 1298 deletions(-) delete mode 100644 drivers/gpu/drm/drm_gem_cma_helper.c create mode 100644 drivers/gpu/drm/drm_gem_dma_helper.c delete mode 100644 include/drm/drm_gem_cma_helper.h create mode 100644 include/drm/drm_gem_dma_helper.h (limited to 'Documentation') diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index f32ccce5722d..a79fd3549ff8 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst @@ -300,12 +300,12 @@ Drivers that want to map the GEM object upfront instead of handling page faults can implement their own mmap file operation handler. For platforms without MMU the GEM core provides a helper method -drm_gem_cma_get_unmapped_area(). The mmap() routines will call this to get a +drm_gem_dma_get_unmapped_area(). The mmap() routines will call this to get a proposed address for the mapping. -To use drm_gem_cma_get_unmapped_area(), drivers must fill the struct +To use drm_gem_dma_get_unmapped_area(), drivers must fill the struct :c:type:`struct file_operations ` get_unmapped_area field with -a pointer on drm_gem_cma_get_unmapped_area(). +a pointer on drm_gem_dma_get_unmapped_area(). More detailed information about get_unmapped_area can be found in Documentation/admin-guide/mm/nommu-mmap.rst @@ -355,16 +355,16 @@ GEM Function Reference .. kernel-doc:: drivers/gpu/drm/drm_gem.c :export: -GEM CMA Helper Functions Reference +GEM DMA Helper Functions Reference ---------------------------------- -.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c - :doc: cma helpers +.. kernel-doc:: drivers/gpu/drm/drm_gem_dma_helper.c + :doc: dma helpers -.. kernel-doc:: include/drm/drm_gem_cma_helper.h +.. kernel-doc:: include/drm/drm_gem_dma_helper.h :internal: -.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c +.. kernel-doc:: drivers/gpu/drm/drm_gem_dma_helper.c :export: GEM SHMEM Helper Function Reference diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 1c91e1e861a5..0b2ad7212ee6 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -200,11 +200,11 @@ config DRM_TTM_HELPER help Helpers for ttm-based gem objects -config DRM_GEM_CMA_HELPER +config DRM_GEM_DMA_HELPER tristate depends on DRM help - Choose this if you need the GEM CMA helper functions + Choose this if you need the GEM DMA helper functions config DRM_GEM_SHMEM_HELPER tristate diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 1d6e4f672b59..25d0ba310509 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -40,9 +40,9 @@ obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o obj-$(CONFIG_DRM_BUDDY) += drm_buddy.o -drm_cma_helper-y := drm_gem_cma_helper.o -drm_cma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_dma_helper.o -obj-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_cma_helper.o +drm_dma_helper-y := drm_gem_dma_helper.o +drm_dma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_dma_helper.o +obj-$(CONFIG_DRM_GEM_DMA_HELPER) += drm_dma_helper.o drm_shmem_helper-y := drm_gem_shmem_helper.o obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o diff --git a/drivers/gpu/drm/arm/Kconfig b/drivers/gpu/drm/arm/Kconfig index 6e3f1d600541..c1b89274d2a4 100644 --- a/drivers/gpu/drm/arm/Kconfig +++ b/drivers/gpu/drm/arm/Kconfig @@ -6,7 +6,7 @@ config DRM_HDLCD depends on DRM && OF && (ARM || ARM64 || COMPILE_TEST) depends on COMMON_CLK select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER help Choose this option if you have an ARM High Definition Colour LCD controller. @@ -27,7 +27,7 @@ config DRM_MALI_DISPLAY depends on DRM && OF && (ARM || ARM64 || COMPILE_TEST) depends on COMMON_CLK select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select VIDEOMODE_HELPERS help Choose this option if you want to compile the ARM Mali Display diff --git a/drivers/gpu/drm/arm/display/Kconfig b/drivers/gpu/drm/arm/display/Kconfig index e91598b60781..4acc4285a4eb 100644 --- a/drivers/gpu/drm/arm/display/Kconfig +++ b/drivers/gpu/drm/arm/display/Kconfig @@ -4,7 +4,7 @@ config DRM_KOMEDA depends on DRM && OF depends on COMMON_CLK select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select VIDEOMODE_HELPERS help Choose this option if you want to compile the ARM Komeda display diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c index ea45da663dfb..f1b27db5dad5 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include "komeda_framebuffer.h" @@ -137,7 +137,7 @@ komeda_fb_none_afbc_size_check(struct komeda_dev *mdev, struct komeda_fb *kfb, } min_size = komeda_fb_get_pixel_addr(kfb, 0, fb->height, i) - - to_drm_gem_cma_obj(obj)->paddr; + - to_drm_gem_dma_obj(obj)->paddr; if (obj->size < min_size) { DRM_DEBUG_KMS("The fb->obj[%d] size: 0x%zx lower than the minimum requirement: 0x%llx.\n", i, obj->size, min_size); @@ -239,7 +239,7 @@ dma_addr_t komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane) { struct drm_framebuffer *fb = &kfb->base; - const struct drm_gem_cma_object *obj; + const struct drm_gem_dma_object *obj; u32 offset, plane_x, plane_y, block_w, block_sz; if (plane >= fb->format->num_planes) { diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c index 327051bba5b6..451746ebbe71 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include @@ -21,9 +21,9 @@ #include "komeda_framebuffer.h" #include "komeda_kms.h" -DEFINE_DRM_GEM_CMA_FOPS(komeda_cma_fops); +DEFINE_DRM_GEM_DMA_FOPS(komeda_cma_fops); -static int komeda_gem_cma_dumb_create(struct drm_file *file, +static int komeda_gem_dma_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args) { @@ -32,7 +32,7 @@ static int komeda_gem_cma_dumb_create(struct drm_file *file, args->pitch = ALIGN(pitch, mdev->chip.bus_width); - return drm_gem_cma_dumb_create_internal(file, dev, args); + return drm_gem_dma_dumb_create_internal(file, dev, args); } static irqreturn_t komeda_kms_irq_handler(int irq, void *data) @@ -60,7 +60,7 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data) static const struct drm_driver komeda_kms_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .lastclose = drm_fb_helper_lastclose, - DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(komeda_gem_cma_dumb_create), + DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(komeda_gem_dma_dumb_create), .fops = &komeda_cma_fops, .name = "komeda", .desc = "Arm Komeda Display Processor driver", diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index d3cf788c0fa9..7030339fa232 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index b32168e3f9ae..a032003c340c 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -225,11 +225,11 @@ static void hdlcd_debugfs_init(struct drm_minor *minor) } #endif -DEFINE_DRM_GEM_CMA_FOPS(fops); +DEFINE_DRM_GEM_DMA_FOPS(fops); static const struct drm_driver hdlcd_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, #ifdef CONFIG_DEBUG_FS .debugfs_init = hdlcd_debugfs_init, #endif diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index fa6c1a4254dc..1d0b0c54ccc7 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -456,7 +456,7 @@ static int malidp_irq_init(struct platform_device *pdev) return 0; } -DEFINE_DRM_GEM_CMA_FOPS(fops); +DEFINE_DRM_GEM_DMA_FOPS(fops); static int malidp_dumb_create(struct drm_file *file_priv, struct drm_device *drm, @@ -468,7 +468,7 @@ static int malidp_dumb_create(struct drm_file *file_priv, args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), alignment); - return drm_gem_cma_dumb_create_internal(file_priv, drm, args); + return drm_gem_dma_dumb_create_internal(file_priv, drm, args); } #ifdef CONFIG_DEBUG_FS @@ -565,7 +565,7 @@ static void malidp_debugfs_init(struct drm_minor *minor) static const struct drm_driver malidp_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(malidp_dumb_create), + DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(malidp_dumb_create), #ifdef CONFIG_DEBUG_FS .debugfs_init = malidp_debugfs_init, #endif diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c index 7a9c900626ec..cefae03f1bcc 100644 --- a/drivers/gpu/drm/arm/malidp_mw.c +++ b/drivers/gpu/drm/arm/malidp_mw.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include @@ -160,7 +160,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder, n_planes = fb->format->num_planes; for (i = 0; i < n_planes; i++) { - struct drm_gem_cma_object *obj = drm_fb_dma_get_gem_obj(fb, i); + struct drm_gem_dma_object *obj = drm_fb_dma_get_gem_obj(fb, i); /* memory write buffers are never rotated */ u8 alignment = malidp_hw_get_pitch_align(malidp->dev, 0); diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 72e0162735fa..b7948ca0060c 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include @@ -333,15 +333,15 @@ static bool malidp_check_pages_threshold(struct malidp_plane_state *ms, for (i = 0; i < ms->n_planes; i++) { struct drm_gem_object *obj; - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; struct sg_table *sgt; struct scatterlist *sgl; obj = drm_gem_fb_get_obj(ms->base.fb, i); - cma_obj = to_drm_gem_cma_obj(obj); + dma_obj = to_drm_gem_dma_obj(obj); - if (cma_obj->sgt) - sgt = cma_obj->sgt; + if (dma_obj->sgt) + sgt = dma_obj->sgt; else sgt = obj->funcs->get_sg_table(obj); @@ -352,14 +352,14 @@ static bool malidp_check_pages_threshold(struct malidp_plane_state *ms, while (sgl) { if (sgl->length < pgsize) { - if (!cma_obj->sgt) + if (!dma_obj->sgt) kfree(sgt); return false; } sgl = sg_next(sgl); } - if (!cma_obj->sgt) + if (!dma_obj->sgt) kfree(sgt); } @@ -732,7 +732,7 @@ static void malidp_set_plane_base_addr(struct drm_framebuffer *fb, paddr = drm_fb_dma_get_gem_addr(fb, plane->state, plane_index); } else { - struct drm_gem_cma_object *obj; + struct drm_gem_dma_object *obj; obj = drm_fb_dma_get_gem_obj(fb, plane_index); diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index 147abf1a3968..5430265ad458 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -107,11 +107,11 @@ armada_gem_linear_back(struct drm_device *dev, struct armada_gem_object *obj) } /* - * We could grab something from CMA if it's enabled, but that + * We could grab something from DMA if it's enabled, but that * involves building in a problem: * - * CMA's interface uses dma_alloc_coherent(), which provides us - * with an CPU virtual address and a device address. + * GEM DMA helper interface uses dma_alloc_coherent(), which provides + * us with an CPU virtual address and a device address. * * The CPU virtual address may be either an address in the kernel * direct mapped region (for example, as it would be on x86) or diff --git a/drivers/gpu/drm/aspeed/Kconfig b/drivers/gpu/drm/aspeed/Kconfig index 024ccab14f88..8137c39b057b 100644 --- a/drivers/gpu/drm/aspeed/Kconfig +++ b/drivers/gpu/drm/aspeed/Kconfig @@ -5,7 +5,7 @@ config DRM_ASPEED_GFX depends on (COMPILE_TEST || ARCH_ASPEED) depends on MMU select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DMA_CMA if HAVE_DMA_CONTIGUOUS select CMA if HAVE_DMA_CONTIGUOUS select MFD_SYSCON diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c index cc4d0fa6262c..996b03bac87f 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include @@ -168,7 +168,7 @@ static void aspeed_gfx_pipe_update(struct drm_simple_display_pipe *pipe, struct drm_crtc *crtc = &pipe->crtc; struct drm_framebuffer *fb = pipe->plane.state->fb; struct drm_pending_vblank_event *event; - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; spin_lock_irq(&crtc->dev->event_lock); event = crtc->state->event; diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c index 54aa8af45829..a94f1a9e8f40 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -245,11 +245,11 @@ static void aspeed_gfx_unload(struct drm_device *drm) drm_kms_helper_poll_fini(drm); } -DEFINE_DRM_GEM_CMA_FOPS(fops); +DEFINE_DRM_GEM_DMA_FOPS(fops); static const struct drm_driver aspeed_gfx_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, .fops = &fops, .name = "aspeed-gfx-drm", .desc = "ASPEED GFX DRM", diff --git a/drivers/gpu/drm/atmel-hlcdc/Kconfig b/drivers/gpu/drm/atmel-hlcdc/Kconfig index 8ae679f1a518..3bdbab3a6333 100644 --- a/drivers/gpu/drm/atmel-hlcdc/Kconfig +++ b/drivers/gpu/drm/atmel-hlcdc/Kconfig @@ -2,7 +2,7 @@ config DRM_ATMEL_HLCDC tristate "DRM Support for ATMEL HLCDC Display Controller" depends on DRM && OF && COMMON_CLK && MFD_ATMEL_HLCDC && ARM - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER select DRM_PANEL help diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 651e3c109360..f7e7f4e919c7 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -730,11 +730,11 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev) clk_disable_unprepare(dc->hlcdc->periph_clk); } -DEFINE_DRM_GEM_CMA_FOPS(fops); +DEFINE_DRM_GEM_DMA_FOPS(fops); static const struct drm_driver atmel_hlcdc_dc_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, .fops = &fops, .name = "atmel-hlcdc", .desc = "Atmel HLCD Controller DRM", diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index ddcbfe7ea0c8..48481aa2731a 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include "atmel_hlcdc_dc.h" @@ -448,7 +448,7 @@ static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane, sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR); for (i = 0; i < state->nplanes; i++) { - struct drm_gem_cma_object *gem = drm_fb_dma_get_gem_obj(fb, i); + struct drm_gem_dma_object *gem = drm_fb_dma_get_gem_obj(fb, i); state->dscrs[i]->addr = gem->paddr + state->offsets[i]; diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c b/drivers/gpu/drm/drm_fb_dma_helper.c index 85fd21cd9dda..b601073c22de 100644 --- a/drivers/gpu/drm/drm_fb_dma_helper.c +++ b/drivers/gpu/drm/drm_fb_dma_helper.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -35,15 +35,15 @@ */ /** - * drm_fb_dma_get_gem_obj() - Get CMA GEM object for framebuffer + * drm_fb_dma_get_gem_obj() - Get DMA GEM object for framebuffer * @fb: The framebuffer * @plane: Which plane * - * Return the CMA GEM object for given framebuffer. + * Return the DMA GEM object for given framebuffer. * * This function will usually be called from the CRTC callback functions. */ -struct drm_gem_cma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb, +struct drm_gem_dma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb, unsigned int plane) { struct drm_gem_object *gem; @@ -52,7 +52,7 @@ struct drm_gem_cma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb, if (!gem) return NULL; - return to_drm_gem_cma_obj(gem); + return to_drm_gem_dma_obj(gem); } EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_obj); @@ -71,7 +71,7 @@ dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb, struct drm_plane_state *state, unsigned int plane) { - struct drm_gem_cma_object *obj; + struct drm_gem_dma_object *obj; dma_addr_t paddr; u8 h_div = 1, v_div = 1; u32 block_w = drm_format_info_block_width(fb->format, plane); @@ -113,7 +113,7 @@ EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_addr); * @state: New plane state * * This function can be used by drivers that use damage clips and have - * CMA GEM objects backed by non-coherent memory. Calling this function + * DMA GEM objects backed by non-coherent memory. Calling this function * in a plane's .atomic_update ensures that all the data in the backing * memory have been written to RAM. */ @@ -123,15 +123,15 @@ void drm_fb_dma_sync_non_coherent(struct drm_device *drm, { const struct drm_format_info *finfo = state->fb->format; struct drm_atomic_helper_damage_iter iter; - const struct drm_gem_cma_object *cma_obj; + const struct drm_gem_dma_object *dma_obj; unsigned int offset, i; struct drm_rect clip; dma_addr_t daddr; size_t nb_bytes; for (i = 0; i < finfo->num_planes; i++) { - cma_obj = drm_fb_dma_get_gem_obj(state->fb, i); - if (!cma_obj->map_noncoherent) + dma_obj = drm_fb_dma_get_gem_obj(state->fb, i); + if (!dma_obj->map_noncoherent) continue; daddr = drm_fb_dma_get_gem_addr(state->fb, state, i); diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index ed25168619fc..fa55c9a562f3 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -131,7 +131,7 @@ bool drm_dev_needs_global_mutex(struct drm_device *dev) * }; * * For plain GEM based drivers there is the DEFINE_DRM_GEM_FOPS() macro, and for - * CMA based drivers there is the DEFINE_DRM_GEM_CMA_FOPS() macro to make this + * DMA based drivers there is the DEFINE_DRM_GEM_DMA_FOPS() macro to make this * simpler. * * The driver's &file_operations must be stored in &drm_driver.fops. diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c deleted file mode 100644 index 42abee9a0f4f..000000000000 --- a/drivers/gpu/drm/drm_gem_cma_helper.c +++ /dev/null @@ -1,605 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * drm gem CMA (contiguous memory allocator) helper functions - * - * Copyright (C) 2012 Sascha Hauer, Pengutronix - * - * Based on Samsung Exynos code - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/** - * DOC: cma helpers - * - * The DRM GEM/CMA helpers are a means to provide buffer objects that are - * presented to the device as a contiguous chunk of memory. This is useful - * for devices that do not support scatter-gather DMA (either directly or - * by using an intimately attached IOMMU). - * - * Despite the name, the DRM GEM/CMA helpers are not hardwired to use the - * Contiguous Memory Allocator (CMA). - * - * For devices that access the memory bus through an (external) IOMMU then - * the buffer objects are allocated using a traditional page-based - * allocator and may be scattered through physical memory. However they - * are contiguous in the IOVA space so appear contiguous to devices using - * them. - * - * For other devices then the helpers rely on CMA to provide buffer - * objects that are physically contiguous in memory. - * - * For GEM callback helpers in struct &drm_gem_object functions, see likewise - * named functions with an _object_ infix (e.g., drm_gem_cma_object_vmap() wraps - * drm_gem_cma_vmap()). These helpers perform the necessary type conversion. - */ - -static const struct drm_gem_object_funcs drm_gem_cma_default_funcs = { - .free = drm_gem_cma_object_free, - .print_info = drm_gem_cma_object_print_info, - .get_sg_table = drm_gem_cma_object_get_sg_table, - .vmap = drm_gem_cma_object_vmap, - .mmap = drm_gem_cma_object_mmap, - .vm_ops = &drm_gem_cma_vm_ops, -}; - -/** - * __drm_gem_cma_create - Create a GEM CMA object without allocating memory - * @drm: DRM device - * @size: size of the object to allocate - * @private: true if used for internal purposes - * - * This function creates and initializes a GEM CMA object of the given size, - * but doesn't allocate any memory to back the object. - * - * Returns: - * A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative - * error code on failure. - */ -static struct drm_gem_cma_object * -__drm_gem_cma_create(struct drm_device *drm, size_t size, bool private) -{ - struct drm_gem_cma_object *cma_obj; - struct drm_gem_object *gem_obj; - int ret = 0; - - if (drm->driver->gem_create_object) { - gem_obj = drm->driver->gem_create_object(drm, size); - if (IS_ERR(gem_obj)) - return ERR_CAST(gem_obj); - cma_obj = to_drm_gem_cma_obj(gem_obj); - } else { - cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL); - if (!cma_obj) - return ERR_PTR(-ENOMEM); - gem_obj = &cma_obj->base; - } - - if (!gem_obj->funcs) - gem_obj->funcs = &drm_gem_cma_default_funcs; - - if (private) { - drm_gem_private_object_init(drm, gem_obj, size); - - /* Always use writecombine for dma-buf mappings */ - cma_obj->map_noncoherent = false; - } else { - ret = drm_gem_object_init(drm, gem_obj, size); - } - if (ret) - goto error; - - ret = drm_gem_create_mmap_offset(gem_obj); - if (ret) { - drm_gem_object_release(gem_obj); - goto error; - } - - return cma_obj; - -error: - kfree(cma_obj); - return ERR_PTR(ret); -} - -/** - * drm_gem_cma_create - allocate an object with the given size - * @drm: DRM device - * @size: size of the object to allocate - * - * This function creates a CMA GEM object and allocates memory as backing store. - * The allocated memory will occupy a contiguous chunk of bus address space. - * - * For devices that are directly connected to the memory bus then the allocated - * memory will be physically contiguous. For devices that access through an - * IOMMU, then the allocated memory is not expected to be physically contiguous - * because having contiguous IOVAs is sufficient to meet a devices DMA - * requirements. - * - * Returns: - * A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative - * error code on failure. - */ -struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, - size_t size) -{ - struct drm_gem_cma_object *cma_obj; - int ret; - - size = round_up(size, PAGE_SIZE); - - cma_obj = __drm_gem_cma_create(drm, size, false); - if (IS_ERR(cma_obj)) - return cma_obj; - - if (cma_obj->map_noncoherent) { - cma_obj->vaddr = dma_alloc_noncoherent(drm->dev, size, - &cma_obj->paddr, - DMA_TO_DEVICE, - GFP_KERNEL | __GFP_NOWARN); - } else { - cma_obj->vaddr = dma_alloc_wc(drm->dev, size, &cma_obj->paddr, - GFP_KERNEL | __GFP_NOWARN); - } - if (!cma_obj->vaddr) { - drm_dbg(drm, "failed to allocate buffer with size %zu\n", - size); - ret = -ENOMEM; - goto error; - } - - return cma_obj; - -error: - drm_gem_object_put(&cma_obj->base); - return ERR_PTR(ret); -} -EXPORT_SYMBOL_GPL(drm_gem_cma_create); - -/** - * drm_gem_cma_create_with_handle - allocate an object with the given size and - * return a GEM handle to it - * @file_priv: DRM file-private structure to register the handle for - * @drm: DRM device - * @size: size of the object to allocate - * @handle: return location for the GEM handle - * - * This function creates a CMA GEM object, allocating a chunk of memory as - * backing store. The GEM object is then added to the list of object associated - * with the given file and a handle to it is returned. - * - * The allocated memory will occupy a contiguous chunk of bus address space. - * See drm_gem_cma_create() for more details. - * - * Returns: - * A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative - * error code on failure. - */ -static struct drm_gem_cma_object * -drm_gem_cma_create_with_handle(struct drm_file *file_priv, - struct drm_device *drm, size_t size, - uint32_t *handle) -{ - struct drm_gem_cma_object *cma_obj; - struct drm_gem_object *gem_obj; - int ret; - - cma_obj = drm_gem_cma_create(drm, size); - if (IS_ERR(cma_obj)) - return cma_obj; - - gem_obj = &cma_obj->base; - - /* - * allocate a id of idr table where the obj is registered - * and handle has the id what user can see. - */ - ret = drm_gem_handle_create(file_priv, gem_obj, handle); - /* drop reference from allocate - handle holds it now. */ - drm_gem_object_put(gem_obj); - if (ret) - return ERR_PTR(ret); - - return cma_obj; -} - -/** - * drm_gem_cma_free - free resources associated with a CMA GEM object - * @cma_obj: CMA GEM object to free - * - * This function frees the backing memory of the CMA GEM object, cleans up the - * GEM object state and frees the memory used to store the object itself. - * If the buffer is imported and the virtual address is set, it is released. - */ -void drm_gem_cma_free(struct drm_gem_cma_object *cma_obj) -{ - struct drm_gem_object *gem_obj = &cma_obj->base; - struct iosys_map map = IOSYS_MAP_INIT_VADDR(cma_obj->vaddr); - - if (gem_obj->import_attach) { - if (cma_obj->vaddr) - dma_buf_vunmap(gem_obj->import_attach->dmabuf, &map); - drm_prime_gem_destroy(gem_obj, cma_obj->sgt); - } else if (cma_obj->vaddr) { - if (cma_obj->map_noncoherent) - dma_free_noncoherent(gem_obj->dev->dev, cma_obj->base.size, - cma_obj->vaddr, cma_obj->paddr, - DMA_TO_DEVICE); - else - dma_free_wc(gem_obj->dev->dev, cma_obj->base.size, - cma_obj->vaddr, cma_obj->paddr); - } - - drm_gem_object_release(gem_obj); - - kfree(cma_obj); -} -EXPORT_SYMBOL_GPL(drm_gem_cma_free); - -/** - * drm_gem_cma_dumb_create_internal - create a dumb buffer object - * @file_priv: DRM file-private structure to create the dumb buffer for - * @drm: DRM device - * @args: IOCTL data - * - * This aligns the pitch and size arguments to the minimum required. This is - * an internal helper that can be wrapped by a driver to account for hardware - * with more specific alignment requirements. It should not be used directly - * as their &drm_driver.dumb_create callback. - * - * Returns: - * 0 on success or a negative error code on failure. - */ -int drm_gem_cma_dumb_create_internal(struct drm_file *file_priv, - struct drm_device *drm, - struct drm_mode_create_dumb *args) -{ - unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); - struct drm_gem_cma_object *cma_obj; - - if (args->pitch < min_pitch) - args->pitch = min_pitch; - - if (args->size < args->pitch * args->height) - args->size = args->pitch * args->height; - - cma_obj = drm_gem_cma_create_with_handle(file_priv, drm, args->size, - &args->handle); - return PTR_ERR_OR_ZERO(cma_obj); -} -EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create_internal); - -/** - * drm_gem_cma_dumb_create - create a dumb buffer object - * @file_priv: DRM file-private structure to create the dumb buffer for - * @drm: DRM device - * @args: IOCTL data - * - * This function computes the pitch of the dumb buffer and rounds it up to an - * integer number of bytes per pixel. Drivers for hardware that doesn't have - * any additional restrictions on the pitch can directly use this function as - * their &drm_driver.dumb_create callback. - * - * For hardware with additional restrictions, drivers can adjust the fields - * set up by userspace and pass the IOCTL data along to the - * drm_gem_cma_dumb_create_internal() function. - * - * Returns: - * 0 on success or a negative error code on failure. - */ -int drm_gem_cma_dumb_create(struct drm_file *file_priv, - struct drm_device *drm, - struct drm_mode_create_dumb *args) -{ - struct drm_gem_cma_object *cma_obj; - - args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8); - args->size = args->pitch * args->height; - - cma_obj = drm_gem_cma_create_with_handle(file_priv, drm, args->size, - &args->handle); - return PTR_ERR_OR_ZERO(cma_obj); -} -EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create); - -const struct vm_operations_struct drm_gem_cma_vm_ops = { - .open = drm_gem_vm_open, - .close = drm_gem_vm_close, -}; -EXPORT_SYMBOL_GPL(drm_gem_cma_vm_ops); - -#ifndef CONFIG_MMU -/** - * drm_gem_cma_get_unmapped_area - propose address for mapping in noMMU cases - * @filp: file object - * @addr: memory address - * @len: buffer size - * @pgoff: page offset - * @flags: memory flags - * - * This function is used in noMMU platforms to propose address mapping - * for a given buffer. - * It's intended to be used as a direct handler for the struct - * &file_operations.get_unmapped_area operation. - * - * Returns: - * mapping address on success or a negative error code on failure. - */ -unsigned long drm_gem_cma_get_unmapped_area(struct file *filp, - unsigned long addr, - unsigned long len, - unsigned long pgoff, - unsigned long flags) -{ - struct drm_gem_cma_object *cma_obj; - struct drm_gem_object *obj = NULL; - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->minor->dev; - struct drm_vma_offset_node *node; - - if (drm_dev_is_unplugged(dev)) - return -ENODEV; - - drm_vma_offset_lock_lookup(dev->vma_offset_manager); - node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager, - pgoff, - len >> PAGE_SHIFT); - if (likely(node)) { - obj = container_of(node, struct drm_gem_object, vma_node); - /* - * When the object is being freed, after it hits 0-refcnt it - * proceeds to tear down the object. In the process it will - * attempt to remove the VMA offset and so acquire this - * mgr->vm_lock. Therefore if we find an object with a 0-refcnt - * that matches our range, we know it is in the process of being - * destroyed and will be freed as soon as we release the lock - - * so we have to check for the 0-refcnted object and treat it as - * invalid. - */ - if (!kref_get_unless_zero(&obj->refcount)) - obj = NULL; - } - - drm_vma_offset_unlock_lookup(dev->vma_offset_manager); - - if (!obj) - return -EINVAL; - - if (!drm_vma_node_is_allowed(node, priv)) { - drm_gem_object_put(obj); - return -EACCES; - } - - cma_obj = to_drm_gem_cma_obj(obj); - - drm_gem_object_put(obj); - - return cma_obj->vaddr ? (unsigned long)cma_obj->vaddr : -EINVAL; -} -EXPORT_SYMBOL_GPL(drm_gem_cma_get_unmapped_area); -#endif - -/** - * drm_gem_cma_print_info() - Print &drm_gem_cma_object info for debugfs - * @cma_obj: CMA GEM object - * @p: DRM printer - * @indent: Tab indentation level - * - * This function prints paddr and vaddr for use in e.g. debugfs output. - */ -void drm_gem_cma_print_info(const struct drm_gem_cma_object *cma_obj, - struct drm_printer *p, unsigned int indent) -{ - drm_printf_indent(p, indent, "paddr=%pad\n", &cma_obj->paddr); - drm_printf_indent(p, indent, "vaddr=%p\n", cma_obj->vaddr); -} -EXPORT_SYMBOL(drm_gem_cma_print_info); - -/** - * drm_gem_cma_get_sg_table - provide a scatter/gather table of pinned - * pages for a CMA GEM object - * @cma_obj: CMA GEM object - * - * This function exports a scatter/gather table by calling the standard - * DMA mapping API. - * - * Returns: - * A pointer to the scatter/gather table of pinned pages or NULL on failure. - */ -struct sg_table *drm_gem_cma_get_sg_table(struct drm_gem_cma_object *cma_obj) -{ - struct drm_gem_object *obj = &cma_obj->base; - struct sg_table *sgt; - int ret; - - sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); - if (!sgt) - return ERR_PTR(-ENOMEM); - - ret = dma_get_sgtable(obj->dev->dev, sgt, cma_obj->vaddr, - cma_obj->paddr, obj->size); - if (ret < 0) - goto out; - - return sgt; - -out: - kfree(sgt); - return ERR_PTR(ret); -} -EXPORT_SYMBOL_GPL(drm_gem_cma_get_sg_table); - -/** - * drm_gem_cma_prime_import_sg_table - produce a CMA GEM object from another - * driver's scatter/gather table of pinned pages - * @dev: device to import into - * @attach: DMA-BUF attachment - * @sgt: scatter/gather table of pinned pages - * - * This function imports a scatter/gather table exported via DMA-BUF by - * another driver. Imported buffers must be physically contiguous in memory - * (i.e. the scatter/gather table must contain a single entry). Drivers that - * use the CMA helpers should set this as their - * &drm_driver.gem_prime_import_sg_table callback. - * - * Returns: - * A pointer to a newly created GEM object or an ERR_PTR-encoded negative - * error code on failure. - */ -struct drm_gem_object * -drm_gem_cma_prime_import_sg_table(struct drm_device *dev, - struct dma_buf_attachment *attach, - struct sg_table *sgt) -{ - struct drm_gem_cma_object *cma_obj; - - /* check if the entries in the sg_table are contiguous */ - if (drm_prime_get_contiguous_size(sgt) < attach->dmabuf->size) - return ERR_PTR(-EINVAL); - - /* Create a CMA GEM buffer. */ - cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size, true); - if (IS_ERR(cma_obj)) - return ERR_CAST(cma_obj); - - cma_obj->paddr = sg_dma_address(sgt->sgl); - cma_obj->sgt = sgt; - - DRM_DEBUG_PRIME("dma_addr = %pad, size = %zu\n", &cma_obj->paddr, attach->dmabuf->size); - - return &cma_obj->base; -} -EXPORT_SYMBOL_GPL(drm_gem_cma_prime_import_sg_table); - -/** - * drm_gem_cma_vmap - map a CMA GEM object into the kernel's virtual - * address space - * @cma_obj: CMA GEM object - * @map: Returns the kernel virtual address of the CMA GEM object's backing - * store. - * - * This function maps a buffer into the kernel's virtual address space. - * Since the CMA buffers are already mapped into the kernel virtual address - * space this simply returns the cached virtual address. - * - * Returns: - * 0 on success, or a negative error code otherwise. - */ -int drm_gem_cma_vmap(struct drm_gem_cma_object *cma_obj, - struct iosys_map *map) -{ - iosys_map_set_vaddr(map, cma_obj->vaddr); - - return 0; -} -EXPORT_SYMBOL_GPL(drm_gem_cma_vmap); - -/** - * drm_gem_cma_mmap - memory-map an exported CMA GEM object - * @cma_obj: CMA GEM object - * @vma: VMA for the area to be mapped - * - * This function maps a buffer into a userspace process's address space. - * In addition to the usual GEM VMA setup it immediately faults in the entire - * object instead of using on-demand faulting. - * - * Returns: - * 0 on success or a negative error code on failure. - */ -int drm_gem_cma_mmap(struct drm_gem_cma_object *cma_obj, struct vm_area_struct *vma) -{ - struct drm_gem_object *obj = &cma_obj->base; - int ret; - - /* - * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the - * vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map - * the whole buffer. - */ - vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node); - vma->vm_flags &= ~VM_PFNMAP; - vma->vm_flags |= VM_DONTEXPAND; - - if (cma_obj->map_noncoherent) { - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); - - ret = dma_mmap_pages(cma_obj->base.dev->dev, - vma, vma->vm_end - vma->vm_start, - virt_to_page(cma_obj->vaddr)); - } else { - ret = dma_mmap_wc(cma_obj->base.dev->dev, vma, cma_obj->vaddr, - cma_obj->paddr, vma->vm_end - vma->vm_start); - } - if (ret) - drm_gem_vm_close(vma); - - return ret; -} -EXPORT_SYMBOL_GPL(drm_gem_cma_mmap); - -/** - * drm_gem_cma_prime_import_sg_table_vmap - PRIME import another driver's - * scatter/gather table and get the virtual address of the buffer - * @dev: DRM device - * @attach: DMA-BUF attachment - * @sgt: Scatter/gather table of pinned pages - * - * This function imports a scatter/gather table using - * drm_gem_cma_prime_import_sg_table() and uses dma_buf_vmap() to get the kernel - * virtual address. This ensures that a CMA GEM object always has its virtual - * address set. This address is released when the object is freed. - * - * This function can be used as the &drm_driver.gem_prime_import_sg_table - * callback. The &DRM_GEM_CMA_DRIVER_OPS_VMAP macro provides a shortcut to set - * the necessary DRM driver operations. - * - * Returns: - * A pointer to a newly created GEM object or an ERR_PTR-encoded negative - * error code on failure. - */ -struct drm_gem_object * -drm_gem_cma_prime_import_sg_table_vmap(struct drm_device *dev, - struct dma_buf_attachment *attach, - struct sg_table *sgt) -{ - struct drm_gem_cma_object *cma_obj; - struct drm_gem_object *obj; - struct iosys_map map; - int ret; - - ret = dma_buf_vmap(attach->dmabuf, &map); - if (ret) { - DRM_ERROR("Failed to vmap PRIME buffer\n"); - return ERR_PTR(ret); - } - - obj = drm_gem_cma_prime_import_sg_table(dev, attach, sgt); - if (IS_ERR(obj)) { - dma_buf_vunmap(attach->dmabuf, &map); - return obj; - } - - cma_obj = to_drm_gem_cma_obj(obj); - cma_obj->vaddr = map.vaddr; - - return obj; -} -EXPORT_SYMBOL(drm_gem_cma_prime_import_sg_table_vmap); - -MODULE_DESCRIPTION("DRM CMA memory-management helpers"); -MODULE_IMPORT_NS(DMA_BUF); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/drm_gem_dma_helper.c b/drivers/gpu/drm/drm_gem_dma_helper.c new file mode 100644 index 000000000000..f1780c01c928 --- /dev/null +++ b/drivers/gpu/drm/drm_gem_dma_helper.c @@ -0,0 +1,602 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * drm gem DMA helper functions + * + * Copyright (C) 2012 Sascha Hauer, Pengutronix + * + * Based on Samsung Exynos code + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/** + * DOC: dma helpers + * + * The DRM GEM/DMA helpers are a means to provide buffer objects that are + * presented to the device as a contiguous chunk of memory. This is useful + * for devices that do not support scatter-gather DMA (either directly or + * by using an intimately attached IOMMU). + * + * For devices that access the memory bus through an (external) IOMMU then + * the buffer objects are allocated using a traditional page-based + * allocator and may be scattered through physical memory. However they + * are contiguous in the IOVA space so appear contiguous to devices using + * them. + * + * For other devices then the helpers rely on CMA to provide buffer + * objects that are physically contiguous in memory. + * + * For GEM callback helpers in struct &drm_gem_object functions, see likewise + * named functions with an _object_ infix (e.g., drm_gem_dma_object_vmap() wraps + * drm_gem_dma_vmap()). These helpers perform the necessary type conversion. + */ + +static const struct drm_gem_object_funcs drm_gem_dma_default_funcs = { + .free = drm_gem_dma_object_free, + .print_info = drm_gem_dma_object_print_info, + .get_sg_table = drm_gem_dma_object_get_sg_table, + .vmap = drm_gem_dma_object_vmap, + .mmap = drm_gem_dma_object_mmap, + .vm_ops = &drm_gem_dma_vm_ops, +}; + +/** + * __drm_gem_dma_create - Create a GEM DMA object without allocating memory + * @drm: DRM device + * @size: size of the object to allocate + * @private: true if used for internal purposes + * + * This function creates and initializes a GEM DMA object of the given size, + * but doesn't allocate any memory to back the object. + * + * Returns: + * A struct drm_gem_dma_object * on success or an ERR_PTR()-encoded negative + * error code on failure. + */ +static struct drm_gem_dma_object * +__drm_gem_dma_create(struct drm_device *drm, size_t size, bool private) +{ + struct drm_gem_dma_object *dma_obj; + struct drm_gem_object *gem_obj; + int ret = 0; + + if (drm->driver->gem_create_object) { + gem_obj = drm->driver->gem_create_object(drm, size); + if (IS_ERR(gem_obj)) + return ERR_CAST(gem_obj); + dma_obj = to_drm_gem_dma_obj(gem_obj); + } else { + dma_obj = kzalloc(sizeof(*dma_obj), GFP_KERNEL); + if (!dma_obj) + return ERR_PTR(-ENOMEM); + gem_obj = &dma_obj->base; + } + + if (!gem_obj->funcs) + gem_obj->funcs = &drm_gem_dma_default_funcs; + + if (private) { + drm_gem_private_object_init(drm, gem_obj, size); + + /* Always use writecombine for dma-buf mappings */ + dma_obj->map_noncoherent = false; + } else { + ret = drm_gem_object_init(drm, gem_obj, size); + } + if (ret) + goto error; + + ret = drm_gem_create_mmap_offset(gem_obj); + if (ret) { + drm_gem_object_release(gem_obj); + goto error; + } + + return dma_obj; + +error: + kfree(dma_obj); + return ERR_PTR(ret); +} + +/** + * drm_gem_dma_create - allocate an object with the given size + * @drm: DRM device + * @size: size of the object to allocate + * + * This function creates a DMA GEM object and allocates memory as backing store. + * The allocated memory will occupy a contiguous chunk of bus address space. + * + * For devices that are directly connected to the memory bus then the allocated + * memory will be physically contiguous. For devices that access through an + * IOMMU, then the allocated memory is not expected to be physically contiguous + * because having contiguous IOVAs is sufficient to meet a devices DMA + * requirements. + * + * Returns: + * A struct drm_gem_dma_object * on success or an ERR_PTR()-encoded negative + * error code on failure. + */ +struct drm_gem_dma_object *drm_gem_dma_create(struct drm_device *drm, + size_t size) +{ + struct drm_gem_dma_object *dma_obj; + int ret; + + size = round_up(size, PAGE_SIZE); + + dma_obj = __drm_gem_dma_create(drm, size, false); + if (IS_ERR(dma_obj)) + return dma_obj; + + if (dma_obj->map_noncoherent) { + dma_obj->vaddr = dma_alloc_noncoherent(drm->dev, size, + &dma_obj->paddr, + DMA_TO_DEVICE, + GFP_KERNEL | __GFP_NOWARN); + } else { + dma_obj->vaddr = dma_alloc_wc(drm->dev, size, &dma_obj->paddr, + GFP_KERNEL | __GFP_NOWARN); + } + if (!dma_obj->vaddr) { + drm_dbg(drm, "failed to allocate buffer with size %zu\n", + size); + ret = -ENOMEM; + goto error; + } + + return dma_obj; + +error: + drm_gem_object_put(&dma_obj->base); + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(drm_gem_dma_create); + +/** + * drm_gem_dma_create_with_handle - allocate an object with the given size and + * return a GEM handle to it + * @file_priv: DRM file-private structure to register the handle for + * @drm: DRM device + * @size: size of the object to allocate + * @handle: return location for the GEM handle + * + * This function creates a DMA GEM object, allocating a chunk of memory as + * backing store. The GEM object is then added to the list of object associated + * with the given file and a handle to it is returned. + * + * The allocated memory will occupy a contiguous chunk of bus address space. + * See drm_gem_dma_create() for more details. + * + * Returns: + * A struct drm_gem_dma_object * on success or an ERR_PTR()-encoded negative + * error code on failure. + */ +static struct drm_gem_dma_object * +drm_gem_dma_create_with_handle(struct drm_file *file_priv, + struct drm_device *drm, size_t size, + uint32_t *handle) +{ + struct drm_gem_dma_object *dma_obj; + struct drm_gem_object *gem_obj; + int ret; + + dma_obj = drm_gem_dma_create(drm, size); + if (IS_ERR(dma_obj)) + return dma_obj; + + gem_obj = &dma_obj->base; + + /* + * allocate a id of idr table where the obj is registered + * and handle has the id what user can see. + */ + ret = drm_gem_handle_create(file_priv, gem_obj, handle); + /* drop reference from allocate - handle holds it now. */ + drm_gem_object_put(gem_obj); + if (ret) + return ERR_PTR(ret); + + return dma_obj; +} + +/** + * drm_gem_dma_free - free resources associated with a DMA GEM object + * @dma_obj: DMA GEM object to free + * + * This function frees the backing memory of the DMA GEM object, cleans up the + * GEM object state and frees the memory used to store the object itself. + * If the buffer is imported and the virtual address is set, it is released. + */ +void drm_gem_dma_free(struct drm_gem_dma_object *dma_obj) +{ + struct drm_gem_object *gem_obj = &dma_obj->base; + struct iosys_map map = IOSYS_MAP_INIT_VADDR(dma_obj->vaddr); + + if (gem_obj->import_attach) { + if (dma_obj->vaddr) + dma_buf_vunmap(gem_obj->import_attach->dmabuf, &map); + drm_prime_gem_destroy(gem_obj, dma_obj->sgt); + } else if (dma_obj->vaddr) { + if (dma_obj->map_noncoherent) + dma_free_noncoherent(gem_obj->dev->dev, dma_obj->base.size, + dma_obj->vaddr, dma_obj->paddr, + DMA_TO_DEVICE); + else + dma_free_wc(gem_obj->dev->dev, dma_obj->base.size, + dma_obj->vaddr, dma_obj->paddr); + } + + drm_gem_object_release(gem_obj); + + kfree(dma_obj); +} +EXPORT_SYMBOL_GPL(drm_gem_dma_free); + +/** + * drm_gem_dma_dumb_create_internal - create a dumb buffer object + * @file_priv: DRM file-private structure to create the dumb buffer for + * @drm: DRM device + * @args: IOCTL data + * + * This aligns the pitch and size arguments to the minimum required. This is + * an internal helper that can be wrapped by a driver to account for hardware + * with more specific alignment requirements. It should not be used directly + * as their &drm_driver.dumb_create callback. + * + * Returns: + * 0 on success or a negative error code on failure. + */ +int drm_gem_dma_dumb_create_internal(struct drm_file *file_priv, + struct drm_device *drm, + struct drm_mode_create_dumb *args) +{ + unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); + struct drm_gem_dma_object *dma_obj; + + if (args->pitch < min_pitch) + args->pitch = min_pitch; + + if (args->size < args->pitch * args->height) + args->size = args->pitch * args->height; + + dma_obj = drm_gem_dma_create_with_handle(file_priv, drm, args->size, + &args->handle); + return PTR_ERR_OR_ZERO(dma_obj); +} +EXPORT_SYMBOL_GPL(drm_gem_dma_dumb_create_internal); + +/** + * drm_gem_dma_dumb_create - create a dumb buffer object + * @file_priv: DRM file-private structure to create the dumb buffer for + * @drm: DRM device + * @args: IOCTL data + * + * This function computes the pitch of the dumb buffer and rounds it up to an + * integer number of bytes per pixel. Drivers for hardware that doesn't have + * any additional restrictions on the pitch can directly use this function as + * their &drm_driver.dumb_create callback. + * + * For hardware with additional restrictions, drivers can adjust the fields + * set up by userspace and pass the IOCTL data along to the + * drm_gem_dma_dumb_create_internal() function. + * + * Returns: + * 0 on success or a negative error code on failure. + */ +int drm_gem_dma_dumb_create(struct drm_file *file_priv, + struct drm_device *drm, + struct drm_mode_create_dumb *args) +{ + struct drm_gem_dma_object *dma_obj; + + args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8); + args->size = args->pitch * args->height; + + dma_obj = drm_gem_dma_create_with_handle(file_priv, drm, args->size, + &args->handle); + return PTR_ERR_OR_ZERO(dma_obj); +} +EXPORT_SYMBOL_GPL(drm_gem_dma_dumb_create); + +const struct vm_operations_struct drm_gem_dma_vm_ops = { + .open = drm_gem_vm_open, + .close = drm_gem_vm_close, +}; +EXPORT_SYMBOL_GPL(drm_gem_dma_vm_ops); + +#ifndef CONFIG_MMU +/** + * drm_gem_dma_get_unmapped_area - propose address for mapping in noMMU cases + * @filp: file object + * @addr: memory address + * @len: buffer size + * @pgoff: page offset + * @flags: memory flags + * + * This function is used in noMMU platforms to propose address mapping + * for a given buffer. + * It's intended to be used as a direct handler for the struct + * &file_operations.get_unmapped_area operation. + * + * Returns: + * mapping address on success or a negative error code on failure. + */ +unsigned long drm_gem_dma_get_unmapped_area(struct file *filp, + unsigned long addr, + unsigned long len, + unsigned long pgoff, + unsigned long flags) +{ + struct drm_gem_dma_object *dma_obj; + struct drm_gem_object *obj = NULL; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->minor->dev; + struct drm_vma_offset_node *node; + + if (drm_dev_is_unplugged(dev)) + return -ENODEV; + + drm_vma_offset_lock_lookup(dev->vma_offset_manager); + node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager, + pgoff, + len >> PAGE_SHIFT); + if (likely(node)) { + obj = container_of(node, struct drm_gem_object, vma_node); + /* + * When the object is being freed, after it hits 0-refcnt it + * proceeds to tear down the object. In the process it will + * attempt to remove the VMA offset and so acquire this + * mgr->vm_lock. Therefore if we find an object with a 0-refcnt + * that matches our range, we know it is in the process of being + * destroyed and will be freed as soon as we release the lock - + * so we have to check for the 0-refcnted object and treat it as + * invalid. + */ + if (!kref_get_unless_zero(&obj->refcount)) + obj = NULL; + } + + drm_vma_offset_unlock_lookup(dev->vma_offset_manager); + + if (!obj) + return -EINVAL; + + if (!drm_vma_node_is_allowed(node, priv)) { + drm_gem_object_put(obj); + return -EACCES; + } + + dma_obj = to_drm_gem_dma_obj(obj); + + drm_gem_object_put(obj); + + return dma_obj->vaddr ? (unsigned long)dma_obj->vaddr : -EINVAL; +} +EXPORT_SYMBOL_GPL(drm_gem_dma_get_unmapped_area); +#endif + +/** + * drm_gem_dma_print_info() - Print &drm_gem_dma_object info for debugfs + * @dma_obj: DMA GEM object + * @p: DRM printer + * @indent: Tab indentation level + * + * This function prints paddr and vaddr for use in e.g. debugfs output. + */ +void drm_gem_dma_print_info(const struct drm_gem_dma_object *dma_obj, + struct drm_printer *p, unsigned int indent) +{ + drm_printf_indent(p, indent, "paddr=%pad\n", &dma_obj->paddr); + drm_printf_indent(p, indent, "vaddr=%p\n", dma_obj->vaddr); +} +EXPORT_SYMBOL(drm_gem_dma_print_info); + +/** + * drm_gem_dma_get_sg_table - provide a scatter/gather table of pinned + * pages for a DMA GEM object + * @dma_obj: DMA GEM object + * + * This function exports a scatter/gather table by calling the standard + * DMA mapping API. + * + * Returns: + * A pointer to the scatter/gather table of pinned pages or NULL on failure. + */ +struct sg_table *drm_gem_dma_get_sg_table(struct drm_gem_dma_object *dma_obj) +{ + struct drm_gem_object *obj = &dma_obj->base; + struct sg_table *sgt; + int ret; + + sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) + return ERR_PTR(-ENOMEM); + + ret = dma_get_sgtable(obj->dev->dev, sgt, dma_obj->vaddr, + dma_obj->paddr, obj->size); + if (ret < 0) + goto out; + + return sgt; + +out: + kfree(sgt); + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(drm_gem_dma_get_sg_table); + +/** + * drm_gem_dma_prime_import_sg_table - produce a DMA GEM object from another + * driver's scatter/gather table of pinned pages + * @dev: device to import into + * @attach: DMA-BUF attachment + * @sgt: scatter/gather table of pinned pages + * + * This function imports a scatter/gather table exported via DMA-BUF by + * another driver. Imported buffers must be physically contiguous in memory + * (i.e. the scatter/gather table must contain a single entry). Drivers that + * use the DMA helpers should set this as their + * &drm_driver.gem_prime_import_sg_table callback. + * + * Returns: + * A pointer to a newly created GEM object or an ERR_PTR-encoded negative + * error code on failure. + */ +struct drm_gem_object * +drm_gem_dma_prime_import_sg_table(struct drm_device *dev, + struct dma_buf_attachment *attach, + struct sg_table *sgt) +{ + struct drm_gem_dma_object *dma_obj; + + /* check if the entries in the sg_table are contiguous */ + if (drm_prime_get_contiguous_size(sgt) < attach->dmabuf->size) + return ERR_PTR(-EINVAL); + + /* Create a DMA GEM buffer. */ + dma_obj = __drm_gem_dma_create(dev, attach->dmabuf->size, true); + if (IS_ERR(dma_obj)) + return ERR_CAST(dma_obj); + + dma_obj->paddr = sg_dma_address(sgt->sgl); + dma_obj->sgt = sgt; + + DRM_DEBUG_PRIME("dma_addr = %pad, size = %zu\n", &dma_obj->paddr, attach->dmabuf->size); + + return &dma_obj->base; +} +EXPORT_SYMBOL_GPL(drm_gem_dma_prime_import_sg_table); + +/** + * drm_gem_dma_vmap - map a DMA GEM object into the kernel's virtual + * address space + * @dma_obj: DMA GEM object + * @map: Returns the kernel virtual address of the DMA GEM object's backing + * store. + * + * This function maps a buffer into the kernel's virtual address space. + * Since the DMA buffers are already mapped into the kernel virtual address + * space this simply returns the cached virtual address. + * + * Returns: + * 0 on success, or a negative error code otherwise. + */ +int drm_gem_dma_vmap(struct drm_gem_dma_object *dma_obj, + struct iosys_map *map) +{ + iosys_map_set_vaddr(map, dma_obj->vaddr); + + return 0; +} +EXPORT_SYMBOL_GPL(drm_gem_dma_vmap); + +/** + * drm_gem_dma_mmap - memory-map an exported DMA GEM object + * @dma_obj: DMA GEM object + * @vma: VMA for the area to be mapped + * + * This function maps a buffer into a userspace process's address space. + * In addition to the usual GEM VMA setup it immediately faults in the entire + * object instead of using on-demand faulting. + * + * Returns: + * 0 on success or a negative error code on failure. + */ +int drm_gem_dma_mmap(struct drm_gem_dma_object *dma_obj, struct vm_area_struct *vma) +{ + struct drm_gem_object *obj = &dma_obj->base; + int ret; + + /* + * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the + * vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map + * the whole buffer. + */ + vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node); + vma->vm_flags &= ~VM_PFNMAP; + vma->vm_flags |= VM_DONTEXPAND; + + if (dma_obj->map_noncoherent) { + vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + + ret = dma_mmap_pages(dma_obj->base.dev->dev, + vma, vma->vm_end - vma->vm_start, + virt_to_page(dma_obj->vaddr)); + } else { + ret = dma_mmap_wc(dma_obj->base.dev->dev, vma, dma_obj->vaddr, + dma_obj->paddr, vma->vm_end - vma->vm_start); + } + if (ret) + drm_gem_vm_close(vma); + + return ret; +} +EXPORT_SYMBOL_GPL(drm_gem_dma_mmap); + +/** + * drm_gem_dma_prime_import_sg_table_vmap - PRIME import another driver's + * scatter/gather table and get the virtual address of the buffer + * @dev: DRM device + * @attach: DMA-BUF attachment + * @sgt: Scatter/gather table of pinned pages + * + * This function imports a scatter/gather table using + * drm_gem_dma_prime_import_sg_table() and uses dma_buf_vmap() to get the kernel + * virtual address. This ensures that a DMA GEM object always has its virtual + * address set. This address is released when the object is freed. + * + * This function can be used as the &drm_driver.gem_prime_import_sg_table + * callback. The &DRM_GEM_DMA_DRIVER_OPS_VMAP macro provides a shortcut to set + * the necessary DRM driver operations. + * + * Returns: + * A pointer to a newly created GEM object or an ERR_PTR-encoded negative + * error code on failure. + */ +struct drm_gem_object * +drm_gem_dma_prime_import_sg_table_vmap(struct drm_device *dev, + struct dma_buf_attachment *attach, + struct sg_table *sgt) +{ + struct drm_gem_dma_object *dma_obj; + struct drm_gem_object *obj; + struct iosys_map map; + int ret; + + ret = dma_buf_vmap(attach->dmabuf, &map); + if (ret) { + DRM_ERROR("Failed to vmap PRIME buffer\n"); + return ERR_PTR(ret); + } + + obj = drm_gem_dma_prime_import_sg_table(dev, attach, sgt); + if (IS_ERR(obj)) { + dma_buf_vunmap(attach->dmabuf, &map); + return obj; + } + + dma_obj = to_drm_gem_dma_obj(obj); + dma_obj->vaddr = map.vaddr; + + return obj; +} +EXPORT_SYMBOL(drm_gem_dma_prime_import_sg_table_vmap); + +MODULE_DESCRIPTION("DRM DMA memory-management helpers"); +MODULE_IMPORT_NS(DMA_BUF); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index 2f61f53d472f..2ecaf3cb7afb 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -1136,7 +1136,7 @@ int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *dbi, /* * Even though it's not the SPI device that does DMA (the master does), * the dma mask is necessary for the dma_alloc_wc() in the GEM code - * (e.g., drm_gem_cma_create()). The dma_addr returned will be a physical + * (e.g., drm_gem_dma_create()). The dma_addr returned will be a physical * address which might be different from the bus address, but this is * not a problem since the address will not be used. * The virtual address is used in the transfer and the SPI core diff --git a/drivers/gpu/drm/fsl-dcu/Kconfig b/drivers/gpu/drm/fsl-dcu/Kconfig index e95e96c565ba..5ca71ef87325 100644 --- a/drivers/gpu/drm/fsl-dcu/Kconfig +++ b/drivers/gpu/drm/fsl-dcu/Kconfig @@ -3,7 +3,7 @@ config DRM_FSL_DCU tristate "DRM Support for Freescale DCU" depends on DRM && OF && ARM && COMMON_CLK select BACKLIGHT_CLASS_DEVICE - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER select DRM_PANEL select REGMAP_MMIO diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index 4baa4977e473..b4acc3422ba4 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -149,13 +149,13 @@ static void fsl_dcu_unload(struct drm_device *dev) dev->dev_private = NULL; } -DEFINE_DRM_GEM_CMA_FOPS(fsl_dcu_drm_fops); +DEFINE_DRM_GEM_DMA_FOPS(fsl_dcu_drm_fops); static const struct drm_driver fsl_dcu_drm_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .load = fsl_dcu_load, .unload = fsl_dcu_unload, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, .fops = &fsl_dcu_drm_fops, .name = "fsl-dcu-drm", .desc = "Freescale DCU DRM", diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c index aba2b714e8a6..48c98331a3c0 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include @@ -84,7 +84,7 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane); struct drm_framebuffer *fb = plane->state->fb; - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; unsigned int alpha = DCU_LAYER_AB_NONE, bpp; int index; diff --git a/drivers/gpu/drm/hisilicon/kirin/Kconfig b/drivers/gpu/drm/hisilicon/kirin/Kconfig index b770f7662830..c5265675bf0c 100644 --- a/drivers/gpu/drm/hisilicon/kirin/Kconfig +++ b/drivers/gpu/drm/hisilicon/kirin/Kconfig @@ -3,7 +3,7 @@ config DRM_HISI_KIRIN tristate "DRM Support for Hisilicon Kirin series SoCs Platform" depends on DRM && OF && ARM64 select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_MIPI_DSI help Choose this option if you have a hisilicon Kirin chipsets(hi6220). diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c index c5d304826c3b..9666d71a83cc 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -548,7 +548,7 @@ static const struct drm_crtc_funcs ade_crtc_funcs = { static void ade_rdma_set(void __iomem *base, struct drm_framebuffer *fb, u32 ch, u32 y, u32 in_h, u32 fmt) { - struct drm_gem_cma_object *obj = drm_fb_dma_get_gem_obj(fb, 0); + struct drm_gem_dma_object *obj = drm_fb_dma_get_gem_obj(fb, 0); u32 reg_ctrl, reg_addr, reg_size, reg_stride, reg_space, reg_en; u32 stride = fb->pitches[0]; u32 addr = (u32)obj->paddr + y * stride; @@ -919,12 +919,12 @@ static const struct drm_mode_config_funcs ade_mode_config_funcs = { }; -DEFINE_DRM_GEM_CMA_FOPS(ade_fops); +DEFINE_DRM_GEM_DMA_FOPS(ade_fops); static const struct drm_driver ade_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &ade_fops, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, .name = "kirin", .desc = "Hisilicon Kirin620 SoC DRM Driver", .date = "20150718", diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c index e8b0fe970969..73ee7f25f734 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig index bb9738c7c825..975de4ff7313 100644 --- a/drivers/gpu/drm/imx/Kconfig +++ b/drivers/gpu/drm/imx/Kconfig @@ -3,7 +3,7 @@ config DRM_IMX tristate "DRM Support for Freescale i.MX" select DRM_KMS_HELPER select VIDEOMODE_HELPERS - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER depends on DRM && (ARCH_MXC || ARCH_MULTIPLATFORM || COMPILE_TEST) depends on IMX_IPUV3_CORE diff --git a/drivers/gpu/drm/imx/dcss/Kconfig b/drivers/gpu/drm/imx/dcss/Kconfig index 5c2b2277afbf..3ffc061d392b 100644 --- a/drivers/gpu/drm/imx/dcss/Kconfig +++ b/drivers/gpu/drm/imx/dcss/Kconfig @@ -2,7 +2,7 @@ config DRM_IMX_DCSS tristate "i.MX8MQ DCSS" select IMX_IRQSTEER select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select VIDEOMODE_HELPERS depends on DRM && ARCH_MXC && ARM64 help diff --git a/drivers/gpu/drm/imx/dcss/dcss-kms.c b/drivers/gpu/drm/imx/dcss/dcss-kms.c index 9b84df34a6a1..f50814e9d549 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-kms.c +++ b/drivers/gpu/drm/imx/dcss/dcss-kms.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -17,7 +17,7 @@ #include "dcss-dev.h" #include "dcss-kms.h" -DEFINE_DRM_GEM_CMA_FOPS(dcss_cma_fops); +DEFINE_DRM_GEM_DMA_FOPS(dcss_cma_fops); static const struct drm_mode_config_funcs dcss_drm_mode_config_funcs = { .fb_create = drm_gem_fb_create, @@ -28,7 +28,7 @@ static const struct drm_mode_config_funcs dcss_drm_mode_config_funcs = { static const struct drm_driver dcss_kms_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_DMA_DRIVER_OPS, .fops = &dcss_cma_fops, .name = "imx-dcss", .desc = "i.MX8MQ Display Subsystem", diff --git a/drivers/gpu/drm/imx/dcss/dcss-plane.c b/drivers/gpu/drm/imx/dcss/dcss-plane.c index a333c13c9ebc..4c41c93ac900 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-plane.c +++ b/drivers/gpu/drm/imx/dcss/dcss-plane.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include "dcss-dev.h" #include "dcss-kms.h" @@ -147,7 +147,7 @@ static int dcss_plane_atomic_check(struct drm_plane *plane, struct dcss_dev *dcss = plane->dev->dev_private; struct drm_framebuffer *fb = new_plane_state->fb; bool is_primary_plane = plane->type == DRM_PLANE_TYPE_PRIMARY; - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; struct drm_crtc_state *crtc_state; int hdisplay, vdisplay; int min, max; @@ -156,8 +156,8 @@ static int dcss_plane_atomic_check(struct drm_plane *plane, if (!fb || !new_plane_state->crtc) return 0; - cma_obj = drm_fb_dma_get_gem_obj(fb, 0); - WARN_ON(!cma_obj); + dma_obj = drm_fb_dma_get_gem_obj(fb, 0); + WARN_ON(!dma_obj); crtc_state = drm_atomic_get_existing_crtc_state(state, new_plane_state->crtc); @@ -218,26 +218,26 @@ static void dcss_plane_atomic_set_base(struct dcss_plane *dcss_plane) struct dcss_dev *dcss = plane->dev->dev_private; struct drm_framebuffer *fb = state->fb; const struct drm_format_info *format = fb->format; - struct drm_gem_cma_object *cma_obj = drm_fb_dma_get_gem_obj(fb, 0); + struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0); unsigned long p1_ba = 0, p2_ba = 0; if (!format->is_yuv || format->format == DRM_FORMAT_NV12 || format->format == DRM_FORMAT_NV21) - p1_ba = cma_obj->paddr + fb->offsets[0] + + p1_ba = dma_obj->paddr + fb->offsets[0] + fb->pitches[0] * (state->src.y1 >> 16) + format->char_per_block[0] * (state->src.x1 >> 16); else if (format->format == DRM_FORMAT_UYVY || format->format == DRM_FORMAT_VYUY || format->format == DRM_FORMAT_YUYV || format->format == DRM_FORMAT_YVYU) - p1_ba = cma_obj->paddr + fb->offsets[0] + + p1_ba = dma_obj->paddr + fb->offsets[0] + fb->pitches[0] * (state->src.y1 >> 16) + 2 * format->char_per_block[0] * (state->src.x1 >> 17); if (format->format == DRM_FORMAT_NV12 || format->format == DRM_FORMAT_NV21) - p2_ba = cma_obj->paddr + fb->offsets[1] + + p2_ba = dma_obj->paddr + fb->offsets[1] + (((fb->pitches[1] >> 1) * (state->src.y1 >> 17) + (state->src.x1 >> 17)) << 1); diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index e43345bd1346..8dd8b0f912af 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -32,7 +32,7 @@ static int legacyfb_depth = 16; module_param(legacyfb_depth, int, 0444); -DEFINE_DRM_GEM_CMA_FOPS(imx_drm_driver_fops); +DEFINE_DRM_GEM_DMA_FOPS(imx_drm_driver_fops); void imx_drm_connector_destroy(struct drm_connector *connector) { @@ -152,7 +152,7 @@ static int imx_drm_dumb_create(struct drm_file *file_priv, args->width = ALIGN(width, 8); - ret = drm_gem_cma_dumb_create(file_priv, drm, args); + ret = drm_gem_dma_dumb_create(file_priv, drm, args); if (ret) return ret; @@ -162,7 +162,7 @@ static int imx_drm_dumb_create(struct drm_file *file_priv, static const struct drm_driver imx_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(imx_drm_dumb_create), + DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(imx_drm_dumb_create), .ioctls = imx_drm_ioctls, .num_ioctls = ARRAY_SIZE(imx_drm_ioctls), .fops = &imx_drm_driver_fops, diff --git a/drivers/gpu/drm/imx/imx-drm.h b/drivers/gpu/drm/imx/imx-drm.h index c3e1a3f14d30..e721bebda2bd 100644 --- a/drivers/gpu/drm/imx/imx-drm.h +++ b/drivers/gpu/drm/imx/imx-drm.h @@ -32,7 +32,7 @@ extern struct platform_driver ipu_drm_driver; void imx_drm_mode_config_init(struct drm_device *drm); -struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb); +struct drm_gem_dma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb); int imx_drm_encoder_parse_of(struct drm_device *drm, struct drm_encoder *encoder, struct device_node *np); diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index d9f832f952c2..5f26090b0c98 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 27bd16418002..07c0b9def383 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include