diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c index 533d4f76d37..28499455396 100644 --- a/arch/arm/mach-msm/board-8930.c +++ b/arch/arm/mach-msm/board-8930.c @@ -128,10 +128,11 @@ struct sx150x_platform_data msm8930_sx150x_data[] = { #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION #define MSM_PMEM_KERNEL_EBI1_SIZE 0xB0C000 -#define MSM_ION_SF_SIZE 0x1800000 /* 24MB */ +#define MSM_ION_SF_SIZE 0x2800000 /* 40MB */ +#define MSM_ION_MM_FW_SIZE 0x200000 /* (2MB) */ #define MSM_ION_MM_SIZE 0x4000000 /* (64MB) */ #define MSM_ION_MFC_SIZE SZ_8K -#define MSM_ION_HEAP_NUM 5 +#define MSM_ION_HEAP_NUM 6 #else #define MSM_PMEM_KERNEL_EBI1_SIZE 0x110C000 #define MSM_ION_HEAP_NUM 1 @@ -285,12 +286,20 @@ static int msm8930_paddr_to_memtype(unsigned int paddr) #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION static struct ion_cp_heap_pdata cp_mm_ion_pdata = { .permission_type = IPT_TYPE_MM_CARVEOUT, + .align = PAGE_SIZE, }; static struct ion_cp_heap_pdata cp_mfc_ion_pdata = { .permission_type = IPT_TYPE_MFC_SHAREDMEM, + .align = PAGE_SIZE, }; static struct ion_co_heap_pdata co_ion_pdata = { + .adjacent_mem_id = INVALID_HEAP_ID, + .align = PAGE_SIZE, +}; +static struct ion_co_heap_pdata fw_co_ion_pdata = { + .adjacent_mem_id = ION_CP_MM_HEAP_ID, + .align = SZ_128K, }; #endif static struct ion_platform_data ion_pdata = { @@ -308,7 +317,7 @@ static struct ion_platform_data ion_pdata = { .name = ION_SF_HEAP_NAME, .size = MSM_ION_SF_SIZE, .memory_type = ION_EBI_TYPE, - .extra_data = &co_ion_pdata, + .extra_data = (void *) &co_ion_pdata, }, { .id = ION_CP_MM_HEAP_ID, @@ -318,6 +327,14 @@ static struct ion_platform_data ion_pdata = { .memory_type = ION_EBI_TYPE, .extra_data = (void *) &cp_mm_ion_pdata, }, + { + .id = ION_MM_FIRMWARE_HEAP_ID, + .type = ION_HEAP_TYPE_CARVEOUT, + .name = ION_MM_FIRMWARE_HEAP_NAME, + .size = MSM_ION_MM_FW_SIZE, + .memory_type = ION_EBI_TYPE, + .extra_data = (void *) &fw_co_ion_pdata, + }, { .id = ION_CP_MFC_HEAP_ID, .type = ION_HEAP_TYPE_CP, @@ -347,6 +364,7 @@ static void reserve_ion_memory(void) #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION) msm8930_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE; msm8930_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_SIZE; + msm8930_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_FW_SIZE; msm8930_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MFC_SIZE; #endif } diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c index b19445d86c5..b67fdd07c04 100644 --- a/arch/arm/mach-msm/board-8960.c +++ b/arch/arm/mach-msm/board-8960.c @@ -142,9 +142,10 @@ struct sx150x_platform_data msm8960_sx150x_data[] = { #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION #define MSM_PMEM_KERNEL_EBI1_SIZE 0xB0C000 #define MSM_ION_SF_SIZE 0x2800000 /* (40MB) */ +#define MSM_ION_MM_FW_SIZE 0x200000 /* (2MB) */ #define MSM_ION_MM_SIZE 0x4000000 /* (64MB) */ #define MSM_ION_MFC_SIZE SZ_8K -#define MSM_ION_HEAP_NUM 5 +#define MSM_ION_HEAP_NUM 6 #define MSM_LIQUID_ION_MM_SIZE (MSM_ION_MM_SIZE + 0x600000) static unsigned int msm_ion_cp_mm_size = MSM_ION_MM_SIZE; #else @@ -312,16 +313,24 @@ static int msm8960_paddr_to_memtype(unsigned int paddr) #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION static struct ion_cp_heap_pdata cp_mm_ion_pdata = { .permission_type = IPT_TYPE_MM_CARVEOUT, + .align = PAGE_SIZE, }; static struct ion_cp_heap_pdata cp_mfc_ion_pdata = { .permission_type = IPT_TYPE_MFC_SHAREDMEM, + .align = PAGE_SIZE, }; static struct ion_co_heap_pdata co_ion_pdata = { + .adjacent_mem_id = INVALID_HEAP_ID, + .align = PAGE_SIZE, +}; + +static struct ion_co_heap_pdata fw_co_ion_pdata = { + .adjacent_mem_id = ION_CP_MM_HEAP_ID, + .align = SZ_128K, }; #endif - static struct ion_platform_data ion_pdata = { .nr = MSM_ION_HEAP_NUM, .heaps = { @@ -337,7 +346,7 @@ static struct ion_platform_data ion_pdata = { .name = ION_SF_HEAP_NAME, .size = MSM_ION_SF_SIZE, .memory_type = ION_EBI_TYPE, - .extra_data = &co_ion_pdata, + .extra_data = (void *) &co_ion_pdata, }, { .id = ION_CP_MM_HEAP_ID, @@ -347,6 +356,14 @@ static struct ion_platform_data ion_pdata = { .memory_type = ION_EBI_TYPE, .extra_data = (void *) &cp_mm_ion_pdata, }, + { + .id = ION_MM_FIRMWARE_HEAP_ID, + .type = ION_HEAP_TYPE_CARVEOUT, + .name = ION_MM_FIRMWARE_HEAP_NAME, + .size = MSM_ION_MM_FW_SIZE, + .memory_type = ION_EBI_TYPE, + .extra_data = (void *) &fw_co_ion_pdata, + }, { .id = ION_CP_MFC_HEAP_ID, .type = ION_HEAP_TYPE_CP, @@ -394,6 +411,7 @@ static void reserve_ion_memory(void) } } 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; #endif diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c index df04bb2a5c2..7699aa890e7 100644 --- a/arch/arm/mach-msm/board-msm8x60.c +++ b/arch/arm/mach-msm/board-msm8x60.c @@ -2672,12 +2672,13 @@ static void __init msm8x60_init_dsps(void) #define MSM_ION_SF_SIZE 0x1800000 /* 24MB */ #define MSM_ION_CAMERA_SIZE MSM_PMEM_ADSP_SIZE -#define MSM_ION_MM_SIZE 0x3800000 /* 56MB */ +#define MSM_ION_MM_FW_SIZE 0x200000 /* (2MB) */ +#define MSM_ION_MM_SIZE 0x3600000 /* (54MB) */ #define MSM_ION_MFC_SIZE SZ_8K #define MSM_ION_WB_SIZE 0x600000 /* 6MB */ #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION -#define MSM_ION_HEAP_NUM 6 +#define MSM_ION_HEAP_NUM 7 #else #define MSM_ION_HEAP_NUM 1 #endif @@ -5242,6 +5243,7 @@ static struct platform_device *surf_devices[] __initdata = { #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION static struct ion_cp_heap_pdata cp_mm_ion_pdata = { .permission_type = IPT_TYPE_MM_CARVEOUT, + .align = PAGE_SIZE, .request_region = request_smi_region, .release_region = release_smi_region, .setup_region = setup_smi_region, @@ -5249,6 +5251,7 @@ static struct ion_cp_heap_pdata cp_mm_ion_pdata = { static struct ion_cp_heap_pdata cp_mfc_ion_pdata = { .permission_type = IPT_TYPE_MFC_SHAREDMEM, + .align = PAGE_SIZE, .request_region = request_smi_region, .release_region = release_smi_region, .setup_region = setup_smi_region, @@ -5256,9 +5259,17 @@ static struct ion_cp_heap_pdata cp_mfc_ion_pdata = { static struct ion_cp_heap_pdata cp_wb_ion_pdata = { .permission_type = IPT_TYPE_MDP_WRITEBACK, + .align = PAGE_SIZE, +}; + +static struct ion_co_heap_pdata fw_co_ion_pdata = { + .adjacent_mem_id = ION_CP_MM_HEAP_ID, + .align = SZ_128K, }; static struct ion_co_heap_pdata co_ion_pdata = { + .adjacent_mem_id = INVALID_HEAP_ID, + .align = PAGE_SIZE, }; #endif static struct ion_platform_data ion_pdata = { @@ -5276,7 +5287,7 @@ static struct ion_platform_data ion_pdata = { .name = ION_SF_HEAP_NAME, .size = MSM_ION_SF_SIZE, .memory_type = ION_EBI_TYPE, - .extra_data = &co_ion_pdata, + .extra_data = (void *)&co_ion_pdata, }, { .id = ION_CP_MM_HEAP_ID, @@ -5286,6 +5297,14 @@ static struct ion_platform_data ion_pdata = { .memory_type = ION_SMI_TYPE, .extra_data = (void *) &cp_mm_ion_pdata, }, + { + .id = ION_MM_FIRMWARE_HEAP_ID, + .type = ION_HEAP_TYPE_CARVEOUT, + .name = ION_MM_FIRMWARE_HEAP_NAME, + .size = MSM_ION_MM_FW_SIZE, + .memory_type = ION_SMI_TYPE, + .extra_data = (void *) &fw_co_ion_pdata, + }, { .id = ION_CAMERA_HEAP_ID, .type = ION_HEAP_TYPE_CARVEOUT, @@ -5353,6 +5372,7 @@ static void reserve_ion_memory(void) { #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION) msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE; + msm8x60_reserve_table[MEMTYPE_SMI].size += MSM_ION_MM_FW_SIZE; msm8x60_reserve_table[MEMTYPE_SMI].size += MSM_ION_MM_SIZE; msm8x60_reserve_table[MEMTYPE_SMI].size += MSM_ION_MFC_SIZE; msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_CAMERA_SIZE; diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c index 5737d21de18..22ff44848d8 100644 --- a/drivers/gpu/ion/ion_cp_heap.c +++ b/drivers/gpu/ion/ion_cp_heap.c @@ -39,6 +39,8 @@ * @base: the base address of the memory pool. * @permission_type: Identifier for the memory used by SCM for protecting * and unprotecting memory. + * @secure_base: Base address used when securing a heap that is shared. + * @secure_size: Size used when securing a heap that is shared. * @lock: mutex to protect shared access. * @heap_secured: Identifies the heap_id as secure or not. * @allocated_bytes: the total number of allocated bytes from the pool. @@ -59,6 +61,8 @@ struct ion_cp_heap { struct gen_pool *pool; ion_phys_addr_t base; unsigned int permission_type; + ion_phys_addr_t secure_base; + size_t secure_size; struct mutex lock; unsigned int heap_secured; unsigned long allocated_bytes; @@ -94,8 +98,8 @@ static int ion_cp_protect(struct ion_heap *heap) int ret_value = 0; if (cp_heap->heap_secured == NON_SECURED_HEAP) { - int ret_value = ion_cp_protect_mem(cp_heap->base, - cp_heap->total_size, cp_heap->permission_type); + int ret_value = ion_cp_protect_mem(cp_heap->secure_base, + cp_heap->secure_size, cp_heap->permission_type); if (ret_value) { pr_err("Failed to protect memory for heap %s - " "error code: %d", heap->name, ret_value); @@ -119,7 +123,7 @@ static void ion_cp_unprotect(struct ion_heap *heap) if (cp_heap->heap_secured == SECURED_HEAP) { int error_code = ion_cp_unprotect_mem( - cp_heap->base, cp_heap->total_size, + cp_heap->secure_base, cp_heap->secure_size, cp_heap->permission_type); if (error_code) { pr_err("Failed to un-protect memory for heap %s - " @@ -567,22 +571,6 @@ static struct ion_heap_ops cp_heap_ops = { .unsecure_heap = ion_cp_unsecure_heap, }; -static unsigned long ion_cp_get_base(unsigned long size, int memory_type) -{ - switch (memory_type) { - case ION_EBI_TYPE: - return allocate_contiguous_ebi_nomap(size, PAGE_SIZE); - break; - case ION_SMI_TYPE: - return allocate_contiguous_memory_nomap(size, MEMTYPE_SMI, - PAGE_SIZE); - break; - default: - return 0; - } -} - - struct ion_heap *ion_cp_heap_create(struct ion_platform_heap *heap_data) { struct ion_cp_heap *cp_heap; @@ -592,15 +580,6 @@ struct ion_heap *ion_cp_heap_create(struct ion_platform_heap *heap_data) if (!cp_heap) return ERR_PTR(-ENOMEM); - heap_data->base = ion_cp_get_base(heap_data->size, - heap_data->memory_type); - if (!heap_data->base) { - pr_err("%s: could not get memory for heap %s" - " (id %x)\n", __func__, heap_data->name, - heap_data->id); - goto free_heap; - } - mutex_init(&cp_heap->lock); cp_heap->pool = gen_pool_create(12, -1); @@ -620,10 +599,16 @@ struct ion_heap *ion_cp_heap_create(struct ion_platform_heap *heap_data) cp_heap->heap.ops = &cp_heap_ops; cp_heap->heap.type = ION_HEAP_TYPE_CP; cp_heap->heap_secured = NON_SECURED_HEAP; + cp_heap->secure_base = cp_heap->base; + cp_heap->secure_size = heap_data->size; if (heap_data->extra_data) { struct ion_cp_heap_pdata *extra_data = heap_data->extra_data; cp_heap->permission_type = extra_data->permission_type; + if (extra_data->secure_size) { + cp_heap->secure_base = extra_data->secure_base; + cp_heap->secure_size = extra_data->secure_size; + } if (extra_data->setup_region) cp_heap->bus_id = extra_data->setup_region(); if (extra_data->request_region) diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c index 3df2b53bc25..b56c99b7efb 100644 --- a/drivers/gpu/ion/msm/msm_ion.c +++ b/drivers/gpu/ion/msm/msm_ion.c @@ -42,21 +42,118 @@ int msm_ion_unsecure_heap(int heap_id) } EXPORT_SYMBOL(msm_ion_unsecure_heap); -static unsigned long msm_ion_get_base(unsigned long size, int memory_type) +static unsigned long msm_ion_get_base(unsigned long size, int memory_type, + unsigned int align) { switch (memory_type) { case ION_EBI_TYPE: - return allocate_contiguous_ebi_nomap(size, PAGE_SIZE); + return allocate_contiguous_ebi_nomap(size, align); break; case ION_SMI_TYPE: return allocate_contiguous_memory_nomap(size, MEMTYPE_SMI, - PAGE_SIZE); + align); break; default: return 0; } } +static struct ion_platform_heap *find_heap(const struct ion_platform_heap + heap_data[], + unsigned int nr_heaps, + int heap_id) +{ + unsigned int i; + for (i = 0; i < nr_heaps; ++i) { + const struct ion_platform_heap *heap = &heap_data[i]; + if (heap->id == heap_id) + return (struct ion_platform_heap *) heap; + } + return 0; +} + +static void allocate_co_memory(struct ion_platform_heap *heap, + struct ion_platform_heap heap_data[], + unsigned int nr_heaps) +{ + struct ion_co_heap_pdata *co_heap_data = + (struct ion_co_heap_pdata *) heap->extra_data; + if (co_heap_data->adjacent_mem_id != INVALID_HEAP_ID) { + struct ion_platform_heap *shared_heap = + find_heap(heap_data, nr_heaps, + co_heap_data->adjacent_mem_id); + if (shared_heap) { + struct ion_cp_heap_pdata *cp_data = + (struct ion_cp_heap_pdata *) shared_heap->extra_data; + heap->base = msm_ion_get_base( + heap->size + shared_heap->size, + shared_heap->memory_type, + co_heap_data->align); + if (heap->base) { + shared_heap->base = heap->base + heap->size; + cp_data->secure_base = heap->base; + cp_data->secure_size = + heap->size + shared_heap->size; + } else { + pr_err("%s: could not get memory for heap %s " + "(id %x)\n", __func__, heap->name, heap->id); + } + + } + } +} + +/* Fixup heaps in board file to support two heaps being adjacent to each other. + * A flag (adjacent_mem_id) in the platform data tells us that the heap phy + * memory location must be adjacent to the specified heap. We do this by + * carving out memory for both heaps and then splitting up the memory to the + * two heaps. The heap specifying the "adjacent_mem_id" get the base of the + * memory while heap specified in "adjacent_mem_id" get base+size as its + * base address. + * Note: Modifies platform data and allocates memory. + */ +static void msm_ion_heap_fixup(struct ion_platform_heap heap_data[], + unsigned int nr_heaps) +{ + unsigned int i; + + for (i = 0; i < nr_heaps; i++) { + struct ion_platform_heap *heap = &heap_data[i]; + if (!heap->base && heap->type == ION_HEAP_TYPE_CARVEOUT) { + if (heap->extra_data) + allocate_co_memory(heap, heap_data, nr_heaps); + } + } +} + +static void msm_ion_allocate(struct ion_platform_heap *heap) +{ + + if (!heap->base && heap->extra_data) { + unsigned int align = 0; + switch (heap->type) { + case ION_HEAP_TYPE_CARVEOUT: + align = + ((struct ion_co_heap_pdata *) heap->extra_data)->align; + break; + case ION_HEAP_TYPE_CP: + align = + ((struct ion_cp_heap_pdata *) heap->extra_data)->align; + break; + default: + break; + } + if (align) { + heap->base = msm_ion_get_base(heap->size, + heap->memory_type, + align); + if (!heap->base) + pr_err("%s: could not get memory for heap %s " + "(id %x)\n", __func__, heap->name, heap->id); + } + } +} + static int msm_ion_probe(struct platform_device *pdev) { struct ion_platform_data *pdata = pdev->dev.platform_data; @@ -78,20 +175,12 @@ static int msm_ion_probe(struct platform_device *pdev) goto freeheaps; } + msm_ion_heap_fixup(pdata->heaps, num_heaps); + /* create the heaps as specified in the board file */ for (i = 0; i < num_heaps; i++) { struct ion_platform_heap *heap_data = &pdata->heaps[i]; - - if (heap_data->type == ION_HEAP_TYPE_CARVEOUT) { - heap_data->base = msm_ion_get_base(heap_data->size, - heap_data->memory_type); - if (!heap_data->base) { - pr_err("%s: could not get memory for heap %s" - " (id %x)\n", __func__, heap_data->name, - heap_data->id); - continue; - } - } + msm_ion_allocate(heap_data); heaps[i] = ion_heap_create(heap_data); if (IS_ERR_OR_NULL(heaps[i])) { diff --git a/include/linux/ion.h b/include/linux/ion.h index fa5017aef72..f46d4784ed2 100644 --- a/include/linux/ion.h +++ b/include/linux/ion.h @@ -63,6 +63,7 @@ enum ion_heap_type { */ enum ion_heap_ids { + INVALID_HEAP_ID = -1, ION_IOMMU_HEAP_ID = 4, ION_CP_MM_HEAP_ID = 8, ION_CP_MFC_HEAP_ID = 12, @@ -71,6 +72,7 @@ enum ion_heap_ids { ION_SF_HEAP_ID = 24, ION_AUDIO_HEAP_ID = 28, + ION_MM_FIRMWARE_HEAP_ID = 29, ION_SYSTEM_HEAP_ID = 30, ION_HEAP_ID_RESERVED = 31 /** Bit reserved for ION_SECURE flag */ @@ -94,6 +96,7 @@ enum ion_heap_ids { #define ION_IOMMU_HEAP_NAME "iommu" #define ION_MFC_HEAP_NAME "mfc" #define ION_WB_HEAP_NAME "wb" +#define ION_MM_FIRMWARE_HEAP_NAME "mm_fw" #define CACHED 1 #define UNCACHED 0 @@ -149,12 +152,17 @@ struct ion_platform_heap { struct ion_cp_heap_pdata { enum ion_permission_type permission_type; + unsigned int align; + ion_phys_addr_t secure_base; /* Base addr used when heap is shared */ + size_t secure_size; /* Size used for securing heap when heap is shared*/ int (*request_region)(void *); int (*release_region)(void *); void *(*setup_region)(void); }; struct ion_co_heap_pdata { + int adjacent_mem_id; + unsigned int align; int (*request_region)(void *); int (*release_region)(void *); void *(*setup_region)(void);