Ion module: version1.0
authorkfx <kfx@rock-chips.com>
Mon, 26 Mar 2012 01:30:42 +0000 (09:30 +0800)
committerkfx <kfx@rock-chips.com>
Mon, 26 Mar 2012 01:30:42 +0000 (09:30 +0800)
drivers/gpu/ion/ion.c
drivers/gpu/ion/ion_carveout_heap.c
drivers/gpu/ion/ion_priv.h
drivers/gpu/ion/ion_system_heap.c
drivers/gpu/ion/ion_system_mapper.c
drivers/gpu/ion/rockchip/rockchip_ion.c
include/linux/ion.h

index 90316b5613aa0be32331ca38399c115feb477474..abf2dbe884faf6a90c255b86b13b2c8b4ae3fe04 100755 (executable)
@@ -29,7 +29,6 @@
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
 #include <linux/debugfs.h>
-#include <linux/android_pmem.h>
 #include <linux/dma-mapping.h>
 #include <asm/cacheflush.h>
 #include "ion_priv.h"
@@ -156,8 +155,8 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
        }
        buffer->dev = dev;
        buffer->size = len;
-       buffer->flags = flags;
        mutex_init(&buffer->lock);
+       INIT_LIST_HEAD(&buffer->map_addr);
        ion_buffer_add(dev, buffer);
        return buffer;
 }
@@ -328,7 +327,9 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
 
        mutex_lock(&client->lock);
        ion_handle_add(client, handle);
+       buffer->pid = client->pid;
        mutex_unlock(&client->lock);
+
        return handle;
 
 end:
@@ -808,6 +809,7 @@ static void ion_vma_close(struct vm_area_struct *vma)
        struct ion_handle *handle = vma->vm_private_data;
        struct ion_buffer *buffer = vma->vm_file->private_data;
        struct ion_client *client;
+       struct ion_user_map_addr *map = NULL;
 
        pr_debug("%s: %d\n", __func__, __LINE__);
        /* this indicates the client is gone, nothing to do here */
@@ -826,6 +828,11 @@ static void ion_vma_close(struct vm_area_struct *vma)
                 atomic_read(&client->ref.refcount),
                 atomic_read(&handle->ref.refcount),
                 atomic_read(&buffer->ref.refcount));
+       list_for_each_entry(map, &buffer->map_addr, list)
+               if(map->vaddr == vma->vm_start){
+                       list_del(&map->list);
+                       break;
+               }
 }
 
 static struct vm_operations_struct ion_vm_ops = {
@@ -840,9 +847,7 @@ static int ion_share_mmap(struct file *file, struct vm_area_struct *vma)
        struct ion_client *client;
        struct ion_handle *handle;
        int ret;
-       unsigned long flags = file->f_flags & O_DSYNC ?
-                               ION_SET_CACHE(UNCACHED) :
-                               ION_SET_CACHE(CACHED);
+       struct ion_user_map_addr *map = NULL;
 
        pr_debug("%s: %d\n", __func__, __LINE__);
        /* make sure the client still exists, it's possible for the client to
@@ -879,7 +884,7 @@ static int ion_share_mmap(struct file *file, struct vm_area_struct *vma)
 
        mutex_lock(&buffer->lock);
        /* now map it to userspace */
-       ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma, flags);
+       ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma);
        mutex_unlock(&buffer->lock);
        if (ret) {
                pr_err("%s: failure mapping buffer to userspace\n",
@@ -891,11 +896,19 @@ static int ion_share_mmap(struct file *file, struct vm_area_struct *vma)
        /* move the handle into the vm_private_data so we can access it from
           vma_open/close */
        vma->vm_private_data = handle;
+
+       map = kzalloc(sizeof(struct ion_user_map_addr), GFP_KERNEL);
+       if(!map)
+               goto err1;
+       map->vaddr = vma->vm_start;
+       map->size = buffer->size;
+       list_add_tail(&map->list, &buffer->map_addr);
        pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n",
                 __func__, __LINE__,
                 atomic_read(&client->ref.refcount),
                 atomic_read(&handle->ref.refcount),
                 atomic_read(&buffer->ref.refcount));
+
        return 0;
 
 err1:
@@ -907,33 +920,37 @@ err:
        return ret;
 }
 
+/* Compatible with pmem */
 static long ion_share_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        struct ion_buffer *buffer = filp->private_data;
