aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYixun Lan <yixun.lan@gmail.com>2016-03-01 12:48:09 +0800
committerYing-Chun Liu (PaulLiu) <paulliu@debian.org>2016-03-02 13:30:44 +0800
commit2fd651604a6dbc8d707470b8fe08982790aa7734 (patch)
tree3e0994de42a116a72ed7862e6932c915f186049c
parent9986a91bb86649daa7826d96555671f73a788f6c (diff)
aboot: improve the buffer allocation schemebubblegum96
we try several granularity to make the allocation failure less happen 1) we first will try to allocate buffer as max order of CONFIG_FILL_BUFF_MAX_SIZE, eg 8192 blocks for SZ_4M if blksz = 512byte 2) if failure occur, we will try to allocate 8192/2=4096 blocks 3) still fail to allocate, we will try size 4096/2=2048 blocks .. 4) untill the allocation success ( the min buffer = 1 block) Signed-off-by: Yixun Lan <yixun.lan@gmail.com>
-rw-r--r--common/aboot.c34
-rw-r--r--include/aboot.h7
2 files changed, 31 insertions, 10 deletions
diff --git a/common/aboot.c b/common/aboot.c
index 1cfc606dd4..54374c9f17 100644
--- a/common/aboot.c
+++ b/common/aboot.c
@@ -41,27 +41,32 @@
#include <part.h>
#include <sparse_format.h>
#include <linux/sizes.h>
+#include <linux/kernel.h>
-#ifndef CONFIG_FILL_BUFF_SIZE
-#define CONFIG_FILL_BUFF_SIZE SZ_4M
+#ifndef CONFIG_FILL_BUFF_MAX_SIZE
+#define CONFIG_FILL_BUFF_MAX_SIZE SZ_4M
#endif
static int write_fill_multi_blks(block_dev_desc_t *dev_desc,
disk_partition_t *info,
lbaint_t *blk, lbaint_t blkcnt, uint32_t fill_val)
{
- int i, size;;
+ int i, size, order;
uint32_t *fill_buf;
lbaint_t blks, fill_cnt, written_blks = 0;
- fill_cnt = CONFIG_FILL_BUFF_SIZE / info->blksz;
- lbaint_t quot = blkcnt / fill_cnt;
- lbaint_t remd = blkcnt % fill_cnt;
-
- size = blkcnt > fill_cnt ? CONFIG_FILL_BUFF_SIZE : (blkcnt * info->blksz);
+ order = get_order(MIN(CONFIG_FILL_BUFF_MAX_SIZE, (blkcnt * info->blksz)),
+ info->blksz);
- fill_buf = (uint32_t *) memalign(ARCH_DMA_MINALIGN,
+ while(order >= 0) {
+ size = info->blksz << order;
+ fill_buf = (uint32_t *) memalign(ARCH_DMA_MINALIGN,
ROUNDUP(size, ARCH_DMA_MINALIGN));
+ if (fill_buf)
+ break;
+
+ order--;
+ }
if (!fill_buf) {
fastboot_fail(
@@ -69,6 +74,13 @@ static int write_fill_multi_blks(block_dev_desc_t *dev_desc,
return -1;
}
+ fill_cnt = 0x1 << order;
+ lbaint_t quot = blkcnt / fill_cnt;
+ lbaint_t remd = blkcnt % fill_cnt;
+
+ if (blkcnt < fill_cnt)
+ size = blkcnt * info->blksz;
+
for (i = 0; i < (size / sizeof(fill_val)); i++)
fill_buf[i] = fill_val;
@@ -237,7 +249,9 @@ void write_sparse_image(block_dev_desc_t *dev_desc,
fill_val = *(uint32_t *)data;
data = (char *) data + sizeof(uint32_t);
- write_fill_multi_blks(dev_desc, info, &blk, blkcnt, fill_val);
+ if (write_fill_multi_blks(dev_desc, info, &blk,
+ blkcnt, fill_val) < 0)
+ return;
bytes_written += blkcnt * info->blksz;
total_blocks += chunk_data_sz / sparse_header->blk_sz;
diff --git a/include/aboot.h b/include/aboot.h
index 30e4d36df8..60a425ae7a 100644
--- a/include/aboot.h
+++ b/include/aboot.h
@@ -7,11 +7,18 @@
#include <part.h>
#include <sparse_format.h>
+#define MIN(x,y) (x < y ? x : y)
#define ROUNDUP(x, y) (((x) + ((y) - 1)) & ~((y) - 1))
void fastboot_fail(const char *s);
void fastboot_okay(const char *s);
+static inline int get_order(uint32_t size, uint32_t blksz)
+{
+ size--;
+ return fls(size / blksz);
+}
+
static inline int is_sparse_image(void *buf)
{
sparse_header_t *s_header = (sparse_header_t *)buf;