diff options
author | John Stultz <john.stultz@linaro.org> | 2013-11-25 10:54:08 -0800 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2013-11-25 10:54:08 -0800 |
commit | 2c6193b7527e92a5916e6f798ddf47401afa17c3 (patch) | |
tree | b7a3efa93f354255d2466691da3b41c9df6e4b72 /drivers/staging | |
parent | 305a41042d6127e9596f66382bf4e81a70e24bb3 (diff) | |
parent | f2ec29aa62924e6b1ce5edb3bfc7dcd206023740 (diff) |
Merge branch 'upstream/android-3.10' into linaro-fixes/android-3.10
Update to latest android-3.10 branch.
Minor conflict with the direct printk stuff
Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/android/ion/compat_ion.c | 19 | ||||
-rw-r--r-- | drivers/staging/android/ion/ion.c | 84 | ||||
-rw-r--r-- | drivers/staging/android/ion/ion_chunk_heap.c | 19 | ||||
-rw-r--r-- | drivers/staging/android/ion/ion_heap.c | 12 | ||||
-rw-r--r-- | drivers/staging/android/ion/ion_page_pool.c | 9 | ||||
-rw-r--r-- | drivers/staging/android/ion/ion_priv.h | 12 | ||||
-rw-r--r-- | drivers/staging/android/ion/ion_system_heap.c | 7 |
7 files changed, 108 insertions, 54 deletions
diff --git a/drivers/staging/android/ion/compat_ion.c b/drivers/staging/android/ion/compat_ion.c index 0416fabfc1b9..a89b067ec051 100644 --- a/drivers/staging/android/ion/compat_ion.c +++ b/drivers/staging/android/ion/compat_ion.c @@ -35,6 +35,12 @@ struct compat_ion_custom_data { compat_ulong_t arg; }; +#define COMPAT_ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \ + struct compat_ion_allocation_data) +#define COMPAT_ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data) +#define COMPAT_ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, \ + struct compat_ion_custom_data) + static int compat_get_ion_allocation_data( struct compat_ion_allocation_data __user *data32, struct ion_allocation_data __user *data) @@ -105,7 +111,7 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -ENOTTY; switch (cmd) { - case ION_IOC_ALLOC: + case COMPAT_ION_IOC_ALLOC: { struct compat_ion_allocation_data __user *data32; struct ion_allocation_data __user *data; @@ -119,13 +125,12 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) err = compat_get_ion_allocation_data(data32, data); if (err) return err; - - ret = filp->f_op->unlocked_ioctl(filp, cmd, + ret = filp->f_op->unlocked_ioctl(filp, ION_IOC_ALLOC, (unsigned long)data); err = compat_put_ion_allocation_data(data32, data); return ret ? ret : err; } - case ION_IOC_FREE: + case COMPAT_ION_IOC_FREE: { struct compat_ion_allocation_data __user *data32; struct ion_allocation_data __user *data; @@ -140,10 +145,10 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (err) return err; - return filp->f_op->unlocked_ioctl(filp, cmd, + return filp->f_op->unlocked_ioctl(filp, ION_IOC_FREE, (unsigned long)data); } - case ION_IOC_CUSTOM: { + case COMPAT_ION_IOC_CUSTOM: { struct compat_ion_custom_data __user *data32; struct ion_custom_data __user *data; int err; @@ -157,7 +162,7 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (err) return err; - return filp->f_op->unlocked_ioctl(filp, cmd, + return filp->f_op->unlocked_ioctl(filp, ION_IOC_CUSTOM, (unsigned long)data); } case ION_IOC_SHARE: diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 5c886fc9cd7e..4d19716cabd2 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -224,7 +224,7 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, for_each_sg(table->sgl, sg, table->nents, i) { struct page *page = sg_page(sg); - for (j = 0; j < sg_dma_len(sg) / PAGE_SIZE; j++) + for (j = 0; j < sg->length / PAGE_SIZE; j++) buffer->pages[k++] = page++; } @@ -383,7 +383,14 @@ static void ion_handle_get(struct ion_handle *handle) static int ion_handle_put(struct ion_handle *handle) { - return kref_put(&handle->ref, ion_handle_destroy); + struct ion_client *client = handle->client; + int ret; + + mutex_lock(&client->lock); + ret = kref_put(&handle->ref, ion_handle_destroy); + mutex_unlock(&client->lock); + + return ret; } static struct ion_handle *ion_handle_lookup(struct ion_client *client, @@ -403,14 +410,24 @@ static struct ion_handle *ion_handle_lookup(struct ion_client *client, return ERR_PTR(-EINVAL); } -static struct ion_handle *ion_uhandle_get(struct ion_client *client, int id) +static struct ion_handle *ion_handle_get_by_id(struct ion_client *client, + int id) { - return idr_find(&client->idr, id); + struct ion_handle *handle; + + mutex_lock(&client->lock); + handle = idr_find(&client->idr, id); + if (handle) + ion_handle_get(handle); + mutex_unlock(&client->lock); + + return handle ? handle : ERR_PTR(-EINVAL); } static bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle) { - return (ion_uhandle_get(client, handle->id) == handle); + WARN_ON(!mutex_is_locked(&client->lock)); + return (idr_find(&client->idr, handle->id) == handle); } static int ion_handle_add(struct ion_client *client, struct ion_handle *handle) @@ -468,11 +485,11 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, * request of the caller allocate from it. Repeat until allocate has * succeeded or all heaps have been tried */ - if (WARN_ON(!len)) - return ERR_PTR(-EINVAL); - len = PAGE_ALIGN(len); + if (!len) + return ERR_PTR(-EINVAL); + down_read(&dev->lock); plist_for_each_entry(heap, &dev->heaps, node) { /* if the caller didn't specify this heap id */ @@ -503,11 +520,11 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, mutex_lock(&client->lock); ret = ion_handle_add(client, handle); + mutex_unlock(&client->lock); if (ret) { ion_handle_put(handle); handle = ERR_PTR(ret); } - mutex_unlock(&client->lock); return handle; } @@ -527,8 +544,8 @@ void ion_free(struct ion_client *client, struct ion_handle *handle) mutex_unlock(&client->lock); return; } - ion_handle_put(handle); mutex_unlock(&client->lock); + ion_handle_put(handle); } EXPORT_SYMBOL(ion_free); @@ -823,6 +840,22 @@ static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, { } +void ion_pages_sync_for_device(struct device *dev, struct page *page, + size_t size, enum dma_data_direction dir) +{ + struct scatterlist sg; + + sg_init_table(&sg, 1); + sg_set_page(&sg, page, size, 0); + /* + * This is not correct - sg_dma_address needs a dma_addr_t that is valid + * for the the targeted device, but this works on the currently targeted + * hardware. + */ + sg_dma_address(&sg) = page_to_phys(page); + dma_sync_sg_for_device(dev, &sg, 1, dir); +} + struct ion_vma_list { struct list_head list; struct vm_area_struct *vma; @@ -847,7 +880,9 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer, struct page *page = buffer->pages[i]; if (ion_buffer_page_is_dirty(page)) - __dma_page_cpu_to_dev(page, 0, PAGE_SIZE, dir); + ion_pages_sync_for_device(dev, ion_buffer_page(page), + PAGE_SIZE, dir); + ion_buffer_page_clean(buffer->pages + i); } list_for_each_entry(vma_list, &buffer->vmas, list) { @@ -1021,14 +1056,15 @@ struct dma_buf *ion_share_dma_buf(struct ion_client *client, 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 share.\n", __func__); + mutex_unlock(&client->lock); return ERR_PTR(-EINVAL); } - buffer = handle->buffer; ion_buffer_get(buffer); + mutex_unlock(&client->lock); + dmabuf = dma_buf_export(buffer, &dma_buf_ops, buffer->size, O_RDWR); if (IS_ERR(dmabuf)) { ion_buffer_put(buffer); @@ -1081,18 +1117,24 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) handle = ion_handle_lookup(client, buffer); if (!IS_ERR(handle)) { ion_handle_get(handle); + mutex_unlock(&client->lock); goto end; } + mutex_unlock(&client->lock); + handle = ion_handle_create(client, buffer); if (IS_ERR(handle)) goto end; + + mutex_lock(&client->lock); ret = ion_handle_add(client, handle); + mutex_unlock(&client->lock); if (ret) { ion_handle_put(handle); handle = ERR_PTR(ret); } + end: - mutex_unlock(&client->lock); dma_buf_put(dmabuf); return handle; } @@ -1156,12 +1198,11 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_from_user(&data, (void __user *)arg, sizeof(struct ion_handle_data))) return -EFAULT; - mutex_lock(&client->lock); - handle = ion_uhandle_get(client, data.handle); - mutex_unlock(&client->lock); - if (!handle) - return -EINVAL; + handle = ion_handle_get_by_id(client, data.handle); + if (IS_ERR(handle)) + return PTR_ERR(handle); ion_free(client, handle); + ion_handle_put(handle); break; } case ION_IOC_SHARE: @@ -1172,8 +1213,11 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_from_user(&data, (void __user *)arg, sizeof(data))) return -EFAULT; - handle = ion_uhandle_get(client, data.handle); + handle = ion_handle_get_by_id(client, data.handle); + if (IS_ERR(handle)) + return PTR_ERR(handle); data.fd = ion_share_dma_buf_fd(client, handle); + ion_handle_put(handle); if (copy_to_user((void __user *)arg, &data, sizeof(data))) return -EFAULT; if (data.fd < 0) diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 217563da3cfc..2e6d610e5e64 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -84,7 +84,7 @@ err: sg = table->sgl; for (i -= 1; i >= 0; i--) { gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)), - sg_dma_len(sg)); + sg->length); sg = sg_next(sg); } sg_free_table(table); @@ -106,13 +106,13 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) ion_heap_buffer_zero(buffer); + if (ion_buffer_cached(buffer)) + dma_sync_sg_for_device(NULL, table->sgl, table->nents, + DMA_BIDIRECTIONAL); + for_each_sg(table->sgl, sg, table->nents, i) { - if (ion_buffer_cached(buffer)) - arm_dma_ops.sync_single_for_device(NULL, - pfn_to_dma(NULL, page_to_pfn(sg_page(sg))), - sg_dma_len(sg), DMA_BIDIRECTIONAL); gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)), - sg_dma_len(sg)); + sg->length); } chunk_heap->allocated -= allocated_size; sg_free_table(table); @@ -148,7 +148,6 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) pgprot_t pgprot = pgprot_writecombine(PAGE_KERNEL); int i, ret; - chunk_heap = kzalloc(sizeof(struct ion_chunk_heap), GFP_KERNEL); if (!chunk_heap) return ERR_PTR(-ENOMEM); @@ -181,9 +180,9 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) } free_vm_area(vm_struct); - arm_dma_ops.sync_single_for_device(NULL, - pfn_to_dma(NULL, page_to_pfn(phys_to_page(heap_data->base))), - heap_data->size, DMA_BIDIRECTIONAL); + ion_pages_sync_for_device(NULL, pfn_to_page(PFN_DOWN(heap_data->base)), + heap_data->size, DMA_BIDIRECTIONAL); + gen_pool_add(chunk_heap->pool, chunk_heap->base, heap_data->size, -1); chunk_heap->heap.ops = &chunk_heap_ops; chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 9be246f50a01..f32f4e69765a 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -46,7 +46,7 @@ void *ion_heap_map_kernel(struct ion_heap *heap, pgprot = pgprot_writecombine(PAGE_KERNEL); for_each_sg(table->sgl, sg, table->nents, i) { - int npages_this_entry = PAGE_ALIGN(sg_dma_len(sg)) / PAGE_SIZE; + int npages_this_entry = PAGE_ALIGN(sg->length) / PAGE_SIZE; struct page *page = sg_page(sg); BUG_ON(i >= npages); for (j = 0; j < npages_this_entry; j++) { @@ -80,14 +80,14 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, for_each_sg(table->sgl, sg, table->nents, i) { struct page *page = sg_page(sg); unsigned long remainder = vma->vm_end - addr; - unsigned long len = sg_dma_len(sg); + unsigned long len = sg->length; - if (offset >= sg_dma_len(sg)) { - offset -= sg_dma_len(sg); + if (offset >= sg->length) { + offset -= sg->length; continue; } else if (offset) { page += offset / PAGE_SIZE; - len = sg_dma_len(sg) - offset; + len = sg->length - offset; offset = 0; } len = min(len, remainder); @@ -119,7 +119,7 @@ int ion_heap_buffer_zero(struct ion_buffer *buffer) for_each_sg(table->sgl, sg, table->nents, i) { struct page *page = sg_page(sg); - unsigned long len = sg_dma_len(sg); + unsigned long len = sg->length; for (j = 0; j < len / PAGE_SIZE; j++) { struct page *sub_page = page + j; diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 7e00f51292e1..b052ff6bf383 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -34,13 +34,8 @@ static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool) if (!page) return NULL; - /* this is only being used to flush the page for dma, - this api is not really suitable for calling from a driver - but no better way to flush a page for dma exist at this time */ - arm_dma_ops.sync_single_for_device(NULL, - pfn_to_dma(NULL, page_to_pfn(page)), - PAGE_SIZE << pool->order, - DMA_BIDIRECTIONAL); + ion_pages_sync_for_device(NULL, page, PAGE_SIZE << pool->order, + DMA_BIDIRECTIONAL); return page; } diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 0ccf409cde7d..ea87b54987e7 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -17,6 +17,7 @@ #ifndef _ION_PRIV_H #define _ION_PRIV_H +#include <linux/dma-direction.h> #include <linux/kref.h> #include <linux/mm_types.h> #include <linux/mutex.h> @@ -357,4 +358,15 @@ void ion_page_pool_free(struct ion_page_pool *, struct page *); int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, int nr_to_scan); +/** + * ion_pages_sync_for_device - cache flush pages for use with the specified + * device + * @dev: the device the pages will be used with + * @page: the first page to be flushed + * @size: size in bytes of region to be flushed + * @dir: direction of dma transfer + */ +void ion_pages_sync_for_device(struct device *dev, struct page *page, + size_t size, enum dma_data_direction dir); + #endif /* _ION_PRIV_H */ diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 06e0702396a4..ecae16f2109a 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -77,9 +77,8 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, page = ion_heap_alloc_pages(buffer, gfp_flags, order); if (!page) return 0; - arm_dma_ops.sync_single_for_device(NULL, - pfn_to_dma(NULL, page_to_pfn(page)), - PAGE_SIZE << order, DMA_BIDIRECTIONAL); + ion_pages_sync_for_device(NULL, page, PAGE_SIZE << order, + DMA_BIDIRECTIONAL); } if (!page) return 0; @@ -210,7 +209,7 @@ void ion_system_heap_free(struct ion_buffer *buffer) for_each_sg(table->sgl, sg, table->nents, i) free_buffer_page(sys_heap, buffer, sg_page(sg), - get_order(sg_dma_len(sg))); + get_order(sg->length)); sg_free_table(table); kfree(table); } |