summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiro Sugawara <hsugawara@nvidia.com>2011-03-17 13:58:13 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:45:02 -0800
commitef904466ea970cfd116c1310cbec0d38c2dccbe3 (patch)
tree5a0d363545d9bce9bd0aa2e8fdaf1eb8c211f6a5
parent7d9ab1f1bd1b473774027d75f939f0b62b29d6bb (diff)
arm: tegra: nvmap: Forcing to convert CarveOut requests to IOVM
Adding a build time CONFIG option to enable forcing of conversion of non-IRAM CarveOut memory allocation requests to IOVM requests. Default is "y" to force the conversion. Each forced conversion is reported to console. Allocation alignments larger than page size for IOVM are enabled. Single page CarveOut allocations are converted to system memory. CarveOut memory reservation has been removed for aruba, cardhu, and enterprise. Original-Change-Id: I3a598431d15b92ce853b3bec97be4b583d021264 Reviewed-on: http://git-master/r/29849 Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Tested-by: Varun Colbert <vcolbert@nvidia.com> Rebase-Id: R602260e283f721b7e0f0d802092516ff68c068fe
-rw-r--r--arch/arm/mach-tegra/include/mach/nvmap.h2
-rw-r--r--drivers/video/tegra/Kconfig9
-rw-r--r--drivers/video/tegra/nvmap/nvmap.h9
-rw-r--r--drivers/video/tegra/nvmap/nvmap_dev.c32
-rw-r--r--drivers/video/tegra/nvmap/nvmap_handle.c72
-rw-r--r--drivers/video/tegra/nvmap/nvmap_heap.c6
-rw-r--r--drivers/video/tegra/nvmap/nvmap_heap.h3
-rw-r--r--drivers/video/tegra/nvmap/nvmap_mru.c9
8 files changed, 91 insertions, 51 deletions
diff --git a/arch/arm/mach-tegra/include/mach/nvmap.h b/arch/arm/mach-tegra/include/mach/nvmap.h
index b19ccf6ae7dd..280dff4ae999 100644
--- a/arch/arm/mach-tegra/include/mach/nvmap.h
+++ b/arch/arm/mach-tegra/include/mach/nvmap.h
@@ -1,5 +1,5 @@
/*
- * include/linux/nvmap.h
+ * arch/arm/mach-tegra/include/mach/nvmap.h
*
* structure declarations for nvmem and nvmap user-space ioctls
*
diff --git a/drivers/video/tegra/Kconfig b/drivers/video/tegra/Kconfig
index ec610eaf077e..d91fefc10783 100644
--- a/drivers/video/tegra/Kconfig
+++ b/drivers/video/tegra/Kconfig
@@ -99,5 +99,14 @@ config TEGRA_DSI
default n
help
Say Y here to enable the DSI panel.
+
+config NVMAP_CONVERT_CARVEOUT_TO_IOVMM
+ bool "Convert carveout to IOVMM"
+ depends on TEGRA_NVMAP && TEGRA_IOVMM
+ default y
+ help
+ Say Y here to force to convert carveout memory requests to
+ I/O virtual memory requests.
+
endif
diff --git a/drivers/video/tegra/nvmap/nvmap.h b/drivers/video/tegra/nvmap/nvmap.h
index 923ff8fc8d8a..713e6f4e2926 100644
--- a/drivers/video/tegra/nvmap/nvmap.h
+++ b/drivers/video/tegra/nvmap/nvmap.h
@@ -3,7 +3,7 @@
*
* GPU memory management driver for Tegra
*
- * Copyright (c) 2010, NVIDIA Corporation.
+ * Copyright (c) 2010-2011, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -71,6 +71,7 @@ struct nvmap_handle {
unsigned long flags;
size_t size; /* padded (as-allocated) size */
size_t orig_size; /* original (as-requested) size */
+ size_t align;
struct nvmap_client *owner;
struct nvmap_device *dev;
union {
@@ -153,10 +154,8 @@ void nvmap_usecount_inc(struct nvmap_handle *h);
void nvmap_usecount_dec(struct nvmap_handle *h);
struct nvmap_heap_block *nvmap_carveout_alloc(struct nvmap_client *dev,
- size_t len, size_t align,
- unsigned long usage,
- unsigned int prot,
- struct nvmap_handle *handle);
+ struct nvmap_handle *handle,
+ unsigned long type);
unsigned long nvmap_carveout_usage(struct nvmap_client *c,
struct nvmap_heap_block *b);
diff --git a/drivers/video/tegra/nvmap/nvmap_dev.c b/drivers/video/tegra/nvmap/nvmap_dev.c
index c15cc1b21901..aeba57c85482 100644
--- a/drivers/video/tegra/nvmap/nvmap_dev.c
+++ b/drivers/video/tegra/nvmap/nvmap_dev.c
@@ -437,11 +437,10 @@ out:
return wait;
}
+static
struct nvmap_heap_block *do_nvmap_carveout_alloc(struct nvmap_client *client,
- size_t len, size_t align,
- unsigned long usage,
- unsigned int prot,
- struct nvmap_handle *handle)
+ struct nvmap_handle *handle,
+ unsigned long type)
{
struct nvmap_carveout_node *co_heap;
struct nvmap_device *dev = client->dev;
@@ -451,14 +450,12 @@ struct nvmap_heap_block *do_nvmap_carveout_alloc(struct nvmap_client *client,
struct nvmap_heap_block *block;
co_heap = &dev->heaps[i];
- if (!(co_heap->heap_bit & usage))
+ if (!(co_heap->heap_bit & type))
continue;
- block = nvmap_heap_alloc(co_heap->carveout, len,
- align, prot, handle);
- if (block) {
+ block = nvmap_heap_alloc(co_heap->carveout, handle);
+ if (block)
return block;
- }
}
return NULL;
}
@@ -470,10 +467,8 @@ static bool nvmap_carveout_freed(int count)
}
struct nvmap_heap_block *nvmap_carveout_alloc(struct nvmap_client *client,
- size_t len, size_t align,
- unsigned long usage,
- unsigned int prot,
- struct nvmap_handle *handle)
+ struct nvmap_handle *handle,
+ unsigned long type)
{
struct nvmap_heap_block *block;
struct nvmap_carveout_node *co_heap;
@@ -484,8 +479,7 @@ struct nvmap_heap_block *nvmap_carveout_alloc(struct nvmap_client *client,
int count = 0;
do {
- block = do_nvmap_carveout_alloc(client, len, align, usage,
- prot, handle);
+ block = do_nvmap_carveout_alloc(client, handle, type);
if (!carveout_killer)
return block;
@@ -500,11 +494,11 @@ struct nvmap_heap_block *nvmap_carveout_alloc(struct nvmap_client *client,
task_comm[0] = 0;
pr_info("%s: failed to allocate %u bytes for "
"process %s, firing carveout "
- "killer!\n", __func__, len, task_comm);
+ "killer!\n", __func__, handle->size, task_comm);
} else {
pr_info("%s: still can't allocate %u bytes, "
- "attempt %d!\n", __func__, len, count);
+ "attempt %d!\n", __func__, handle->size, count);
}
/* shrink carveouts that matter and try again */
@@ -512,7 +506,7 @@ struct nvmap_heap_block *nvmap_carveout_alloc(struct nvmap_client *client,
int count;
co_heap = &dev->heaps[i];
- if (!(co_heap->heap_bit & usage))
+ if (!(co_heap->heap_bit & type))
continue;
count = wait_count;
@@ -1177,6 +1171,8 @@ static int nvmap_probe(struct platform_device *pdev)
for (i = 0; i < plat->nr_carveouts; i++) {
struct nvmap_carveout_node *node = &dev->heaps[i];
const struct nvmap_platform_carveout *co = &plat->carveouts[i];
+ if (!co->size)
+ continue;
node->carveout = nvmap_heap_create(dev->dev_user.this_device,
co->name, co->base, co->size,
co->buddy_size, node);
diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c
index 6e6b6d47d28c..3b1c2ee06b10 100644
--- a/drivers/video/tegra/nvmap/nvmap_handle.c
+++ b/drivers/video/tegra/nvmap/nvmap_handle.c
@@ -1,5 +1,5 @@
/*
- * drivers/video/tegra/nvmap_handle.c
+ * drivers/video/tegra/nvmap/nvmap_handle.c
*
* Handle allocation and freeing routines for nvmap
*
@@ -39,6 +39,13 @@
#include "nvmap_mru.h"
#include "nvmap_common.h"
+#define PRINT_CARVEOUT_CONVERSION 0
+#if PRINT_CARVEOUT_CONVERSION
+#define PR_INFO pr_info
+#else
+#define PR_INFO(...)
+#endif
+
#define NVMAP_SECURE_HEAPS (NVMAP_HEAP_CARVEOUT_IRAM | NVMAP_HEAP_IOVMM)
#ifdef CONFIG_NVMAP_HIGHMEM_ONLY
#define GFP_NVMAP (__GFP_HIGHMEM | __GFP_NOWARN)
@@ -184,7 +191,7 @@ static int handle_page_alloc(struct nvmap_client *client,
#ifndef CONFIG_NVMAP_RECLAIM_UNPINNED_VM
h->pgalloc.area = tegra_iovmm_create_vm(client->share->iovmm,
- NULL, size, prot);
+ NULL, size, h->align, prot);
if (!h->pgalloc.area)
goto fail;
@@ -207,18 +214,43 @@ fail:
return -ENOMEM;
}
-static void alloc_handle(struct nvmap_client *client, size_t align,
+static void alloc_handle(struct nvmap_client *client,
struct nvmap_handle *h, unsigned int type)
{
BUG_ON(type & (type - 1));
- if (type & NVMAP_HEAP_CARVEOUT_MASK) {
- struct nvmap_heap_block *b;
+#ifdef CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM
+#define __NVMAP_HEAP_CARVEOUT NVMAP_HEAP_CARVEOUT_IRAM
+#define __NVMAP_HEAP_IOVMM (NVMAP_HEAP_IOVMM | NVMAP_HEAP_CARVEOUT_GENERIC)
+ if (type & NVMAP_HEAP_CARVEOUT_GENERIC) {
+#ifdef CONFIG_NVMAP_ALLOW_SYSMEM
+ if (h->size <= PAGE_SIZE) {
+ PR_INFO("###CARVEOUT CONVERTED TO SYSMEM "
+ "0x%x bytes %s(%d)###\n",
+ h->size, current->comm, current->pid);
+ goto sysheap;
+ }
+#endif
+ PR_INFO("###CARVEOUT CONVERTED TO IOVM "
+ "0x%x bytes %s(%d)###\n",
+ h->size, current->comm, current->pid);
+ }
+#else
+#define __NVMAP_HEAP_CARVEOUT NVMAP_HEAP_CARVEOUT_MASK
+#define __NVMAP_HEAP_IOVMM NVMAP_HEAP_IOVMM
+#endif
+
+ if (type & __NVMAP_HEAP_CARVEOUT) {
+ struct nvmap_heap_block *b;
+#ifdef CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM
+ PR_INFO("###IRAM REQUEST RETAINED "
+ "0x%x bytes %s(%d)###\n",
+ h->size, current->comm, current->pid);
+#endif
/* Protect handle from relocation */
nvmap_usecount_inc(h);
- b = nvmap_carveout_alloc(client, h->size, align,
- type, h->flags, h);
+ b = nvmap_carveout_alloc(client, h, type);
if (b) {
h->heap_pgalloc = false;
h->alloc = true;
@@ -228,13 +260,11 @@ static void alloc_handle(struct nvmap_client *client, size_t align,
}
nvmap_usecount_dec(h);
- } else if (type & NVMAP_HEAP_IOVMM) {
+ } else if (type & __NVMAP_HEAP_IOVMM) {
size_t reserved = PAGE_ALIGN(h->size);
int commit;
int ret;
- BUG_ON(align > PAGE_SIZE);
-
/* increment the committed IOVM space prior to allocation
* to avoid race conditions with other threads simultaneously
* allocating. */
@@ -253,7 +283,10 @@ static void alloc_handle(struct nvmap_client *client, size_t align,
}
} else if (type & NVMAP_HEAP_SYSMEM) {
-
+#if defined(CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM) && \
+ defined(CONFIG_NVMAP_ALLOW_SYSMEM)
+sysheap:
+#endif
if (handle_page_alloc(client, h, true) == 0) {
BUG_ON(!h->pgalloc.contig);
h->heap_pgalloc = true;
@@ -295,12 +328,6 @@ int nvmap_alloc_handle_id(struct nvmap_client *client,
int nr_page;
int err = -ENOMEM;
- align = max_t(size_t, align, L1_CACHE_BYTES);
-
- /* can't do greater than page size alignment with page alloc */
- if (align > PAGE_SIZE)
- heap_mask &= NVMAP_HEAP_CARVEOUT_MASK;
-
h = nvmap_get_handle_id(client, id);
if (!h)
@@ -312,7 +339,14 @@ int nvmap_alloc_handle_id(struct nvmap_client *client,
nr_page = ((h->size + PAGE_SIZE - 1) >> PAGE_SHIFT);
h->secure = !!(flags & NVMAP_HANDLE_SECURE);
h->flags = (flags & NVMAP_HANDLE_CACHE_FLAG);
-
+ h->align = max_t(size_t, align, L1_CACHE_BYTES);
+#ifndef CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM
+ /* This resriction is deprecated as alignments greater than
+ PAGE_SIZE are now correctly handled, but it is retained for
+ AP20 compatibility. */
+ if (h->align > PAGE_SIZE)
+ heap_mask &= NVMAP_HEAP_CARVEOUT_MASK;
+#endif
/* secure allocations can only be served from secure heaps */
if (h->secure)
heap_mask &= NVMAP_SECURE_HEAPS;
@@ -341,7 +375,7 @@ int nvmap_alloc_handle_id(struct nvmap_client *client,
/* iterate possible heaps MSB-to-LSB, since higher-
* priority carveouts will have higher usage masks */
heap = 1 << __fls(heap_type);
- alloc_handle(client, align, h, heap);
+ alloc_handle(client, h, heap);
heap_type &= ~heap;
}
}
diff --git a/drivers/video/tegra/nvmap/nvmap_heap.c b/drivers/video/tegra/nvmap/nvmap_heap.c
index b90a87671f98..1378a5cb1f79 100644
--- a/drivers/video/tegra/nvmap/nvmap_heap.c
+++ b/drivers/video/tegra/nvmap/nvmap_heap.c
@@ -844,11 +844,13 @@ void nvmap_usecount_dec(struct nvmap_handle *h)
/* nvmap_heap_alloc: allocates a block of memory of len bytes, aligned to
* align bytes. */
-struct nvmap_heap_block *nvmap_heap_alloc(struct nvmap_heap *h, size_t len,
- size_t align, unsigned int prot,
+struct nvmap_heap_block *nvmap_heap_alloc(struct nvmap_heap *h,
struct nvmap_handle *handle)
{
struct nvmap_heap_block *b;
+ size_t len = handle->size;
+ size_t align = handle->align;
+ unsigned int prot = handle->flags;
mutex_lock(&h->lock);
diff --git a/drivers/video/tegra/nvmap/nvmap_heap.h b/drivers/video/tegra/nvmap/nvmap_heap.h
index a8884be218d1..2533c13049c8 100644
--- a/drivers/video/tegra/nvmap/nvmap_heap.h
+++ b/drivers/video/tegra/nvmap/nvmap_heap.h
@@ -45,8 +45,7 @@ void *nvmap_heap_device_to_arg(struct device *dev);
void *nvmap_heap_to_arg(struct nvmap_heap *heap);
-struct nvmap_heap_block *nvmap_heap_alloc(struct nvmap_heap *heap, size_t len,
- size_t align, unsigned int prot,
+struct nvmap_heap_block *nvmap_heap_alloc(struct nvmap_heap *heap,
struct nvmap_handle *handle);
struct nvmap_heap *nvmap_block_to_heap(struct nvmap_heap_block *b);
diff --git a/drivers/video/tegra/nvmap/nvmap_mru.c b/drivers/video/tegra/nvmap/nvmap_mru.c
index 252665427568..d525fbed74d2 100644
--- a/drivers/video/tegra/nvmap/nvmap_mru.c
+++ b/drivers/video/tegra/nvmap/nvmap_mru.c
@@ -1,9 +1,9 @@
/*
- * drivers/video/tegra/nvmap_mru.c
+ * drivers/video/tegra/nvmap/nvmap_mru.c
*
* IOVMM virtualization support for nvmap
*
- * Copyright (c) 2009-2010, NVIDIA Corporation.
+ * Copyright (c) 2009-2011, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -115,7 +115,8 @@ struct tegra_iovmm_area *nvmap_handle_iovmm(struct nvmap_client *c,
return h->pgalloc.area;
}
- vm = tegra_iovmm_create_vm(c->share->iovmm, NULL, h->size, prot);
+ vm = tegra_iovmm_create_vm(c->share->iovmm, NULL,
+ h->size, h->align, prot);
if (vm) {
INIT_LIST_HEAD(&h->pgalloc.mru_list);
@@ -159,7 +160,7 @@ struct tegra_iovmm_area *nvmap_handle_iovmm(struct nvmap_client *c,
tegra_iovmm_free_vm(evict->pgalloc.area);
evict->pgalloc.area = NULL;
vm = tegra_iovmm_create_vm(c->share->iovmm,
- NULL, h->size, prot);
+ NULL, h->size, h->align, prot);
nvmap_mru_lock(c->share);
}
}