aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/lantiq/ltq-adsl-mei
diff options
context:
space:
mode:
authorJohn Crispin <blogic@openwrt.org>2014-03-30 09:16:39 +0000
committerJohn Crispin <blogic@openwrt.org>2014-03-30 09:16:39 +0000
commitc2d755eb76cce43b41fc26d20f08ac66a24eb83c (patch)
tree7b6bfb58dfa2134a174176c128ade027c118961f /package/kernel/lantiq/ltq-adsl-mei
parentcd9f4bad16c6e5f6f94218ff17ba5d1a71cef2f7 (diff)
downloadmaster-187ad058-c2d755eb76cce43b41fc26d20f08ac66a24eb83c.tar.gz
master-187ad058-c2d755eb76cce43b41fc26d20f08ac66a24eb83c.tar.bz2
master-187ad058-c2d755eb76cce43b41fc26d20f08ac66a24eb83c.zip
ltq-adsl-mei: improve memory allocation
The ltq-adsl-mei driver allocates memory for the ADSL firmware in a rather stupid way, leading to several 128k allocations, which fail when many services are enabled. This patch tries to allocate 64 kiB chunks, and only falls back to larger allocations if the returned pointers are not correctly aligned. Fixes out-of-memory errors on Danube boards with 32 MiB RAM. Signed-off-by: Matti Laakso <malaakso@elisanet.fi> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@40325 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/kernel/lantiq/ltq-adsl-mei')
-rw-r--r--package/kernel/lantiq/ltq-adsl-mei/src/lantiq_mei.c53
1 files changed, 44 insertions, 9 deletions
diff --git a/package/kernel/lantiq/ltq-adsl-mei/src/lantiq_mei.c b/package/kernel/lantiq/ltq-adsl-mei/src/lantiq_mei.c
index 443b9d90ac..561b300710 100644
--- a/package/kernel/lantiq/ltq-adsl-mei/src/lantiq_mei.c
+++ b/package/kernel/lantiq/ltq-adsl-mei/src/lantiq_mei.c
@@ -1513,13 +1513,31 @@ IFX_MEI_DFEMemoryAlloc (DSL_DEV_Device_t * pDev, long size)
allocate_size = size;
else
allocate_size = SDRAM_SEGMENT_SIZE;
- org_mem_ptr = kmalloc (allocate_size + 1024, GFP_KERNEL);
+
+ org_mem_ptr = kmalloc (allocate_size, GFP_KERNEL);
if (org_mem_ptr == NULL) {
IFX_MEI_EMSG ("%d: kmalloc %d bytes memory fail!\n", idx, allocate_size);
err = -ENOMEM;
goto allocate_error;
}
- mem_ptr = (unsigned long) (org_mem_ptr + 1023) & ~(1024 -1);
+
+ if (((unsigned long)org_mem_ptr) & (1023)) {
+ /* Pointer not 1k aligned, so free it and allocate a larger chunk
+ * for further alignment.
+ */
+ kfree(org_mem_ptr);
+ org_mem_ptr = kmalloc (allocate_size + 1024, GFP_KERNEL);
+ if (org_mem_ptr == NULL) {
+ IFX_MEI_EMSG ("%d: kmalloc %d bytes memory fail!\n",
+ idx, allocate_size + 1024);
+ err = -ENOMEM;
+ goto allocate_error;
+ }
+ mem_ptr = (unsigned long) (org_mem_ptr + 1023) & ~(1024 -1);
+ } else {
+ mem_ptr = (unsigned long) org_mem_ptr;
+ }
+
adsl_mem_info[idx].address = (char *) mem_ptr;
adsl_mem_info[idx].org_address = org_mem_ptr;
adsl_mem_info[idx].size = allocate_size;
@@ -1591,6 +1609,7 @@ DSL_BSP_FWDownload (DSL_DEV_Device_t * pDev, const char *buf,
size_t nRead = 0, nCopy = 0;
char *mem_ptr;
+ char *org_mem_ptr = NULL;
ssize_t retval = -ENOMEM;
int idx = 0;
@@ -1634,17 +1653,33 @@ DSL_BSP_FWDownload (DSL_DEV_Device_t * pDev, const char *buf,
DSL_DEV_PRIVATE(pDev)->img_hdr =
(ARC_IMG_HDR *) adsl_mem_info[0].address;
- adsl_mem_info[XDATA_REGISTER].org_address = kmalloc (SDRAM_SEGMENT_SIZE + 1024, GFP_KERNEL);
- adsl_mem_info[XDATA_REGISTER].address =
- (char *) ((unsigned long) (adsl_mem_info[XDATA_REGISTER].org_address + 1023) & 0xFFFFFC00);
-
- adsl_mem_info[XDATA_REGISTER].size = SDRAM_SEGMENT_SIZE;
-
- if (adsl_mem_info[XDATA_REGISTER].address == NULL) {
+ org_mem_ptr = kmalloc (SDRAM_SEGMENT_SIZE, GFP_KERNEL);
+ if (org_mem_ptr == NULL) {
IFX_MEI_EMSG ("kmalloc memory fail!\n");
retval = -ENOMEM;
goto error;
}
+
+ if (((unsigned long)org_mem_ptr) & (1023)) {
+ /* Pointer not 1k aligned, so free it and allocate a larger chunk
+ * for further alignment.
+ */
+ kfree(org_mem_ptr);
+ org_mem_ptr = kmalloc (SDRAM_SEGMENT_SIZE + 1024, GFP_KERNEL);
+ if (org_mem_ptr == NULL) {
+ IFX_MEI_EMSG ("kmalloc memory fail!\n");
+ retval = -ENOMEM;
+ goto error;
+ }
+ adsl_mem_info[XDATA_REGISTER].address =
+ (char *) ((unsigned long) (org_mem_ptr + 1023) & ~(1024 -1));
+ } else {
+ adsl_mem_info[XDATA_REGISTER].address = org_mem_ptr;
+ }
+
+ adsl_mem_info[XDATA_REGISTER].org_address = org_mem_ptr;
+ adsl_mem_info[XDATA_REGISTER].size = SDRAM_SEGMENT_SIZE;
+
adsl_mem_info[XDATA_REGISTER].type = FREE_RELOAD;
IFX_MEI_DMSG("-> IFX_MEI_BarUpdate()\n");
IFX_MEI_BarUpdate (pDev, (DSL_DEV_PRIVATE(pDev)->nBar));