From 82a647d8b474ddea076f8dbb92bb29b87f7d2da0 Mon Sep 17 00:00:00 2001 From: CMY Date: Fri, 28 Mar 2014 18:58:21 +0800 Subject: [PATCH] rk: ion: force unmap iommu while destroy buffer --- drivers/staging/android/ion/ion.c | 36 +++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index c7e7ca354799..9fbecf4c8415 100755 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -115,6 +115,8 @@ struct ion_handle { int id; }; +static void ion_iommu_force_unmap(struct ion_buffer *buffer); + bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer) { return (buffer->flags & ION_FLAG_CACHED) && @@ -275,6 +277,9 @@ void ion_buffer_destroy(struct ion_buffer *buffer) if (WARN_ON(buffer->kmap_cnt > 0)) buffer->heap->ops->unmap_kernel(buffer->heap, buffer); buffer->heap->ops->unmap_dma(buffer->heap, buffer); +#ifdef CONFIG_ROCKCHIP_IOMMU + ion_iommu_force_unmap(buffer); +#endif buffer->heap->ops->free(buffer); if (buffer->pages) vfree(buffer->pages); @@ -772,7 +777,7 @@ int ion_map_iommu(struct device *iommu_dev, struct ion_client *client, } buffer = handle->buffer; - pr_debug("%s: map buffer(%x)\n", __func__, buffer); + pr_debug("%s: map buffer(%p)\n", __func__, buffer); mutex_lock(&buffer->lock); @@ -798,10 +803,10 @@ int ion_map_iommu(struct device *iommu_dev, struct ion_client *client, iommu_map = ion_iommu_lookup(buffer, (uint32_t)iommu_dev); if (!iommu_map) { - pr_debug("%s: create new map for buffer(%x)\n", __func__, buffer); + pr_debug("%s: create new map for buffer(%p)\n", __func__, buffer); iommu_map = __ion_iommu_map(buffer, iommu_dev, iova); } else { - pr_debug("%s: buffer(%x) already mapped\n", __func__, buffer); + pr_debug("%s: buffer(%p) already mapped\n", __func__, buffer); if (iommu_map->mapped_size != buffer->size) { pr_err("%s: handle %p is already mapped with length" " %x, trying to map with length %x\n", @@ -833,6 +838,29 @@ static void ion_iommu_release(struct kref *kref) kfree(map); } +/** + * Unmap any outstanding mappings which would otherwise have been leaked. + */ +static void ion_iommu_force_unmap(struct ion_buffer *buffer) +{ + struct ion_iommu_map *iommu_map; + struct rb_node *node; + const struct rb_root *rb = &(buffer->iommu_maps); + + pr_debug("%s: force unmap buffer(%p)\n", __func__, buffer); + + mutex_lock(&buffer->lock); + + while ((node = rb_first(rb)) != 0) { + iommu_map = rb_entry(node, struct ion_iommu_map, node); + /* set ref count to 1 to force release */ + kref_init(&iommu_map->ref); + kref_put(&iommu_map->ref, ion_iommu_release); + } + + mutex_unlock(&buffer->lock); +} + void ion_unmap_iommu(struct device *iommu_dev, struct ion_client *client, struct ion_handle *handle) { @@ -841,7 +869,7 @@ void ion_unmap_iommu(struct device *iommu_dev, struct ion_client *client, mutex_lock(&client->lock); buffer = handle->buffer; - pr_debug("%s: unmap buffer(%x)\n", __func__, buffer); + pr_debug("%s: unmap buffer(%p)\n", __func__, buffer); mutex_lock(&buffer->lock); -- 2.34.1