8960: Add support for using CMA with Ion heaps
Adjust the memory reservation/placing code in the board
file to account for heaps that might use CMA. This includes
both dedicated CMA heaps and cp heaps marked as using CMA.
Change-Id: Ifb715bc2d4bf7fbba78a7201a68ccf3ec93c38b2
Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 32ab870..28bb0fe 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -30,6 +30,7 @@
#include <linux/android_pmem.h>
#endif
#include <linux/cyttsp-qc.h>
+#include <linux/dma-contiguous.h>
#include <linux/dma-mapping.h>
#include <linux/platform_data/qcom_crypto_device.h>
#include <linux/platform_data/qcom_wcnss_device.h>
@@ -387,6 +388,17 @@
};
#endif
+static u64 msm_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device ion_mm_heap_device = {
+ .name = "ion-mm-heap-device",
+ .id = -1,
+ .dev = {
+ .dma_mask = &msm_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+
/**
* These heaps are listed in the order they will be allocated. Due to
* video hardware restrictions and content protection the FW heap has to
@@ -412,6 +424,7 @@
.size = MSM_ION_MM_SIZE,
.memory_type = ION_EBI_TYPE,
.extra_data = (void *) &cp_mm_msm8960_ion_pdata,
+ .priv = &ion_mm_heap_device.dev,
},
{
.id = ION_MM_FIRMWARE_HEAP_ID,
@@ -548,21 +561,29 @@
{
#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
unsigned int i;
+ int ret;
unsigned int fixed_size = 0;
unsigned int fixed_low_size, fixed_middle_size, fixed_high_size;
unsigned long fixed_low_start, fixed_middle_start, fixed_high_start;
+ unsigned long cma_alignment;
+ unsigned int low_use_cma = 0;
+ unsigned int middle_use_cma = 0;
+ unsigned int high_use_cma = 0;
adjust_mem_for_liquid();
fixed_low_size = 0;
fixed_middle_size = 0;
fixed_high_size = 0;
+ cma_alignment = PAGE_SIZE << max(MAX_ORDER, pageblock_order);
+
for (i = 0; i < msm8960_ion_pdata.nr; ++i) {
struct ion_platform_heap *heap =
&(msm8960_ion_pdata.heaps[i]);
int align = SZ_4K;
int iommu_map_all = 0;
int adjacent_mem_id = INVALID_HEAP_ID;
+ int use_cma = 0;
if (heap->extra_data) {
int fixed_position = NOT_FIXED;
@@ -576,7 +597,16 @@
iommu_map_all =
((struct ion_cp_heap_pdata *)
heap->extra_data)->iommu_map_all;
+ if (((struct ion_cp_heap_pdata *)
+ heap->extra_data)->is_cma) {
+ heap->size = ALIGN(heap->size,
+ cma_alignment);
+ use_cma = 1;
+ }
break;
+ case ION_HEAP_TYPE_DMA:
+ use_cma = 1;
+ /* Purposely fall through here */
case ION_HEAP_TYPE_CARVEOUT:
fixed_position = ((struct ion_co_heap_pdata *)
heap->extra_data)->fixed_position;
@@ -600,28 +630,71 @@
else
reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
- if (fixed_position == FIXED_LOW)
+ if (fixed_position == FIXED_LOW) {
fixed_low_size += heap->size;
- else if (fixed_position == FIXED_MIDDLE)
+ low_use_cma = use_cma;
+ } else if (fixed_position == FIXED_MIDDLE) {
fixed_middle_size += heap->size;
- else if (fixed_position == FIXED_HIGH)
+ middle_use_cma = use_cma;
+ } else if (fixed_position == FIXED_HIGH) {
fixed_high_size += heap->size;
+ high_use_cma = use_cma;
+ } else if (use_cma) {
+ /*
+ * Heaps that use CMA but are not part of the
+ * fixed set. Create wherever.
+ */
+ dma_declare_contiguous(
+ heap->priv,
+ heap->size,
+ 0,
+ 0xb0000000);
+ }
}
}
if (!fixed_size)
return;
- /* Since the fixed area may be carved out of lowmem,
- * make sure the length is a multiple of 1M.
+ /*
+ * Given the setup for the fixed area, we can't round up all sizes.
+ * Some sizes must be set up exactly and aligned correctly. Incorrect
+ * alignments are considered a configuration issue
*/
- fixed_size = (fixed_size + MSM_MM_FW_SIZE + SECTION_SIZE - 1)
- & SECTION_MASK;
- msm8960_reserve_fixed_area(fixed_size);
fixed_low_start = MSM8960_FIXED_AREA_START;
+ if (low_use_cma) {
+ BUG_ON(!IS_ALIGNED(fixed_low_start, cma_alignment));
+ BUG_ON(!IS_ALIGNED(fixed_low_size + HOLE_SIZE, cma_alignment));
+ } else {
+ BUG_ON(!IS_ALIGNED(fixed_low_size + HOLE_SIZE, SECTION_SIZE));
+ ret = memblock_remove(fixed_low_start,
+ fixed_low_size + HOLE_SIZE);
+ BUG_ON(ret);
+ }
+
fixed_middle_start = fixed_low_start + fixed_low_size + HOLE_SIZE;
+ if (middle_use_cma) {
+ BUG_ON(!IS_ALIGNED(fixed_middle_start, cma_alignment));
+ BUG_ON(!IS_ALIGNED(fixed_middle_size, cma_alignment));
+ } else {
+ BUG_ON(!IS_ALIGNED(fixed_middle_size, SECTION_SIZE));
+ ret = memblock_remove(fixed_middle_start, fixed_middle_size);
+ BUG_ON(ret);
+ }
+
fixed_high_start = fixed_middle_start + fixed_middle_size;
+ if (high_use_cma) {
+ fixed_high_size = ALIGN(fixed_high_size, cma_alignment);
+ BUG_ON(!IS_ALIGNED(fixed_high_start, cma_alignment));
+ } else {
+ /* This is the end of the fixed area so it's okay to round up */
+ fixed_high_size = ALIGN(fixed_high_size, SECTION_SIZE);
+ ret = memblock_remove(fixed_high_start, fixed_high_size);
+ BUG_ON(ret);
+ }
+
+
for (i = 0; i < msm8960_ion_pdata.nr; ++i) {
struct ion_platform_heap *heap = &(msm8960_ion_pdata.heaps[i]);
@@ -637,6 +710,7 @@
fixed_position = pdata->fixed_position;
break;
case ION_HEAP_TYPE_CARVEOUT:
+ case ION_HEAP_TYPE_DMA:
fixed_position = ((struct ion_co_heap_pdata *)
heap->extra_data)->fixed_position;
break;
@@ -650,6 +724,14 @@
break;
case FIXED_MIDDLE:
heap->base = fixed_middle_start;
+ if (middle_use_cma) {
+ ret = dma_declare_contiguous(
+ &ion_mm_heap_device.dev,
+ heap->size,
+ fixed_middle_start,
+ 0xa0000000);
+ WARN_ON(ret);
+ }
pdata->secure_base = fixed_middle_start
- HOLE_SIZE;
pdata->secure_size = HOLE_SIZE + heap->size;