-
+       
        switch (cmd) {
-       case PMEM_GET_PHYS:
+       case ION_PMEM_GET_PHYS:
        {
-               struct pmem_region region;
+               struct ion_pmem_region region;
                region.offset = buffer->priv_phys;
                region.len = buffer->size;
 
                if (copy_to_user((void __user *)arg, &region,
-                               sizeof(struct pmem_region)))
+                               sizeof(struct ion_pmem_region)))
                        return -EFAULT;
                break;
        }
-       case PMEM_CACHE_FLUSH:
+       case ION_PMEM_CACHE_FLUSH:
        {
-               struct pmem_region region;
+               struct ion_pmem_region region;
+                struct ion_user_map_addr *map = NULL;
                if (copy_from_user(&region, (void __user *)arg,
-                               sizeof(struct pmem_region)))
+                               sizeof(struct ion_pmem_region)))
                        return -EFAULT;
-                if(!(region.offset & 0xf0000000))
-                        region.offset = buffer->vm_start;
-
-               dmac_flush_range((void *)region.offset, (void *)(region.offset + region.len));
-
+                if(!(region.offset & 0xf0000000)) {
+                        list_for_each_entry(map, &buffer->map_addr, list) {
+                               dmac_flush_range((void *)map->vaddr, (void *)(map->vaddr + map->size));
+                        }
+                }else {
+                       dmac_flush_range((void *)region.offset, (void *)(region.offset + region.len));
+                }
                break;
        }
        default:
@@ -965,7 +982,7 @@ static int ion_ioctl_share(struct file *parent, struct ion_client *client,
 
        if (parent->f_flags & O_DSYNC)
                file->f_flags |= O_DSYNC;
-
+       
        ion_buffer_get(handle->buffer);
        fd_install(fd, file);
 
@@ -984,15 +1001,15 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        case ION_IOC_ALLOC:
        {
                struct ion_allocation_data data;
-
                if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
                        return -EFAULT;
+
                data.handle = ion_alloc(client, data.len, data.align,
                                             data.flags);
                if (IS_ERR_OR_NULL(data.handle)) {
-                       printk("%s: alloc 0x%x bytes failed\n", __func__, data.len);
-                       return -ENOMEM;
-               }
+                       pr_err("%s: alloc 0x%x bytes failed\n", __func__, data.len);
+            return -ENOMEM;
+               } 
                if (copy_to_user((void __user *)arg, &data, sizeof(data)))
                        return -EFAULT;
                break;
@@ -1017,6 +1034,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        case ION_IOC_SHARE:
        {
                struct ion_fd_data data;
+
                if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
                        return -EFAULT;
                mutex_lock(&client->lock);
@@ -1061,89 +1079,124 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        return -EFAULT;
                return dev->custom_ioctl(client, data.cmd, data.arg);
        }
-       case ION_GET_PHYS:
+       case ION_CUSTOM_GET_PHYS:
        {
                int err = 0;
                struct ion_phys_data data;
+               
                if (copy_from_user(&data, (void __user *)arg,
-                                  sizeof(struct ion_phys_data)))
+                               sizeof(struct ion_phys_data)))
                        return -EFAULT;
-               err = ion_phys(client, data.handle, &data.phys, &data.size);
-               if(err < 0){
+               err = ion_phys(client, data.handle, &data.phys, (size_t *)&data.size);
+               if(err < 0)
                        return err;
-               }
                if (copy_to_user((void __user *)arg, &data,
-                                sizeof(struct ion_phys_data)))
+                               sizeof(struct ion_phys_data)))
                        return -EFAULT;
                break;
        }
-       case ION_CACHE_FLUSH:
-       case ION_CACHE_CLEAN:
-       case ION_CACHE_INVALID:
+       case ION_CUSTOM_CACHE_OP:
        {
-               int err = 0;
-               bool valid;
+               struct ion_cacheop_data data;
                struct ion_buffer *buffer;
-               struct ion_flush_data data;
+               int err = -EINVAL;
+               
                if (copy_from_user(&data, (void __user *)arg,
-                                  sizeof(struct ion_flush_data)))
+                               sizeof(struct ion_cacheop_data)))
                        return -EFAULT;
                mutex_lock(&client->lock);
