summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/iovmm.c
diff options
context:
space:
mode:
authorKirill Artamonov <kartamonov@nvidia.com>2011-06-26 21:37:18 +0300
committerRohan Somvanshi <rsomvanshi@nvidia.com>2011-06-28 22:57:12 -0700
commit4a4cae3323d3287e77fdc504e38656974ef24848 (patch)
tree87fcc00355de2566fca2a0104770cbf57dcb1e1b /arch/arm/mach-tegra/iovmm.c
parentddfc93d27830a28a1c9786fd5bce6dc35727e9ff (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 bug 844307 Conflicts: drivers/video/tegra/nvmap/nvmap_mru.c Change-Id: Ie44fa88510f62ce5c7d31af3b07afdf69a3ad4a6 Reviewed-on: http://git-master/r/38430 Reviewed-by: Kirill Artamonov <kartamonov@nvidia.com> Tested-by: Kirill Artamonov <kartamonov@nvidia.com> Tested-by: Gerrit_Virtual_Submit Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
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 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,