gpu: ion: Add callbacks to enable SMI voting in ION.

This change is part of the move from PMEM to ION. ION needs an SMI
voting interface smiliar to PMEM's.

Change-Id: I18888f46198848694fb7e1e0d2671074bf51d7c9
Signed-off-by: Alex Bird <alexbird@codeaurora.org>
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index 71dea89..7c542b8 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -33,6 +33,10 @@
 	ion_phys_addr_t base;
 	unsigned long allocated_bytes;
 	unsigned long total_size;
+	void (*request_region)(void *);
+	void (*release_region)(void *);
+	atomic_t map_count;
+	void *bus_id;
 };
 
 ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap,
@@ -128,6 +132,12 @@
 				   struct ion_buffer *buffer,
 				   unsigned long flags)
 {
+	struct ion_carveout_heap *carveout_heap =
+		container_of(heap, struct ion_carveout_heap, heap);
+
+	if (atomic_inc_return(&carveout_heap->map_count) == 1)
+		carveout_heap->request_region(carveout_heap->bus_id);
+
 	if (ION_IS_CACHED(flags))
 		return ioremap_cached(buffer->priv_phys, buffer->size);
 	else
@@ -137,14 +147,27 @@
 void ion_carveout_heap_unmap_kernel(struct ion_heap *heap,
 				    struct ion_buffer *buffer)
 {
+	struct ion_carveout_heap *carveout_heap =
+		container_of(heap, struct ion_carveout_heap, heap);
+
 	__arch_iounmap(buffer->vaddr);
 	buffer->vaddr = NULL;
+
+	if (atomic_dec_and_test(&carveout_heap->map_count))
+		carveout_heap->release_region(carveout_heap->bus_id);
+
 	return;
 }
 
 int ion_carveout_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
 			       struct vm_area_struct *vma, unsigned long flags)
 {
+	struct ion_carveout_heap *carveout_heap =
+		container_of(heap, struct ion_carveout_heap, heap);
+
+	if (atomic_inc_return(&carveout_heap->map_count) == 1)
+		carveout_heap->request_region(carveout_heap->bus_id);
+
 	if (ION_IS_CACHED(flags))
 		return remap_pfn_range(vma, vma->vm_start,
 			       __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff,
@@ -157,6 +180,16 @@
 					pgprot_noncached(vma->vm_page_prot));
 }
 
+void ion_carveout_heap_unmap_user(struct ion_heap *heap,
+				    struct ion_buffer *buffer)
+{
+	struct ion_carveout_heap *carveout_heap =
+		container_of(heap, struct ion_carveout_heap, heap);
+
+	if (atomic_dec_and_test(&carveout_heap->map_count))
+		carveout_heap->release_region(carveout_heap->bus_id);
+}
+
 int ion_carveout_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer,
 			void *vaddr, unsigned int offset, unsigned int length,
 			unsigned int cmd)
@@ -205,6 +238,7 @@
 	.phys = ion_carveout_heap_phys,
 	.map_user = ion_carveout_heap_map_user,
 	.map_kernel = ion_carveout_heap_map_kernel,
+	.unmap_user = ion_carveout_heap_unmap_user,
 	.unmap_kernel = ion_carveout_heap_unmap_kernel,
 	.map_dma = ion_carveout_heap_map_dma,
 	.unmap_dma = ion_carveout_heap_unmap_dma,
@@ -238,6 +272,9 @@
 	carveout_heap->heap.type = ION_HEAP_TYPE_CARVEOUT;
 	carveout_heap->allocated_bytes = 0;
 	carveout_heap->total_size = heap_data->size;
+	carveout_heap->bus_id = heap_data->setup_region();
+	carveout_heap->request_region = heap_data->request_region;
+	carveout_heap->release_region = heap_data->release_region;
 
 	return &carveout_heap->heap;
 }
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index 888b599..ac51854 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -86,6 +86,7 @@
  * @map_kernel		map memory to the kernel
  * @unmap_kernel	unmap memory to the kernel
  * @map_user		map memory to userspace
+ * @unmap_user		unmap memory to userspace
  */
 struct ion_heap_ops {
 	int (*allocate) (struct ion_heap *heap,
@@ -102,6 +103,7 @@
 	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);
+	void (*unmap_user) (struct ion_heap *mapper, struct ion_buffer *buffer);
 	int (*cache_op)(struct ion_heap *heap, struct ion_buffer *buffer,
 			void *vaddr, unsigned int offset,
 			unsigned int length, unsigned int cmd);
diff --git a/include/linux/ion.h b/include/linux/ion.h
index 89ac992..a7f3de5 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -99,6 +99,11 @@
  * @name:	used for debug purposes
  * @base:	base address of heap in physical memory if applicable
  * @size:	size of the heap in bytes if applicable
+ * @request_region: function to be called when the number of allocations goes
+ *						from 0 -> 1
+ * @release_region: function to be called when the number of allocations goes
+ *						from 1 -> 0
+ * @setup_region:   function to be called upon ion registration
  *
  * Provided by the board file.
  */
@@ -109,6 +114,9 @@
 	ion_phys_addr_t base;
 	size_t size;
 	enum ion_memory_types memory_type;
+	void (*request_region)(void *);
+	void (*release_region)(void *);
+	void *(*setup_region)(void);
 };
 
 /**