Re: [PATCH] regmap: flat: introduce register striding to save some memories
On Mon, Dec 14, 2015 at 03:14:34PM +0800, Xiubo Li wrote: > static int regcache_flat_write(struct regmap *map, unsigned int reg, > unsigned int value) > { > + unsigned int index = reg / map->reg_stride; So, this does save some memory. On the other hand one of the big goals for the flat cache is to be as fast as possible to match the performance of MMIO and divisions aren't the cheapest operations. If this was the rbtree cache then it'd not be an issue but in the flat cache speed is definitely the top priority, at least by default. I'm guessing for your particular register maps the performance isn't too big an issue... do you have any numbers for how much space you're saving overall? Is it worth finding a way to make this possible to enable on maps that benefit? signature.asc Description: PGP signature
Re: [PATCH] regmap: flat: introduce register striding to save some memories
On Mon, Dec 14, 2015 at 03:14:34PM +0800, Xiubo Li wrote: > static int regcache_flat_write(struct regmap *map, unsigned int reg, > unsigned int value) > { > + unsigned int index = reg / map->reg_stride; So, this does save some memory. On the other hand one of the big goals for the flat cache is to be as fast as possible to match the performance of MMIO and divisions aren't the cheapest operations. If this was the rbtree cache then it'd not be an issue but in the flat cache speed is definitely the top priority, at least by default. I'm guessing for your particular register maps the performance isn't too big an issue... do you have any numbers for how much space you're saving overall? Is it worth finding a way to make this possible to enable on maps that benefit? signature.asc Description: PGP signature
[PATCH] regmap: flat: introduce register striding to save some memories
Throughout the regcache-flat code, for the flat cache array, the actual register address offsets are used to index the values, and this will waste some memory spaces. For example, on 64-BIT platform, device A has three registers: register offsets: {0x00, 0x08, 0x10} max_register: 0x10 regsiter striding: 8 And the size of flat cache memory space will be: (max_register + 1 ) * sizeof(unsigned int) = (0x10 + 1) * sizeof(unsigned int) = 17 * 8 = 136 Bytes Since map->reg_stride has been introduced and all extant register addresses are a multiple of this value, it could use the address offsets divide by the stride to determine the index. Then the size of flat cache memory space will be: (max_register / reg_stride + 1 ) * sizeof(unsigned int) = (0x10 / 8 + 1) * sizeof(unsigned int) = 3 * 8 = 24 Bytes And the bigger of the striding value, there will be more memory space wasted. After introducing the register striding here can save some memeories for the system. Signed-off-by: Xiubo Li --- drivers/base/regmap/regcache-flat.c | 18 +++--- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/base/regmap/regcache-flat.c b/drivers/base/regmap/regcache-flat.c index 686c9e0..160d636 100644 --- a/drivers/base/regmap/regcache-flat.c +++ b/drivers/base/regmap/regcache-flat.c @@ -19,17 +19,19 @@ static int regcache_flat_init(struct regmap *map) { int i; - unsigned int *cache; + unsigned int index, *cache; - map->cache = kcalloc(map->max_register + 1, sizeof(unsigned int), -GFP_KERNEL); + map->cache = kcalloc(map->max_register / map->reg_stride + 1, +sizeof(unsigned int), GFP_KERNEL); if (!map->cache) return -ENOMEM; cache = map->cache; - for (i = 0; i < map->num_reg_defaults; i++) - cache[map->reg_defaults[i].reg] = map->reg_defaults[i].def; + for (i = 0; i < map->num_reg_defaults; i++) { + index = map->reg_defaults[i].reg / map->reg_stride; + cache[index] = map->reg_defaults[i].def; + } return 0; } @@ -45,9 +47,10 @@ static int regcache_flat_exit(struct regmap *map) static int regcache_flat_read(struct regmap *map, unsigned int reg, unsigned int *value) { + unsigned int index = reg / map->reg_stride; unsigned int *cache = map->cache; - *value = cache[reg]; + *value = cache[index]; return 0; } @@ -55,9 +58,10 @@ static int regcache_flat_read(struct regmap *map, static int regcache_flat_write(struct regmap *map, unsigned int reg, unsigned int value) { + unsigned int index = reg / map->reg_stride; unsigned int *cache = map->cache; - cache[reg] = value; + cache[index] = value; return 0; } -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] regmap: flat: introduce register striding to save some memories
Throughout the regcache-flat code, for the flat cache array, the actual register address offsets are used to index the values, and this will waste some memory spaces. For example, on 64-BIT platform, device A has three registers: register offsets: {0x00, 0x08, 0x10} max_register: 0x10 regsiter striding: 8 And the size of flat cache memory space will be: (max_register + 1 ) * sizeof(unsigned int) = (0x10 + 1) * sizeof(unsigned int) = 17 * 8 = 136 Bytes Since map->reg_stride has been introduced and all extant register addresses are a multiple of this value, it could use the address offsets divide by the stride to determine the index. Then the size of flat cache memory space will be: (max_register / reg_stride + 1 ) * sizeof(unsigned int) = (0x10 / 8 + 1) * sizeof(unsigned int) = 3 * 8 = 24 Bytes And the bigger of the striding value, there will be more memory space wasted. After introducing the register striding here can save some memeories for the system. Signed-off-by: Xiubo Li--- drivers/base/regmap/regcache-flat.c | 18 +++--- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/base/regmap/regcache-flat.c b/drivers/base/regmap/regcache-flat.c index 686c9e0..160d636 100644 --- a/drivers/base/regmap/regcache-flat.c +++ b/drivers/base/regmap/regcache-flat.c @@ -19,17 +19,19 @@ static int regcache_flat_init(struct regmap *map) { int i; - unsigned int *cache; + unsigned int index, *cache; - map->cache = kcalloc(map->max_register + 1, sizeof(unsigned int), -GFP_KERNEL); + map->cache = kcalloc(map->max_register / map->reg_stride + 1, +sizeof(unsigned int), GFP_KERNEL); if (!map->cache) return -ENOMEM; cache = map->cache; - for (i = 0; i < map->num_reg_defaults; i++) - cache[map->reg_defaults[i].reg] = map->reg_defaults[i].def; + for (i = 0; i < map->num_reg_defaults; i++) { + index = map->reg_defaults[i].reg / map->reg_stride; + cache[index] = map->reg_defaults[i].def; + } return 0; } @@ -45,9 +47,10 @@ static int regcache_flat_exit(struct regmap *map) static int regcache_flat_read(struct regmap *map, unsigned int reg, unsigned int *value) { + unsigned int index = reg / map->reg_stride; unsigned int *cache = map->cache; - *value = cache[reg]; + *value = cache[index]; return 0; } @@ -55,9 +58,10 @@ static int regcache_flat_read(struct regmap *map, static int regcache_flat_write(struct regmap *map, unsigned int reg, unsigned int value) { + unsigned int index = reg / map->reg_stride; unsigned int *cache = map->cache; - cache[reg] = value; + cache[index] = value; return 0; } -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/