void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle, unsigned long flags) { struct ion_buffer *buffer; void *vaddr; mutex_lock(&client->lock); if (!ion_handle_validate(client, handle)) { pr_err("%s: invalid handle passed to map_kernel.\n", __func__); mutex_unlock(&client->lock); return ERR_PTR(-EINVAL); } buffer = handle->buffer; if (!handle->buffer->heap->ops->map_kernel) { pr_err("%s: map_kernel is not implemented by this heap.\n", __func__); mutex_unlock(&client->lock); return ERR_PTR(-ENODEV); } if (ion_validate_buffer_flags(buffer, flags)) { mutex_unlock(&client->lock); return ERR_PTR(-EEXIST); } mutex_lock(&buffer->lock); vaddr = ion_handle_kmap_get(handle); mutex_unlock(&buffer->lock); mutex_unlock(&client->lock); return vaddr; }
static int ion_share_set_flags(struct ion_client *client, struct ion_handle *handle, unsigned long flags) { struct ion_buffer *buffer; bool valid_handle; unsigned long ion_flags = ION_SET_CACHE(CACHED); if (flags & O_DSYNC) ion_flags = ION_SET_CACHE(UNCACHED); mutex_lock(&client->lock); valid_handle = ion_handle_validate(client, handle); mutex_unlock(&client->lock); if (!valid_handle) { WARN(1, "%s: invalid handle passed to set_flags.\n", __func__); return -EINVAL; } buffer = handle->buffer; mutex_lock(&buffer->lock); if (ion_validate_buffer_flags(buffer, ion_flags)) { mutex_unlock(&buffer->lock); return -EEXIST; } mutex_unlock(&buffer->lock); return 0; }
void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle, unsigned long flags) { struct ion_buffer *buffer; void *vaddr; mutex_lock(&client->lock); if (!ion_handle_validate(client, handle)) { pr_err("%s: invalid handle passed to map_kernel.\n", __func__); mutex_unlock(&client->lock); return ERR_PTR(-EINVAL); } buffer = handle->buffer; mutex_lock(&buffer->lock); if (!handle->buffer->heap->ops->map_kernel) { pr_err("%s: map_kernel is not implemented by this heap.\n", __func__); mutex_unlock(&buffer->lock); mutex_unlock(&client->lock); return ERR_PTR(-ENODEV); } if (ion_validate_buffer_flags(buffer, flags)) { vaddr = ERR_PTR(-EEXIST); goto out; } if (_ion_map(&buffer->kmap_cnt, &handle->kmap_cnt)) { vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer, flags); if (IS_ERR_OR_NULL(vaddr)) _ion_unmap(&buffer->kmap_cnt, &handle->kmap_cnt); buffer->vaddr = vaddr; } else { vaddr = buffer->vaddr; } out: mutex_unlock(&buffer->lock); mutex_unlock(&client->lock); return vaddr; }
struct scatterlist *ion_map_dma(struct ion_client *client, struct ion_handle *handle, unsigned long flags) { struct ion_buffer *buffer; struct scatterlist *sglist; mutex_lock(&client->lock); if (!ion_handle_validate(client, handle)) { pr_err("%s: invalid handle passed to map_dma.\n", __func__); mutex_unlock(&client->lock); return ERR_PTR(-EINVAL); } buffer = handle->buffer; mutex_lock(&buffer->lock); if (!handle->buffer->heap->ops->map_dma) { pr_err("%s: map_kernel is not implemented by this heap.\n", __func__); mutex_unlock(&buffer->lock); mutex_unlock(&client->lock); return ERR_PTR(-ENODEV); } if (ion_validate_buffer_flags(buffer, flags)) { sglist = ERR_PTR(-EEXIST); goto out; } if (_ion_map(&buffer->dmap_cnt, &handle->dmap_cnt)) { sglist = buffer->heap->ops->map_dma(buffer->heap, buffer); if (IS_ERR_OR_NULL(sglist)) _ion_unmap(&buffer->dmap_cnt, &handle->dmap_cnt); buffer->sglist = sglist; } else { sglist = buffer->sglist; } out: mutex_unlock(&buffer->lock); mutex_unlock(&client->lock); return sglist; }
int ion_map_iommu(struct ion_client *client, struct ion_handle *handle, int domain_num, int partition_num, unsigned long align, unsigned long iova_length, unsigned long *iova, unsigned long *buffer_size, unsigned long flags) { struct ion_buffer *buffer; struct ion_iommu_map *iommu_map; int ret = 0; mutex_lock(&client->lock); if (!ion_handle_validate(client, handle)) { pr_err("%s: invalid handle passed to map_kernel.\n", __func__); mutex_unlock(&client->lock); return -EINVAL; } buffer = handle->buffer; mutex_lock(&buffer->lock); if (!handle->buffer->heap->ops->map_iommu) { pr_err("%s: map_iommu is not implemented by this heap.\n", __func__); ret = -ENODEV; goto out; } if (ion_validate_buffer_flags(buffer, flags)) { ret = -EEXIST; goto out; } /* * If clients don't want a custom iova length, just use whatever * the buffer size is */ if (!iova_length) iova_length = buffer->size; if (buffer->size > iova_length) { pr_debug("%s: iova length %lx is not at least buffer size" " %x\n", __func__, iova_length, buffer->size); ret = -EINVAL; goto out; } if (buffer->size & ~PAGE_MASK) { pr_debug("%s: buffer size %x is not aligned to %lx", __func__, buffer->size, PAGE_SIZE); ret = -EINVAL; goto out; } if (iova_length & ~PAGE_MASK) { pr_debug("%s: iova_length %lx is not aligned to %lx", __func__, iova_length, PAGE_SIZE); ret = -EINVAL; goto out; } iommu_map = ion_iommu_lookup(buffer, domain_num, partition_num); if (_ion_map(&buffer->iommu_map_cnt, &handle->iommu_map_cnt) || !iommu_map) { ret = __ion_iommu_map(buffer, domain_num, partition_num, align, iova_length, flags, iova); if (ret < 0) _ion_unmap(&buffer->iommu_map_cnt, &handle->iommu_map_cnt); } else { if (iommu_map->mapped_size != iova_length) { pr_err("%s: handle %p is already mapped with length" " %x, trying to map with length %lx\n", __func__, handle, iommu_map->mapped_size, iova_length); _ion_unmap(&buffer->iommu_map_cnt, &handle->iommu_map_cnt); ret = -EINVAL; } else { kref_get(&iommu_map->ref); *iova = iommu_map->iova_addr; } } *buffer_size = buffer->size; out: mutex_unlock(&buffer->lock); mutex_unlock(&client->lock); return ret; }