diff options
author | Yixun Lan <yixun.lan@gmail.com> | 2016-03-01 12:48:09 +0800 |
---|---|---|
committer | Ying-Chun Liu (PaulLiu) <paulliu@debian.org> | 2016-03-02 13:30:44 +0800 |
commit | 2fd651604a6dbc8d707470b8fe08982790aa7734 (patch) | |
tree | 3e0994de42a116a72ed7862e6932c915f186049c | |
parent | 9986a91bb86649daa7826d96555671f73a788f6c (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.c | 34 | ||||
-rw-r--r-- | include/aboot.h | 7 |
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; |