-               valid = ion_handle_validate(client, data.handle);
-               if (!valid){
-                   mutex_unlock(&client->lock);
-                       return -EINVAL;
-        }
-               buffer = data.handle->buffer;
-               if (!buffer->heap->ops->cache_op) {
-                       pr_err("%s: cache_op is not implemented by this heap.\n",
-                      __func__);
-                       err = -ENODEV;
-                       mutex_unlock(&client->lock);
-                       return err;
+               if(ion_handle_validate(client, data.handle)){
+                       buffer = data.handle->buffer;
+                       if(buffer->heap->ops->cache_op){
+                               buffer->heap->ops->cache_op(buffer->heap, buffer, data.virt, data.type);
+                               err = 0;
+                       }
                }
-
-               err = data.handle->buffer->heap->ops->cache_op(buffer->heap, buffer,
-                       data.virt, data.size, cmd);
                mutex_unlock(&client->lock);
-               if(err < 0)
-                       return err;
                break;
        }
-        case ION_GET_CLIENT:
-        {
-                struct ion_handle *handle;
-               struct ion_client_data data;
-                struct rb_node *n;
+       case ION_CUSTOM_GET_CLIENT_INFO:
+       {
+               struct rb_node *n;
+               struct ion_client_info info;
+#if 0
+               int i;
 
-               if (copy_from_user(&data, (void __user *)arg,
-                                  sizeof(struct ion_client_data)))
+               mutex_lock(&client->lock);
+               info.total_size = 0;
+               info.count = atomic_read(&client->ref.refcount);
+               if(info.count > MAX_BUFFER_COUNT){
+                       pr_err("%s: buffer count(%u) ge MAX_BUFFER_COUNT(%d)\n",
+                               __func__, info.count, MAX_BUFFER_COUNT);
+                       mutex_unlock(&client->lock);
                        return -EFAULT;
+               }
+               for (i = 0, n = rb_first(&client->handles); n; i++, n = rb_next(n)) {
+                       struct ion_handle *handle = rb_entry(n, struct ion_handle,
+                                                    node);
+                       info.buf[i].phys = handle->buffer->priv_phys;
+                       info.buf[i].size = handle->buffer->size;
+                       info.total_size += handle->buffer->size;
 
+               }
+#else
                mutex_lock(&client->lock);
-                switch (data.type) {
-                        case ION_TYPE_GET_TOTAL_SIZE:
-                                data.total_size = 0;
-                               for (n = rb_first(&client->handles); n; n = rb_next(n)) {
-                                       handle = rb_entry(n, struct ion_handle, node);
-                                        data.total_size += handle->buffer->size;
-                                }
-                                break;
-                        case ION_TYPE_SIZE_GET_COUNT:
-                                data.count = 0;
-                               for (n = rb_first(&client->handles); n; n = rb_next(n)) {
-                                       handle = rb_entry(n, struct ion_handle, node);
-                                        if(handle->buffer->size == data.size)
-                                                data.count++;
-                                }
-                                break;
-                }
+               info.total_size = 0;
+               info.count = 0;
+               for (n = rb_first(&client->dev->buffers); n; n = rb_next(n)) {
+                       struct ion_buffer *buf = rb_entry(n, struct ion_buffer,
+                                                    node);
+
+                       if(info.count > MAX_BUFFER_COUNT){
+                               pr_err("%s: buffer count(%u) ge MAX_BUFFER_COUNT(%d)\n",
+                                       __func__, info.count, MAX_BUFFER_COUNT);
+                               mutex_unlock(&client->lock);
+                               return -EFAULT;
+                       }
+                       if(buf->pid == client->pid) {
+                               info.buf[info.count].phys = buf->priv_phys;
+                               info.buf[info.count].size = buf->size;
+                               info.total_size += buf->size;
+                               info.count++;
+                       }
+               }
+#endif
                mutex_unlock(&client->lock);
-               if (copy_to_user((void __user *)arg, &data,
-                                sizeof(struct ion_client_data)))
+               if (copy_to_user((void __user *)arg, &info,
+                               sizeof(struct ion_client_info)))
+                       return -EFAULT;
+               break;
+       }
+       case ION_CUSTOM_GET_HEAP_INFO:
+       {
+               struct rb_node *n;
+               struct ion_heap_info info;
+               struct ion_heap *heap = NULL;
+               int err = -EINVAL;
+               
+               if (copy_from_user(&info, (void __user *)arg,
+                               sizeof(struct ion_heap_info)))
                        return -EFAULT;
-                break;
-        }
+               mutex_lock(&client->dev->lock);
+               for (n = rb_first(&client->dev->heaps); n != NULL; n = rb_next(n)) {
+                       heap = rb_entry(n, struct ion_heap, node);
+
+                       if(heap->id == info.id){
+                               info.allocated_size = heap->allocated_size;
+                               info.max_allocated = heap->max_allocated;
+                               info.total_size = heap->total_size;
+
+                               err = 0;
+                       }
+                               
+               }
+               mutex_unlock(&client->dev->lock);
+
+               if (copy_to_user((void __user *)arg, &info,
+                               sizeof(struct ion_heap_info)))
+                       err = -EFAULT;
+               break;
+       }
        default:
                return -ENOTTY;
        }
