aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2013-11-25 10:54:08 -0800
committerJohn Stultz <john.stultz@linaro.org>2013-11-25 10:54:08 -0800
commit2c6193b7527e92a5916e6f798ddf47401afa17c3 (patch)
treeb7a3efa93f354255d2466691da3b41c9df6e4b72 /drivers/staging
parent305a41042d6127e9596f66382bf4e81a70e24bb3 (diff)
parentf2ec29aa62924e6b1ce5edb3bfc7dcd206023740 (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.c19
-rw-r--r--drivers/staging/android/ion/ion.c84
-rw-r--r--drivers/staging/android/ion/ion_chunk_heap.c19
-rw-r--r--drivers/staging/android/ion/ion_heap.c12
-rw-r--r--drivers/staging/android/ion/ion_page_pool.c9
-rw-r--r--drivers/staging/android/ion/ion_priv.h12
-rw-r--r--drivers/staging/android/ion/ion_system_heap.c7
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);
}