summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/iovmm.c
diff options
context:
space:
mode:
authorKirill Artamonov <kartamonov@nvidia.com>2011-06-15 03:40:32 +0300
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:47:23 -0800
commit9cb88b1cea01dda012134c76d0a1d56a263b02ca (patch)
tree1b2108820d183b235633dfc37a86bce9ddca6710 /arch/arm/mach-tegra/iovmm.c
parent4604a9ef07f231a41c28e52add8e5d92ae840d79 (diff)
video: tegra: nvmap: fix GART pin lockups
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 Original-Change-Id: I420447ffb4e02fb78a7987e22a537eefc16ff524 Reviewed-on: http://git-master/r/36129 Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Tested-by: Varun Colbert <vcolbert@nvidia.com> Rebase-Id: R893c97003f2ec2f69e224f35d99d3488f673d620
Diffstat (limited to 'arch/arm/mach-tegra/iovmm.c')
-rw-r--r--arch/arm/mach-tegra/iovmm.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/iovmm.c b/arch/arm/mach-tegra/iovmm.c
index 2baa00470177..dfe02fc17b7c 100644
--- a/arch/arm/mach-tegra/iovmm.c
+++ b/arch/arm/mach-tegra/iovmm.c
@@ -96,6 +96,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, size_t *total_free, size_t *max_free)