diff options
author | Kirill Artamonov <kartamonov@nvidia.com> | 2011-06-15 03:40:32 +0300 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:47:23 -0800 |
commit | 9cb88b1cea01dda012134c76d0a1d56a263b02ca (patch) | |
tree | 1b2108820d183b235633dfc37a86bce9ddca6710 /arch/arm/mach-tegra/iovmm.c | |
parent | 4604a9ef07f231a41c28e52add8e5d92ae840d79 (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.c | 22 |
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) |