@@ -1284,7 +1337,7 @@ static int ion_debug_leak_show(struct seq_file *s, void *unused)
        struct rb_node *n2;
 
        /* mark all buffers as 1 */
-       seq_printf(s, "%16.s %16.s %16.s %16.s\n", "buffer", "heap", "size(K)",
+       seq_printf(s, "%16.s %16.s %16.s %16.s %16.s\n", "pid", "buffer", "heap", "size(K)",
                "ref_count");
        mutex_lock(&dev->lock);
        for (n = rb_first(&dev->buffers); n; n = rb_next(n)) {
@@ -1332,8 +1385,8 @@ static int ion_debug_leak_show(struct seq_file *s, void *unused)
                                                     node);
 
                if (buf->marked == 1)
-                       seq_printf(s, "%16.x %16.s %16.d %16.d\n",
-                               (int)buf, buf->heap->name, buf->size/SZ_1K,
+                       seq_printf(s, "%16.u %16.x %16.s %16.d %16.d\n",
+                               buf->pid, (int)buf, buf->heap->name, buf->size/SZ_1K,
                                atomic_read(&buf->ref.refcount));
        }
        mutex_unlock(&dev->lock);
@@ -1351,7 +1404,6 @@ static const struct file_operations debug_leak_fops = {
        .llseek = seq_lseek,
        .release = single_release,
 };
-
 struct ion_device *ion_device_create(long (*custom_ioctl)
                                     (struct ion_client *client,
                                      unsigned int cmd,
index 38080f12aee52fba593b12e4075f1f42afb42225..76aaa3b6f8e90f903a499401e1d3baedaf1b1d08 100755 (executable)
@@ -13,8 +13,8 @@
  * GNU General Public License for more details.
  *
  */
-#include <linux/spinlock.h>
 
+ #include <linux/spinlock.h>
 #include <linux/err.h>
 #include <linux/genalloc.h>
 #include <linux/io.h>
 #include <linux/vmalloc.h>
 #include <linux/iommu.h>
 #include <linux/seq_file.h>
+#include <asm/mach/map.h>
 #include <linux/dma-mapping.h>
 #include <asm/cacheflush.h>
 #include "ion_priv.h"
 
-#include <asm/mach/map.h>
-
-#define RESERVED_SIZE(total)   ((total)/10)
-
 struct ion_carveout_heap {
        struct ion_heap heap;
        struct gen_pool *pool;
        ion_phys_addr_t base;
-       unsigned long allocated_bytes;
-       unsigned long vpu_allocated_bytes;
-       unsigned long max_allocated;
-       unsigned long total_size;
        unsigned long bit_nr;
        unsigned long *bits;
 };
-
 ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap,
                                      unsigned long size,
-                                     unsigned long align,
-                                     unsigned long flags)
+                                     unsigned long align)
 {
        struct ion_carveout_heap *carveout_heap =
                container_of(heap, struct ion_carveout_heap, heap);
-       unsigned long offset;
-       unsigned long free_size = carveout_heap->total_size - carveout_heap->allocated_bytes;
-
-       if ((flags & (1<<ION_VPU_ID)) &&
-               (free_size < RESERVED_SIZE(carveout_heap->total_size))) {
-               printk("%s: heap %s has not enough memory for vpu: vpu allocated(%luM)\n",
-                       __func__, heap->name, carveout_heap->vpu_allocated_bytes/SZ_1M);
-               return ION_CARVEOUT_ALLOCATE_FAIL;
-       }
-       offset = gen_pool_alloc(carveout_heap->pool, size);
+       unsigned long offset = gen_pool_alloc(carveout_heap->pool, size);
 
        if (!offset) {
-               if ((carveout_heap->total_size -
-                     carveout_heap->allocated_bytes) > size)
+               if ((heap->total_size - heap->allocated_size) > size)
                        printk("%s: heap %s has enough memory (%luK) but"
-                               " the allocation of size %lu pages still failed."
+                               " the allocation of size(%luK) still failed."
                                " Memory is probably fragmented.\n",
                                __func__, heap->name,
-                               (carveout_heap->total_size - carveout_heap->allocated_bytes)/SZ_1K,
+                               (heap->total_size - heap->allocated_size)/SZ_1K, 
                                size/SZ_1K);
                else
                        printk("%s: heap %s has not enough memory(%luK)"
                                "the alloction of size is %luK.\n",
                                __func__, heap->name,
-                               (carveout_heap->total_size - carveout_heap->allocated_bytes)/SZ_1K,
+                               (heap->total_size - heap->allocated_size)/SZ_1K, 
                                size/SZ_1K);
                return ION_CARVEOUT_ALLOCATE_FAIL;
        }
 
-       if(flags & (1<<ION_VPU_ID))
-               carveout_heap->vpu_allocated_bytes += size;
-       carveout_heap->allocated_bytes += size;
+       heap->allocated_size += size;
 
-       if((offset + size - carveout_heap->base) > carveout_heap->max_allocated)
-               carveout_heap->max_allocated = offset + size - carveout_heap->base;
+       if((offset + size - carveout_heap->base) > heap->max_allocated)
+               heap->max_allocated = offset + size - carveout_heap->base;
 
-       bitmap_set(carveout_heap->bits,
+       bitmap_set(carveout_heap->bits, 
                (offset - carveout_heap->base)/PAGE_SIZE , size/PAGE_SIZE);
        return offset;
 }
 
 void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr,
-                      unsigned long size, unsigned long flags)
+                      unsigned long size)
 {
        struct ion_carveout_heap *carveout_heap =
                container_of(heap, struct ion_carveout_heap, heap);
@@ -102,10 +81,9 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr,
        if (addr == ION_CARVEOUT_ALLOCATE_FAIL)
                return;
        gen_pool_free(carveout_heap->pool, addr, size);
-       if(flags & (1<<ION_VPU_ID))
-               carveout_heap->vpu_allocated_bytes -= size;
-       carveout_heap->allocated_bytes -= size;
-       bitmap_clear(carveout_heap->bits,
+
+       heap->allocated_size -= size;
+       bitmap_clear(carveout_heap->bits, 
                (addr - carveout_heap->base)/PAGE_SIZE, size/PAGE_SIZE);
 }
 
@@ -123,7 +101,7 @@ static int ion_carveout_heap_allocate(struct ion_heap *heap,
                                      unsigned long size, unsigned long align,
                                      unsigned long flags)
 {
-       buffer->priv_phys = ion_carveout_allocate(heap, size, align, flags);
+       buffer->priv_phys = ion_carveout_allocate(heap, size, align);
        return buffer->priv_phys == ION_CARVEOUT_ALLOCATE_FAIL ? -ENOMEM : 0;
 }
 
@@ -131,7 +109,7 @@ static void ion_carveout_heap_free(struct ion_buffer *buffer)
 {
        struct ion_heap *heap = buffer->heap;
 
-       ion_carveout_free(heap, buffer->priv_phys, buffer->size, buffer->flags);
+       ion_carveout_free(heap, buffer->priv_phys, buffer->size);
        buffer->priv_phys = ION_CARVEOUT_ALLOCATE_FAIL;
 }
 
@@ -163,52 +141,58 @@ void ion_carveout_heap_unmap_kernel(struct ion_heap *heap,
 }
 
 int ion_carveout_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
-                              struct vm_area_struct *vma, unsigned long flags)
+                              struct vm_area_struct *vma)
 {
-       int err = 0;
-       if (ION_IS_CACHED(flags))
-               err = remap_pfn_range(vma, vma->vm_start,
+       return remap_pfn_range(vma, vma->vm_start,
                               __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff,
-                              vma->vm_end - vma->vm_start,
-                              vma->vm_page_prot);
-       else
-               err = remap_pfn_range(vma, vma->vm_start,
-                              __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff,
-                                       vma->vm_end - vma->vm_start,
-                                       pgprot_noncached(vma->vm_page_prot));
-
-        buffer->vm_start = vma->vm_start;
-       return err;
+                              buffer->size,
+                                       vma->vm_page_prot);
 }
