diff --git a/Documentation/devicetree/bindings/video/tegra/nvmap/nvidia,vi-carveout.yaml b/Documentation/devicetree/bindings/video/tegra/nvmap/nvidia,vi-carveout.yaml new file mode 100644 index 00000000..1110951a --- /dev/null +++ b/Documentation/devicetree/bindings/video/tegra/nvmap/nvidia,vi-carveout.yaml @@ -0,0 +1,67 @@ +# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. + +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/vi-carveout/nvidia,vi-carveout.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Nvidia VI Carveout + +maintainers: + - Ketan Patil + +description: | + This schema defines the properties for the NVIDIA VI carveout (mempool) memory + node. The reference to this DT node should be added memory-region in tegra carveout + to create the VI carveout. + +select: + properties: + compatible: + minItems: 1 + maxItems: 1 + items: + enum: + - nvidia,vi_carveout + + required: + - compatible + +properties: + ivm: + description: | + A phandle to the tegra-hv node followed by the mempool id. + items: + minItems: 2 + maxItems: 2 + items: + - $ref: "/schemas/types.yaml#/definitions/phandle" + - $ref: "/schemas/types.yaml#/definitions/uint32" + + status: + description: | + The status of the carveouts node. + enum: + - okay + - disabled + +required: + - compatible + - ivm + +examples: + - | + vi-carveout { + compatible = "nvidia,vi_carveout"; + ivm = <&tegra_hv 3>; + status = "okay"; + }; diff --git a/drivers/video/tegra/nvmap/nvmap_dev.h b/drivers/video/tegra/nvmap/nvmap_dev.h index aa2ccc4f..a31e8e1a 100644 --- a/drivers/video/tegra/nvmap/nvmap_dev.h +++ b/drivers/video/tegra/nvmap/nvmap_dev.h @@ -6,15 +6,16 @@ #include -#define NVMAP_HEAP_IOVMM (1ul<<30) +#define NVMAP_HEAP_IOVMM (1ul << 30) /* common carveout heaps */ -#define NVMAP_HEAP_CARVEOUT_VPR (1ul<<28) -#define NVMAP_HEAP_CARVEOUT_TSEC (1ul<<27) -#define NVMAP_HEAP_CARVEOUT_VIDMEM (1ul<<26) -#define NVMAP_HEAP_CARVEOUT_GPU (1ul << 3) -#define NVMAP_HEAP_CARVEOUT_FSI (1ul<<2) -#define NVMAP_HEAP_CARVEOUT_IVM (1ul<<1) -#define NVMAP_HEAP_CARVEOUT_GENERIC (1ul<<0) +#define NVMAP_HEAP_CARVEOUT_VPR (1ul << 28) +#define NVMAP_HEAP_CARVEOUT_TSEC (1ul << 27) +#define NVMAP_HEAP_CARVEOUT_VIDMEM (1ul << 26) +#define NVMAP_HEAP_CARVEOUT_VI (1ul << 4) +#define NVMAP_HEAP_CARVEOUT_GPU (1ul << 3) +#define NVMAP_HEAP_CARVEOUT_FSI (1ul << 2) +#define NVMAP_HEAP_CARVEOUT_IVM (1ul << 1) +#define NVMAP_HEAP_CARVEOUT_GENERIC (1ul << 0) #define NVMAP_HEAP_CARVEOUT_MASK (NVMAP_HEAP_IOVMM - 1) diff --git a/drivers/video/tegra/nvmap/nvmap_init.c b/drivers/video/tegra/nvmap/nvmap_init.c index 64c40c1e..baab97c2 100644 --- a/drivers/video/tegra/nvmap/nvmap_init.c +++ b/drivers/video/tegra/nvmap/nvmap_init.c @@ -91,12 +91,14 @@ static struct nvmap_platform_carveout nvmap_carveouts[] = { .size = 0, .numa_node_id = 0, }, - /* Need uninitialized entries for IVM carveouts */ [5] = { - .name = NULL, - .usage_mask = NVMAP_HEAP_CARVEOUT_IVM, + .name = "vimem", + .usage_mask = NVMAP_HEAP_CARVEOUT_VI, + .base = 0, + .size = 0, .numa_node_id = 0, }, + /* Need uninitialized entries for IVM carveouts */ [6] = { .name = NULL, .usage_mask = NVMAP_HEAP_CARVEOUT_IVM, @@ -112,11 +114,16 @@ static struct nvmap_platform_carveout nvmap_carveouts[] = { .usage_mask = NVMAP_HEAP_CARVEOUT_IVM, .numa_node_id = 0, }, + [9] = { + .name = NULL, + .usage_mask = NVMAP_HEAP_CARVEOUT_IVM, + .numa_node_id = 0, + }, }; static struct nvmap_platform_data nvmap_data = { .carveouts = nvmap_carveouts, - .nr_carveouts = 5, + .nr_carveouts = 6, }; static struct nvmap_platform_carveout *nvmap_get_carveout_pdata(const char *name) @@ -149,12 +156,21 @@ static int __init nvmap_populate_ivm_carveout(struct device *dev) struct tegra_hv_ivm_cookie *ivm; unsigned long long id; unsigned int guestid, result; + bool is_vi_heap; if (!of_phandle_iterator_init(&it, dev->of_node, "memory-region", NULL, 0)) { while (!of_phandle_iterator_next(&it) && it.node) { - if (of_device_is_available(it.node) && - of_device_is_compatible(it.node, "nvidia,ivm_carveout") > 0) { - co = nvmap_get_carveout_pdata("nvidia,ivm_carveout"); + is_vi_heap = false; + if (of_device_is_available(it.node)) { + if (of_device_is_compatible(it.node, "nvidia,ivm_carveout") > 0) { + co = nvmap_get_carveout_pdata("nvidia,ivm_carveout"); + } else if (of_device_is_compatible(it.node, + "nvidia,vi_carveout") > 0) { + co = nvmap_get_carveout_pdata("vimem"); + is_vi_heap = true; + } else + continue; + if (!co) { ret = -ENOMEM; goto err; @@ -198,25 +214,29 @@ static int __init nvmap_populate_ivm_carveout(struct device *dev) /* See if this VM can allocate (or just create handle from ID) * generated by peer partition */ - prop = of_get_property(it.node, "alloc", NULL); - if (!prop) { - pr_err("failed to read alloc property\n"); - ret = -EINVAL; - goto fail; - } + if (!is_vi_heap) { + prop = of_get_property(it.node, "alloc", NULL); + if (!prop) { + pr_err("failed to read alloc property\n"); + ret = -EINVAL; + goto fail; + } - name = kzalloc(32, GFP_KERNEL); - if (!name) { - ret = -ENOMEM; - goto fail; - } + name = kzalloc(32, GFP_KERNEL); + if (!name) { + ret = -ENOMEM; + goto fail; + } - co->can_alloc = of_read_number(prop, 1); - co->is_ivm = true; - sprintf(name, "ivm%02u%02u%02d", co->vmid, co->peer, co->can_alloc); - pr_info("IVM carveout IPA:%p, size=%zu, peer vmid=%u, name=%s\n", - (void *)(uintptr_t)co->base, co->size, co->peer, name); - co->name = name; + co->can_alloc = of_read_number(prop, 1); + co->is_ivm = true; + sprintf(name, "ivm%02u%02u%02d", co->vmid, co->peer, + co->can_alloc); + pr_info("IVM carveout IPA:%p, size=%zu, peer vmid=%u," + "name=%s\n", (void *)(uintptr_t)co->base, co->size, + co->peer, name); + co->name = name; + } if (check_add_overflow(nvmap_data.nr_carveouts, 1U, &result)) { co->name = NULL; @@ -226,12 +246,12 @@ static int __init nvmap_populate_ivm_carveout(struct device *dev) } nvmap_data.nr_carveouts = result; - } } } return 0; fail: + (void)tegra_hv_mempool_unreserve(ivm); co->base = 0; co->peer = 0; co->size = 0; @@ -381,7 +401,8 @@ int __init nvmap_init(struct platform_device *pdev) if (!of_phandle_iterator_init(&it, np, "memory-region", NULL, 0)) { while (!of_phandle_iterator_next(&it) && it.node) { if (of_device_is_available(it.node) && - !of_device_is_compatible(it.node, "nvidia,ivm_carveout")) { + !of_device_is_compatible(it.node, "nvidia,ivm_carveout") && + !of_device_is_compatible(it.node, "nvidia,vi_carveout")) { rmem2 = of_reserved_mem_lookup(it.node); if (!rmem2) { if (!of_property_read_string(it.node, "compatible", &compp))