summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
authorKirill Artamonov <kartamonov@nvidia.com>2011-06-26 21:37:18 +0300
committerAnnamaria Pyreddy <apyreddy@nvidia.com>2011-08-19 16:43:42 -0700
commit48d10f659a21fd6d0dff5e073663f9689b549db4 (patch)
treed54fa117c1c2918a1678320247e496cce5ee9d92 /arch/arm/mach-tegra
parent9d650429b634914e0705c37d84a9cfa44375391a (diff)
video: tegra: nvmap: fix GART pin lockupstegra-10.11.14
Fix GART lockups caused by fragmentation by evicting mapped areas from iovm space after unsuccessful array pinning attempt. Fix double unpin error happening during interrupted submit. Fix possible sleep in atomic context in iovmm code (semaphore inside spinlock) by replacing spinlock with mutex. Fix race between handle_unpin and pin_handle. bug 838579 bug 838073 bug 818058 bug 844307 Conflicts: drivers/video/tegra/nvmap/nvmap_mru.c Reviewed-on: http://git-master/r/38430 (cherry picked from commit 4a4cae3323d3287e77fdc504e38656974ef24848) Change-Id: I385913569ef455a1ceb5083829959de24f5309a7 Reviewed-on: http://git-master/r/47832 Reviewed-by: Andre Sihera <asihera@nvidia.com> Tested-by: Andre Sihera <asihera@nvidia.com> Reviewed-by: Kirill Artamonov <kartamonov@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r--arch/arm/mach-tegra/include/mach/iovmm.h3
-rw-r--r--arch/arm/mach-tegra/iovmm.c22
2 files changed, 25 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/include/mach/iovmm.h b/arch/arm/mach-tegra/include/mach/iovmm.h
index 8f111605e065..e30d3dcf2859 100644
--- a/arch/arm/mach-tegra/include/mach/iovmm.h
+++ b/arch/arm/mach-tegra/include/mach/iovmm.h
@@ -166,6 +166,9 @@ void tegra_iovmm_unzap_vm(struct tegra_iovmm_area *vm);
/* called by clients to return an iovmm_area to the free pool for the domain */
void tegra_iovmm_free_vm(struct tegra_iovmm_area *vm);
+/* returns size of largest free iovm block */
+size_t tegra_iovmm_get_max_free(struct tegra_iovmm_client *client);
+
/* called by client software to map the page-aligned I/O address vaddr to
* a specific physical address pfn. I/O VMA should have been created with
* a NULL tegra_iovmm_area_ops structure. */
diff --git a/arch/arm/mach-tegra/iovmm.c b/arch/arm/mach-tegra/iovmm.c
index 1f9e49902188..1afdaf3b53cc 100644
--- a/arch/arm/mach-tegra/iovmm.c
+++ b/arch/arm/mach-tegra/iovmm.c
@@ -90,6 +90,28 @@ static tegra_iovmm_addr_t iovmm_align_down(struct tegra_iovmm_device *dev,
#define iovmprint(fmt, arg...) snprintf(page+len, count-len, fmt, ## arg)
+size_t tegra_iovmm_get_max_free(struct tegra_iovmm_client *client)
+{
+ struct rb_node *n;
+ struct tegra_iovmm_block *b;
+ struct tegra_iovmm_domain *domain = client->domain;
+
+ spin_lock(&domain->block_lock);
+ n = rb_first(&domain->all_blocks);
+ tegra_iovmm_addr_t max_free = 0;
+ while (n) {
+ b = rb_entry(n, struct tegra_iovmm_block, all_node);
+ n = rb_next(n);
+ if (test_bit(BK_free, &b->flags)) {
+ max_free = max_t(tegra_iovmm_addr_t,
+ max_free, iovmm_length(b));
+ }
+ }
+ spin_unlock(&domain->block_lock);
+ return max_free;
+}
+
+
static void tegra_iovmm_block_stats(struct tegra_iovmm_domain *domain,
unsigned int *num_blocks, unsigned int *num_free,
tegra_iovmm_addr_t *total, tegra_iovmm_addr_t *total_free,