summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/nvmap/nvmap_mru.c
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 /drivers/video/tegra/nvmap/nvmap_mru.c
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 'drivers/video/tegra/nvmap/nvmap_mru.c')
-rw-r--r--drivers/video/tegra/nvmap/nvmap_mru.c15
1 files changed, 2 insertions, 13 deletions
diff --git a/drivers/video/tegra/nvmap/nvmap_mru.c b/drivers/video/tegra/nvmap/nvmap_mru.c
index 252665427568..f38d0c390ca2 100644
--- a/drivers/video/tegra/nvmap/nvmap_mru.c
+++ b/drivers/video/tegra/nvmap/nvmap_mru.c
@@ -90,7 +90,7 @@ void nvmap_mru_remove(struct nvmap_share *s, struct nvmap_handle *h)
* and if that fails, iteratively evict handles from the MRU lists and free
* their allocations, until the new allocation succeeds.
*/
-struct tegra_iovmm_area *nvmap_handle_iovmm(struct nvmap_client *c,
+struct tegra_iovmm_area *nvmap_handle_iovmm_locked(struct nvmap_client *c,
struct nvmap_handle *h)
{
struct list_head *mru;
@@ -104,14 +104,9 @@ struct tegra_iovmm_area *nvmap_handle_iovmm(struct nvmap_client *c,
prot = nvmap_pgprot(h, pgprot_kernel);
if (h->pgalloc.area) {
- /* since this is only called inside the pin lock, and the
- * handle is gotten before it is pinned, there are no races
- * where h->pgalloc.area is changed after the comparison */
- nvmap_mru_lock(c->share);
BUG_ON(list_empty(&h->pgalloc.mru_list));
list_del(&h->pgalloc.mru_list);
INIT_LIST_HEAD(&h->pgalloc.mru_list);
- nvmap_mru_unlock(c->share);
return h->pgalloc.area;
}
@@ -125,8 +120,6 @@ struct tegra_iovmm_area *nvmap_handle_iovmm(struct nvmap_client *c,
* same size bin as the current handle. If that fails, iteratively
* evict handles (starting from the current bin) until an allocation
* succeeds or no more areas can be evicted */
-
- nvmap_mru_lock(c->share);
mru = mru_list(c->share, h->size);
if (!list_empty(mru))
evict = list_first_entry(mru, struct nvmap_handle,
@@ -137,7 +130,6 @@ struct tegra_iovmm_area *nvmap_handle_iovmm(struct nvmap_client *c,
vm = evict->pgalloc.area;
evict->pgalloc.area = NULL;
INIT_LIST_HEAD(&evict->pgalloc.mru_list);
- nvmap_mru_unlock(c->share);
return vm;
}
@@ -155,22 +147,19 @@ struct tegra_iovmm_area *nvmap_handle_iovmm(struct nvmap_client *c,
BUG_ON(!evict->pgalloc.area);
list_del(&evict->pgalloc.mru_list);
INIT_LIST_HEAD(&evict->pgalloc.mru_list);
- nvmap_mru_unlock(c->share);
tegra_iovmm_free_vm(evict->pgalloc.area);
evict->pgalloc.area = NULL;
vm = tegra_iovmm_create_vm(c->share->iovmm,
NULL, h->size, prot);
- nvmap_mru_lock(c->share);
}
}
- nvmap_mru_unlock(c->share);
return vm;
}
int nvmap_mru_init(struct nvmap_share *share)
{
int i;
- spin_lock_init(&share->mru_lock);
+ mutex_init(&share->mru_lock);
share->nr_mru = ARRAY_SIZE(mru_cutoff) + 1;
share->mru_lists = kzalloc(sizeof(struct list_head) * share->nr_mru,