FMEM: allocate non-fixed FMEM from memory pool
On platforms whose FMEM is not at a fixed place
and which don't have DMM (such as 7x27a), FMEM
and the EBI memory pool would incorrectly overlap,
and the same memory would be used both as FMEM
and as memory allocated by allocate_contiguous_memory()
at the same time leading to crashes and strange behavior.
There are some unsolved problems related to
allocating FMEM from unstable memory, so we have
decided not to do this any longer. This decision allows
us to simply allocate non-fixed FMEM from the
EBI memory pool (this will prevent FMEM's memory
from being used by another allocator at the same time).
In this case FMEM will appear to "overlap" with
the memory pool, but this now OK as FMEM is allocated
from it.
This also re-enables FMEM on 7x27a and 8625, which
had been disabled due to the above-mentioned bug.
CRs-Fixed: 354254
Change-Id: I8e0bba332c7ddcac1d280de9642078fdfe61bbcc
Signed-off-by: Larry Bassel <lbassel@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 2cf3b8d..df4ca83 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -48,6 +48,7 @@
#include <mach/msm_battery.h>
#include <linux/smsc911x.h>
#include <linux/atmel_maxtouch.h>
+#include <linux/fmem.h>
#include <linux/msm_adc.h>
#include "devices.h"
#include "timer.h"
@@ -435,6 +436,9 @@
.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
.cached = 1,
.memory_type = MEMTYPE_EBI1,
+ .request_region = request_fmem_c_region,
+ .release_region = release_fmem_c_region,
+ .reusable = 1,
};
static struct platform_device android_pmem_adsp_device = {
@@ -756,6 +760,14 @@
static void msm7x27a_cfg_uart2dm_serial(void) { }
#endif
+struct fmem_platform_data fmem_pdata;
+
+struct platform_device fmem_device = {
+ .name = "fmem",
+ .id = 1,
+ .dev = { .platform_data = &fmem_pdata },
+};
+
static struct platform_device *rumi_sim_devices[] __initdata = {
&msm_device_dmov,
&msm_device_smd,
@@ -793,6 +805,7 @@
&android_pmem_device,
&android_pmem_adsp_device,
&android_pmem_audio_device,
+ &fmem_device,
&msm_device_nand,
&msm_device_snd,
&msm_device_adspdec,
@@ -843,8 +856,19 @@
},
};
+#ifdef CONFIG_ANDROID_PMEM
+static struct android_pmem_platform_data *pmem_pdata_array[] __initdata = {
+ &android_pmem_adsp_pdata,
+ &android_pmem_audio_pdata,
+ &android_pmem_pdata,
+};
+#endif
+
static void __init size_pmem_devices(void)
{
+#ifdef CONFIG_ANDROID_PMEM
+ unsigned int i;
+ unsigned int reusable_count = 0;
if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
pmem_mdp_size = MSM7x25A_MSM_PMEM_MDP_SIZE;
@@ -854,11 +878,30 @@
pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
}
-#ifdef CONFIG_ANDROID_PMEM
android_pmem_adsp_pdata.size = pmem_adsp_size;
android_pmem_pdata.size = pmem_mdp_size;
android_pmem_audio_pdata.size = pmem_audio_size;
+
+ fmem_pdata.size = 0;
+
+ /* Find pmem devices that should use FMEM (reusable) memory.
+ */
+ for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
+ struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
+
+ if (!reusable_count && pdata->reusable)
+ fmem_pdata.size += pdata->size;
+
+ reusable_count += (pdata->reusable) ? 1 : 0;
+
+ if (pdata->reusable && reusable_count > 1) {
+ pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
+ __func__, pdata->name);
+ pdata->reusable = 0;
+ }
+ }
#endif
+
}
static void __init reserve_memory_for(struct android_pmem_platform_data *p)
@@ -869,9 +912,10 @@
static void __init reserve_pmem_memory(void)
{
#ifdef CONFIG_ANDROID_PMEM
- reserve_memory_for(&android_pmem_adsp_pdata);
- reserve_memory_for(&android_pmem_pdata);
- reserve_memory_for(&android_pmem_audio_pdata);
+ unsigned int i;
+ for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i)
+ reserve_memory_for(pmem_pdata_array[i]);
+
msm7x27a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
#endif
}