-
 int ion_carveout_cache_op(struct ion_heap *heap, struct ion_buffer *buffer,
-                       void *virt, size_t size, unsigned int cmd)
+                       void *virt, unsigned int type)
 {
-       unsigned long start, end;
-
-       start = (unsigned long)virt;
-       end = start + size;
-       switch(cmd) {
-               case ION_CACHE_FLUSH:
-                       dmac_flush_range((void *)start, (void *)end);
-                       outer_flush_range(buffer->priv_phys,buffer->priv_phys + size);
-                       break;
-               case ION_CACHE_CLEAN:
-            /* When cleaning, always clean the innermost (L1) cache first
-             * and then clean the outer cache(s).
-             */
-                       dmac_clean_range((void *)start, (void *)end);
-                       outer_clean_range(buffer->priv_phys,buffer->priv_phys + size);
+       unsigned long phys_start = 0, phys_end = 0;
+       void *virt_start = NULL, *virt_end = NULL;
+       struct ion_user_map_addr *map = NULL;
+
+        if(!buffer)
+                return -EINVAL;
+       phys_start = buffer->priv_phys;
+       phys_end = buffer->priv_phys + buffer->size;
+       
+       list_for_each_entry(map, &buffer->map_addr, list) {
+               if(map->vaddr == (unsigned long)virt){
+                       virt_start = virt;
+                       virt_end = (void *)((unsigned long)virt + map->size);
                        break;
-               case ION_CACHE_INVALID:
-            /* When invalidating, always invalidate the outermost cache first
-             * and the L1 cache last.
-             */
-                       outer_inv_range(buffer->priv_phys,buffer->priv_phys + size);
-                       dmac_inv_range((void *)start, (void *)end);
-                       break;
-               default:
-                       return -EINVAL;
+               }
+       }
+       if(!virt_start){
+               pr_err("%s: virt(%p) has not been maped or has been unmaped\n",
+                       __func__, virt);
+               return -EINVAL;
+       }
+       switch(type) {
+       case ION_CACHE_FLUSH:
+               dmac_flush_range(virt_start, virt_end);
+               outer_flush_range(phys_start,phys_end); 
+               break;
+       case ION_CACHE_CLEAN:
+               /* When cleaning, always clean the innermost (L1) cache first 
+               * and then clean the outer cache(s).
+               */
+               dmac_clean_range(virt_start, virt_end);
+               outer_clean_range(phys_start,phys_end); 
+               break;
+       case ION_CACHE_INV:
+               /* When invalidating, always invalidate the outermost cache first 
+               * and the L1 cache last.
+               */
+               outer_inv_range(phys_start,phys_end); 
+               dmac_inv_range(virt_start, virt_end);
+               break;
+       default:
+               return -EINVAL;
        }
        return 0;
 }
@@ -220,7 +204,7 @@ static int ion_carveout_print_debug(struct ion_heap *heap, struct seq_file *s)
                container_of(heap, struct ion_carveout_heap, heap);
 
        for(i = carveout_heap->bit_nr/8 - 1; i>= 0; i--){
-               seq_printf(s, "%.3uM> Bits[%.3d - %.3d]: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+               seq_printf(s, "%.3uM> Bits[%.3d - %.3d]: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", 
                                i+1, i*8 + 7, i*8,
                                carveout_heap->bits[i*8 + 7],
                                carveout_heap->bits[i*8 + 6],
@@ -231,17 +215,14 @@ static int ion_carveout_print_debug(struct ion_heap *heap, struct seq_file *s)
                                carveout_heap->bits[i*8 + 1],
                                carveout_heap->bits[i*8]);
        }
-       seq_printf(s, "VPU allocated: %luM\n",
-               carveout_heap->vpu_allocated_bytes/SZ_1M);
        seq_printf(s, "Total allocated: %luM\n",
-               carveout_heap->allocated_bytes/SZ_1M);
+               heap->allocated_size/SZ_1M);
        seq_printf(s, "max_allocated: %luM\n",
-               carveout_heap->max_allocated/SZ_1M);
-       seq_printf(s, "Heap size: %luM, heap base: 0x%lx\n",
-               carveout_heap->total_size/SZ_1M, carveout_heap->base);
+               heap->max_allocated/SZ_1M);
+       seq_printf(s, "Heap size: %luM, heap base: 0x%lx\n", 
+               heap->total_size/SZ_1M, carveout_heap->base);
        return 0;
 }
