board: 8960: Make the ion multimedia heap reusable
Mark the ion multimedia heap used by camera and video as
reusable. When no memory is allocated from this heap,
the pages are available for use by the system. The memory
is made available as soon as the first Ion allocation occurs.
Change-Id: I66df78d20e797647ca8b866d3fe60bd683742983
Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
Signed-off-by: Olav Haugan <ohaugan@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 3f58da8a..786ec01 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -301,10 +301,6 @@
#endif
}
-static void __init reserve_fmem_memory(void)
-{
-}
-
static int msm8960_paddr_to_memtype(unsigned int paddr)
{
return MEMTYPE_EBI1;
@@ -315,11 +311,13 @@
static struct ion_cp_heap_pdata cp_mm_ion_pdata = {
.permission_type = IPT_TYPE_MM_CARVEOUT,
.align = PAGE_SIZE,
+ .reusable = 1,
};
static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
.permission_type = IPT_TYPE_MFC_SHAREDMEM,
.align = PAGE_SIZE,
+ .reusable = 0,
};
static struct ion_co_heap_pdata co_ion_pdata = {
@@ -411,9 +409,8 @@
.dev = { .platform_data = &fmem_pdata },
};
-static void reserve_ion_memory(void)
+static void __init adjust_mem_for_liquid(void)
{
-#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
unsigned int i;
if (!pmem_param_set && machine_is_msm8960_liquid()) {
@@ -427,12 +424,99 @@
}
}
}
- msm8960_reserve_table[MEMTYPE_EBI1].size += msm_ion_cp_mm_size;
- msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_FW_SIZE;
- msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE;
- msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MFC_SIZE;
- msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_QSECOM_SIZE;
- msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE;
+}
+
+static void __init reserve_mem_for_ion(enum ion_memory_types mem_type,
+ unsigned long size)
+{
+ msm8960_reserve_table[mem_type].size += size;
+}
+
+static __init const struct ion_platform_heap *find_ion_heap(int heap_id)
+{
+ unsigned int i;
+ for (i = 0; i < ion_pdata.nr; ++i) {
+ const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+ if (heap->id == heap_id)
+ return (const struct ion_platform_heap *) heap;
+ }
+ return 0;
+}
+
+/**
+ * Reserve memory for ION and calculate amount of reusable memory for fmem.
+ * We only reserve memory for heaps that are not reusable. However, we only
+ * support one reusable heap at the moment so we ignore the reusable flag for
+ * other than the first heap with reusable flag set. Also handle special case
+ * for adjacent heap when the adjacent heap is adjacent to a reusable heap.
+ */
+static void __init reserve_ion_memory(void)
+{
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+ unsigned int i;
+ unsigned int reusable_count = 0;
+
+ adjust_mem_for_liquid();
+ fmem_pdata.size = 0;
+ fmem_pdata.reserved_size = 0;
+
+ /* We only support 1 reusable heap. Check if more than one heap
+ * is specified as reusable and set as non-reusable if found.
+ */
+ for (i = 0; i < ion_pdata.nr; ++i) {
+ const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+
+ if (heap->type == ION_HEAP_TYPE_CP && heap->extra_data) {
+ struct ion_cp_heap_pdata *data = heap->extra_data;
+
+ reusable_count += (data->reusable) ? 1 : 0;
+
+ if (data->reusable && reusable_count > 1) {
+ pr_err("%s: Too many heaps specified as "
+ "reusable. Heap %s was not configured "
+ "as reusable.\n", __func__, heap->name);
+ data->reusable = 0;
+ }
+ }
+ }
+
+ for (i = 0; i < ion_pdata.nr; ++i) {
+ int reusable = 0;
+ int adjacent_heap_id = INVALID_HEAP_ID;
+ int adj_reusable = 0;
+ const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+
+ if (heap->extra_data) {
+ switch (heap->type) {
+ case ION_HEAP_TYPE_CP:
+ reusable = ((struct ion_cp_heap_pdata *)
+ heap->extra_data)->reusable;
+ break;
+ case ION_HEAP_TYPE_CARVEOUT:
+ adjacent_heap_id = ((struct ion_co_heap_pdata *)
+ heap->extra_data)->adjacent_mem_id;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (adjacent_heap_id != INVALID_HEAP_ID) {
+ const struct ion_platform_heap *adj_heap =
+ find_ion_heap(adjacent_heap_id);
+ if (adj_heap) {
+ adj_reusable = ((struct ion_cp_heap_pdata *)
+ adj_heap->extra_data)->reusable;
+ if (adj_reusable)
+ fmem_pdata.reserved_size += heap->size;
+ }
+ }
+
+ if (!reusable && !adj_reusable)
+ reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
+ else
+ fmem_pdata.size += heap->size;
+ }
#endif
}
@@ -446,7 +530,6 @@
size_pmem_devices();
reserve_pmem_memory();
reserve_ion_memory();
- reserve_fmem_memory();
reserve_mdp_memory();
}