regcache-rbtree.c (c0cc6fe1d09e3f1baecbdf8922473c8e7d3a5317) | regcache-rbtree.c (f01ee60fffa4dc6c77122121233a793f7f696e67) |
---|---|
1/* 2 * Register cache access API - rbtree caching support 3 * 4 * Copyright 2011 Wolfson Microelectronics plc 5 * 6 * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> 7 * 8 * This program is free software; you can redistribute it and/or modify --- 25 unchanged lines hidden (view full) --- 34} __attribute__ ((packed)); 35 36struct regcache_rbtree_ctx { 37 struct rb_root root; 38 struct regcache_rbtree_node *cached_rbnode; 39}; 40 41static inline void regcache_rbtree_get_base_top_reg( | 1/* 2 * Register cache access API - rbtree caching support 3 * 4 * Copyright 2011 Wolfson Microelectronics plc 5 * 6 * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> 7 * 8 * This program is free software; you can redistribute it and/or modify --- 25 unchanged lines hidden (view full) --- 34} __attribute__ ((packed)); 35 36struct regcache_rbtree_ctx { 37 struct rb_root root; 38 struct regcache_rbtree_node *cached_rbnode; 39}; 40 41static inline void regcache_rbtree_get_base_top_reg( |
42 struct regmap *map, |
|
42 struct regcache_rbtree_node *rbnode, 43 unsigned int *base, unsigned int *top) 44{ 45 *base = rbnode->base_reg; | 43 struct regcache_rbtree_node *rbnode, 44 unsigned int *base, unsigned int *top) 45{ 46 *base = rbnode->base_reg; |
46 *top = rbnode->base_reg + rbnode->blklen - 1; | 47 *top = rbnode->base_reg + ((rbnode->blklen - 1) * map->reg_stride); |
47} 48 49static unsigned int regcache_rbtree_get_register( 50 struct regcache_rbtree_node *rbnode, unsigned int idx, 51 unsigned int word_size) 52{ 53 return regcache_get_val(rbnode->block, idx, word_size); 54} --- 10 unchanged lines hidden (view full) --- 65{ 66 struct regcache_rbtree_ctx *rbtree_ctx = map->cache; 67 struct rb_node *node; 68 struct regcache_rbtree_node *rbnode; 69 unsigned int base_reg, top_reg; 70 71 rbnode = rbtree_ctx->cached_rbnode; 72 if (rbnode) { | 48} 49 50static unsigned int regcache_rbtree_get_register( 51 struct regcache_rbtree_node *rbnode, unsigned int idx, 52 unsigned int word_size) 53{ 54 return regcache_get_val(rbnode->block, idx, word_size); 55} --- 10 unchanged lines hidden (view full) --- 66{ 67 struct regcache_rbtree_ctx *rbtree_ctx = map->cache; 68 struct rb_node *node; 69 struct regcache_rbtree_node *rbnode; 70 unsigned int base_reg, top_reg; 71 72 rbnode = rbtree_ctx->cached_rbnode; 73 if (rbnode) { |
73 regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg); | 74 regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg, 75 &top_reg); |
74 if (reg >= base_reg && reg <= top_reg) 75 return rbnode; 76 } 77 78 node = rbtree_ctx->root.rb_node; 79 while (node) { 80 rbnode = container_of(node, struct regcache_rbtree_node, node); | 76 if (reg >= base_reg && reg <= top_reg) 77 return rbnode; 78 } 79 80 node = rbtree_ctx->root.rb_node; 81 while (node) { 82 rbnode = container_of(node, struct regcache_rbtree_node, node); |
81 regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg); | 83 regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg, 84 &top_reg); |
82 if (reg >= base_reg && reg <= top_reg) { 83 rbtree_ctx->cached_rbnode = rbnode; 84 return rbnode; 85 } else if (reg > top_reg) { 86 node = node->rb_right; 87 } else if (reg < base_reg) { 88 node = node->rb_left; 89 } 90 } 91 92 return NULL; 93} 94 | 85 if (reg >= base_reg && reg <= top_reg) { 86 rbtree_ctx->cached_rbnode = rbnode; 87 return rbnode; 88 } else if (reg > top_reg) { 89 node = node->rb_right; 90 } else if (reg < base_reg) { 91 node = node->rb_left; 92 } 93 } 94 95 return NULL; 96} 97 |
95static int regcache_rbtree_insert(struct rb_root *root, | 98static int regcache_rbtree_insert(struct regmap *map, struct rb_root *root, |
96 struct regcache_rbtree_node *rbnode) 97{ 98 struct rb_node **new, *parent; 99 struct regcache_rbtree_node *rbnode_tmp; 100 unsigned int base_reg_tmp, top_reg_tmp; 101 unsigned int base_reg; 102 103 parent = NULL; 104 new = &root->rb_node; 105 while (*new) { 106 rbnode_tmp = container_of(*new, struct regcache_rbtree_node, 107 node); 108 /* base and top registers of the current rbnode */ | 99 struct regcache_rbtree_node *rbnode) 100{ 101 struct rb_node **new, *parent; 102 struct regcache_rbtree_node *rbnode_tmp; 103 unsigned int base_reg_tmp, top_reg_tmp; 104 unsigned int base_reg; 105 106 parent = NULL; 107 new = &root->rb_node; 108 while (*new) { 109 rbnode_tmp = container_of(*new, struct regcache_rbtree_node, 110 node); 111 /* base and top registers of the current rbnode */ |
109 regcache_rbtree_get_base_top_reg(rbnode_tmp, &base_reg_tmp, | 112 regcache_rbtree_get_base_top_reg(map, rbnode_tmp, &base_reg_tmp, |
110 &top_reg_tmp); 111 /* base register of the rbnode to be added */ 112 base_reg = rbnode->base_reg; 113 parent = *new; 114 /* if this register has already been inserted, just return */ 115 if (base_reg >= base_reg_tmp && 116 base_reg <= top_reg_tmp) 117 return 0; --- 15 unchanged lines hidden (view full) --- 133{ 134 struct regmap *map = s->private; 135 struct regcache_rbtree_ctx *rbtree_ctx = map->cache; 136 struct regcache_rbtree_node *n; 137 struct rb_node *node; 138 unsigned int base, top; 139 int nodes = 0; 140 int registers = 0; | 113 &top_reg_tmp); 114 /* base register of the rbnode to be added */ 115 base_reg = rbnode->base_reg; 116 parent = *new; 117 /* if this register has already been inserted, just return */ 118 if (base_reg >= base_reg_tmp && 119 base_reg <= top_reg_tmp) 120 return 0; --- 15 unchanged lines hidden (view full) --- 136{ 137 struct regmap *map = s->private; 138 struct regcache_rbtree_ctx *rbtree_ctx = map->cache; 139 struct regcache_rbtree_node *n; 140 struct rb_node *node; 141 unsigned int base, top; 142 int nodes = 0; 143 int registers = 0; |
141 int average; | 144 int this_registers, average; |
142 143 map->lock(map); 144 145 for (node = rb_first(&rbtree_ctx->root); node != NULL; 146 node = rb_next(node)) { 147 n = container_of(node, struct regcache_rbtree_node, node); 148 | 145 146 map->lock(map); 147 148 for (node = rb_first(&rbtree_ctx->root); node != NULL; 149 node = rb_next(node)) { 150 n = container_of(node, struct regcache_rbtree_node, node); 151 |
149 regcache_rbtree_get_base_top_reg(n, &base, &top); 150 seq_printf(s, "%x-%x (%d)\n", base, top, top - base + 1); | 152 regcache_rbtree_get_base_top_reg(map, n, &base, &top); 153 this_registers = ((top - base) / map->reg_stride) + 1; 154 seq_printf(s, "%x-%x (%d)\n", base, top, this_registers); |
151 152 nodes++; | 155 156 nodes++; |
153 registers += top - base + 1; | 157 registers += this_registers; |
154 } 155 156 if (nodes) 157 average = registers / nodes; 158 else 159 average = 0; 160 161 seq_printf(s, "%d nodes, %d registers, average %d registers\n", --- 88 unchanged lines hidden (view full) --- 250static int regcache_rbtree_read(struct regmap *map, 251 unsigned int reg, unsigned int *value) 252{ 253 struct regcache_rbtree_node *rbnode; 254 unsigned int reg_tmp; 255 256 rbnode = regcache_rbtree_lookup(map, reg); 257 if (rbnode) { | 158 } 159 160 if (nodes) 161 average = registers / nodes; 162 else 163 average = 0; 164 165 seq_printf(s, "%d nodes, %d registers, average %d registers\n", --- 88 unchanged lines hidden (view full) --- 254static int regcache_rbtree_read(struct regmap *map, 255 unsigned int reg, unsigned int *value) 256{ 257 struct regcache_rbtree_node *rbnode; 258 unsigned int reg_tmp; 259 260 rbnode = regcache_rbtree_lookup(map, reg); 261 if (rbnode) { |
258 reg_tmp = reg - rbnode->base_reg; | 262 reg_tmp = (reg - rbnode->base_reg) / map->reg_stride; |
259 *value = regcache_rbtree_get_register(rbnode, reg_tmp, 260 map->cache_word_size); 261 } else { 262 return -ENOENT; 263 } 264 265 return 0; 266} --- 38 unchanged lines hidden (view full) --- 305 int ret; 306 307 rbtree_ctx = map->cache; 308 /* if we can't locate it in the cached rbnode we'll have 309 * to traverse the rbtree looking for it. 310 */ 311 rbnode = regcache_rbtree_lookup(map, reg); 312 if (rbnode) { | 263 *value = regcache_rbtree_get_register(rbnode, reg_tmp, 264 map->cache_word_size); 265 } else { 266 return -ENOENT; 267 } 268 269 return 0; 270} --- 38 unchanged lines hidden (view full) --- 309 int ret; 310 311 rbtree_ctx = map->cache; 312 /* if we can't locate it in the cached rbnode we'll have 313 * to traverse the rbtree looking for it. 314 */ 315 rbnode = regcache_rbtree_lookup(map, reg); 316 if (rbnode) { |
313 reg_tmp = reg - rbnode->base_reg; | 317 reg_tmp = (reg - rbnode->base_reg) / map->reg_stride; |
314 val = regcache_rbtree_get_register(rbnode, reg_tmp, 315 map->cache_word_size); 316 if (val == value) 317 return 0; 318 regcache_rbtree_set_register(rbnode, reg_tmp, value, 319 map->cache_word_size); 320 } else { 321 /* look for an adjacent register to the one we are about to add */ 322 for (node = rb_first(&rbtree_ctx->root); node; 323 node = rb_next(node)) { | 318 val = regcache_rbtree_get_register(rbnode, reg_tmp, 319 map->cache_word_size); 320 if (val == value) 321 return 0; 322 regcache_rbtree_set_register(rbnode, reg_tmp, value, 323 map->cache_word_size); 324 } else { 325 /* look for an adjacent register to the one we are about to add */ 326 for (node = rb_first(&rbtree_ctx->root); node; 327 node = rb_next(node)) { |
324 rbnode_tmp = rb_entry(node, struct regcache_rbtree_node, node); | 328 rbnode_tmp = rb_entry(node, struct regcache_rbtree_node, 329 node); |
325 for (i = 0; i < rbnode_tmp->blklen; i++) { | 330 for (i = 0; i < rbnode_tmp->blklen; i++) { |
326 reg_tmp = rbnode_tmp->base_reg + i; 327 if (abs(reg_tmp - reg) != 1) | 331 reg_tmp = rbnode_tmp->base_reg + 332 (i * map->reg_stride); 333 if (abs(reg_tmp - reg) != map->reg_stride) |
328 continue; 329 /* decide where in the block to place our register */ | 334 continue; 335 /* decide where in the block to place our register */ |
330 if (reg_tmp + 1 == reg) | 336 if (reg_tmp + map->reg_stride == reg) |
331 pos = i + 1; 332 else 333 pos = i; 334 ret = regcache_rbtree_insert_to_block(rbnode_tmp, pos, 335 reg, value, 336 map->cache_word_size); 337 if (ret) 338 return ret; --- 13 unchanged lines hidden (view full) --- 352 rbnode->base_reg = reg; 353 rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size, 354 GFP_KERNEL); 355 if (!rbnode->block) { 356 kfree(rbnode); 357 return -ENOMEM; 358 } 359 regcache_rbtree_set_register(rbnode, 0, value, map->cache_word_size); | 337 pos = i + 1; 338 else 339 pos = i; 340 ret = regcache_rbtree_insert_to_block(rbnode_tmp, pos, 341 reg, value, 342 map->cache_word_size); 343 if (ret) 344 return ret; --- 13 unchanged lines hidden (view full) --- 358 rbnode->base_reg = reg; 359 rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size, 360 GFP_KERNEL); 361 if (!rbnode->block) { 362 kfree(rbnode); 363 return -ENOMEM; 364 } 365 regcache_rbtree_set_register(rbnode, 0, value, map->cache_word_size); |
360 regcache_rbtree_insert(&rbtree_ctx->root, rbnode); | 366 regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode); |
361 rbtree_ctx->cached_rbnode = rbnode; 362 } 363 364 return 0; 365} 366 367static int regcache_rbtree_sync(struct regmap *map, unsigned int min, 368 unsigned int max) --- 23 unchanged lines hidden (view full) --- 392 base = 0; 393 394 if (max < rbnode->base_reg + rbnode->blklen) 395 end = rbnode->base_reg + rbnode->blklen - max; 396 else 397 end = rbnode->blklen; 398 399 for (i = base; i < end; i++) { | 367 rbtree_ctx->cached_rbnode = rbnode; 368 } 369 370 return 0; 371} 372 373static int regcache_rbtree_sync(struct regmap *map, unsigned int min, 374 unsigned int max) --- 23 unchanged lines hidden (view full) --- 398 base = 0; 399 400 if (max < rbnode->base_reg + rbnode->blklen) 401 end = rbnode->base_reg + rbnode->blklen - max; 402 else 403 end = rbnode->blklen; 404 405 for (i = base; i < end; i++) { |
400 regtmp = rbnode->base_reg + i; | 406 regtmp = rbnode->base_reg + (i * map->reg_stride); |
401 val = regcache_rbtree_get_register(rbnode, i, 402 map->cache_word_size); 403 404 /* Is this the hardware default? If so skip. */ 405 ret = regcache_lookup_reg(map, regtmp); 406 if (ret >= 0 && val == map->reg_defaults[ret].def) 407 continue; 408 --- 22 unchanged lines hidden --- | 407 val = regcache_rbtree_get_register(rbnode, i, 408 map->cache_word_size); 409 410 /* Is this the hardware default? If so skip. */ 411 ret = regcache_lookup_reg(map, regtmp); 412 if (ret >= 0 && val == map->reg_defaults[ret].def) 413 continue; 414 --- 22 unchanged lines hidden --- |