-
 static struct ion_heap_ops carveout_heap_ops = {
        .allocate = ion_carveout_heap_allocate,
        .free = ion_carveout_heap_free,
@@ -271,12 +252,11 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
                     -1);
        carveout_heap->heap.ops = &carveout_heap_ops;
        carveout_heap->heap.type = ION_HEAP_TYPE_CARVEOUT;
-       carveout_heap->vpu_allocated_bytes = 0;
-       carveout_heap->allocated_bytes = 0;
-       carveout_heap->max_allocated = 0;
-       carveout_heap->total_size = heap_data->size;
+       carveout_heap->heap.allocated_size = 0;
+       carveout_heap->heap.max_allocated = 0;
+       carveout_heap->heap.total_size = heap_data->size;
        carveout_heap->bit_nr = heap_data->size/(PAGE_SIZE * sizeof(unsigned long) * 8);
-       carveout_heap->bits =
+       carveout_heap->bits = 
                (unsigned long *)kzalloc(carveout_heap->bit_nr * sizeof(unsigned long), GFP_KERNEL);
 
        return &carveout_heap->heap;
index 75b1e753628e7684891dcb8b3d6d3aace85ad5d7..3dbe298e114932fcf4079b3f11c20f7abf310eec 100755 (executable)
@@ -26,6 +26,7 @@
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
 #include <linux/debugfs.h>
+#include <linux/list.h>
 
 struct ion_mapping;
 
@@ -39,6 +40,11 @@ struct ion_kernel_mapping {
        void *vaddr;
 };
 
+struct ion_user_map_addr {
+       unsigned long vaddr;
+       unsigned long size;
+       struct list_head list;
+};
 struct ion_buffer *ion_handle_buffer(struct ion_handle *handle);
 
 /**
@@ -75,7 +81,8 @@ struct ion_buffer {
        void *vaddr;
        int dmap_cnt;
        struct scatterlist *sglist;
-       unsigned long vm_start;
+        struct list_head map_addr;
+       pid_t pid;
        int marked;
 };
 
@@ -104,9 +111,9 @@ struct ion_heap_ops {
        void * (*map_kernel) (struct ion_heap *heap, struct ion_buffer *buffer);
        void (*unmap_kernel) (struct ion_heap *heap, struct ion_buffer *buffer);
        int (*map_user) (struct ion_heap *mapper, struct ion_buffer *buffer,
-                        struct vm_area_struct *vma, unsigned long flags);
+                        struct vm_area_struct *vma);
        int (*cache_op)(struct ion_heap *heap, struct ion_buffer *buffer,
-                       void *virt, size_t size, unsigned int cmd);
+                       void *virt, unsigned int type);
        int (*print_debug)(struct ion_heap *heap, struct seq_file *s);
 };
 
@@ -133,6 +140,10 @@ struct ion_heap {
        struct ion_heap_ops *ops;
        int id;
        const char *name;
+
+       unsigned long allocated_size;
+       unsigned long max_allocated;
+       unsigned long total_size;
 };
 
 /**
@@ -181,9 +192,9 @@ void ion_carveout_heap_destroy(struct ion_heap *);
  * used to back an architecture specific custom heap
  */
 ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, unsigned long size,
-                                     unsigned long align, unsigned long flags);
+                                     unsigned long align);
 void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr,
-                      unsigned long size, unsigned long flags);
+                      unsigned long size);
 /**
  * The carveout heap returns physical addresses, since 0 may be a valid
  * physical address, this is used to indicate allocation failed
index 2756f3054ec2b7ac43abb2efc4bdf8377e10f28a..c046cf1a32199022c9f77838a29d0caa4599385e 100755 (executable)
@@ -86,7 +86,7 @@ void ion_system_heap_unmap_kernel(struct ion_heap *heap,
 }
 
 int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
-                            struct vm_area_struct *vma, unsigned long flags)
+                            struct vm_area_struct *vma)
 {
        return remap_vmalloc_range(vma, buffer->priv_virt, vma->vm_pgoff);
 }
@@ -159,8 +159,7 @@ struct scatterlist *ion_system_contig_heap_map_dma(struct ion_heap *heap,
 
 int ion_system_contig_heap_map_user(struct ion_heap *heap,
                                    struct ion_buffer *buffer,
-                                   struct vm_area_struct *vma,
-                                   unsigned long flags)
+                                   struct vm_area_struct *vma)
 {
        unsigned long pfn = __phys_to_pfn(virt_to_phys(buffer->priv_virt));
        return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff,
index 0a1fc49a80c739d57095c0e9833eec5c94c9147d..692458e07b5e8b8b29e7d9a023159bcd70bd3c06 100755 (executable)
@@ -63,8 +63,7 @@ static void *ion_kernel_mapper_map_kernel(struct ion_mapper *mapper,
 static int ion_kernel_mapper_map_user(struct ion_mapper *mapper,
                                      struct ion_buffer *buffer,
                                      struct vm_area_struct *vma,
-                                     struct ion_mapping *mapping,
-                                     unsigned long flags)
+                                     struct ion_mapping *mapping)
 {
        int ret;
 
index 3e8f86745e28b9b1dcfacf5d5c3e47ea2f41ccb8..1fa448688fde47c0775dafde5b23d5b00b5b5cea 100755 (executable)
@@ -55,6 +55,7 @@ static int rockchip_ion_probe(struct platform_device *pdev)
                ion_device_add_heap(idev, heaps[i]);
        }
        platform_set_drvdata(pdev, idev);
+        pr_info("Rockchip ion module(version: %s) is successfully loaded\n", ION_VERSION);
        return 0;
 err:
        for (i = 0; i < num_heaps; i++) {
index da979c28eb5358231b5f231a23f3f1f18297c43b..1e94610735ae55d242d75496ec235254119fcb5f 100755 (executable)
 #define _LINUX_ION_H
 
 #include <linux/types.h>
+#define ION_VERSION     "1.0"
 
-
-#define CACHED          1
-#define UNCACHED        0
-
-#define ION_CACHE_SHIFT 0
-
-#define ION_SET_CACHE(__cache)  ((__cache) << ION_CACHE_SHIFT)
-
-#define ION_IS_CACHED(__flags) ((__flags) & (1 << ION_CACHE_SHIFT))
 struct ion_handle;
 /**
  * enum ion_heap_types - list of all possible types of heaps
@@ -305,24 +297,31 @@ struct ion_custom_data {
 struct ion_phys_data {
        struct ion_handle *handle;
        unsigned long phys;
-       size_t size;
+       unsigned long size;
 };
-
-struct ion_flush_data {
+struct ion_cacheop_data {
+#define ION_CACHE_FLUSH                0
+#define ION_CACHE_CLEAN                1
+#define ION_CACHE_INV          2
+       unsigned int type;
        struct ion_handle *handle;
        void *virt;
-       size_t size;
 };
-
-struct ion_client_data {
-#define ION_TYPE_GET_TOTAL_SIZE  0
-#define ION_TYPE_SIZE_GET_COUNT  1
-       unsigned int type;
-       union {
-               size_t size;
-               size_t total_size;
-       };
+struct ion_buffer_info {
+       unsigned long phys;
+       unsigned long size;
+};
+struct ion_client_info {
+#define MAX_BUFFER_COUNT       127
        unsigned int count;
+       unsigned long total_size;
+       struct ion_buffer_info buf[MAX_BUFFER_COUNT];
+};
+struct ion_heap_info {
+       unsigned int id;
+       unsigned long allocated_size;
+       unsigned long max_allocated;
+       unsigned long total_size;
 };
 
 #define ION_IOC_MAGIC          'I'
@@ -379,11 +378,24 @@ struct ion_client_data {
  * Takes the argument of the architecture specific ioctl to call and
  * passes appropriate userdata for that ioctl
  */
-#define ION_IOC_CUSTOM         _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data)
-#define ION_CACHE_FLUSH                _IOWR(ION_IOC_MAGIC, 7, struct ion_flush_data)
-#define ION_CACHE_CLEAN                _IOWR(ION_IOC_MAGIC, 8, struct ion_flush_data)
-#define ION_CACHE_INVALID      _IOWR(ION_IOC_MAGIC, 9, struct ion_flush_data)
-#define ION_GET_PHYS           _IOWR(ION_IOC_MAGIC, 10, unsigned long)
-#define ION_GET_CLIENT         _IOWR(ION_IOC_MAGIC, 11, struct ion_client_data)
-
+#define ION_IOC_CUSTOM                 _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data)
+
+#define ION_CUSTOM_GET_PHYS            _IOWR(ION_IOC_MAGIC, 7, \
+                                               struct ion_phys_data)
+                                     
+#define ION_CUSTOM_CACHE_OP            _IOWR(ION_IOC_MAGIC, 8, \
+                                               struct ion_cacheop_data)                                     
+
+#define ION_CUSTOM_GET_CLIENT_INFO     _IOWR(ION_IOC_MAGIC, 9, \
+                                               struct ion_client_info) 
+
+#define ION_CUSTOM_GET_HEAP_INFO       _IOWR(ION_IOC_MAGIC, 10, \
+                                               struct ion_heap_info) 
+/* Compatible with pmem */
+struct ion_pmem_region {
+       unsigned long offset;
+       unsigned long len;
+};
+#define ION_PMEM_GET_PHYS              _IOW('p', 1, unsigned int)
+#define ION_PMEM_CACHE_FLUSH           _IOW('p', 8, unsigned int)
 #endif /* _LINUX_ION_H */